-- T65 Core Wrapper
-- 17.06.2009 mit bereinigten Clock-Signalen von C. Meyer, cm@ctmagazin.de

-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- You are responsible for any legal issues arising from your use of this code.
--
-- The latest version of this file can be found at: www.fpgaarcade.com
--

library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_arith.all;
  use ieee.std_logic_unsigned.all;


entity t65_wrap is
  port (
    ADDR         : out   std_logic_vector(15 downto 0);
    DATA_O       : out   std_logic_vector(7 downto 0);
    DATA_I       : in   std_logic_vector(7 downto 0);
    --
    RST          : in    std_logic;
    IRQ          : in    std_logic;
    NMI          : in    std_logic;
    WR_N         : out    std_logic;
	 BUSENA_N     : out    std_logic;
    HALT         : in    std_logic;
    HALTED       : out    std_logic;
    RD_N         : out    std_logic;
    CLK_X4       : in    std_logic
    );
end;

architecture RTL of t65_wrap is

	signal ena_count            : std_logic_vector(3 downto 0) := (others => '0');
	signal ena_clk_x1           : std_ulogic;

  -- cpu
	signal c_rw_l               : std_logic:='1';
	signal c_irq_l              : std_logic:='1';
	signal c_nmi_l              : std_logic:='1';
	signal reset_l              : std_logic:='1';
	signal sync_h               : std_logic;
	signal halt_i             : std_logic;
	signal rd_n_i               : std_logic;
	signal addr_intern          : std_logic_vector(15 downto 0);
	signal addr_unused          : std_logic_vector(23 downto 16);

	component T65 is
		port(
			Mode    : in  std_logic_vector(1 downto 0);      -- "00" => 6502, "01" => 65C02, "10" => 65C816
			Res_n   : in  std_logic;
			Enable  : in  std_logic;
			Clk     : in  std_logic;
			Rdy     : in  std_logic;
			Abort_n : in  std_logic;
			IRQ_n   : in  std_logic;
			NMI_n   : in  std_logic;
			SO_n    : in  std_logic;
			R_W_n   : out std_logic;
			Sync    : out std_logic;
			EF      : out std_logic;
			MF      : out std_logic;
			XF      : out std_logic;
			ML_n    : out std_logic;
			VP_n    : out std_logic;
			VDA     : out std_logic;
			VPA     : out std_logic;
			A       : out std_logic_vector(23 downto 0);
			DI      : in  std_logic_vector(7 downto 0);
			DO      : out std_logic_vector(7 downto 0)
		);
	end component;
	
begin

  p_halt : process(ena_count(1),RST) 
  -- HALT sync für DMA-Zugriff, HALTED geht im Opcode-Fetch-Zyklus high und bleibt dort
  -- bis HALT wieder 0 wird, geht dann mit nächstem CPU-Clock wieder auf '0'.
  begin
		if RST='1' then
			halt_i <='0';
		else
			if rising_edge(ena_count(1)) then
				if (HALT='1') then -- (sync_h='1' and HALT='1') 
					halt_i<='1';
				elsif HALT='0' then
					halt_i<='0';
				end if;
			end if;
		end if;
  end process;

	
p_ena : process(CLK_X4)  -- clock divider and delay
	begin
		if rising_edge(CLK_X4) then
			ADDR<=addr_intern;	-- um 1 CLK verzögert
			HALTED<=halt_i;
			ena_count <= ena_count + "1";
			ena_clk_x1 <= '0';
			if (ena_count(1 downto 0) = "00") then
				ena_clk_x1 <= '1'; -- 1.5 Mhz
			end if;
		end if;
	end process;


  cpu : T65 -- main cpu
      port map (
          Mode    => "00",
          Res_n   => reset_l,
          Enable  => ena_clk_x1,
          Clk     => CLK_X4,
          Rdy     => not halt_i,
          Abort_n => '1',
          IRQ_n   => c_irq_l,
          NMI_n   => c_nmi_l,
          SO_n    => '1',
          R_W_n   => c_rw_l,
          Sync    => sync_h,
          EF      => open,
          MF      => open,
          XF      => open,
          ML_n    => open,
          VP_n    => open,
          VDA     => open,
          VPA     => open,
          A(15 downto 0)  => addr_intern,
          A(23 downto 16)  => addr_unused,
          DI      => DATA_I,
          DO      => DATA_O
      );
		
  c_irq_l <= not IRQ;
  c_nmi_l <= not NMI;
  WR_N <= ena_count(1) when c_rw_l='0' else '1'; -- c_rw_l or (not ena_clk_x1_l);
  RD_N <= ena_count(1) when c_rw_l='1' else '1';
  reset_l <= not RST;
  BUSENA_N <= ena_count(1);

end RTL;
