Z80: Rd/Wr Mem/IO breakpoint/watchpoint sampled in middle of T3

Change-Id: I9dcca58f121da9e443bd18da8f13a099cfbc2056
This commit is contained in:
David Banks 2021-03-20 17:22:53 +00:00
parent 0e6a31360f
commit a7cb67c469

View File

@ -110,10 +110,8 @@ type state_type is (idle, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa, rd_t2, r
signal RFSH_n_int : std_logic;
signal M1_n_int : std_logic;
signal BUSAK_n_int : std_logic;
signal BUSAK_n_comb : std_logic;
signal WAIT_n_latched : std_logic;
signal TState : std_logic_vector(2 downto 0);
signal TState1 : std_logic_vector(2 downto 0);
signal SS_Single : std_logic;
signal SS_Step : std_logic;
signal SS_Step_held : std_logic;
@ -153,23 +151,17 @@ type state_type is (idle, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa, rd_t2, r
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;
signal Sync1 : std_logic;
signal Mem_IO_n : 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);
@ -327,40 +319,32 @@ begin
-- really care about the data (it's re-read from memory by the disassembler).
Sync0 <= '1' when WAIT_n = '1' and M1_n_int = '0' and TState = "010" and skipNextOpcode = '0' else '0';
-- For memory reads/write breakpoints we make the monitoring decision in the middle of T2
-- but only if WAIT_n is '1' so we catch the right data.
Read_n0 <= not (WAIT_n and (not RD_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "010" else '1';
Write_n0 <= not (WAIT_n and ( RD_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "010" else '1';
-- For IO reads/writes we make the monitoring decision in the middle of the second T2 cycle
-- but only if WAIT_n is '1' so we catch the right data.
-- This one cycle delay accounts for the forced wait state
ReadIO_n0 <= not (WAIT_n and (not RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState1 = "010" else '1';
WriteIO_n0 <= not (WAIT_n and ( RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState1 = "010" else '1';
-- For reads/write breakpoints we make the monitoring decision in the middle of T3
Read_n0 <= not ((not RD_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "011" else '1';
Write_n0 <= not (( RD_n_int) and (not MREQ_n_int) and (M1_n_int)) when TState = "011" else '1';
ReadIO_n0 <= not ((not RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "011" else '1';
WriteIO_n0 <= not (( RD_n_int) and (not IORQ_n_int) and (M1_n_int)) when TState = "011" else '1';
-- 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
-- For instruction fetches the monitor sees these at the end of T2
-- For reads and writes, the data is sampled in the middle of T3 so delay until end of T3
watch_gen : process(CLK_n)
begin
if falling_edge(CLK_n) then
Sync <= Sync0;
Read_n1 <= Read_n0;
Read_n <= Read_n1;
Read_n <= Read_n0;
Write_n <= Write_n0;
ReadIO_n1 <= ReadIO_n0;
ReadIO_n <= ReadIO_n1;
ReadIO_n <= ReadIO_n0;
WriteIO_n <= WriteIO_n0;
-- Latch wait seen by T80 on the falling edge, for use on the next rising edge
WAIT_n_latched <= WAIT_n;
end if;
end process;
-- Register the exec data on the rising at the end of T2
-- Register the exec data on the rising edge of the clock at the end of T2
ex_data_latch : process(CLK_n)
begin
if rising_edge(CLK_n) then
TState1 <= TState;
if Sync = '1' then
ex_data <= Data;
end if;
@ -371,14 +355,14 @@ begin
rd_data_latch : process(CLK_n)
begin
if falling_edge(CLK_n) then
if Read_n1 = '0' or ReadIO_n1 = '0' then
if Read_n0 = '0' or ReadIO_n0 = '0' then
rd_data <= Data;
end if;
memory_din <= Data;
end if;
end process;
-- Register the write data on the falling edge in the middle of T2
-- Register the read data on the falling edge of clock in the middle of T3
wr_data_latch : process(CLK_n)
begin
if falling_edge(CLK_n) then