From 4ecd60065e672f088f60a2d6faaf5713c02093d7 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 30 Jun 2021 19:44:01 +0100 Subject: [PATCH] Z80: Revert T80a wrapper to previous version Change-Id: I856a39c51305e99c3d8b32efe5be1f8ed8b2583f --- src/T80/T80a.vhd | 306 +++++++++++++++++++---------------------------- 1 file changed, 123 insertions(+), 183 deletions(-) diff --git a/src/T80/T80a.vhd b/src/T80/T80a.vhd index 0eca83f..f225df2 100644 --- a/src/T80/T80a.vhd +++ b/src/T80/T80a.vhd @@ -1,16 +1,7 @@ --- **** --- T80(b) core. In an effort to merge and maintain bug fixes .... --- --- --- Ver 300 started tidyup --- MikeJ March 2005 --- Latest version from www.fpgaarcade.com (original www.opencores.org) --- --- **** -- -- Z80 compatible microprocessor core, asynchronous top level -- --- Version : 0250 +-- Version : 0247a -- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- @@ -47,32 +38,28 @@ -- you have the latest version of this file. -- -- The latest version of this file can be found at: --- http://www.opencores.org/cvsweb.shtml/t80/ +-- http://www.opencores.org/cvsweb.shtml/t80/ -- -- Limitations : -- -- File history : -- --- 0208 : First complete release +-- 0208 : First complete release -- --- 0211 : Fixed interrupt cycle +-- 0211 : Fixed interrupt cycle -- --- 0235 : Updated for T80 interface change +-- 0235 : Updated for T80 interface change -- --- 0238 : Updated for T80 interface change +-- 0238 : Updated for T80 interface change -- --- 0240 : Updated for T80 interface change +-- 0240 : Updated for T80 interface change -- --- 0242 : Updated for T80 interface change +-- 0242 : Updated for T80 interface change -- --- 0247 : Fixed bus req/ack cycle --- --- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 --- --- Bus signal logic changes from the ZX Spectrum Next were made by: --- --- Fabio Belavenuto, Charlie Ingley +-- 0247 : Fixed bus req/ack cycle -- +-- 0247a: 7th of September, 2003 by Kazuhiro Tsujikawa (tujikawa@hat.hi-ho.ne.jp) +-- Fixed IORQ_n, RD_n, WR_n bus timing library IEEE; use IEEE.std_logic_1164.all; @@ -81,37 +68,34 @@ use work.T80_Pack.all; entity T80a is generic( - Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB - IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle - ); + Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); port( - -- DMB - TS : out std_logic_vector(2 downto 0); - Regs : out std_logic_vector(255 downto 0); - PdcData : out std_logic_vector(7 downto 0); - CEN : in std_logic; - Din : in std_logic_vector(7 downto 0); - Dout : out std_logic_vector(7 downto 0); - Den : out std_logic; + -- Additions + TS : out std_logic_vector(2 downto 0); + Regs : out std_logic_vector(255 downto 0); + PdcData : out std_logic_vector(7 downto 0); -- Original Signals - RESET_n : in std_logic; - R800_mode : in std_logic := '0'; - 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; - A : out std_logic_vector(15 downto 0) --- D : inout std_logic_vector(7 downto 0) - ); + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : 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; + A : out std_logic_vector(15 downto 0); + Din : in std_logic_vector(7 downto 0); + Dout : out std_logic_vector(7 downto 0); + Den : out std_logic + ); end T80a; architecture rtl of T80a is @@ -124,55 +108,51 @@ architecture rtl of T80a is signal Write : std_logic; signal MREQ : std_logic; signal MReq_Inhibit : std_logic; + signal IReq_Inhibit : std_logic; -- 0247a signal Req_Inhibit : std_logic; signal RD : std_logic; signal MREQ_n_i : std_logic; - signal MREQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add MREQ control signal IORQ_n_i : std_logic; - signal IORQ_t1 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_int : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ interrupt control - signal IORQ_int_inhibit : std_logic_vector(2 downto 0); signal RD_n_i : std_logic; signal WR_n_i : std_logic; - signal WR_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add WR control + signal WR_n_j : std_logic; -- 0247a signal RFSH_n_i : std_logic; signal BUSAK_n_i : std_logic; signal A_i : std_logic_vector(15 downto 0); signal DO : std_logic_vector(7 downto 0); - signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser + signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser signal Wait_s : std_logic; signal MCycle : std_logic_vector(2 downto 0); signal TState : std_logic_vector(2 downto 0); signal HALT_n_int : std_logic; + signal iack1 : std_logic; + signal iack2 : std_logic; begin - BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes - MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control - MREQ_n_i <= not MREQ_rw; -- changed MREQ generation - IORQ_rw <= IORQ and not (IORQ_t1 or IORQ_t2); -- added IORQ generation timing control - IORQ_n_i <= not ((IORQ_int and not IORQ_int_inhibit(2)) or IORQ_rw); -- changed IORQ generation - RD_n_i <= not (RD and (MREQ_rw or IORQ_rw)); -- changed RD/IORQ generation - WR_n_i <= not (Write and ((WR_t2 and MREQ_rw) or IORQ_rw)); -- added WR/IORQ timing control + + BUSAK_n <= BUSAK_n_i; + MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit); + RD_n_i <= not RD or (IORQ and IReq_Inhibit) or Req_Inhibit; -- DMB + WR_n_j <= WR_n_i or (IORQ and IReq_Inhibit); -- DMB HALT_n <= HALT_n_int; + --Remove tristate as in ICE-Z80 this is implmeneted in Z80CpuMon - --MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; - --IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; + --MREQ_n <= MREQ_n_i; when BUSAK_n_i = '1' else 'Z'; + --IORQ_n <= IORQ_n_i or IReq_Inhibit when BUSAK_n_i = '1' else 'Z'; -- 0247a --RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; - --WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z'; + --WR_n <= WR_n_j when BUSAK_n_i = '1' else 'Z'; -- 0247a --RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; --A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); - --D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); MREQ_n <= MREQ_n_i; - IORQ_n <= IORQ_n_i; + IORQ_n <= IORQ_n_i or IReq_Inhibit or Req_inhibit; --DMB RD_n <= RD_n_i; - WR_n <= WR_n_i; + WR_n <= WR_n_j; -- 0247a RFSH_n <= RFSH_n_i; A <= A_i; + Dout <= DO; Den <= Write and BUSAK_n_i; @@ -181,18 +161,15 @@ begin if RESET_n = '0' then Reset_s <= '0'; elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - Reset_s <= '1'; - end if; + Reset_s <= '1'; end if; end process; u0 : T80 generic map( Mode => Mode, - IOWait => IOWait) + IOWait => 1) port map( - R800_mode => R800_mode, CEN => CEN, M1_n => M1_n, IORQ => IORQ, @@ -214,7 +191,6 @@ begin MC => MCycle, TS => TState, IntCycle_n => IntCycle_n, - -- DMB NMICycle_n => NMICycle_n, REG => Regs(211 downto 0), DIRSet => '0', @@ -235,72 +211,102 @@ begin end if; end process; --- 30/10/19 Charlie Ingley - Generate WR_t2 to correct MREQ/WR timing - process (Reset_s,CLK_n) + process (CLK_n) -- 0247a + begin + if CLK_n'event and CLK_n = '1' then + IReq_Inhibit <= (not IORQ) and IntCycle_n; + end if; + end process; + + process (Reset_s,CLK_n) -- 0247a begin if Reset_s = '0' then - WR_t2 <= '0'; + WR_n_i <= '1'; elsif CLK_n'event and CLK_n = '0' then if CEN = '1' then - if MCycle /= "001" then - if TState = "010" then -- WR starts on falling edge of T2 for MREQ - WR_t2 <= Write; + if (IORQ = '0') then + if TState = "010" then + WR_n_i <= not Write; + elsif Tstate = "011" then + WR_n_i <= '1'; + end if; + else + if TState = "001" then -- DMB + WR_n_i <= not Write; + elsif Tstate = "011" then + WR_n_i <= '1'; end if; end if; - if TState = "011" then -- end WR - WR_t2 <= '0'; + end if; + end if; + end process; + + process (Reset_s,CLK_n) -- 0247a + begin + if Reset_s = '0' then + Req_Inhibit <= '0'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if MCycle = "001" and TState = "010" and wait_s = '1' then + Req_Inhibit <= '1'; + else + Req_Inhibit <= '0'; end if; end if; end if; end process; --- Generate Req_Inhibit process (Reset_s,CLK_n) begin if Reset_s = '0' then - Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - Req_Inhibit <= '0'; - else - Req_Inhibit <= '1'; - end if; - end if; - end if; - end process; - --- Generate MReq_Inhibit - process (Reset_s, CLK_n) - begin - if Reset_s = '0' then - MReq_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity + MReq_Inhibit <= '0'; elsif CLK_n'event and CLK_n = '0' then if CEN = '1' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - MReq_Inhibit <= '0'; - else + if MCycle = "001" and TState = "010" then MReq_Inhibit <= '1'; + else + MReq_Inhibit <= '0'; end if; end if; end if; end process; --- Generate RD for MREQ - process(Reset_s,CLK_n) + process(Reset_s,CLK_n) -- 0247a begin if Reset_s = '0' then RD <= '0'; + IORQ_n_i <= '1'; MREQ <= '0'; + iack1 <= '0'; + iack2 <= '0'; elsif CLK_n'event and CLK_n = '0' then if CEN = '1' then if MCycle = "001" then - if TState = "001" then - RD <= IntCycle_n; - MREQ <= IntCycle_n; + if IntCycle_n = '1' then + -- Normal M1 Cycle + if TState = "001" then + RD <= '1'; + MREQ <= '1'; + IORQ_n_i <= '1'; + end if; + else + -- Interupt Ack Cycle + -- 5 T-states: T1 T1 (auto wait) T1 (auto wait) T2 T3 + -- Assert IORQ in middle of third T1 + if TState = "001" then + iack1 <= '1'; + iack2 <= iack1; + else + iack1 <= '0'; + iack2 <= '0'; + end if; + if iack2 = '1' then + IORQ_n_i <= '0'; + end if; end if; if TState = "011" then RD <= '0'; + IORQ_n_i <= '1'; MREQ <= '1'; end if; if TState = "100" then @@ -308,11 +314,13 @@ begin end if; else if TState = "001" and NoRead = '0' then - RD <= not Write; + IORQ_n_i <= not IORQ; MREQ <= not IORQ; + RD <= not Write; -- DMB end if; if TState = "011" then RD <= '0'; + IORQ_n_i <= '1'; MREQ <= '0'; end if; end if; @@ -320,74 +328,6 @@ begin end if; end process; - -- 30/10/19 Charlie Ingley - Generate IORQ_int for IORQ interrupt timing control - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - IORQ_int <= '0'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - if MCycle = "001" then - if TState = "001" then - IORQ_int <= not IntCycle_n; - end if; - if TState = "010" then - IORQ_int <= '0'; - end if; - end if; - end if; - end if; - end process; - - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - IORQ_int_inhibit <= "111"; - elsif CLK_n'event and CLK_n = '0' then - if CEN = '1' then - if IntCycle_n = '0' then - if MCycle = "001" then - IORQ_int_inhibit <= IORQ_int_inhibit(1 downto 0) & '0'; - end if; - if MCycle = "010" then - IORQ_int_inhibit <= "111"; - end if; - end if; - end if; - end if; - end process; - --- 30/10/19 Charlie Ingley - Generate IORQ_t1 for IORQ timing control - process(Reset_s, CLK_n) - begin - if Reset_s = '0' then - IORQ_t1 <= '1'; - elsif CLK_n'event and CLK_n = '0' then - if CEN = '1' then - if TState = "001" then - IORQ_t1 <= not IntCycle_n; - end if; - if TState = "011" then - IORQ_t1 <= '1'; - end if; - end if; - end if; - end process; - --- 30/10/19 Charlie Ingley - Generate IORQ_t2 for IORQ timing control - process (RESET_n, CLK_n) - begin - if RESET_n = '0' then - IORQ_t2 <= '1'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - IORQ_t2 <= IORQ_t1; - end if; - end if; - end process; - --- DMB - TS <= TState; PdcData <= (not HALT_n_int) & (not NMICycle_n) & (not IntCycle_n) & "00000";