Z80: Output NOPs when paused (inc M1)

Change-Id: I100fac021d68662497fbd2d0c7428dcaf9ef98a3
This commit is contained in:
David Banks 2019-10-26 15:19:44 +01:00
parent ac521aad15
commit 26f0bea110
3 changed files with 92 additions and 72 deletions

View File

@ -104,6 +104,7 @@ type state_type is (idle, resume, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa,
signal RFSH_n_int : std_logic; signal RFSH_n_int : std_logic;
signal M1_n_int : std_logic; signal M1_n_int : std_logic;
signal WAIT_n_int : std_logic; signal WAIT_n_int : std_logic;
signal WAIT_n_int1 : std_logic;
signal TState : std_logic_vector(2 downto 0); signal TState : std_logic_vector(2 downto 0);
signal SS_Single : std_logic; signal SS_Single : std_logic;
signal SS_Step : std_logic; signal SS_Step : std_logic;
@ -127,6 +128,8 @@ type state_type is (idle, resume, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa,
signal io_wr1 : std_logic; signal io_wr1 : std_logic;
signal memory_rd1 : std_logic; signal memory_rd1 : std_logic;
signal memory_wr1 : std_logic; signal memory_wr1 : std_logic;
signal mon_m1_n : std_logic;
signal mon_xx_n : std_logic;
signal mon_mreq_n : std_logic; signal mon_mreq_n : std_logic;
signal mon_iorq_n : std_logic; signal mon_iorq_n : std_logic;
signal mon_rfsh_n : std_logic; signal mon_rfsh_n : std_logic;
@ -171,9 +174,6 @@ type state_type is (idle, resume, nop_t1, nop_t2, nop_t3, nop_t4, rd_t1, rd_wa,
signal avr_TxD_int : std_logic; 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);
signal rfsh_addr : std_logic_vector(15 downto 0); signal rfsh_addr : std_logic_vector(15 downto 0);
begin begin
@ -318,7 +318,7 @@ begin
skip_opcode_latch : process(CLK_n) skip_opcode_latch : process(CLK_n)
begin begin
if rising_edge(CLK_n) then if rising_edge(CLK_n) then
if (M1_n_int = '0' and WAIT_n_int = '1' and TState = "010") then if (M1_n_int = '0' and WAIT_n_int1 = '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 if (skipNextOpcode = '0' and (Data = x"CB" or Data = x"DD" or Data = x"ED" or Data = x"FD")) then
skipNextOpcode <= '1'; skipNextOpcode <= '1';
else else
@ -347,13 +347,15 @@ begin
watch_gen : process(CLK_n) watch_gen : process(CLK_n)
begin begin
if falling_edge(CLK_n) then if falling_edge(CLK_n) then
Sync <= Sync0; Sync <= Sync0;
Read_n1 <= Read_n0; Read_n1 <= Read_n0;
Read_n <= Read_n1; Read_n <= Read_n1;
Write_n <= Write_n0; Write_n <= Write_n0;
ReadIO_n1 <= ReadIO_n0; ReadIO_n1 <= ReadIO_n0;
ReadIO_n <= ReadIO_n1; ReadIO_n <= ReadIO_n1;
WriteIO_n <= WriteIO_n0; WriteIO_n <= WriteIO_n0;
-- Latch wait seen by T80 on the falling edge, for use on the next rising edge
WAIT_n_int1 <= WAIT_n_int;
end if; end if;
end process; end process;
@ -390,12 +392,12 @@ begin
-- TODO: Also need to take account of BUSRQ_n/BUSAK_n -- TODO: Also need to take account of BUSRQ_n/BUSAK_n
MREQ_n <= MREQ_n_int when state = idle or state = resume else mon_mreq_n; MREQ_n <= MREQ_n_int when state = idle or state = resume else mon_mreq_n and mon_xx_n;
IORQ_n <= IORQ_n_int when state = idle or state = resume else mon_iorq_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; 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; 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; RD_n <= RD_n_int when state = idle or state = resume else mon_rd_n and mon_xx_n;
M1_n <= M1_n_int when state = idle or state = resume else '1'; M1_n <= M1_n_int when state = idle or state = resume else mon_m1_n;
Addr <= Addr_int when state = idle or state = resume else Addr <= Addr_int when state = idle or state = resume else
x"0000" when state = nop_t1 or state = nop_t2 else x"0000" when state = nop_t1 or state = nop_t2 else
@ -422,6 +424,8 @@ begin
io_wr1 <= '0'; io_wr1 <= '0';
SS_Step_held <= '0'; SS_Step_held <= '0';
mon_rfsh_n <= '1'; mon_rfsh_n <= '1';
mon_m1_n <= '1';
mon_xx_n <= '1';
elsif rising_edge(CLK_n) then elsif rising_edge(CLK_n) then
@ -461,20 +465,31 @@ begin
-- Idle is when T80 is running -- Idle is when T80 is running
when idle => when idle =>
if SS_Single = '1' and Sync1 = '1' 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 -- Load the initial refresh address from I/R in the T80
rfsh_addr <= Regs(199 downto 192) & Regs(207 downto 200); rfsh_addr <= Regs(199 downto 192) & Regs(207 downto 200);
-- Start genering NOP cycles
if mon_wait_n = '1' then
state <= nop_t3;
else
mon_m1_n <= '0';
mon_xx_n <= '0';
state <= nop_t2;
end if;
end if; end if;
-- Refresh cycle -- NOP cycle
when nop_t1 => when nop_t1 =>
state <= nop_t2; state <= nop_t2;
-- Increment the refresh address (7 bits, just like the Z80) -- Increment the refresh address (7 bits, just like the Z80)
rfsh_addr(6 downto 0) <= rfsh_addr(6 downto 0) + 1; rfsh_addr(6 downto 0) <= rfsh_addr(6 downto 0) + 1;
mon_xx_n <= '0';
when nop_t2 => when nop_t2 =>
mon_rfsh_n <= '0'; if mon_wait_n = '1' then
state <= nop_t3; mon_rfsh_n <= '0';
state <= nop_t3;
mon_m1_n <= '1';
mon_xx_n <= '1';
end if;
when nop_t3 => when nop_t3 =>
state <= nop_t4; state <= nop_t4;
when nop_t4 => when nop_t4 =>
@ -489,6 +504,7 @@ begin
state <= resume; state <= resume;
else else
state <= nop_t1; state <= nop_t1;
mon_m1_n <= '0';
end if; end if;
-- Resume, -- Resume,
@ -545,8 +561,8 @@ begin
mon_mreq_n <= '1'; mon_mreq_n <= '1';
mon_iorq_n <= '0'; mon_iorq_n <= '0';
end if; end if;
elsif state = nop_t3 then elsif state = nop_t1 or state = nop_t3 then
-- Refresh cycle -- M1 cycle
mon_mreq_n <= '0'; mon_mreq_n <= '0';
mon_iorq_n <= '1'; mon_iorq_n <= '1';
else else
@ -555,7 +571,7 @@ begin
mon_iorq_n <= '1'; mon_iorq_n <= '1';
end if; end if;
-- Read strobe -- Read strobe
if state = rd_t1 or state = rd_wa or state = rd_t2 then if state = nop_t1 or state = rd_t1 or state = rd_wa or state = rd_t2 then
mon_rd_n <= '0'; mon_rd_n <= '0';
else else
mon_rd_n <= '1'; mon_rd_n <= '1';
@ -571,35 +587,13 @@ begin
end if; end if;
end process; end process;
RESET_n_int <= RESET_n and sw_interrupt_n and nRST; RESET_n_int <= RESET_n and sw_interrupt_n and nRST;
avr_TxD <= avr_Txd_int; avr_TxD <= avr_Txd_int;
test1 <= sw_interrupt_n and sw_reset_n; test1 <= '1';
test2 <= '1';
process(clock_avr) test3 <= '1';
begin test4 <= '1';
if rising_edge(clock_avr) then
clock_avr_ctr <= clock_avr_ctr + 1;
test2 <= sw_interrupt_n or clock_avr_ctr(23);
end if;
end process;
process(clock49)
begin
if rising_edge(clock49) then
clock_49_ctr <= clock_49_ctr + 1;
test3 <= sw_reset_n or clock_49_ctr(23);
end if;
end process;
test4 <= not avr_TxD_int;
--test1 <= TState(0);
--test2 <= TState(1);
--test3 <= TState(2);
--test4 <= CLK_n;
end behavioral; end behavioral;

View File

@ -75,24 +75,44 @@ entity Z80CpuMonALS is
tcclk : out std_logic; tcclk : out std_logic;
-- Optional Debugging signals -- Optional Debugging signals
test1 : out std_logic; test : out std_logic_vector(9 downto 0)
test2 : out std_logic;
test3 : out std_logic;
test4 : out std_logic
); );
end Z80CpuMonALS; end Z80CpuMonALS;
architecture behavioral of Z80CpuMonALS is architecture behavioral of Z80CpuMonALS is
signal BUSAK_n_int : std_logic; signal MREQ_n_int : std_logic;
signal IORQ_n_int : std_logic;
signal M1_n_int : std_logic;
signal RD_n_int : std_logic;
signal WR_n_int : std_logic; signal WR_n_int : std_logic;
signal RFSH_n_int : std_logic;
signal HALT_n_int : std_logic;
signal BUSAK_n_int : std_logic;
signal DOE_n : std_logic; signal DOE_n : std_logic;
begin begin
BUSAK_n <= BUSAK_n_int; MREQ_n <= MREQ_n_int;
IORQ_n <= IORQ_n_int;
M1_n <= M1_n_int;
RD_n <= RD_n_int;
WR_n <= WR_n_int; WR_n <= WR_n_int;
RFSH_n <= RFSH_n_int;
HALT_n <= HALT_n_int;
BUSAK_n <= BUSAK_n_int;
test(0) <= M1_n_int;
test(1) <= RD_n_int;
test(2) <= WR_n_int;
test(3) <= MREQ_n_int;
test(4) <= IORQ_n_int;
test(5) <= WAIT_n;
test(6) <= RESET_n;
test(7) <= CLK_n;
test(8) <= RFSH_n_int;
test(9) <= INT_n;
OEC_n <= not BUSAK_n_int; OEC_n <= not BUSAK_n_int;
OEA1_n <= not BUSAK_n_int; OEA1_n <= not BUSAK_n_int;
@ -123,13 +143,13 @@ begin
INT_n => INT_n, INT_n => INT_n,
NMI_n => NMI_n, NMI_n => NMI_n,
BUSRQ_n => BUSRQ_n, BUSRQ_n => BUSRQ_n,
M1_n => M1_n, M1_n => M1_n_int,
MREQ_n => MREQ_n, MREQ_n => MREQ_n_int,
IORQ_n => IORQ_n, IORQ_n => IORQ_n_int,
RD_n => RD_n, RD_n => RD_n_int,
WR_n => WR_n_int, WR_n => WR_n_int,
RFSH_n => RFSH_n, RFSH_n => RFSH_n_int,
HALT_n => HALT_n, HALT_n => HALT_n_int,
BUSAK_n => BUSAK_n_int, BUSAK_n => BUSAK_n_int,
Addr => Addr, Addr => Addr,
Data => Data, Data => Data,
@ -157,10 +177,10 @@ begin
tcclk => tcclk, tcclk => tcclk,
-- Debugging signals -- Debugging signals
test1 => test1, test1 => open,
test2 => test2, test2 => open,
test3 => test3, test3 => open,
test4 => test4 test4 => open
); );
end behavioral; end behavioral;

View File

@ -77,13 +77,19 @@ NET "avr_RxD" LOC="P55" | IOSTANDARD = LVCMOS33 ;
NET "trig<0>" LOC="P127" | IOSTANDARD = LVCMOS33 ; NET "trig<0>" LOC="P127" | IOSTANDARD = LVCMOS33 ;
NET "trig<1>" LOC="P126" | IOSTANDARD = LVCMOS33 ; NET "trig<1>" LOC="P126" | IOSTANDARD = LVCMOS33 ;
# 7-segment LED (connect to J5 on FPGA board) # 7-segment LED (connect to unused pins on adapter)
NET "tmosi" LOC="P58" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "tmosi" LOC="P8" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "tdin" LOC="P61" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "tdin" LOC="P9" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "tcclk" LOC="P62" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "tcclk" LOC="P11" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
# Test outputs (connect to J5 on FPGA board) # Test outputs (connect to J5 on FPGA board)
NET "test1" LOC="P46" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "test<0>" LOC="P46" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test2" LOC="P48" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "test<1>" LOC="P47" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test3" LOC="P57" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "test<2>" LOC="P48" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test4" LOC="P59" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "test<3>" LOC="P56" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test<4>" LOC="P57" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test<5>" LOC="P58" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test<6>" LOC="P59" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test<7>" LOC="P61" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test<8>" LOC="P144" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;
NET "test<9>" LOC="P62" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ;