Project

General

Profile

---------------------------------------------------------------------------
-- (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;
(18-18/18)