2015-06-27 10:07:58 +00:00
|
|
|
--------------------------------------------------------------------------------
|
2019-10-14 12:35:13 +00:00
|
|
|
-- Copyright (c) 2019 David Banks
|
2015-06-27 10:07:58 +00:00
|
|
|
--
|
|
|
|
--------------------------------------------------------------------------------
|
2017-07-26 13:59:20 +00:00
|
|
|
-- ____ ____
|
|
|
|
-- / /\/ /
|
|
|
|
-- /___/ \ /
|
|
|
|
-- \ \ \/
|
|
|
|
-- \ \
|
2015-06-27 10:07:58 +00:00
|
|
|
-- / / Filename : Z80CpuMon.vhd
|
2019-10-14 12:35:13 +00:00
|
|
|
-- /___/ /\ Timestamp : 14/10/2018
|
2017-07-26 13:59:20 +00:00
|
|
|
-- \ \ / \
|
|
|
|
-- \___\/\___\
|
2015-06-27 10:07:58 +00:00
|
|
|
--
|
|
|
|
--Design Name: Z80CpuMon
|
2019-10-14 12:35:13 +00:00
|
|
|
--Device: multiple
|
2015-06-27 10:07:58 +00:00
|
|
|
|
|
|
|
library ieee;
|
|
|
|
use ieee.std_logic_1164.all;
|
|
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
use ieee.numeric_std.all;
|
|
|
|
|
|
|
|
entity Z80CpuMon is
|
|
|
|
generic (
|
2019-10-25 16:11:13 +00:00
|
|
|
UseT80Core : boolean := true;
|
|
|
|
LEDsActiveHigh : boolean := false; -- default value correct for GODIL
|
|
|
|
SW1ActiveHigh : boolean := true; -- default value correct for GODIL
|
|
|
|
SW2ActiveHigh : boolean := false; -- default value correct for GODIL
|
|
|
|
ClkMult : integer := 10; -- default value correct for GODIL
|
|
|
|
ClkDiv : integer := 31; -- default value correct for GODIL
|
|
|
|
ClkPer : real := 20.345; -- default value correct for GODIL
|
|
|
|
num_comparators : integer := 4; -- default value correct for GODIL
|
|
|
|
avr_prog_mem_size : integer := 1024 * 9 -- default value correct for GODIL
|
2015-06-27 10:07:58 +00:00
|
|
|
);
|
|
|
|
port (
|
|
|
|
clock49 : in std_logic;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
-- Z80 Signals
|
|
|
|
RESET_n : in std_logic;
|
|
|
|
CLK_n : in std_logic;
|
|
|
|
WAIT_n : in std_logic;
|
|
|
|
INT_n : in std_logic;
|
|
|
|
NMI_n : in std_logic;
|
|
|
|
BUSRQ_n : in std_logic;
|
|
|
|
M1_n : out std_logic;
|
|
|
|
MREQ_n : out std_logic;
|
|
|
|
IORQ_n : out std_logic;
|
|
|
|
RD_n : out std_logic;
|
|
|
|
WR_n : out std_logic;
|
|
|
|
RFSH_n : out std_logic;
|
|
|
|
HALT_n : out std_logic;
|
|
|
|
BUSAK_n : out std_logic;
|
|
|
|
Addr : out std_logic_vector(15 downto 0);
|
|
|
|
Data : inout std_logic_vector(7 downto 0);
|
2019-10-14 12:35:13 +00:00
|
|
|
DOE_n : out std_logic;
|
2015-06-27 10:07:58 +00:00
|
|
|
|
|
|
|
-- External trigger inputs
|
|
|
|
trig : in std_logic_vector(1 downto 0);
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
-- Serial Console
|
|
|
|
avr_RxD : in std_logic;
|
|
|
|
avr_TxD : out std_logic;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
-- GODIL Switches
|
|
|
|
sw1 : in std_logic;
|
2017-07-25 18:18:59 +00:00
|
|
|
sw2 : in std_logic;
|
2015-06-27 10:07:58 +00:00
|
|
|
|
|
|
|
-- GODIL LEDs
|
|
|
|
led3 : out std_logic;
|
|
|
|
led6 : out std_logic;
|
|
|
|
led8 : out std_logic;
|
|
|
|
|
|
|
|
-- OHO_DY1 connected to test connector
|
|
|
|
tmosi : out std_logic;
|
|
|
|
tdin : out std_logic;
|
|
|
|
tcclk : out std_logic;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
-- Debugging signals
|
|
|
|
test1 : out std_logic;
|
|
|
|
test2 : out std_logic;
|
|
|
|
test3 : out std_logic;
|
|
|
|
test4 : out std_logic
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
);
|
|
|
|
end Z80CpuMon;
|
|
|
|
|
|
|
|
architecture behavioral of Z80CpuMon is
|
|
|
|
|
2019-10-15 10:46:50 +00:00
|
|
|
type state_type is (idle, resume, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa, rd_t2, rd_t3, wr_t1, wr_wa, wr_t2, wr_t3);
|
2015-06-28 18:42:25 +00:00
|
|
|
|
2017-07-26 13:59:20 +00:00
|
|
|
signal state : state_type;
|
|
|
|
|
|
|
|
signal clock_avr : std_logic;
|
|
|
|
|
|
|
|
signal RESET_n_int : std_logic;
|
|
|
|
signal cpu_clk : std_logic;
|
|
|
|
signal busmon_clk : std_logic;
|
|
|
|
|
|
|
|
signal Addr_int : std_logic_vector(15 downto 0);
|
|
|
|
signal RD_n_int : std_logic;
|
|
|
|
signal WR_n_int : std_logic;
|
|
|
|
signal MREQ_n_int : std_logic;
|
|
|
|
signal IORQ_n_int : std_logic;
|
2019-10-14 19:26:04 +00:00
|
|
|
signal RFSH_n_int : std_logic;
|
2017-07-26 13:59:20 +00:00
|
|
|
signal M1_n_int : std_logic;
|
|
|
|
signal WAIT_n_int : std_logic;
|
|
|
|
signal TState : std_logic_vector(2 downto 0);
|
|
|
|
signal SS_Single : std_logic;
|
|
|
|
signal SS_Step : std_logic;
|
|
|
|
signal SS_Step_held : std_logic;
|
|
|
|
signal CountCycle : std_logic;
|
|
|
|
signal skipNextOpcode : std_logic;
|
|
|
|
|
|
|
|
signal Regs : std_logic_vector(255 downto 0);
|
|
|
|
signal io_not_mem : std_logic;
|
|
|
|
signal io_rd : std_logic;
|
|
|
|
signal io_wr : std_logic;
|
|
|
|
signal memory_rd : std_logic;
|
|
|
|
signal memory_wr : std_logic;
|
|
|
|
signal memory_addr : std_logic_vector(15 downto 0);
|
|
|
|
signal memory_dout : std_logic_vector(7 downto 0);
|
|
|
|
signal memory_din : std_logic_vector(7 downto 0);
|
|
|
|
signal memory_done : std_logic;
|
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
signal io_rd1 : std_logic;
|
|
|
|
signal io_wr1 : std_logic;
|
|
|
|
signal memory_rd1 : std_logic;
|
|
|
|
signal memory_wr1 : std_logic;
|
|
|
|
signal mon_mreq_n : std_logic;
|
|
|
|
signal mon_iorq_n : std_logic;
|
2019-10-14 19:26:04 +00:00
|
|
|
signal mon_rfsh_n : std_logic;
|
2019-10-14 12:35:13 +00:00
|
|
|
signal mon_rd_n : std_logic;
|
|
|
|
signal mon_wr_n : std_logic;
|
|
|
|
signal mon_wait_n : std_logic;
|
|
|
|
|
2017-07-26 13:59:20 +00:00
|
|
|
signal INT_n_sync : std_logic;
|
|
|
|
signal NMI_n_sync : std_logic;
|
|
|
|
|
|
|
|
signal Rdy : std_logic;
|
|
|
|
signal Read_n : std_logic;
|
|
|
|
signal Read_n0 : std_logic;
|
|
|
|
signal Read_n1 : std_logic;
|
|
|
|
signal Write_n : std_logic;
|
|
|
|
signal Write_n0 : std_logic;
|
|
|
|
signal ReadIO_n : std_logic;
|
|
|
|
signal ReadIO_n0 : std_logic;
|
|
|
|
signal ReadIO_n1 : std_logic;
|
|
|
|
signal WriteIO_n : std_logic;
|
|
|
|
signal WriteIO_n0 : std_logic;
|
|
|
|
signal Sync : std_logic;
|
|
|
|
signal Sync0 : std_logic;
|
2019-10-14 16:33:32 +00:00
|
|
|
signal Sync1 : std_logic;
|
2017-07-26 13:59:20 +00:00
|
|
|
signal Mem_IO_n : std_logic;
|
|
|
|
signal nRST : std_logic;
|
|
|
|
|
|
|
|
signal MemState : std_logic_vector(2 downto 0);
|
|
|
|
|
|
|
|
signal Din : std_logic_vector(7 downto 0);
|
|
|
|
signal Dout : std_logic_vector(7 downto 0);
|
|
|
|
signal Den : std_logic;
|
|
|
|
signal ex_data : std_logic_vector(7 downto 0);
|
|
|
|
signal rd_data : std_logic_vector(7 downto 0);
|
|
|
|
signal mon_data : std_logic_vector(7 downto 0);
|
|
|
|
|
|
|
|
signal led3_n : std_logic; -- led to indicate ext trig 0 is active
|
|
|
|
signal led6_n : std_logic; -- led to indicate ext trig 1 is active
|
|
|
|
signal led8_n : std_logic; -- led to indicate CPU has hit a breakpoint (and is stopped)
|
|
|
|
signal sw_interrupt_n : std_logic; -- switch to pause the CPU
|
|
|
|
signal sw_reset_n : std_logic; -- switch to reset the CPU
|
2017-07-25 18:18:59 +00:00
|
|
|
|
2017-07-29 18:55:27 +00:00
|
|
|
signal avr_TxD_int : std_logic;
|
|
|
|
|
|
|
|
signal clock_49_ctr : std_logic_vector(23 downto 0);
|
|
|
|
signal clock_avr_ctr : std_logic_vector(23 downto 0);
|
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
signal rfsh_addr : std_logic_vector(15 downto 0);
|
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
begin
|
|
|
|
|
2017-07-25 18:18:59 +00:00
|
|
|
-- Generics allows polarity of switches/LEDs to be tweaked from the project file
|
2017-08-01 07:18:20 +00:00
|
|
|
sw_interrupt_n <= not sw1 when SW1ActiveHigh else sw1;
|
|
|
|
sw_reset_n <= not sw2 when SW2ActiveHigh else sw2;
|
2017-07-25 18:18:59 +00:00
|
|
|
led3 <= not led3_n when LEDsActiveHigh else led3_n;
|
|
|
|
led6 <= not led6_n when LEDsActiveHigh else led6_n;
|
|
|
|
led8 <= not led8_n when LEDsActiveHigh else led8_n;
|
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
--------------------------------------------------------
|
|
|
|
-- Clocking
|
|
|
|
--------------------------------------------------------
|
|
|
|
|
2017-07-29 18:55:27 +00:00
|
|
|
inst_dcm0 : entity work.DCM0
|
|
|
|
generic map (
|
|
|
|
ClkMult => ClkMult,
|
|
|
|
ClkDiv => ClkDiv,
|
|
|
|
ClkPer => ClkPer
|
|
|
|
)
|
|
|
|
port map(
|
|
|
|
CLKIN_IN => clock49,
|
|
|
|
CLKFX_OUT => clock_avr
|
|
|
|
);
|
2015-10-31 13:45:09 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
cpu_clk <= CLK_n;
|
|
|
|
busmon_clk <= CLK_n;
|
|
|
|
|
|
|
|
--------------------------------------------------------
|
|
|
|
-- BusMonCore
|
|
|
|
--------------------------------------------------------
|
|
|
|
|
2015-10-31 13:45:09 +00:00
|
|
|
mon : entity work.BusMonCore
|
2015-06-27 10:07:58 +00:00
|
|
|
generic map (
|
2019-10-25 16:11:13 +00:00
|
|
|
num_comparators => num_comparators,
|
|
|
|
avr_prog_mem_size => avr_prog_mem_size
|
2015-06-27 10:07:58 +00:00
|
|
|
)
|
2017-07-26 13:59:20 +00:00
|
|
|
port map (
|
2015-10-31 13:45:09 +00:00
|
|
|
clock_avr => clock_avr,
|
|
|
|
busmon_clk => busmon_clk,
|
|
|
|
busmon_clken => '1',
|
|
|
|
cpu_clk => cpu_clk,
|
|
|
|
cpu_clken => '1',
|
|
|
|
Addr => Addr_int,
|
|
|
|
Data => mon_data,
|
|
|
|
Rd_n => Read_n,
|
|
|
|
Wr_n => Write_n,
|
|
|
|
RdIO_n => ReadIO_n,
|
|
|
|
WrIO_n => WriteIO_n,
|
|
|
|
Sync => Sync,
|
|
|
|
Rdy => Rdy,
|
|
|
|
nRSTin => RESET_n_int,
|
|
|
|
nRSTout => nRST,
|
|
|
|
CountCycle => CountCycle,
|
|
|
|
trig => trig,
|
|
|
|
lcd_rs => open,
|
|
|
|
lcd_rw => open,
|
|
|
|
lcd_e => open,
|
|
|
|
lcd_db => open,
|
|
|
|
avr_RxD => avr_RxD,
|
2017-07-29 18:55:27 +00:00
|
|
|
avr_TxD => avr_TxD_int,
|
2015-10-31 13:45:09 +00:00
|
|
|
sw1 => '0',
|
2017-08-01 07:18:20 +00:00
|
|
|
nsw2 => sw_reset_n,
|
2017-07-25 18:18:59 +00:00
|
|
|
led3 => led3_n,
|
|
|
|
led6 => led6_n,
|
|
|
|
led8 => led8_n,
|
2015-10-31 13:45:09 +00:00
|
|
|
tmosi => tmosi,
|
|
|
|
tdin => tdin,
|
|
|
|
tcclk => tcclk,
|
|
|
|
Regs => Regs,
|
|
|
|
RdMemOut => memory_rd,
|
|
|
|
WrMemOut => memory_wr,
|
|
|
|
RdIOOut => io_rd,
|
|
|
|
WrIOOut => io_wr,
|
|
|
|
AddrOut => memory_addr,
|
|
|
|
DataOut => memory_dout,
|
|
|
|
DataIn => memory_din,
|
|
|
|
Done => memory_done,
|
|
|
|
SS_Single => SS_Single,
|
|
|
|
SS_Step => SS_Step
|
2015-06-27 10:07:58 +00:00
|
|
|
);
|
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
--------------------------------------------------------
|
|
|
|
-- T80
|
|
|
|
--------------------------------------------------------
|
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
GenT80Core: if UseT80Core generate
|
|
|
|
inst_t80: entity work.T80a port map (
|
|
|
|
TS => TState,
|
|
|
|
Regs => Regs,
|
|
|
|
RESET_n => RESET_n_int,
|
|
|
|
CLK_n => cpu_clk,
|
|
|
|
WAIT_n => WAIT_n_int,
|
|
|
|
INT_n => INT_n_sync,
|
|
|
|
NMI_n => NMI_n_sync,
|
|
|
|
BUSRQ_n => BUSRQ_n,
|
|
|
|
M1_n => M1_n_int,
|
|
|
|
MREQ_n => MREQ_n_int,
|
|
|
|
IORQ_n => IORQ_n_int,
|
|
|
|
RD_n => RD_n_int,
|
|
|
|
WR_n => WR_n_int,
|
2019-10-14 19:26:04 +00:00
|
|
|
RFSH_n => RFSH_n_int,
|
2015-06-27 10:07:58 +00:00
|
|
|
HALT_n => HALT_n,
|
|
|
|
BUSAK_n => BUSAK_n,
|
|
|
|
A => Addr_int,
|
2015-06-28 18:42:25 +00:00
|
|
|
Din => Din,
|
|
|
|
Dout => Dout,
|
|
|
|
DEn => Den
|
2015-06-27 10:07:58 +00:00
|
|
|
);
|
|
|
|
end generate;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
--------------------------------------------------------
|
2019-10-14 16:33:32 +00:00
|
|
|
-- Synchronise external interrupts
|
2019-10-14 12:35:13 +00:00
|
|
|
--------------------------------------------------------
|
|
|
|
|
2019-10-14 16:33:32 +00:00
|
|
|
int_gen : process(CLK_n)
|
2015-06-27 10:07:58 +00:00
|
|
|
begin
|
2019-10-14 16:33:32 +00:00
|
|
|
if rising_edge(CLK_n) then
|
2015-06-27 10:07:58 +00:00
|
|
|
NMI_n_sync <= NMI_n;
|
|
|
|
INT_n_sync <= INT_n;
|
|
|
|
end if;
|
|
|
|
end process;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2019-10-14 16:33:32 +00:00
|
|
|
--------------------------------------------------------
|
|
|
|
-- Z80 specific single step / breakpoint logic
|
|
|
|
--------------------------------------------------------
|
|
|
|
|
|
|
|
CountCycle <= '1' when state = idle else '0';
|
|
|
|
|
|
|
|
-- For the break point logic to work, the following must happen
|
|
|
|
-- SS_Single taken high by BusMonCore on the rising edge at the start of T2
|
|
|
|
-- WAIT_n_int must be taken low before the falling edge in the middle of T2
|
|
|
|
-- This implies a combinatorial path from SS_Single to WAIT_n_int
|
|
|
|
|
|
|
|
WAIT_n_int <= '0' when state = idle and SS_Single = '1' and Sync1 = '1' else
|
|
|
|
'0' when state /= idle else
|
|
|
|
WAIT_n;
|
|
|
|
|
2015-06-30 13:19:19 +00:00
|
|
|
-- Logic to ignore the second M1 in multi-byte opcodes
|
|
|
|
skip_opcode_latch : process(CLK_n)
|
|
|
|
begin
|
|
|
|
if rising_edge(CLK_n) then
|
|
|
|
if (M1_n_int = '0' and WAIT_n_int = '1' and TState = "010") then
|
|
|
|
if (skipNextOpcode = '0' and (Data = x"CB" or Data = x"DD" or Data = x"ED" or Data = x"FD")) then
|
|
|
|
skipNextOpcode <= '1';
|
|
|
|
else
|
|
|
|
skipNextOpcode <= '0';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2015-06-29 16:16:23 +00:00
|
|
|
-- For instruction breakpoints, we make the monitoring decision as early as possibe
|
|
|
|
-- to allow time to stop the current instruction, which is possible because we don't
|
|
|
|
-- really care about the data (it's re-read from memory by the disassembler).
|
2017-07-26 13:59:20 +00:00
|
|
|
Sync0 <= '1' when M1_n_int = '0' and TState = "001" and skipNextOpcode = '0' else '0';
|
2015-06-29 16:16:23 +00:00
|
|
|
|
2015-06-30 13:19:19 +00:00
|
|
|
-- For memory reads/write breakpoints we make the monitoring decision in the middle of T2
|
2015-06-29 16:16:23 +00:00
|
|
|
-- but only if WAIT_n is '1' so we catch the right data.
|
2017-07-26 13:59:20 +00:00
|
|
|
Read_n0 <= not (WAIT_n_int and (not RD_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "010" else '1';
|
|
|
|
Write_n0 <= not (WAIT_n_int and (not WR_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "010" else '1';
|
2015-06-27 17:40:12 +00:00
|
|
|
|
2017-07-26 13:59:20 +00:00
|
|
|
ReadIO_n0 <= not (WAIT_n_int and (not RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "010" else '1';
|
|
|
|
WriteIO_n0 <= not ( ( RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "011" else '1';
|
2015-06-27 10:07:58 +00:00
|
|
|
|
|
|
|
-- Hold the monitoring decision so it is valid on the rising edge of the clock
|
|
|
|
-- For instruction fetches and writes, the monitor sees these at the start of T3
|
|
|
|
-- For reads, the data can arrive in the middle of T3 so delay until end of T3
|
|
|
|
watch_gen : process(CLK_n)
|
|
|
|
begin
|
|
|
|
if falling_edge(CLK_n) then
|
2015-06-30 13:19:19 +00:00
|
|
|
Sync <= Sync0;
|
|
|
|
Read_n1 <= Read_n0;
|
|
|
|
Read_n <= Read_n1;
|
|
|
|
Write_n <= Write_n0;
|
|
|
|
ReadIO_n1 <= ReadIO_n0;
|
|
|
|
ReadIO_n <= ReadIO_n1;
|
|
|
|
WriteIO_n <= WriteIO_n0;
|
2015-06-27 10:07:58 +00:00
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
-- Register the exec/write data on the rising at the end of T2
|
|
|
|
ex_data_latch : process(CLK_n)
|
|
|
|
begin
|
|
|
|
if rising_edge(CLK_n) then
|
2017-07-26 13:59:20 +00:00
|
|
|
if (Sync = '1' or Write_n = '0' or WriteIO_n = '0') then
|
2015-06-27 10:07:58 +00:00
|
|
|
ex_data <= Data;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
-- Register the read data on the falling edge of clock in the middle of T3
|
|
|
|
rd_data_latch : process(CLK_n)
|
|
|
|
begin
|
|
|
|
if falling_edge(CLK_n) then
|
2017-07-26 13:59:20 +00:00
|
|
|
if (Read_n1 = '0' or ReadIO_n1 = '0') then
|
2015-06-27 10:07:58 +00:00
|
|
|
rd_data <= Data;
|
|
|
|
end if;
|
2015-06-28 18:42:25 +00:00
|
|
|
memory_din <= Data;
|
2015-06-27 10:07:58 +00:00
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
-- Mux the data seen by the bus monitor appropriately
|
2015-06-30 13:19:19 +00:00
|
|
|
mon_data <= rd_data when Read_n <= '0' or ReadIO_n = '0' else ex_data;
|
2015-06-27 10:07:58 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
-- Mark the memory access as done when t3 is reached
|
|
|
|
memory_done <= '1' when state = rd_t3 or state = wr_t3 else '0';
|
2015-06-28 18:42:25 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
-- Multiplex the bus control signals
|
|
|
|
-- The _int versions come from the T80
|
|
|
|
-- The mon_ versions come from the state machine below
|
2015-06-28 18:42:25 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
-- TODO: Also need to take account of BUSRQ_n/BUSAK_n
|
2015-06-28 18:42:25 +00:00
|
|
|
|
2019-10-15 10:46:50 +00:00
|
|
|
MREQ_n <= MREQ_n_int when state = idle or state = resume else mon_mreq_n;
|
|
|
|
IORQ_n <= IORQ_n_int when state = idle or state = resume else mon_iorq_n;
|
|
|
|
RFSH_n <= RFSH_n_int when state = idle or state = resume else mon_rfsh_n;
|
|
|
|
WR_n <= WR_n_int when state = idle or state = resume else mon_wr_n;
|
|
|
|
RD_n <= RD_n_int when state = idle or state = resume else mon_rd_n;
|
|
|
|
M1_n <= M1_n_int when state = idle or state = resume else '1';
|
2015-06-28 18:42:25 +00:00
|
|
|
|
2019-10-15 10:46:50 +00:00
|
|
|
Addr <= Addr_int when state = idle or state = resume else
|
2019-10-14 12:35:13 +00:00
|
|
|
x"0000" when state = nop_t1 or state = nop_t2 else
|
|
|
|
rfsh_addr when state = nop_t3 or state = nop_t4 else
|
|
|
|
memory_addr;
|
2015-06-28 18:42:25 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
Data <= memory_dout when state = wr_wa or state = wr_t2 or state = wr_t3 else
|
2015-06-28 18:42:25 +00:00
|
|
|
Dout when state = idle and Den = '1' else
|
2019-10-14 12:35:13 +00:00
|
|
|
(others => 'Z');
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
DOE_n <= '0' when state = wr_wa or state = wr_t2 or state = wr_t3 else
|
|
|
|
'0' when state = idle and Den = '1' else
|
|
|
|
'1';
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
Din <= Data;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
men_access_machine_rising : process(CLK_n, RESET_n)
|
2015-06-28 18:42:25 +00:00
|
|
|
begin
|
|
|
|
if (RESET_n = '0') then
|
|
|
|
state <= idle;
|
2019-10-14 12:35:13 +00:00
|
|
|
memory_rd1 <= '0';
|
|
|
|
memory_wr1 <= '0';
|
|
|
|
io_rd1 <= '0';
|
|
|
|
io_wr1 <= '0';
|
2019-10-14 16:33:32 +00:00
|
|
|
SS_Step_held <= '0';
|
2019-10-14 19:26:04 +00:00
|
|
|
mon_rfsh_n <= '1';
|
2019-10-14 12:35:13 +00:00
|
|
|
|
|
|
|
elsif rising_edge(CLK_n) then
|
|
|
|
|
|
|
|
-- Extend the 1-cycle long request strobes from BusMonCore
|
|
|
|
-- until we are ready to generate a bus cycle
|
|
|
|
if memory_rd = '1' then
|
|
|
|
memory_rd1 <= '1';
|
|
|
|
elsif state = rd_t1 then
|
|
|
|
memory_rd1 <= '0';
|
|
|
|
end if;
|
|
|
|
if memory_wr = '1' then
|
|
|
|
memory_wr1 <= '1';
|
|
|
|
elsif state = wr_t1 then
|
|
|
|
memory_wr1 <= '0';
|
|
|
|
end if;
|
|
|
|
if io_rd = '1' then
|
|
|
|
io_rd1 <= '1';
|
|
|
|
elsif state = rd_t1 then
|
|
|
|
io_rd1 <= '0';
|
|
|
|
end if;
|
|
|
|
if io_wr = '1' then
|
|
|
|
io_wr1 <= '1';
|
|
|
|
elsif state = wr_t1 then
|
|
|
|
io_wr1 <= '0';
|
|
|
|
end if;
|
2019-10-14 16:33:32 +00:00
|
|
|
if SS_Step = '1' then
|
|
|
|
SS_Step_held <= '1';
|
|
|
|
elsif state = idle then
|
|
|
|
SS_Step_held <= '0';
|
|
|
|
end if;
|
|
|
|
|
|
|
|
Sync1 <= Sync0;
|
2019-10-14 12:35:13 +00:00
|
|
|
|
|
|
|
-- Main state machine, generating refresh, read and write cycles
|
|
|
|
-- (the timing should exactly match those of the Z80)
|
|
|
|
case state is
|
|
|
|
-- Idle is when T80 is running
|
|
|
|
when idle =>
|
2019-10-14 16:33:32 +00:00
|
|
|
if SS_Single = '1' and Sync1 = '1' then
|
2019-10-14 12:35:13 +00:00
|
|
|
-- If the T80 is stopped, start genering refresh cycles
|
|
|
|
state <= nop_t1;
|
|
|
|
-- Load the initial refresh address from I/R in the T80
|
|
|
|
rfsh_addr <= Regs(199 downto 192) & Regs(207 downto 200);
|
|
|
|
end if;
|
|
|
|
|
|
|
|
-- Refresh cycle
|
|
|
|
when nop_t1 =>
|
|
|
|
state <= nop_t2;
|
|
|
|
-- Increment the refresh address (7 bits, just like the Z80)
|
|
|
|
rfsh_addr(6 downto 0) <= rfsh_addr(6 downto 0) + 1;
|
|
|
|
when nop_t2 =>
|
2019-10-14 19:26:04 +00:00
|
|
|
mon_rfsh_n <= '0';
|
2019-10-14 12:35:13 +00:00
|
|
|
state <= nop_t3;
|
|
|
|
when nop_t3 =>
|
|
|
|
state <= nop_t4;
|
|
|
|
when nop_t4 =>
|
2019-10-14 19:26:04 +00:00
|
|
|
mon_rfsh_n <= '1';
|
2019-10-14 12:35:13 +00:00
|
|
|
if memory_wr1 = '1' or io_wr1 = '1' then
|
|
|
|
state <= wr_t1;
|
|
|
|
io_not_mem <= io_wr1;
|
|
|
|
elsif memory_rd1 = '1' or io_rd1 = '1' then
|
|
|
|
state <= rd_t1;
|
|
|
|
io_not_mem <= io_rd1;
|
|
|
|
elsif SS_Step_held = '1' or SS_Single = '0' then
|
2019-10-15 10:46:50 +00:00
|
|
|
state <= resume;
|
2019-10-14 12:35:13 +00:00
|
|
|
else
|
|
|
|
state <= nop_t1;
|
|
|
|
end if;
|
|
|
|
|
2019-10-15 10:46:50 +00:00
|
|
|
-- Resume,
|
|
|
|
when resume =>
|
|
|
|
state <= idle;
|
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
-- Read cycle
|
|
|
|
when rd_t1 =>
|
|
|
|
if io_not_mem = '1' then
|
|
|
|
state <= rd_wa;
|
|
|
|
else
|
|
|
|
state <= rd_t2;
|
|
|
|
end if;
|
|
|
|
when rd_wa =>
|
|
|
|
state <= rd_t2;
|
|
|
|
when rd_t2 =>
|
|
|
|
if mon_wait_n = '1' then
|
|
|
|
state <= rd_t3;
|
|
|
|
end if;
|
|
|
|
when rd_t3 =>
|
|
|
|
state <= nop_t1;
|
|
|
|
|
|
|
|
-- Write cycle
|
|
|
|
when wr_t1 =>
|
|
|
|
if io_not_mem = '1' then
|
|
|
|
state <= wr_wa;
|
|
|
|
else
|
|
|
|
state <= wr_t2;
|
|
|
|
end if;
|
|
|
|
when wr_wa =>
|
|
|
|
state <= wr_t2;
|
|
|
|
when wr_t2 =>
|
|
|
|
if mon_wait_n = '1' then
|
|
|
|
state <= wr_t3;
|
|
|
|
end if;
|
|
|
|
when wr_t3 =>
|
|
|
|
state <= nop_t1;
|
2015-06-28 18:42:25 +00:00
|
|
|
end case;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
2019-10-14 12:35:13 +00:00
|
|
|
men_access_machine_falling : process(RESET_n)
|
|
|
|
begin
|
|
|
|
if falling_edge(CLK_n) then
|
|
|
|
-- For memory access cycles, mreq/iorq/rd/wr all change in the middle of
|
|
|
|
-- the t state, so retime these on the falling edge of clock
|
|
|
|
if state = rd_t1 or state = rd_wa or state = rd_t2 or state = wr_t1 or state = wr_wa or state = wr_t2 then
|
|
|
|
if io_not_mem = '0' then
|
|
|
|
-- Memory cycle
|
|
|
|
mon_mreq_n <= '0';
|
|
|
|
mon_iorq_n <= '1';
|
|
|
|
else
|
|
|
|
-- IO cycle
|
|
|
|
mon_mreq_n <= '1';
|
|
|
|
mon_iorq_n <= '0';
|
|
|
|
end if;
|
|
|
|
elsif state = nop_t3 then
|
|
|
|
-- Refresh cycle
|
|
|
|
mon_mreq_n <= '0';
|
|
|
|
mon_iorq_n <= '1';
|
|
|
|
else
|
|
|
|
-- Idle cycle
|
|
|
|
mon_mreq_n <= '1';
|
|
|
|
mon_iorq_n <= '1';
|
|
|
|
end if;
|
|
|
|
-- Read strobe
|
|
|
|
if state = rd_t1 or state = rd_wa or state = rd_t2 then
|
|
|
|
mon_rd_n <= '0';
|
|
|
|
else
|
|
|
|
mon_rd_n <= '1';
|
|
|
|
end if;
|
|
|
|
-- Write strobe
|
|
|
|
if state = wr_wa or state = wr_t2 then
|
|
|
|
mon_wr_n <= '0';
|
|
|
|
else
|
|
|
|
mon_wr_n <= '1';
|
|
|
|
end if;
|
|
|
|
-- Sample wait on the falling edge of the clock
|
|
|
|
mon_wait_n <= WAIT_n;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
|
2017-08-01 07:18:20 +00:00
|
|
|
RESET_n_int <= RESET_n and sw_interrupt_n and nRST;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
2017-07-29 18:55:27 +00:00
|
|
|
avr_TxD <= avr_Txd_int;
|
|
|
|
|
2017-08-01 07:18:20 +00:00
|
|
|
test1 <= sw_interrupt_n and sw_reset_n;
|
2017-07-29 18:55:27 +00:00
|
|
|
|
|
|
|
process(clock_avr)
|
|
|
|
begin
|
|
|
|
if rising_edge(clock_avr) then
|
|
|
|
clock_avr_ctr <= clock_avr_ctr + 1;
|
2017-08-01 07:18:20 +00:00
|
|
|
test2 <= sw_interrupt_n or clock_avr_ctr(23);
|
2017-07-29 18:55:27 +00:00
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
process(clock49)
|
|
|
|
begin
|
|
|
|
if rising_edge(clock49) then
|
|
|
|
clock_49_ctr <= clock_49_ctr + 1;
|
2017-08-01 07:18:20 +00:00
|
|
|
test3 <= sw_reset_n or clock_49_ctr(23);
|
2017-07-29 18:55:27 +00:00
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
test4 <= not avr_TxD_int;
|
|
|
|
|
|
|
|
--test1 <= TState(0);
|
|
|
|
--test2 <= TState(1);
|
|
|
|
--test3 <= TState(2);
|
|
|
|
--test4 <= CLK_n;
|
2017-07-26 13:59:20 +00:00
|
|
|
|
|
|
|
|
2015-06-27 10:07:58 +00:00
|
|
|
end behavioral;
|