--------------------------------------------------------------------------- -- (c) 2013 mark watson -- I am happy for anyone to use this for non-commercial use. -- If my vhdl files are used commercially or otherwise sold, -- please contact me for explicit permission at scrameta (gmail). -- This applies for source and binary form and derived works. --------------------------------------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.all; use ieee.numeric_std.all; use IEEE.STD_LOGIC_MISC.all; ENTITY timing6502 IS PORT ( CLK : IN STD_LOGIC; RESET_N : IN STD_LOGIC; PHI0 : IN STD_LOGIC; HALT_N : IN STD_LOGIC; IRQ_N : IN STD_LOGIC; NMI_N : IN STD_LOGIC; -- FPGA side ADDR_IN : IN STD_LOGIC_VECTOR(15 downto 0); DATA_IN : IN STD_LOGIC_VECTOR(7 downto 0); WRITE_IN : IN STD_LOGIC; DATA_OUT : OUT STD_LOGIC_VECTOR(7 downto 0); CPU_REQUEST : OUT STD_LOGIC; CPU_REQUEST_COMPLETE : OUT STD_LOGIC; CPU_IRQ_N : OUT STD_LOGIC; CPU_NMI_N : OUT STD_LOGIC; CPU_RDY : OUT STD_LOGIC; -- 6502 side BUS_DATA_IN : IN STD_LOGIC_VECTOR(7 downto 0); BUS_RDY : IN STD_LOGIC; BUS_PHI1 : OUT STD_LOGIC; BUS_PHI2 : OUT STD_LOGIC; BUS_SUBCYCLE : OUT STD_LOGIC_VECTOR(4 downto 0); BUS_ADDR_OUT : OUT STD_LOGIC_VECTOR(15 downto 0); BUS_ADDR_OE : OUT STD_LOGIC; BUS_DATA_OUT : OUT STD_LOGIC_VECTOR(7 downto 0); BUS_DATA_OE : OUT STD_LOGIC; BUS_WRITE_N : OUT STD_LOGIC; BUS_WRITE_OE : OUT STD_LOGIC ); END timing6502; ARCHITECTURE vhdl OF timing6502 IS signal state_next : std_logic_vector(4 downto 0); signal state_reg : STD_LOGIC_VECTOR(4 DOWNTO 0); signal addr_next : std_logic_vector(15 downto 0); signal addr_reg : std_logic_vector(15 downto 0); signal addr_oe_next : std_logic; signal addr_oe_reg : std_logic; signal data_next : std_logic_vector(7 downto 0); signal data_reg : std_logic_vector(7 downto 0); signal data_oe_next : std_logic; signal data_oe_reg : std_logic; signal data_read_next : std_logic_vector(7 downto 0); signal data_read_reg : std_logic_vector(7 downto 0); signal phi1_next : std_logic; signal phi1_reg : std_logic; signal phi2_next : std_logic; signal phi2_reg : std_logic; signal write_n_next : std_logic; signal write_n_reg : std_logic; signal write_oe_next : std_logic; signal write_oe_reg : std_logic; signal request_handling_next : std_logic; signal request_handling_reg : std_logic; signal PHI0_NEXT : std_logic; signal PHI0_REG : std_logic; signal NMI_N_NEXT : std_logic; signal NMI_N_REG : std_logic; signal IRQ_N_NEXT : std_logic; signal IRQ_N_REG : std_logic; signal RDY_NEXT : std_logic; signal RDY_REG : std_logic; signal HALT_N_NEXT : std_logic; signal HALT_N_REG : std_logic; signal init_next : std_logic_vector(5 downto 0); signal init_reg : std_logic_vector(5 downto 0); signal syncphi2 : std_logic; signal initmode : std_logic; BEGIN -- regs process(clk, reset_n) begin if (reset_n='0') then state_reg <= "01100"; addr_reg <= (others=>'0'); addr_oe_reg <= '0'; data_reg <= (others=>'0'); data_read_reg <= (others=>'0'); data_oe_reg <= '0'; phi1_reg <= '0'; phi2_reg <= '0'; write_n_reg <= '1'; write_oe_reg <= '0'; request_handling_reg <= '0'; PHI0_REG <= '1'; IRQ_N_REG <= '1'; NMI_N_REG <= '1'; HALT_N_REG <= '1'; RDY_REG <= '1'; init_reg <= (others=>'0'); elsif (clk'event and clk='1') then state_reg <= state_next; addr_reg <= addr_next; addr_oe_reg <= addr_oe_next; data_reg <= data_next; data_read_reg <= data_read_next; data_oe_reg <= data_oe_next; phi1_reg <= phi1_next; phi2_reg <= phi2_next; write_n_reg <= write_n_next; write_oe_reg <= write_oe_next; request_handling_reg <= request_handling_next; PHI0_REG <= PHI0_NEXT; IRQ_N_REG <= IRQ_N_NEXT; NMI_N_REG <= NMI_N_NEXT; HALT_N_REG <= HALT_N_NEXT; RDY_REG <= RDY_NEXT; init_reg <= init_next; end if; end process; PHI0_sync : entity work.synchronizer port map (clk=>clk, raw=>PHI0, sync=>PHI0_NEXT); process(init_reg,phi0_reg,phi0_next) begin init_next <= init_reg; initmode <= '0'; syncphi2 <= '0'; if (phi0_reg = '0' and phi0_next='1') then init_next(5 downto 0) <= init_reg(4 downto 0)&'1'; syncphi2 <= '1'; end if; if (and_reduce(init_reg)='0') then initmode <= '1'; end if; end process; -- next state process(initmode, syncphi2, state_reg, phi1_reg, phi2_reg, addr_in, data_in, addr_reg, addr_oe_reg, data_reg, data_oe_reg, data_read_reg, bus_data_in, write_n_reg, write_in, request_handling_reg, write_oe_reg, irq_n_reg, nmi_n_reg, halt_n_reg, bus_rdy, rdy_reg, nmi_n, irq_n, halt_n) begin CPU_REQUEST_COMPLETE <= '0'; state_next <= state_reg; phi1_next <= phi1_reg; phi2_next <= phi2_reg; addr_next <= addr_reg; addr_oe_next <= addr_oe_reg; data_next <= data_reg; data_oe_next <= data_oe_reg; data_read_next <= data_read_reg; write_n_next <= write_n_reg; request_handling_next <= request_handling_reg; write_oe_next <= write_oe_reg; irq_n_next <= irq_n_reg; nmi_n_next <= nmi_n_reg; halt_n_next <= halt_n_reg; rdy_next <= rdy_reg; if (initmode = '0') then state_next <= std_logic_vector(unsigned(state_reg)+1); end if; if (syncphi2 = '1') then phi1_next <= '1'; state_next <= "01111"; end if; rdy_next <= bus_rdy; case state_reg is when "00000" => addr_next <= addr_in; data_next <= data_in; write_n_next <= not(write_in); request_handling_next <= halt_n_reg; when "00010"=> addr_oe_next <= request_handling_reg; write_oe_next <= request_handling_reg; when "01100" => phi1_next <= '0'; when "01110" => phi2_next <= '1'; when "10010" => if (write_in = '1') then data_oe_next <= request_handling_reg; end if; when "11011" => phi2_next <= '0'; when "11100" => data_read_next <= bus_data_in; nmi_n_next <= nmi_n; irq_n_next <= irq_n; halt_n_next <= halt_n; when "11101" => request_handling_next <= '0'; CPU_REQUEST_COMPLETE <= request_handling_reg; when "11110" => addr_next <= (others=>'0'); addr_oe_next <= '0'; write_oe_next <= '0'; data_oe_next <= '0'; write_n_next <= '1'; phi1_next <= '1'; when others=> end case; end process; -- outputs BUS_SUBCYCLE <= state_reg; BUS_PHI1 <= phi1_reg; BUS_PHI2 <= phi2_reg; BUS_ADDR_OUT <= addr_reg; BUS_ADDR_OE <= addr_oe_reg; BUS_DATA_OUT <= data_reg; BUS_DATA_OE <= data_oe_reg; BUS_WRITE_N <= write_n_reg; BUS_WRITE_OE <= write_oe_reg; DATA_OUT <= data_read_reg; CPU_REQUEST <= request_handling_reg; CPU_NMI_N <= NMI_N_REG; CPU_IRQ_N <= IRQ_N_REG; CPU_RDY <= RDY_REG; END vhdl;