From d9d552475a18d4f8e630f555e1d9ff7b3293949c Mon Sep 17 00:00:00 2001 From: David Banks Date: Mon, 14 Oct 2019 17:33:32 +0100 Subject: [PATCH] z80: rework wait state / break point logic Change-Id: I2b41c014165e8d753693d3ed7806087e85202a6e --- src/Z80CpuMon.vhd | 58 ++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/Z80CpuMon.vhd b/src/Z80CpuMon.vhd index 50277e8..e398b32 100644 --- a/src/Z80CpuMon.vhd +++ b/src/Z80CpuMon.vhd @@ -105,7 +105,6 @@ type state_type is (idle, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa, rd_t2, r signal SS_Single : std_logic; signal SS_Step : std_logic; signal SS_Step_held : std_logic; - signal SS_Running : std_logic; signal CountCycle : std_logic; signal skipNextOpcode : std_logic; @@ -146,6 +145,7 @@ type state_type is (idle, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa, rd_t2, r signal WriteIO_n0 : std_logic; signal Sync : std_logic; signal Sync0 : std_logic; + signal Sync1 : std_logic; signal Mem_IO_n : std_logic; signal nRST : std_logic; @@ -281,38 +281,32 @@ begin ); end generate; + -------------------------------------------------------- + -- Synchronise external interrupts + -------------------------------------------------------- + + int_gen : process(CLK_n) + begin + if rising_edge(CLK_n) then + NMI_n_sync <= NMI_n; + INT_n_sync <= INT_n; + end if; + end process; + -------------------------------------------------------- -- Z80 specific single step / breakpoint logic -------------------------------------------------------- - WAIT_n_int <= WAIT_n and SS_Running; + CountCycle <= '1' when state = idle else '0'; - CountCycle <= '1' when SS_Single = '0' or SS_Running = '1' 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 - sync_gen : process(CLK_n, RESET_n_int) - begin - if RESET_n_int = '0' then - NMI_n_sync <= '1'; - INT_n_sync <= '1'; - SS_Running <= '1'; - SS_Step_held <= '0'; - elsif rising_edge(CLK_n) then - NMI_n_sync <= NMI_n; - INT_n_sync <= INT_n; - if Sync0 = '1' and SS_Single = '1' then - -- stop at the end of T1 instruction fetch - SS_Running <= '0'; - elsif SS_Step_held = '1' and state = nop_t4 then - -- start again when the single step command is issued - SS_Running <= '1'; - end if; - if SS_Step = '1' then - SS_Step_held <= '1'; - elsif SS_Running = '1' then - SS_Step_held <= '0'; - end if; - end if; - end process; + WAIT_n_int <= '0' when state = idle and SS_Single = '1' and Sync1 = '1' else + '0' when state /= idle else + WAIT_n; -- Logic to ignore the second M1 in multi-byte opcodes skip_opcode_latch : process(CLK_n) @@ -419,6 +413,7 @@ begin memory_wr1 <= '0'; io_rd1 <= '0'; io_wr1 <= '0'; + SS_Step_held <= '0'; elsif rising_edge(CLK_n) then @@ -444,13 +439,20 @@ begin elsif state = wr_t1 then io_wr1 <= '0'; end if; + if SS_Step = '1' then + SS_Step_held <= '1'; + elsif state = idle then + SS_Step_held <= '0'; + end if; + + Sync1 <= Sync0; -- 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 => - if SS_Running = '0' then + if SS_Single = '1' and Sync1 = '1' then -- If the T80 is stopped, start genering refresh cycles state <= nop_t1; -- Load the initial refresh address from I/R in the T80