From 6a42153a7d482bf8438c5fd09bbc666d2578ca62 Mon Sep 17 00:00:00 2001 From: Eugene Lozovoy Date: Tue, 10 Sep 2024 13:53:34 +0300 Subject: [PATCH] update T80 --- rtl/T80/GBse.vhd | 205 +++++++ rtl/T80/README | 58 ++ rtl/T80/T80.qip | 17 +- rtl/T80/T80.vhd | 1267 +++++++++++++++++++++++------------------ rtl/T80/T8080se.vhd | 194 +++++++ rtl/T80/T80_ALU.vhd | 119 ++-- rtl/T80/T80_MCode.vhd | 734 ++++++++++++++++-------- rtl/T80/T80_Pack.vhd | 248 ++++++++ rtl/T80/T80_Reg.vhd | 50 +- rtl/T80/T80a.vhd | 342 +++++++++++ rtl/T80/T80as.vhd | 289 ++++++++++ rtl/T80/T80pa.vhd | 424 +++++++------- rtl/T80/T80s.vhd | 3 +- rtl/T80/T80se.vhd | 192 +++++++ rtl/T80/T80sed.vhd | 179 ++++++ 15 files changed, 3265 insertions(+), 1056 deletions(-) create mode 100644 rtl/T80/GBse.vhd create mode 100644 rtl/T80/README create mode 100644 rtl/T80/T8080se.vhd create mode 100644 rtl/T80/T80_Pack.vhd create mode 100644 rtl/T80/T80a.vhd create mode 100644 rtl/T80/T80as.vhd create mode 100644 rtl/T80/T80se.vhd create mode 100644 rtl/T80/T80sed.vhd diff --git a/rtl/T80/GBse.vhd b/rtl/T80/GBse.vhd new file mode 100644 index 0000000..102ccbf --- /dev/null +++ b/rtl/T80/GBse.vhd @@ -0,0 +1,205 @@ +-- **** +-- 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, synchronous top level with clock enable +-- Different timing than the original z80 +-- Inputs needs to be synchronous and outputs may glitch +-- +-- Version : 0240 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- 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/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0235 : First release +-- +-- 0236 : Added T2Write generic +-- +-- 0237 : Fixed T2Write with wait state +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity GBse is + generic( + T2Write : integer := 1; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 + IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CLKEN : 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; + STOP : out std_logic; + A : out std_logic_vector(15 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end GBse; + +architecture rtl of GBse is + + signal IntCycle_n : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal IORQ : std_logic; + signal DI_Reg : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + u0 : T80 + generic map( + Mode => 3, + IOWait => IOWait, + Flag_S => 0, + Flag_P => 0, + Flag_X => 0, + Flag_Y => 0, + Flag_C => 4, + Flag_H => 5, + Flag_N => 6, + Flag_Z => 7 + ) + port map( + CEN => CLKEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + Stop => STOP, + WAIT_n => Wait_n, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n, + CLK_n => CLK_n, + A => A, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + elsif CLK_n'event and CLK_n = '1' then + if CLKEN = '1' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + if MCycle = "001" then + if TState = "001" or (TState = "010" and Wait_n = '0') then + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + end if; + if TState = "011" then + MREQ_n <= '0'; + end if; + elsif MCycle = "011" and IntCycle_n = '0' then + if TState = "001" then + IORQ_n <= '0'; -- Acknowledge IRQ + end if; + else + if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then + RD_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + if T2Write = 0 then + if TState = "010" and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + else + if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + end if; + end if; + if TState = "010" and Wait_n = '1' then + DI_Reg <= DI; + end if; + end if; + end if; + end process; + +end; diff --git a/rtl/T80/README b/rtl/T80/README new file mode 100644 index 0000000..2fce770 --- /dev/null +++ b/rtl/T80/README @@ -0,0 +1,58 @@ +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- +-- Version 351. +-- Merged Gameboy fixes from Bruno Duarte Gouveia (brNX) +-- Passes Blargg's test ROMs +-- +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010 +-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle +-- Ver 300 started tidyup. +-- +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- Z80 compatible microprocessor core +-- +-- Version : 0250 +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- diff --git a/rtl/T80/T80.qip b/rtl/T80/T80.qip index df5c769..e7a05b6 100644 --- a/rtl/T80/T80.qip +++ b/rtl/T80/T80.qip @@ -1,6 +1,13 @@ -set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80s.vhd ] -set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80pa.vhd ] -set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_Reg.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) GBse.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80pa.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80s.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80se.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80a.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80as.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80sed.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T8080se.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_Reg.vhd ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_MCode.vhd ] -set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_ALU.vhd ] -set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_ALU.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_Pack.vhd ] \ No newline at end of file diff --git a/rtl/T80/T80.vhd b/rtl/T80/T80.vhd index 813f64c..c081f10 100644 --- a/rtl/T80/T80.vhd +++ b/rtl/T80/T80.vhd @@ -1,13 +1,13 @@ --------------------------------------------------------------------------------- --- **** --- T80(c) core. Attempt to finish all undocumented features and provide --- accurate timings. --- Version 350. --- Copyright (c) 2018 Sorgelig --- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr --- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as --- correct implementation is still unclear. --- +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- -- **** -- T80(b) core. In an effort to merge and maintain bug fixes .... -- @@ -21,7 +21,7 @@ -- **** -- Z80 compatible microprocessor core -- --- Version : 0247 +-- Version : 0250 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- All rights reserved -- @@ -73,17 +73,19 @@ -- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode -- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM -- 0247 : Fixed bus req/ack cycle +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use IEEE.STD_LOGIC_UNSIGNED.all; +use work.T80_Pack.all; entity T80 is generic( Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB - IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle + IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; @@ -117,21 +119,17 @@ entity T80 is IntCycle_n : out std_logic; IntE : out std_logic; Stop : out std_logic; - out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 - REG : out std_logic_vector(207 downto 0) -- IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + R800_mode : in std_logic := '0'; + out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A ); end T80; architecture rtl of T80 is - constant aNone : std_logic_vector(2 downto 0) := "111"; - constant aBC : std_logic_vector(2 downto 0) := "000"; - constant aDE : std_logic_vector(2 downto 0) := "001"; - constant aXY : std_logic_vector(2 downto 0) := "010"; - constant aIOA : std_logic_vector(2 downto 0) := "100"; - constant aSP : std_logic_vector(2 downto 0) := "101"; - constant aZI : std_logic_vector(2 downto 0) := "110"; - -- Registers signal ACC, F : std_logic_vector(7 downto 0); signal Ap, Fp : std_logic_vector(7 downto 0); @@ -155,9 +153,13 @@ architecture rtl of T80 is -- Help Registers signal WZ : std_logic_vector(15 downto 0); -- MEMPTR register + signal TmpAddr2 : std_logic_vector(15 downto 0); -- Temporary address register signal IR : std_logic_vector(7 downto 0); -- Instruction register signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector signal RegBusA_r : std_logic_vector(15 downto 0); + signal MULU_Prod32 : std_logic_vector(31 downto 0); + signal MULU_tmp : std_logic_vector(31 downto 0); + signal MULU_Fakt1 : std_logic_vector(15 downto 0); signal ID16 : signed(15 downto 0); signal Save_Mux : std_logic_vector(7 downto 0); @@ -167,8 +169,8 @@ architecture rtl of T80 is signal IntE_FF1 : std_logic; signal IntE_FF2 : std_logic; signal Halt_FF : std_logic; - signal BusReq_s : std_logic; - signal BusAck : std_logic; + signal BusReq_s : std_logic := '0'; + signal BusAck : std_logic := '0'; signal ClkEn : std_logic; signal NMI_s : std_logic; signal IStatus : std_logic_vector(1 downto 0); @@ -216,6 +218,7 @@ architecture rtl of T80 is signal Set_BusA_To : std_logic_vector(3 downto 0); signal ALU_Op : std_logic_vector(3 downto 0); signal Save_ALU : std_logic; + signal Rot_Akku : std_logic; signal PreserveC : std_logic; signal Arith16 : std_logic; signal Set_Addr_To : std_logic_vector(2 downto 0); @@ -227,12 +230,17 @@ architecture rtl of T80 is signal LDZ : std_logic; signal LDW : std_logic; signal LDSPHL : std_logic; + signal LDHLSP : std_logic; + signal ADDSPdd : std_logic; signal IORQ_i : std_logic; + signal Write_i : std_logic; + signal NoRead_i : std_logic; signal Special_LD : std_logic_vector(2 downto 0); signal ExchangeDH : std_logic; signal ExchangeRp : std_logic; signal ExchangeAF : std_logic; signal ExchangeRS : std_logic; + signal ExchangeWH : std_logic; signal I_DJNZ : std_logic; signal I_CPL : std_logic; signal I_CCF : std_logic; @@ -245,21 +253,26 @@ architecture rtl of T80 is signal I_RRD : std_logic; signal I_RXDD : std_logic; signal I_INRC : std_logic; + signal I_MULUB : std_logic; + signal I_MULU : std_logic; signal SetWZ : std_logic_vector(1 downto 0); signal SetDI : std_logic; signal SetEI : std_logic; signal IMode : std_logic_vector(1 downto 0); signal Halt : std_logic; signal XYbit_undoc : std_logic; + signal No_PC : std_logic; signal DOR : std_logic_vector(127 downto 0); + signal Really_Wait : std_logic; + begin - REG <= DOR & std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC when Alternate = '0' - else DOR(127 downto 112) & DOR(47 downto 0) & DOR(63 downto 48) & DOR(111 downto 64) & + REG <= IntE_FF2 & IntE_FF1 & IStatus & DOR & std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC when Alternate = '0' + else IntE_FF2 & IntE_FF1 & IStatus & DOR(127 downto 112) & DOR(47 downto 0) & DOR(63 downto 48) & DOR(111 downto 64) & std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC; - mcode : work.T80_MCode + mcode : T80_MCode generic map( Mode => Mode, Flag_C => Flag_C, @@ -290,6 +303,7 @@ begin Set_BusA_To => Set_BusA_To, ALU_Op => ALU_Op, Save_ALU => Save_ALU, + Rot_Akku => Rot_Akku, PreserveC => PreserveC, Arith16 => Arith16, Set_Addr_To => Set_Addr_To, @@ -302,11 +316,14 @@ begin LDZ => LDZ, LDW => LDW, LDSPHL => LDSPHL, + LDHLSP => LDHLSP, + ADDSPdd => ADDSPdd, Special_LD => Special_LD, ExchangeDH => ExchangeDH, ExchangeRp => ExchangeRp, ExchangeAF => ExchangeAF, ExchangeRS => ExchangeRS, + ExchangeWH => ExchangeWH, I_DJNZ => I_DJNZ, I_CPL => I_CPL, I_CCF => I_CCF, @@ -318,16 +335,20 @@ begin I_RLD => I_RLD, I_RRD => I_RRD, I_INRC => I_INRC, + I_MULUB => I_MULUB, + I_MULU => I_MULU, SetWZ => SetWZ, SetDI => SetDI, SetEI => SetEI, IMode => IMode, Halt => Halt, - NoRead => NoRead, - Write => Write, + NoRead => NoRead_i, + Write => Write_i, + R800_mode => R800_mode, + No_PC => No_PC, XYbit_undoc => XYbit_undoc); - alu : work.T80_ALU + alu : T80_ALU generic map( Mode => Mode, Flag_C => Flag_C, @@ -344,6 +365,7 @@ begin WZ => WZ, XY_State=> XY_State, ALU_Op => ALU_Op_r, + Rot_Akku => Rot_Akku, IR => IR(5 downto 0), ISet => ISet, BusA => BusA, @@ -352,6 +374,8 @@ begin Q => ALU_Q, F_Out => F_Out); + Really_Wait <= not Wait_n and (Write_i or not NoRead_i); + ClkEn <= CEN and not BusAck; T_Res <= '1' when TState = unsigned(TStates) else '0'; @@ -368,6 +392,8 @@ begin process (RESET_n, CLK_n) variable n : std_logic_vector(7 downto 0); variable ioq : std_logic_vector(8 downto 0); + variable temp_c : unsigned(8 downto 0); + variable temp_h : unsigned(4 downto 0); begin if RESET_n = '0' then PC <= (others => '0'); -- Program Counter @@ -382,6 +408,11 @@ begin ACC <= (others => '1'); F <= (others => '1'); + if Mode = 3 then + ACC <= (others => '0'); + F <= "11110000"; + end if; + Ap <= (others => '1'); Fp <= (others => '1'); I <= (others => '0'); @@ -390,7 +421,6 @@ begin Alternate <= '0'; Read_To_Reg_r <= "00000"; - F <= (others => '1'); Arith16_r <= '0'; BTR_r <= '0'; Z16_r <= '0'; @@ -402,402 +432,508 @@ begin elsif rising_edge(CLK_n) then - if ClkEn = '1' then + if DIRSet = '1' then + ACC <= DIR( 7 downto 0); + F <= DIR(15 downto 8); + Ap <= DIR(23 downto 16); + Fp <= DIR(31 downto 24); + I <= DIR(39 downto 32); + R <= unsigned(DIR(47 downto 40)); + SP <= unsigned(DIR(63 downto 48)); + PC <= unsigned(DIR(79 downto 64)); + A <= DIR(79 downto 64); + IStatus <= DIR(209 downto 208); - ALU_Op_r <= "0000"; - Save_ALU_r <= '0'; - Read_To_Reg_r <= "00000"; + elsif ClkEn = '1' then + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + Read_To_Reg_r <= "00000"; - MCycles <= MCycles_d; + MCycles <= MCycles_d; - if IMode /= "11" then - IStatus <= IMode; - end if; + if LDHLSP = '1' and MCycle = "011" and TState = 1 then + temp_c := unsigned('0'&SP(7 downto 0))+unsigned('0'&Save_Mux); + temp_h := unsigned('0'&SP(3 downto 0))+unsigned('0'&Save_Mux(3 downto 0)); + F(Flag_Z) <= '0'; + F(Flag_N) <= '0'; + F(Flag_H) <= temp_h(4); + F(Flag_C) <= temp_c(8); + end if; - Arith16_r <= Arith16; - PreserveC_r <= PreserveC; - if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then - Z16_r <= '1'; - else - Z16_r <= '0'; - end if; + if ADDSPdd = '1' and TState = 1 then + temp_c := unsigned('0'&SP(7 downto 0))+unsigned('0'&Save_Mux); + temp_h := unsigned('0'&SP(3 downto 0))+unsigned('0'&Save_Mux(3 downto 0)); + F(Flag_Z) <= '0'; + F(Flag_N) <= '0'; + F(Flag_H) <= temp_h(4); + F(Flag_C) <= temp_c(8); + end if; - if MCycle = "001" and TState(2) = '0' then - -- MCycle = 1 and TState = 1, 2, or 3 + if Mode = 3 then + IStatus <= "10"; + elsif IMode /= "11" then + IStatus <= IMode; + end if; - if TState = 2 and Wait_n = '1' then - if Mode < 2 then - A(7 downto 0) <= std_logic_vector(R); - A(15 downto 8) <= I; - R(6 downto 0) <= R(6 downto 0) + 1; - end if; + Arith16_r <= Arith16; + PreserveC_r <= PreserveC; + if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then + Z16_r <= '1'; + else + Z16_r <= '0'; + end if; - if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then - PC <= PC + 1; - end if; + if MCycle = "001" and TState(2) = '0' then + -- MCycle = 1 and TState = 1, 2, or 3 - if IntCycle = '1' and IStatus = "01" then - IR <= "11111111"; - elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then - IR <= "00000000"; - else - IR <= DInst; - end if; + if TState = 2 and Wait_n = '1' then + if Mode < 2 then + A(7 downto 0) <= std_logic_vector(R); + A(15 downto 8) <= I; + R(6 downto 0) <= R(6 downto 0) + 1; + end if; - ISet <= "00"; - if Prefix /= "00" then - if Prefix = "11" then - if IR(5) = '1' then - XY_State <= "10"; + if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then + PC <= PC + 1; + end if; + + if IntCycle = '1' and IStatus = "01" then + IR <= "11111111"; + elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DInst; + end if; + + if Mode <= 1 and IntCycle = '1' and IStatus = "10" then + -- IM2 vector address low byte from bus + WZ(7 downto 0) <= DInst; + end if; + + ISet <= "00"; + if Prefix /= "00" then + if Prefix = "11" then + if IR(5) = '1' then + XY_State <= "10"; + else + XY_State <= "01"; + end if; else - XY_State <= "01"; + if Prefix = "10" then + XY_State <= "00"; + XY_Ind <= '0'; + end if; + ISet <= Prefix; end if; else - if Prefix = "10" then - XY_State <= "00"; - XY_Ind <= '0'; - end if; - ISet <= Prefix; + XY_State <= "00"; + XY_Ind <= '0'; end if; - else - XY_State <= "00"; - XY_Ind <= '0'; end if; - end if; - else - -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + else + -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) - if MCycle = "110" then - XY_Ind <= '1'; - if Prefix = "01" then - ISet <= "01"; + if MCycle = "110" then + XY_Ind <= '1'; + if Prefix = "01" then + ISet <= "01"; + end if; end if; - end if; - if T_Res = '1' then - BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; - if Jump = '1' then - A(15 downto 8) <= DI_Reg; - A(7 downto 0) <= WZ(7 downto 0); - PC(15 downto 8) <= unsigned(DI_Reg); - PC(7 downto 0) <= unsigned(WZ(7 downto 0)); - elsif JumpXY = '1' then - A <= RegBusC; - PC <= unsigned(RegBusC); - elsif Call = '1' or RstP = '1' then - A <= WZ; - PC <= unsigned(WZ); - elsif MCycle = MCycles and NMICycle = '1' then - A <= "0000000001100110"; - PC <= "0000000001100110"; - elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then - A(15 downto 8) <= I; - A(7 downto 0) <= WZ(7 downto 0); - PC(15 downto 8) <= unsigned(I); - PC(7 downto 0) <= unsigned(WZ(7 downto 0)); - else - case Set_Addr_To is - when aXY => - if XY_State = "00" then - A <= RegBusC; - else - if NextIs_XY_Fetch = '1' then - A <= std_logic_vector(PC); + if T_Res = '1' then + BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; + if Jump = '1' then + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= WZ(7 downto 0); + PC(15 downto 8) <= unsigned(DI_Reg); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); + elsif JumpXY = '1' then + A <= RegBusC; + PC <= unsigned(RegBusC); + elsif Call = '1' or RstP = '1' then + A <= WZ; + PC <= unsigned(WZ); + elsif MCycle = MCycles and NMICycle = '1' then + A <= "0000000001100110"; + PC <= "0000000001100110"; + elsif ((Mode /= 3 and MCycle = "011") or (Mode = 3 and MCycle = "100")) + and IntCycle = '1' and IStatus = "10" then + A(15 downto 8) <= I; + A(7 downto 0) <= WZ(7 downto 0); + PC(15 downto 8) <= unsigned(I); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); + else + case Set_Addr_To is + when aXY => + if XY_State = "00" then + A <= RegBusC; else - A <= WZ; + if NextIs_XY_Fetch = '1' then + A <= std_logic_vector(PC); + else + A <= WZ; + end if; end if; - end if; - when aIOA => - if Mode = 3 then - -- Memory map I/O on GBZ80 - A(15 downto 8) <= (others => '1'); - elsif Mode = 2 then - -- Duplicate I/O address on 8080 - A(15 downto 8) <= DI_Reg; - else - A(15 downto 8) <= ACC; - end if; - A(7 downto 0) <= DI_Reg; - WZ <= (ACC & DI_Reg) + "1"; - when aSP => - A <= std_logic_vector(SP); - when aBC => - if Mode = 3 and IORQ_i = '1' then - -- Memory map I/O on GBZ80 - A(15 downto 8) <= (others => '1'); - A(7 downto 0) <= RegBusC(7 downto 0); - else + when aIOA => + if Mode = 3 then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + elsif Mode = 2 then + -- Duplicate I/O address on 8080 + A(15 downto 8) <= DI_Reg; + else + A(15 downto 8) <= ACC; + end if; + A(7 downto 0) <= DI_Reg; + WZ <= (ACC & DI_Reg) + "1"; + when aSP => + A <= std_logic_vector(SP); + when aBC => + if Mode = 3 and IORQ_i = '1' then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + A(7 downto 0) <= RegBusC(7 downto 0); + else + A <= RegBusC; + if SetWZ = "01" then + WZ <= RegBusC + "1"; + end if; + if SetWZ = "10" then + WZ(7 downto 0) <= RegBusC(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; + end if; + when aDE => A <= RegBusC; - if SetWZ = "01" then - WZ <= RegBusC + "1"; - end if; if SetWZ = "10" then WZ(7 downto 0) <= RegBusC(7 downto 0) + "1"; WZ(15 downto 8) <= ACC; end if; - end if; - when aDE => - A <= RegBusC; - if SetWZ = "10" then - WZ(7 downto 0) <= RegBusC(7 downto 0) + "1"; - WZ(15 downto 8) <= ACC; - end if; - when aZI => - if Inc_WZ = '1' then - A <= std_logic_vector(unsigned(WZ) + 1); - else - A(15 downto 8) <= DI_Reg; - A(7 downto 0) <= WZ(7 downto 0); - if SetWZ = "10" then - WZ(7 downto 0) <= WZ(7 downto 0) + "1"; - WZ(15 downto 8) <= ACC; + when aZI => + if Inc_WZ = '1' then + A <= std_logic_vector(unsigned(WZ) + 1); + else + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= WZ(7 downto 0); + if SetWZ = "10" then + WZ(7 downto 0) <= WZ(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; end if; + when others => + if ISet = "10" and IR(7 downto 4) = x"B" and IR(2 downto 1) = "01" and MCycle = 3 and No_BTR = '0' then + -- INIR, INDR, OTIR, OTDR + A <= RegBusA_r; + elsif No_PC = '0' or No_BTR = '1' or (I_DJNZ = '1' and IncDecZ = '1') or Mode > 1 then + A <= std_logic_vector(PC); + end if; + end case; + end if; + + if SetWZ = "11" then + WZ <= std_logic_vector(ID16); + end if; + + Save_ALU_r <= Save_ALU; + ALU_Op_r <= ALU_Op; + + if Mode = 3 then + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_H) <= '1'; + F(Flag_N) <= '1'; end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + else + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + end if; + end if; + + if (TState = 2 and Really_Wait = '0' and I_BTR = '1' and IR(0) = '1') or (TState = 1 and I_BTR = '1' and IR(0) = '0') then + ioq := ('0' & DI_Reg) + ('0' & std_logic_vector(ID16(7 downto 0))); + F(Flag_N) <= DI_Reg(7); + F(Flag_C) <= ioq(8); + F(Flag_H) <= ioq(8); + ioq := (ioq and "000000111") xor ('0'&BusA); + F(Flag_P) <= not (ioq(0) xor ioq(1) xor ioq(2) xor ioq(3) xor ioq(4) xor ioq(5) xor ioq(6) xor ioq(7)); + end if; + + if TState = 2 and Really_Wait = '0' then + if ISet = "01" and MCycle = "111" then + IR <= DInst; + end if; + if JumpE = '1' then + PC <= unsigned(signed(PC) + signed(DI_Reg)); + WZ <= std_logic_vector(signed(PC) + signed(DI_Reg)); + elsif Inc_PC = '1' then + PC <= PC + 1; + end if; + if BTR_r = '1' then + PC <= PC - 2; + end if; + if RstP = '1' then + WZ <= (others =>'0'); + WZ(5 downto 3) <= IR(5 downto 3); + end if; + end if; + if TState = 3 and MCycle = "110" then + WZ <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + end if; + + if MCycle = "011" and TState = 4 and No_BTR = '0' then + if I_BT = '1' or I_BC = '1' then + WZ <= std_logic_vector(PC)-"1"; + end if; + end if; + + if (TState = 2 and Really_Wait = '0') or (TState = 4 and MCycle = "001") then + if IncDec_16(2 downto 0) = "111" then + if IncDec_16(3) = '1' then + SP <= SP - 1; + else + SP <= SP + 1; + end if; + end if; + end if; + + if ADDSPdd = '1' and TState = 2 then + WZ <= std_logic_vector(SP); + SP <= unsigned(signed(SP)+signed(Save_Mux)); + end if; + + if LDSPHL = '1' then + SP <= unsigned(RegBusC); + end if; + if ExchangeAF = '1' then + Ap <= ACC; + ACC <= Ap; + Fp <= F; + F <= Fp; + end if; + if ExchangeRS = '1' then + Alternate <= not Alternate; + end if; + end if; + + if TState = 3 then + if LDZ = '1' then + WZ(7 downto 0) <= DI_Reg; + end if; + if LDW = '1' then + WZ(15 downto 8) <= DI_Reg; + end if; + + if Special_LD(2) = '1' then + case Special_LD(1 downto 0) is + when "00" => + ACC <= I; + F(Flag_P) <= IntE_FF2; + F(Flag_S) <= I(7); + + if I = x"00" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + + F(Flag_Y) <= I(5); + F(Flag_H) <= '0'; + F(Flag_X) <= I(3); + F(Flag_N) <= '0'; + + + when "01" => + ACC <= std_logic_vector(R); + F(Flag_P) <= IntE_FF2; + F(Flag_S) <= R(7); + + if R = x"00" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + + F(Flag_Y) <= R(5); + F(Flag_H) <= '0'; + F(Flag_X) <= R(3); + F(Flag_N) <= '0'; + + when "10" => + I <= ACC; when others => - A <= std_logic_vector(PC); + R <= unsigned(ACC); end case; end if; - - if SetWZ = "11" then - WZ <= std_logic_vector(ID16); - end if; - - Save_ALU_r <= Save_ALU; - ALU_Op_r <= ALU_Op; - - if I_CPL = '1' then - -- CPL - ACC <= not ACC; - F(Flag_Y) <= not ACC(5); - F(Flag_H) <= '1'; - F(Flag_X) <= not ACC(3); - F(Flag_N) <= '1'; - end if; - if I_CCF = '1' then - -- CCF - F(Flag_C) <= not F(Flag_C); - F(Flag_Y) <= ACC(5); - F(Flag_H) <= F(Flag_C); - F(Flag_X) <= ACC(3); - F(Flag_N) <= '0'; - end if; - if I_SCF = '1' then - -- SCF - F(Flag_C) <= '1'; - F(Flag_Y) <= ACC(5); - F(Flag_H) <= '0'; - F(Flag_X) <= ACC(3); - F(Flag_N) <= '0'; - end if; - end if; - - if (TState = 2 and I_BTR = '1' and IR(0) = '1') or (TState = 1 and I_BTR = '1' and IR(0) = '0') then - ioq := ('0' & DI_Reg) + ('0' & std_logic_vector(ID16(7 downto 0))); - F(Flag_N) <= DI_Reg(7); - F(Flag_C) <= ioq(8); - F(Flag_H) <= ioq(8); - ioq := (ioq and x"7") xor ('0'&BusA); - F(Flag_P) <= not (ioq(0) xor ioq(1) xor ioq(2) xor ioq(3) xor ioq(4) xor ioq(5) xor ioq(6) xor ioq(7)); end if; - if TState = 2 and Wait_n = '1' then - if ISet = "01" and MCycle = "111" then - IR <= DInst; - end if; - if JumpE = '1' then - PC <= unsigned(signed(PC) + signed(DI_Reg)); - WZ <= std_logic_vector(signed(PC) + signed(DI_Reg)); - elsif Inc_PC = '1' then - PC <= PC + 1; - end if; - if BTR_r = '1' then - PC <= PC - 2; - end if; - if RstP = '1' then - WZ <= (others =>'0'); - WZ(5 downto 3) <= IR(5 downto 3); - end if; - end if; - if TState = 3 and MCycle = "110" then - WZ <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); - end if; - - if MCycle = "011" and TState = 4 and No_BTR = '0' then - if I_BT = '1' or I_BC = '1' then - WZ <= std_logic_vector(PC)-"1"; - end if; - end if; - - if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then - if IncDec_16(2 downto 0) = "111" then - if IncDec_16(3) = '1' then - SP <= SP - 1; - else - SP <= SP + 1; + if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then + if Mode = 3 then + F(6) <= F_Out(6); + F(5) <= F_Out(5); + F(7) <= F_Out(7); + if PreserveC_r = '0' then + F(4) <= F_Out(4); + end if; + else + F(7 downto 1) <= F_Out(7 downto 1); + if PreserveC_r = '0' then + F(Flag_C) <= F_Out(0); end if; end if; end if; - - if LDSPHL = '1' then - SP <= unsigned(RegBusC); - end if; - if ExchangeAF = '1' then - Ap <= ACC; - ACC <= Ap; - Fp <= F; - F <= Fp; - end if; - if ExchangeRS = '1' then - Alternate <= not Alternate; - end if; - end if; - - if TState = 3 then - if LDZ = '1' then - WZ(7 downto 0) <= DI_Reg; - end if; - if LDW = '1' then - WZ(15 downto 8) <= DI_Reg; + if T_Res = '1' and I_INRC = '1' then + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + F(Flag_X) <= DI_Reg(3); + F(Flag_Y) <= DI_Reg(5); + if DI_Reg(7 downto 0) = "00000000" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + F(Flag_S) <= DI_Reg(7); + F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor + DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); end if; - if Special_LD(2) = '1' then - case Special_LD(1 downto 0) is - when "00" => - ACC <= I; - F(Flag_P) <= IntE_FF2; - F(Flag_S) <= I(7); - - if I = x"00" then - F(Flag_Z) <= '1'; + if TState = 1 and Auto_Wait_t1 = '0' then + -- Keep D0 from M3 for RLD/RRD (Sorgelig) + I_RXDD <= I_RLD or I_RRD; + if I_RXDD='0' then + DO <= BusB; + end if; + if I_RLD = '1' then + DO(3 downto 0) <= BusA(3 downto 0); + DO(7 downto 4) <= BusB(3 downto 0); + end if; + if I_RRD = '1' then + DO(3 downto 0) <= BusB(7 downto 4); + DO(7 downto 4) <= BusA(3 downto 0); + end if; + end if; + + if T_Res = '1' then + Read_To_Reg_r(3 downto 0) <= Set_BusA_To; + Read_To_Reg_r(4) <= Read_To_Reg; + if Read_To_Acc = '1' then + Read_To_Reg_r(3 downto 0) <= "0111"; + Read_To_Reg_r(4) <= '1'; + end if; + end if; + + if TState = 1 and I_BT = '1' then + F(Flag_X) <= ALU_Q(3); + F(Flag_Y) <= ALU_Q(1); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if TState = 1 and I_BC = '1' then + n := ALU_Q - ("0000000" & F_Out(Flag_H)); + F(Flag_X) <= n(3); + F(Flag_Y) <= n(1); + end if; + if I_BC = '1' or I_BT = '1' then + F(Flag_P) <= IncDecZ; + end if; + + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10111" => + ACC <= Save_Mux; + when "10110" => + DO <= Save_Mux; + when "11000" => + SP(7 downto 0) <= unsigned(Save_Mux); + when "11001" => + SP(15 downto 8) <= unsigned(Save_Mux); + when "11011" => + if Mode = 3 then + F(7 downto 4) <= Save_Mux(7 downto 4); + F(3 downto 0) <= "0000"; -- bit 3 to 0 always return 0 else - F(Flag_Z) <= '0'; + F <= Save_Mux; end if; - - F(Flag_Y) <= I(5); - F(Flag_H) <= '0'; - F(Flag_X) <= I(3); - F(Flag_N) <= '0'; - - - when "01" => - ACC <= std_logic_vector(R); - F(Flag_P) <= IntE_FF2; - F(Flag_S) <= R(7); - - if R = x"00" then - F(Flag_Z) <= '1'; - else - F(Flag_Z) <= '0'; - end if; - - F(Flag_Y) <= R(5); - F(Flag_H) <= '0'; - F(Flag_X) <= R(3); - F(Flag_N) <= '0'; - - when "10" => - I <= ACC; when others => - R <= unsigned(ACC); end case; - end if; - end if; - - if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then - if Mode = 3 then - F(6) <= F_Out(6); - F(5) <= F_Out(5); - F(7) <= F_Out(7); - if PreserveC_r = '0' then - F(4) <= F_Out(4); - end if; - else - F(7 downto 1) <= F_Out(7 downto 1); - if PreserveC_r = '0' then - F(Flag_C) <= F_Out(0); + if XYbit_undoc='1' then + DO <= ALU_Q; end if; end if; end if; - if T_Res = '1' and I_INRC = '1' then - F(Flag_H) <= '0'; - F(Flag_N) <= '0'; - F(Flag_X) <= DI_Reg(3); - F(Flag_Y) <= DI_Reg(5); - if DI_Reg(7 downto 0) = "00000000" then - F(Flag_Z) <= '1'; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Multiply +-- +--------------------------------------------------------------------------- + process (CLK_n, ACC, RegBusB, MULU_tmp, MULU_Fakt1, MULU_Prod32) + begin + + MULU_tmp(31 downto 12) <= std_logic_vector((unsigned(MULU_Fakt1)*unsigned(MULU_Prod32(3 downto 0)))+unsigned("0000"&MULU_Prod32(31 downto 16))); + MULU_tmp(11 downto 0) <= MULU_Prod32(15 downto 4); + + if rising_edge(CLK_n) then + if ClkEn = '1' then + if T_Res='1' then + if I_MULUB='1' then + MULU_Prod32(7 downto 0) <= ACC; + MULU_Prod32(15 downto 8) <= "--------"; + MULU_Prod32(31 downto 16) <= X"0000"; + MULU_Fakt1(7 downto 0) <= "00000000"; + if Set_BusB_To(0) = '1' then + MULU_Fakt1(15 downto 8) <= RegBusB(7 downto 0); + else + MULU_Fakt1(15 downto 8) <= RegBusB(15 downto 8); + end if; + else + MULU_Prod32(15 downto 0) <= RegBusA; + MULU_Prod32(31 downto 16) <= X"0000"; + MULU_Fakt1 <= RegBusB; + end if; else - F(Flag_Z) <= '0'; - end if; - F(Flag_S) <= DI_Reg(7); - F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor - DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); - end if; - - if TState = 1 and Auto_Wait_t1 = '0' then - -- Keep D0 from M3 for RLD/RRD (Sorgelig) - I_RXDD <= I_RLD or I_RRD; - if I_RXDD='0' then - DO <= BusB; - end if; - if I_RLD = '1' then - DO(3 downto 0) <= BusA(3 downto 0); - DO(7 downto 4) <= BusB(3 downto 0); - end if; - if I_RRD = '1' then - DO(3 downto 0) <= BusB(7 downto 4); - DO(7 downto 4) <= BusA(3 downto 0); + MULU_Prod32 <= MULU_tmp; end if; end if; - - if T_Res = '1' then - Read_To_Reg_r(3 downto 0) <= Set_BusA_To; - Read_To_Reg_r(4) <= Read_To_Reg; - if Read_To_Acc = '1' then - Read_To_Reg_r(3 downto 0) <= "0111"; - Read_To_Reg_r(4) <= '1'; - end if; - end if; - - if TState = 1 and I_BT = '1' then - F(Flag_X) <= ALU_Q(3); - F(Flag_Y) <= ALU_Q(1); - F(Flag_H) <= '0'; - F(Flag_N) <= '0'; - end if; - if TState = 1 and I_BC = '1' then - n := ALU_Q - ("0000000" & F_Out(Flag_H)); - F(Flag_X) <= n(3); - F(Flag_Y) <= n(1); - end if; - if I_BC = '1' or I_BT = '1' then - F(Flag_P) <= IncDecZ; - end if; - - if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or - (Save_ALU_r = '1' and ALU_OP_r /= "0111") then - case Read_To_Reg_r is - when "10111" => - ACC <= Save_Mux; - when "10110" => - DO <= Save_Mux; - when "11000" => - SP(7 downto 0) <= unsigned(Save_Mux); - when "11001" => - SP(15 downto 8) <= unsigned(Save_Mux); - when "11011" => - F <= Save_Mux; - when others => - end case; - if XYbit_undoc='1' then - DO <= ALU_Q; - end if; - end if; - end if; - - end if; - end process; --------------------------------------------------------------------------- @@ -855,7 +991,13 @@ begin (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else -- EX HL,DL Alternate & "10" when ExchangeDH = '1' and TState = 3 else - Alternate & "01" when ExchangeDH = '1' and TState = 4 else + Alternate & "01" when (ExchangeDH = '1' or I_MULU = '1') and TState = 4 else + -- EX (SP),HL (HL(IX,IY) <= WZ) + Alternate & "10" when ExchangeWH = '1' and XY_State = "00" and TState = 4 else + XY_State(1) & "11" when ExchangeWH = '1' and TState = 4 else + -- LDHLSP + "010" when LDHLSP = '1' and TState = 4 else + -- Bus A / Write RegAddrA_r; @@ -868,8 +1010,8 @@ begin ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else signed(RegBusA) + 1; - process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, - ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, I_MULU, T_Res, + ExchangeDH, ExchangeWH, IncDec_16, MCycle, TState, Really_Wait, LDHLSP) begin RegWEH <= '0'; RegWEL <= '0'; @@ -883,12 +1025,22 @@ begin end case; end if; + if I_MULU = '1' and (T_Res = '1' or TState = 4) then -- TState = 4 DE write + RegWEH <= '1'; + RegWEL <= '1'; + end if; + if ExchangeDH = '1' and (TState = 3 or TState = 4) then RegWEH <= '1'; RegWEL <= '1'; end if; - if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + if ((LDHLSP = '1' and MCycle = "010") or ExchangeWH = '1') and TState = 4 then + RegWEH <= '1'; + RegWEL <= '1'; + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and Really_Wait = '0' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then case IncDec_16(1 downto 0) is when "00" | "01" | "10" => RegWEH <= '1'; @@ -898,12 +1050,29 @@ begin end if; end process; - process (Save_Mux, RegBusB, RegBusA_r, ID16, - ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + TmpAddr2 <= std_logic_vector(unsigned(signed(SP) + signed(Save_Mux))); + + process (Save_Mux, RegBusB, RegBusA_r, ID16, I_MULU, MULU_Prod32, MULU_tmp, T_Res, + ExchangeDH, ExchangeWH, IncDec_16, MCycle, TState, Really_Wait, LDHLSP, TmpAddr2, WZ) begin RegDIH <= Save_Mux; RegDIL <= Save_Mux; + if I_MULU = '1' then + if T_Res = '1' then + RegDIH <= MULU_Prod32(31 downto 24); + RegDIL <= MULU_Prod32(23 downto 16); + else + RegDIH <= MULU_tmp(15 downto 8); -- TState = 4 DE write + RegDIL <= MULU_tmp(7 downto 0); + end if; + end if; + + if LDHLSP = '1' and MCycle = "010" and TState = 4 then + RegDIH <= TmpAddr2(15 downto 8); + RegDIL <= TmpAddr2(7 downto 0); + end if; + if ExchangeDH = '1' and TState = 3 then RegDIH <= RegBusB(15 downto 8); RegDIL <= RegBusB(7 downto 0); @@ -912,14 +1081,17 @@ begin RegDIH <= RegBusA_r(15 downto 8); RegDIL <= RegBusA_r(7 downto 0); end if; - + if ExchangeWH = '1' and TState = 4 then + RegDIH <= WZ(15 downto 8); + RegDIL <= WZ(7 downto 0); + end if; if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then RegDIH <= std_logic_vector(ID16(15 downto 8)); RegDIL <= std_logic_vector(ID16(7 downto 0)); end if; end process; - Regs : work.T80_Reg + Regs : T80_Reg port map( Clk => CLK_n, CEN => ClkEn, @@ -936,7 +1108,9 @@ begin DOBL => RegBusB(7 downto 0), DOCH => RegBusC(15 downto 8), DOCL => RegBusC(7 downto 0), - DOR => DOR); + DOR => DOR, + DIRSet => DIRSet, + DIR => DIR(207 downto 80)); --------------------------------------------------------------------------- -- @@ -947,63 +1121,63 @@ begin begin if rising_edge(CLK_n) then if ClkEn = '1' then - case Set_BusB_To is - when "0111" => - BusB <= ACC; - when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => - if Set_BusB_To(0) = '1' then - BusB <= RegBusB(7 downto 0); - else - BusB <= RegBusB(15 downto 8); - end if; - when "0110" => - BusB <= DI_Reg; - when "1000" => - BusB <= std_logic_vector(SP(7 downto 0)); - when "1001" => - BusB <= std_logic_vector(SP(15 downto 8)); - when "1010" => - BusB <= "00000001"; - when "1011" => - BusB <= F; - when "1100" => - BusB <= std_logic_vector(PC(7 downto 0)); - when "1101" => - BusB <= std_logic_vector(PC(15 downto 8)); - when "1110" => - if IR = x"71" and out0 = '1' then - BusB <= "11111111"; - else - BusB <= "00000000"; - end if; - when others => - BusB <= "--------"; - end case; + case Set_BusB_To is + when "0111" => + BusB <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusB_To(0) = '1' then + BusB <= RegBusB(7 downto 0); + else + BusB <= RegBusB(15 downto 8); + end if; + when "0110" => + BusB <= DI_Reg; + when "1000" => + BusB <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusB <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusB <= "00000001"; + when "1011" => + BusB <= F; + when "1100" => + BusB <= std_logic_vector(PC(7 downto 0)); + when "1101" => + BusB <= std_logic_vector(PC(15 downto 8)); + when "1110" => + if IR = x"71" and out0 = '1' then + BusB <= "11111111"; + else + BusB <= "00000000"; + end if; + when others => + BusB <= "--------"; + end case; - case Set_BusA_To is - when "0111" => - BusA <= ACC; - when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => - if Set_BusA_To(0) = '1' then - BusA <= RegBusA(7 downto 0); - else - BusA <= RegBusA(15 downto 8); + case Set_BusA_To is + when "0111" => + BusA <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusA_To(0) = '1' then + BusA <= RegBusA(7 downto 0); + else + BusA <= RegBusA(15 downto 8); + end if; + when "0110" => + BusA <= DI_Reg; + when "1000" => + BusA <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusA <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusA <= "00000000"; + when others => + BusA <= "--------"; + end case; + if XYbit_undoc='1' then + BusA <= DI_Reg; + BusB <= DI_Reg; end if; - when "0110" => - BusA <= DI_Reg; - when "1000" => - BusA <= std_logic_vector(SP(7 downto 0)); - when "1001" => - BusA <= std_logic_vector(SP(15 downto 8)); - when "1010" => - BusA <= "00000000"; - when others => - BusA <= "--------"; - end case; - if XYbit_undoc='1' then - BusA <= DI_Reg; - BusB <= DI_Reg; - end if; end if; end if; end process; @@ -1018,12 +1192,12 @@ begin if RESET_n = '0' then RFSH_n <= '1'; elsif rising_edge(CLK_n) then - if CEN = '1' then - if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then - RFSH_n <= '0'; - else - RFSH_n <= '1'; - end if; + if DIRSet = '0' and CEN = '1' then + if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then + RFSH_n <= '0'; + else + RFSH_n <= '1'; + end if; end if; end if; end process; @@ -1032,26 +1206,27 @@ begin TS <= std_logic_vector(TState); DI_Reg <= DI; HALT_n <= not Halt_FF; - BUSAK_n <= not BusAck; + BUSAK_n <= not (BusAck and RESET_n); IntCycle_n <= not IntCycle; IntE <= IntE_FF1; IORQ <= IORQ_i; + NoRead <= NoRead_i; + Write <= Write_i; Stop <= I_DJNZ; - ------------------------------------------------------------------------- -- -- Main state machine -- ------------------------------------------------------------------------- process (RESET_n, CLK_n) - variable OldNMI_n : std_logic; + variable OldNMI_n : std_logic; begin if RESET_n = '0' then MCycle <= "001"; TState <= "000"; Pre_XY_F_M <= "000"; Halt_FF <= '0'; - BusAck <= '0'; + --BusAck <= '0'; NMICycle <= '0'; IntCycle <= '0'; IntE_FF1 <= '0'; @@ -1060,108 +1235,112 @@ begin Auto_Wait_t1 <= '0'; Auto_Wait_t2 <= '0'; M1_n <= '1'; - BusReq_s <= '0'; - NMI_s <= '0'; + --BusReq_s <= '0'; + NMI_s <= '0'; elsif rising_edge(CLK_n) then - - if NMI_n = '0' and OldNMI_n = '1' then - NMI_s <= '1'; - end if; - OldNMI_n := NMI_n; - - if CEN = '1' then - BusReq_s <= not BUSRQ_n; - Auto_Wait_t2 <= Auto_Wait_t1; - if T_Res = '1' then - Auto_Wait_t1 <= '0'; - Auto_Wait_t2 <= '0'; - else - Auto_Wait_t1 <= Auto_Wait or IORQ_i; + if DIRSet = '1' then + IntE_FF2 <= DIR(211); + IntE_FF1 <= DIR(210); + else + if NMI_n = '0' and OldNMI_n = '1' then + NMI_s <= '1'; end if; - No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or - (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or - (I_BTR and (not IR(4) or F(Flag_Z))); - if TState = 2 then - if SetEI = '1' then - IntE_FF1 <= '1'; - IntE_FF2 <= '1'; + OldNMI_n := NMI_n; + + if CEN = '1' then + BusReq_s <= not BUSRQ_n; + Auto_Wait_t2 <= Auto_Wait_t1; + if T_Res = '1' then + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + else + Auto_Wait_t1 <= Auto_Wait or IORQ_i; end if; - if I_RETN = '1' then - IntE_FF1 <= IntE_FF2; - end if; - end if; - if TState = 3 then - if SetDI = '1' then - IntE_FF1 <= '0'; - IntE_FF2 <= '0'; - end if; - end if; - if IntCycle = '1' or NMICycle = '1' then - Halt_FF <= '0'; - end if; - if MCycle = "001" and TState = 2 and Wait_n = '1' then - M1_n <= '1'; - end if; - if BusReq_s = '1' and BusAck = '1' then - else - BusAck <= '0'; - if TState = 2 and Wait_n = '0' then - elsif T_Res = '1' then - if Halt = '1' then - Halt_FF <= '1'; + No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or + (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or + (I_BTR and (not IR(4) or F(Flag_Z))); + if TState = 2 then + if SetEI = '1' then + IntE_FF1 <= '1'; + IntE_FF2 <= '1'; end if; - if BusReq_s = '1' then - BusAck <= '1'; - else - TState <= "001"; - if NextIs_XY_Fetch = '1' then - MCycle <= "110"; - Pre_XY_F_M <= MCycle; - if IR = "00110110" and Mode = 0 then - Pre_XY_F_M <= "010"; - end if; - elsif (MCycle = "111") or (MCycle = "110" and Mode = 1 and ISet /= "01") then - MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); - elsif (MCycle = MCycles) or No_BTR = '1' or (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then - M1_n <= '0'; - MCycle <= "001"; - IntCycle <= '0'; - NMICycle <= '0'; - if NMI_s = '1' and Prefix = "00" then - NMI_s <= '0'; - NMICycle <= '1'; - IntE_FF1 <= '0'; - elsif IntE_FF1 = '1' and INT_n='0' and Prefix = "00" and SetEI = '0' then - IntCycle <= '1'; - IntE_FF1 <= '0'; - IntE_FF2 <= '0'; - end if; + if I_RETN = '1' then + IntE_FF1 <= IntE_FF2; + end if; + end if; + if TState = 3 then + if SetDI = '1' then + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + end if; + if IntCycle = '1' or NMICycle = '1' then + Halt_FF <= '0'; + end if; + if MCycle = "001" and TState = 2 and Wait_n = '1' then + M1_n <= '1'; + end if; + if BusReq_s = '1' and BusAck = '1' then + else + BusAck <= '0'; + if TState = 2 and Really_Wait = '1' then + elsif T_Res = '1' then + if Halt = '1' and ( not(Mode = 3 and INT_n = '0' and IntE_FF1 = '0')) then -- halt bug when Mode = 3 , INT_n = '0' and IME=0 + Halt_FF <= '1'; + end if; + if BusReq_s = '1' then + BusAck <= '1'; else - MCycle <= std_logic_vector(unsigned(MCycle) + 1); + TState <= "001"; + if (IntCycle = '1' and Mode = 3) then -- GB: read interrupt at MCycle 3 + if (MCycle = "010") then + M1_n <= '0'; + else + M1_n <= '1'; + end if; + end if; + if NextIs_XY_Fetch = '1' then + MCycle <= "110"; + Pre_XY_F_M <= MCycle; + if IR = "00110110" and Mode = 0 then + Pre_XY_F_M <= "010"; + end if; + elsif (MCycle = "111") or (MCycle = "110" and Mode = 1 and ISet /= "01") then + MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); + elsif (MCycle = MCycles) or No_BTR = '1' or (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then + M1_n <= '0'; + MCycle <= "001"; + IntCycle <= '0'; + NMICycle <= '0'; + if NMI_s = '1' and Prefix = "00" then + NMI_s <= '0'; + NMICycle <= '1'; + IntE_FF1 <= '0'; + elsif IntE_FF1 = '1' and INT_n='0' and Prefix = "00" and SetEI = '0' then + IntCycle <= '1'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + elsif (Halt_FF = '1' and INT_n = '0' and Mode = 3) then + Halt_FF <= '0'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + end if; + else + if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor + (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then + TState <= TState + 1; end if; end if; - else - if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor - (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then - TState <= TState + 1; - end if; + end if; + if TState = 0 then + M1_n <= '0'; end if; end if; - if TState = 0 then - M1_n <= '0'; - end if; - end if; - end if; - end process; - - process (IntCycle, NMICycle, MCycle) - begin - Auto_Wait <= '0'; - if IntCycle = '1' or NMICycle = '1' then - if MCycle = "001" then - Auto_Wait <= '1'; end if; end if; end process; + Auto_Wait <= '1' when IntCycle = '1' and MCycle = "001" else '0'; end; diff --git a/rtl/T80/T8080se.vhd b/rtl/T80/T8080se.vhd new file mode 100644 index 0000000..b18b47a --- /dev/null +++ b/rtl/T80/T8080se.vhd @@ -0,0 +1,194 @@ +-- **** +-- 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) +-- +-- **** +-- +-- 8080 compatible microprocessor core, synchronous top level with clock enable +-- Different timing than the original 8080 +-- Inputs needs to be synchronous and outputs may glitch +-- +-- Version : 0242 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- 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/ +-- +-- Limitations : +-- STACK status output not supported +-- +-- File history : +-- +-- 0237 : First version +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T8080se is + generic( + Mode : integer := 2; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + T2Write : integer := 0 -- 0 => WR_n active in T3, /=0 => WR_n active in T2 + ); + port( + RESET_n : in std_logic; + CLK : in std_logic; + CLKEN : in std_logic; + READY : in std_logic; + HOLD : in std_logic; + INT : in std_logic; + INTE : out std_logic; + DBIN : out std_logic; + SYNC : out std_logic; + VAIT : out std_logic; + HLDA : out std_logic; + WR_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T8080se; + +architecture rtl of T8080se is + + signal IntCycle_n : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal IORQ : std_logic; + signal INT_n : std_logic; + signal HALT_n : std_logic; + signal BUSRQ_n : std_logic; + signal BUSAK_n : std_logic; + signal DO_i : std_logic_vector(7 downto 0); + signal DI_Reg : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + signal One : std_logic; + +begin + + INT_n <= not INT; + BUSRQ_n <= HOLD; + HLDA <= not BUSAK_n; + SYNC <= '1' when TState = "001" else '0'; + VAIT <= '1' when TState = "010" else '0'; + One <= '1'; + + DO(0) <= not IntCycle_n when TState = "001" else DO_i(0); -- INTA + DO(1) <= Write when TState = "001" else DO_i(1); -- WO_n + DO(2) <= DO_i(2); -- STACK not supported !!!!!!!!!! + DO(3) <= not HALT_n when TState = "001" else DO_i(3); -- HLTA + DO(4) <= IORQ and Write when TState = "001" else DO_i(4); -- OUT + DO(5) <= DO_i(5) when TState /= "001" else '1' when MCycle = "001" else '0'; -- M1 + DO(6) <= IORQ and not Write when TState = "001" else DO_i(6); -- INP + DO(7) <= not IORQ and not Write and IntCycle_n when TState = "001" else DO_i(7); -- MEMR + + u0 : T80 + generic map( + Mode => Mode, + IOWait => 0) + port map( + CEN => CLKEN, + M1_n => open, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => open, + HALT_n => HALT_n, + WAIT_n => READY, + INT_n => INT_n, + NMI_n => One, + RESET_n => RESET_n, + BUSRQ_n => One, + BUSAK_n => BUSAK_n, + CLK_n => CLK, + A => A, + DInst => DI, + DI => DI_Reg, + DO => DO_i, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n, + IntE => INTE); + + process (RESET_n, CLK) + begin + if RESET_n = '0' then + DBIN <= '0'; + WR_n <= '1'; + DI_Reg <= "00000000"; + elsif CLK'event and CLK = '1' then + if CLKEN = '1' then + DBIN <= '0'; + WR_n <= '1'; + if MCycle = "001" then + if TState = "001" or (TState = "010" and READY = '0') then + DBIN <= IntCycle_n; + end if; + else + if (TState = "001" or (TState = "010" and READY = '0')) and NoRead = '0' and Write = '0' then + DBIN <= '1'; + end if; + if T2Write = 0 then + if TState = "010" and Write = '1' then + WR_n <= '0'; + end if; + else + if (TState = "001" or (TState = "010" and READY = '0')) and Write = '1' then + WR_n <= '0'; + end if; + end if; + end if; + if TState = "010" and READY = '1' then + DI_Reg <= DI; + end if; + end if; + end if; + end process; + +end; diff --git a/rtl/T80/T80_ALU.vhd b/rtl/T80/T80_ALU.vhd index 3e881ee..1192e0b 100644 --- a/rtl/T80/T80_ALU.vhd +++ b/rtl/T80/T80_ALU.vhd @@ -1,13 +1,13 @@ --------------------------------------------------------------------------------- --- **** --- T80(c) core. Attempt to finish all undocumented features and provide --- accurate timings. --- Version 350. --- Copyright (c) 2018 Sorgelig --- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr --- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as --- correct implementation is still unclear. --- +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- -- **** -- T80(b) core. In an effort to merge and maintain bug fixes .... -- @@ -86,9 +86,10 @@ entity T80_ALU is port( Arith16 : in std_logic; Z16 : in std_logic; - WZ : in std_logic_vector(15 downto 0); - XY_State : in std_logic_vector(1 downto 0); + WZ : in std_logic_vector(15 downto 0); + XY_State : in std_logic_vector(1 downto 0); ALU_Op : in std_logic_vector(3 downto 0); + Rot_Akku : in std_logic; IR : in std_logic_vector(5 downto 0); ISet : in std_logic_vector(1 downto 0); BusA : in std_logic_vector(7 downto 0); @@ -158,7 +159,7 @@ begin end if; end process; - process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, WZ, XY_State) + process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, Rot_Akku, WZ, XY_State) variable Q_t : std_logic_vector(7 downto 0); variable DAA_Q : unsigned(8 downto 0); begin @@ -220,35 +221,64 @@ begin end if; when "1100" => -- DAA - F_Out(Flag_H) <= F_In(Flag_H); - F_Out(Flag_C) <= F_In(Flag_C); - DAA_Q(7 downto 0) := unsigned(BusA); - DAA_Q(8) := '0'; - if F_In(Flag_N) = '0' then - -- After addition - -- Alow > 9 or H = 1 - if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then - if (DAA_Q(3 downto 0) > 9) then - F_Out(Flag_H) <= '1'; - else - F_Out(Flag_H) <= '0'; + if Mode = 3 then + F_Out(Flag_H) <= '0'; + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if F_In(Flag_H) = '1' then + DAA_Q := DAA_Q - 6; + if F_In(Flag_C) = '0' then + DAA_Q(8) := '0'; + end if; + end if; + if F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 96; -- 0x60 end if; - DAA_Q := DAA_Q + 6; - end if; - -- new Ahigh > 9 or C = 1 - if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then - DAA_Q := DAA_Q + 96; -- 0x60 end if; else - -- After subtraction - if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then - if DAA_Q(3 downto 0) > 5 then - F_Out(Flag_H) <= '0'; + F_Out(Flag_H) <= F_In(Flag_H); + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if (DAA_Q(3 downto 0) > 9) then + F_Out(Flag_H) <= '1'; + else + F_Out(Flag_H) <= '0'; + end if; + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if DAA_Q(3 downto 0) > 5 then + F_Out(Flag_H) <= '0'; + end if; + DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; + end if; + if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 352; -- 0x160 end if; - DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; - end if; - if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then - DAA_Q := DAA_Q - 352; -- 0x160 end if; end if; F_Out(Flag_X) <= DAA_Q(3); @@ -297,11 +327,11 @@ begin F_Out(Flag_H) <= '1'; F_Out(Flag_N) <= '0'; if IR(2 downto 0) = "110" or XY_State /= "00" then - F_Out(Flag_X) <= WZ(11); - F_Out(Flag_Y) <= WZ(13); - else - F_Out(Flag_X) <= BusB(3); - F_Out(Flag_Y) <= BusB(5); + F_Out(Flag_X) <= WZ(11); + F_Out(Flag_Y) <= WZ(13); + else + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); end if; when "1010" => -- SET @@ -368,6 +398,9 @@ begin F_Out(Flag_S) <= F_In(Flag_S); F_Out(Flag_Z) <= F_In(Flag_Z); end if; + if Mode = 3 and Rot_Akku = '1' then + F_Out(Flag_Z) <= '0'; + end if; when others => null; end case; diff --git a/rtl/T80/T80_MCode.vhd b/rtl/T80/T80_MCode.vhd index 7d4bbc3..554ec9b 100644 --- a/rtl/T80/T80_MCode.vhd +++ b/rtl/T80/T80_MCode.vhd @@ -1,13 +1,13 @@ -------------------------------------------------------------------------------- --- **** --- T80(c) core. Attempt to finish all undocumented features and provide --- accurate timings. --- Version 350. --- Copyright (c) 2018 Sorgelig --- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr --- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as --- correct implementation is still unclear. --- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- -- **** -- T80(b) core. In an effort to merge and maintain bug fixes .... -- @@ -19,7 +19,7 @@ -- **** -- Z80 compatible microprocessor core -- --- Version : 0242 +-- Version : 0250 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- All rights reserved -- @@ -69,11 +69,13 @@ -- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes -- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR -- 0242 : Fixed I/O instruction timing, cleanup +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +use work.T80_Pack.all; entity T80_MCode is generic( @@ -108,6 +110,7 @@ entity T80_MCode is ALU_Op : out std_logic_vector(3 downto 0); -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None Save_ALU : out std_logic; + Rot_Akku : out std_logic; PreserveC : out std_logic; Arith16 : out std_logic; Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI @@ -120,11 +123,14 @@ entity T80_MCode is LDZ : out std_logic; LDW : out std_logic; LDSPHL : out std_logic; + LDHLSP : out std_logic; + ADDSPdd : out std_logic; Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None ExchangeDH : out std_logic; ExchangeRp : out std_logic; ExchangeAF : out std_logic; ExchangeRS : out std_logic; + ExchangeWH : out std_logic; I_DJNZ : out std_logic; I_CPL : out std_logic; I_CCF : out std_logic; @@ -135,28 +141,24 @@ entity T80_MCode is I_BTR : out std_logic; I_RLD : out std_logic; I_RRD : out std_logic; - I_INRC : out std_logic; + I_INRC : out std_logic; + I_MULUB : out std_logic; + I_MULU : out std_logic; SetWZ : out std_logic_vector(1 downto 0); SetDI : out std_logic; SetEI : out std_logic; IMode : out std_logic_vector(1 downto 0); Halt : out std_logic; NoRead : out std_logic; - Write : out std_logic; + Write : out std_logic; + R800_mode : in std_logic; + No_PC : out std_logic; XYbit_undoc : out std_logic ); end T80_MCode; architecture rtl of T80_MCode is - constant aNone : std_logic_vector(2 downto 0) := "111"; - constant aBC : std_logic_vector(2 downto 0) := "000"; - constant aDE : std_logic_vector(2 downto 0) := "001"; - constant aXY : std_logic_vector(2 downto 0) := "010"; - constant aIOA : std_logic_vector(2 downto 0) := "100"; - constant aSP : std_logic_vector(2 downto 0) := "101"; - constant aZI : std_logic_vector(2 downto 0) := "110"; - function is_cc_true( F : std_logic_vector(7 downto 0); cc : bit_vector(2 downto 0) @@ -164,10 +166,10 @@ architecture rtl of T80_MCode is begin if Mode = 3 then case cc is - when "000" => return F(Flag_S) = '0'; -- NZ - when "001" => return F(Flag_S) = '1'; -- Z - when "010" => return F(Flag_H) = '0'; -- NC - when "011" => return F(Flag_H) = '1'; -- C + when "000" => return F(Flag_Z) = '0'; -- NZ + when "001" => return F(Flag_Z) = '1'; -- Z + when "010" => return F(Flag_C) = '0'; -- NC + when "011" => return F(Flag_C) = '1'; -- C when "100" => return false; when "101" => return false; when "110" => return false; @@ -189,7 +191,7 @@ architecture rtl of T80_MCode is begin - process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State) + process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State, R800_mode) variable DDD : std_logic_vector(2 downto 0); variable SSS : std_logic_vector(2 downto 0); variable DPair : std_logic_vector(1 downto 0); @@ -216,6 +218,7 @@ begin Set_BusA_To <= "0000"; ALU_Op <= "0" & IR(5 downto 3); Save_ALU <= '0'; + Rot_Akku <= '0'; PreserveC <= '0'; Arith16 <= '0'; IORQ <= '0'; @@ -228,11 +231,14 @@ begin LDZ <= '0'; LDW <= '0'; LDSPHL <= '0'; + LDHLSP <= '0'; + ADDSPdd <= '0'; Special_LD <= "000"; ExchangeDH <= '0'; ExchangeRp <= '0'; ExchangeAF <= '0'; ExchangeRS <= '0'; + ExchangeWH <= '0'; I_DJNZ <= '0'; I_CPL <= '0'; I_CCF <= '0'; @@ -244,13 +250,16 @@ begin I_RLD <= '0'; I_RRD <= '0'; I_INRC <= '0'; + I_MULUB <= '0'; + I_MULU <= '0'; SetDI <= '0'; SetEI <= '0'; IMode <= "11"; Halt <= '0'; NoRead <= '0'; - Write <= '0'; - XYbit_undoc <= '0'; + Write <= '0'; + No_PC <= '0'; + XYbit_undoc <= '0'; SetWZ <= "00"; case ISet is @@ -376,7 +385,7 @@ begin when 1 => Set_Addr_To <= aBC; Set_BusB_To <= "0111"; - SetWZ <= "10"; + SetWZ <= "10"; when 2 => Write <= '1'; when others => null; @@ -388,7 +397,7 @@ begin when 1 => Set_Addr_To <= aDE; Set_BusB_To <= "0111"; - SetWZ <= "10"; + SetWZ <= "10"; when 2 => Write <= '1'; when others => null; @@ -414,7 +423,7 @@ begin Inc_PC <= '1'; LDZ <= '1'; when 3 => - Set_Addr_To <= aZI; + Set_Addr_To <= aZI; SetWZ <= "10"; Inc_PC <= '1'; Set_BusB_To <= "0111"; @@ -520,38 +529,76 @@ begin end if; when "11111001" => -- LD SP,HL - TStates <= "110"; - LDSPHL <= '1'; + if Mode = 3 then + MCycles <= "010"; + if MCycle = "010" then + LDSPHL <= '1'; + end if; + else + TStates <= "110"; + LDSPHL <= '1'; + end if; when "11000101"|"11010101"|"11100101"|"11110101" => -- PUSH qq - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_TO <= aSP; - if DPAIR = "11" then - Set_BusB_To <= "0111"; - else - Set_BusB_To(2 downto 1) <= DPAIR; - Set_BusB_To(0) <= '0'; - Set_BusB_To(3) <= '0'; - end if; - when 2 => - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - if DPAIR = "11" then - Set_BusB_To <= "1011"; - else - Set_BusB_To(2 downto 1) <= DPAIR; - Set_BusB_To(0) <= '1'; - Set_BusB_To(3) <= '0'; - end if; - Write <= '1'; - when 3 => - Write <= '1'; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 3 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 4 => + Write <= '1'; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 2 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; when "11000001"|"11010001"|"11100001"|"11110001" => -- POP qq MCycles <= "011"; @@ -615,7 +662,7 @@ begin when "11011001" => if Mode = 3 then -- RETI - MCycles <= "011"; + MCycles <= "100"; case to_integer(unsigned(MCycle)) is when 1 => Set_Addr_TO <= aSP; @@ -626,7 +673,7 @@ begin when 3 => Jump <= '1'; IncDec_16 <= "0111"; - I_RETN <= '1'; + --I_RETN <= '1'; SetEI <= '1'; when others => null; end case; @@ -642,24 +689,21 @@ begin when 1 => Set_Addr_To <= aSP; when 2 => - Read_To_Reg <= '1'; - Set_BusA_To <= "0101"; - Set_BusB_To <= "0101"; - Set_Addr_To <= aSP; - LDZ <= '1'; - when 3 => - IncDec_16 <= "0111"; Set_Addr_To <= aSP; + LDZ <= '1'; + IncDec_16 <= "0111"; -- SP <= SP+1 + when 3 => TStates <= "100"; - Write <= '1'; - when 4 => - Read_To_Reg <= '1'; - Set_BusA_To <= "0100"; Set_BusB_To <= "0100"; Set_Addr_To <= aSP; - LDW <= '1'; + LDW <= '1'; + when 4 => + Set_BusB_To <= "0101"; + Write <= '1'; + IncDec_16 <= "1111"; -- SP <= SP-1 + Set_Addr_To <= aSP; when 5 => - IncDec_16 <= "1111"; + ExchangeWH <= '1'; -- save WZ to HL TStates <= "101"; Write <= '1'; when others => null; @@ -806,42 +850,60 @@ begin Set_Addr_To <= aSP; Set_BusB_To <= "1101"; when 2 => - TStates <= "100"; Write <= '1'; IncDec_16 <= "1111"; Set_Addr_To <= aSP; Set_BusB_To <= "1100"; when 3 => - TStates <= "100"; Write <= '1'; when others => null; end case; elsif IntCycle = '1' then -- INT (IM 2) - MCycles <= "101"; - case to_integer(unsigned(MCycle)) is - when 1 => - LDZ <= '1'; - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1101"; - when 2 => - --TStates <= "100"; - Write <= '1'; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1100"; - when 3 => - --TStates <= "100"; - Write <= '1'; - when 4 => - Inc_PC <= '1'; - LDZ <= '1'; - when 5 => - Jump <= '1'; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "110"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + when 3 => -- GB: interrupt is acknowledged on MCycle 3 + LDZ <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 4 => + Write <= '1'; + when others => null; + end case; + else + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + --TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + --TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + end if; else -- NOP end if; @@ -858,49 +920,108 @@ begin -- 16 BIT ARITHMETIC GROUP when "00001001"|"00011001"|"00101001"|"00111001" => -- ADD HL,ss - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 2 => - NoRead <= '1'; - ALU_Op <= "0000"; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - Set_BusA_To(2 downto 0) <= "101"; - case to_integer(unsigned(IR(5 downto 4))) is - when 0|1|2 => - Set_BusB_To(2 downto 1) <= IR(5 downto 4); - Set_BusB_To(0) <= '1'; + if Mode = 3 then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + SetWZ <= "11"; + when 2 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; when others => - Set_BusB_To <= "1000"; end case; - TStates <= "100"; - Arith16 <= '1'; - SetWZ <= "11"; - when 3 => - NoRead <= '1'; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - ALU_Op <= "0001"; - Set_BusA_To(2 downto 0) <= "100"; - case to_integer(unsigned(IR(5 downto 4))) is - when 0|1|2 => - Set_BusB_To(2 downto 1) <= IR(5 downto 4); + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + No_PC <= '1'; + when 2 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + SetWZ <= "11"; + No_PC <= '1'; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; when others => - Set_BusB_To <= "1001"; end case; - Arith16 <= '1'; - when others => - end case; + end if; when "00000011"|"00010011"|"00100011"|"00110011" => -- INC ss - TStates <= "110"; - IncDec_16(3 downto 2) <= "01"; - IncDec_16(1 downto 0) <= DPair; + if Mode = 3 then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + when others => + end case; + else + TStates <= "110"; + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + end if; when "00001011"|"00011011"|"00101011"|"00111011" => -- DEC ss - TStates <= "110"; - IncDec_16(3 downto 2) <= "11"; - IncDec_16(1 downto 0) <= DPair; + if Mode = 3 then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + when others => + end case; + else + TStates <= "110"; + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + end if; -- ROTATE AND SHIFT GROUP when "00000111" @@ -914,12 +1035,17 @@ begin Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1000"; Read_To_Reg <= '1'; + Rot_Akku <= '1'; Save_ALU <= '1'; -- JUMP GROUP when "11000011" => -- JP nn - MCycles <= "011"; + if Mode = 3 then + MCycles <= "100"; + else + MCycles <= "011"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; @@ -927,7 +1053,9 @@ begin when 3 => Inc_PC <= '1'; Jump <= '1'; - LDW <= '1'; + if Mode /= 3 then + LDW <= '1'; + end if; when others => null; end case; when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => @@ -940,9 +1068,9 @@ begin when 1 => Set_Addr_To <= aBC; Set_BusB_To <= "0111"; + IORQ <= '1'; --TH must be earlier to be stable when address is generated when 2 => Write <= '1'; - IORQ <= '1'; when others => end case; when "01" => @@ -966,9 +1094,9 @@ begin case to_integer(unsigned(MCycle)) is when 1 => Set_Addr_To <= aBC; + IORQ <= '1'; --TH must be earlier to be stable when address is generated when 2 => Read_To_Acc <= '1'; - IORQ <= '1'; when others => end case; when "11" => @@ -988,16 +1116,24 @@ begin end case; else -- JP cc,nn - MCycles <= "011"; + if Mode = 3 then + MCycles <= "100"; + else + MCycles <= "011"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; LDZ <= '1'; when 3 => - LDW <= '1'; + if Mode /= 3 then + LDW <= '1'; + end if; Inc_PC <= '1'; if is_cc_true(F, to_bitvector(IR(5 downto 3))) then Jump <= '1'; + elsif Mode = 3 then + MCycles <= "011"; end if; when others => null; end case; @@ -1009,6 +1145,7 @@ begin case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; + No_PC <= '1'; when 3 => NoRead <= '1'; JumpE <= '1'; @@ -1025,6 +1162,8 @@ begin Inc_PC <= '1'; if F(Flag_C) = '0' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1042,6 +1181,8 @@ begin Inc_PC <= '1'; if F(Flag_C) = '1' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1059,6 +1200,8 @@ begin Inc_PC <= '1'; if F(Flag_Z) = '0' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1076,6 +1219,8 @@ begin Inc_PC <= '1'; if F(Flag_Z) = '1' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1087,9 +1232,15 @@ begin when "11101001" => -- JP (HL) JumpXY <= '1'; - when "00010000" => - if Mode = 3 then + when "00010000" => + if Mode = 3 then -- STOP and skip next byte + MCycles <= "010"; I_DJNZ <= '1'; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + when others => null; + end case; elsif Mode < 2 then -- DJNZ,e MCycles <= "011"; @@ -1105,6 +1256,7 @@ begin when 2 => I_DJNZ <= '1'; Inc_PC <= '1'; + No_PC <= '1'; when 3 => NoRead <= '1'; JumpE <= '1'; @@ -1116,7 +1268,11 @@ begin -- CALL AND RETURN GROUP when "11001101" => -- CALL nn - MCycles <= "101"; + if Mode = 3 then + MCycles <= "110"; + else + MCycles <= "101"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; @@ -1141,7 +1297,11 @@ begin when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" => if IR(5) = '0' or Mode /= 3 then -- CALL cc,nn - MCycles <= "101"; + if Mode = 3 then + MCycles <= "110"; + else + MCycles <= "101"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; @@ -1170,20 +1330,36 @@ begin end if; when "11001001" => -- RET - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - --TStates <= "101"; - Set_Addr_TO <= aSP; - when 2 => - IncDec_16 <= "0111"; - Set_Addr_To <= aSP; - LDZ <= '1'; - when 3 => - Jump <= '1'; - IncDec_16 <= "0111"; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Set_Addr_TO <= aSP; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 4 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + --TStates <= "101"; + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" => if IR(5) = '1' and Mode = 3 then case IRB(4 downto 3) is @@ -1201,22 +1377,11 @@ begin end case; when "01" => -- ADD SP,n - MCycles <= "011"; + MCycles <= "100"; case to_integer(unsigned(MCycle)) is - when 2 => - ALU_Op <= "0000"; - Inc_PC <= '1'; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - Set_BusA_To <= "1000"; - Set_BusB_To <= "0110"; when 3 => - NoRead <= '1'; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - ALU_Op <= "0001"; - Set_BusA_To <= "1001"; - Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + Inc_PC <= '1'; + ADDSPdd <= '1'; when others => end case; when "10" => @@ -1231,67 +1396,100 @@ begin when others => null; end case; when "11" => - -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! - MCycles <= "101"; + -- LD HL,SP+n + MCycles <= "011"; case to_integer(unsigned(MCycle)) is + when 1 => + Inc_PC <= '1'; when 2 => + LDHLSP <= '1'; Inc_PC <= '1'; - LDZ <= '1'; when 3 => - Set_Addr_To <= aZI; - Inc_PC <= '1'; - LDW <= '1'; - when 4 => - Set_BusA_To(2 downto 0) <= "101"; -- L - Read_To_Reg <= '1'; - Inc_WZ <= '1'; - Set_Addr_To <= aZI; - when 5 => - Set_BusA_To(2 downto 0) <= "100"; -- H - Read_To_Reg <= '1'; + LDHLSP <= '1'; when others => null; end case; end case; else -- RET cc - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - if is_cc_true(F, to_bitvector(IR(5 downto 3))) then - Set_Addr_TO <= aSP; - else - MCycles <= "001"; - end if; - TStates <= "101"; - when 2 => - IncDec_16 <= "0111"; - Set_Addr_To <= aSP; - LDZ <= '1'; - when 3 => - Jump <= '1'; - IncDec_16 <= "0111"; - when others => null; - end case; + if Mode = 3 then + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "010"; + end if; + TStates <= "101"; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 4 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "001"; + end if; + TStates <= "101"; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; end if; when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" => -- RST p - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1101"; - when 2 => - Write <= '1'; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1100"; - when 3 => - Write <= '1'; - RstP <= '1'; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 3 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 4 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + end if; -- INPUT AND OUTPUT GROUP when "11011011" => @@ -1591,16 +1789,16 @@ begin | "10101100"|"10101101"|"10101110"|"10101111" | "10110100"|"10110101"|"10110110"|"10110111" | "10111100"|"10111101"|"10111110"|"10111111" - |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" - |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" - |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" - |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11000000"| "11000010" |"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"| "11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"| "11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"| "11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" - |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11110000"|"11110001"|"11110010" |"11110100"|"11110101"|"11110110"|"11110111" |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => null; -- NOP, undocumented - when "01111110"|"01111111" => + when "01110111"|"01111111" => -- NOP, undocumented null; -- 8 BIT LOAD GROUP @@ -1686,7 +1884,7 @@ begin when others => null; end case; when "10100000" | "10101000" | "10110000" | "10111000" => - -- LDI, LDD, LDIR, LDDR + -- LDI, LDD, LDIR, LDDR MCycles <= "100"; case to_integer(unsigned(MCycle)) is when 1 => @@ -1711,6 +1909,7 @@ begin else IncDec_16 <= "1101"; end if; + No_PC <= '1'; when 4 => NoRead <= '1'; TStates <= "101"; @@ -1734,10 +1933,12 @@ begin else IncDec_16 <= "1110"; end if; + No_PC <= '1'; when 3 => NoRead <= '1'; I_BC <= '1'; TStates <= "101"; + No_PC <= '1'; when 4 => NoRead <= '1'; TStates <= "101"; @@ -1756,7 +1957,7 @@ begin when "01010110"|"01110110" => -- IM 1 IMode <= "01"; - when "01011110"|"01110111" => + when "01011110"|"01111110" => -- IM 2 IMode <= "10"; -- 16 bit arithmetic @@ -1764,6 +1965,8 @@ begin -- ADC HL,ss MCycles <= "011"; case to_integer(unsigned(MCycle)) is + when 1 => + No_PC <= '1'; when 2 => NoRead <= '1'; ALU_Op <= "0001"; @@ -1778,7 +1981,8 @@ begin Set_BusB_To <= "1000"; end case; TStates <= "100"; - SetWZ <= "11"; + SetWZ <= "11"; + No_PC <= '1'; when 3 => NoRead <= '1'; Read_To_Reg <= '1'; @@ -1798,6 +2002,8 @@ begin -- SBC HL,ss MCycles <= "011"; case to_integer(unsigned(MCycle)) is + when 1 => + No_PC <= '1'; when 2 => NoRead <= '1'; ALU_Op <= "0011"; @@ -1812,7 +2018,8 @@ begin Set_BusB_To <= "1000"; end case; TStates <= "100"; - SetWZ <= "11"; + SetWZ <= "11"; + No_PC <= '1'; when 3 => NoRead <= '1'; ALU_Op <= "0011"; @@ -1839,6 +2046,7 @@ begin Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1101"; Save_ALU <= '1'; + No_PC <= '1'; when 3 => TStates <= "100"; I_RLD <= '1'; @@ -1860,6 +2068,7 @@ begin Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1110"; Save_ALU <= '1'; + No_PC <= '1'; when 3 => TStates <= "100"; I_RRD <= '1'; @@ -1881,8 +2090,8 @@ begin LDZ <= '1'; when 3 => Jump <= '1'; - IncDec_16 <= "0111"; - LDW <= '1'; + IncDec_16 <= "0111"; + LDW <= '1'; I_RETN <= '1'; when others => null; end case; @@ -1891,7 +2100,7 @@ begin MCycles <= "010"; case to_integer(unsigned(MCycle)) is when 1 => - Set_Addr_To <= aBC; + Set_Addr_To <= aBC; SetWZ <= "01"; when 2 => IORQ <= '1'; @@ -1909,7 +2118,7 @@ begin case to_integer(unsigned(MCycle)) is when 1 => Set_Addr_To <= aBC; - SetWZ <= "01"; + SetWZ <= "01"; Set_BusB_To(2 downto 0) <= IR(5 downto 3); if IR(5 downto 3) = "110" then Set_BusB_To(3) <= '1'; @@ -1930,9 +2139,9 @@ begin Set_BusA_To <= "0000"; Read_To_Reg <= '1'; Save_ALU <= '1'; - ALU_Op <= "0010"; + ALU_Op <= "0010"; SetWZ <= "11"; - IncDec_16(3) <= IR(3); + IncDec_16(3) <= IR(3); when 2 => IORQ <= '1'; Set_BusB_To <= "0110"; @@ -1965,8 +2174,8 @@ begin when 2 => Set_BusB_To <= "0110"; Set_Addr_To <= aBC; - SetWZ <= "11"; - IncDec_16(3) <= IR(3); + SetWZ <= "11"; + IncDec_16(3) <= IR(3); when 3 => if IR(3) = '0' then IncDec_16 <= "0110"; @@ -1981,6 +2190,46 @@ begin TStates <= "101"; when others => null; end case; + when "11000001"|"11001001"|"11010001"|"11011001" => + --R800 MULUB + if R800_mode = '1' then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + I_MULUB <= '1'; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + Set_BusB_To(3) <= '0'; + when 2 => + NoRead <= '1'; + I_MULU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + when others => null; + end case; + end if; + when "11000011"|"11110011" => + --R800 MULUW + if R800_mode = '1' then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + if DPAIR = "11" then + Set_BusB_To(3 downto 0) <= "1000"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + Set_BusA_To(2 downto 0) <= "100"; + when 2 => + TStates <= "101"; + NoRead <= '1'; + I_MULU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + when others => null; + end case; + end if; end case; end case; @@ -2013,6 +2262,9 @@ begin if IRB = "00110110" or IRB = "11001011" then Set_Addr_To <= aNone; end if; + if not (IRB = "00110110" or ISet = "01") then + No_PC <= '1'; + end if; end if; if MCycle = "111" then if Mode = 0 then diff --git a/rtl/T80/T80_Pack.vhd b/rtl/T80/T80_Pack.vhd new file mode 100644 index 0000000..3ac1522 --- /dev/null +++ b/rtl/T80/T80_Pack.vhd @@ -0,0 +1,248 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010 +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0250 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- 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/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T80_Pack is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + component T80 + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + 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; + IORQ : out std_logic; + NoRead : out std_logic; + Write : 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); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic; + R800_mode : in std_logic := '0'; + out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + ); + end component; + + component T80_Reg + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0); + DOR : out std_logic_vector(127 downto 0); + DIRSet : in std_logic; + DIR : in std_logic_vector(127 downto 0) + ); + end component; + + component T80_MCode + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + XY_State : in std_logic_vector(1 downto 0); + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + Rot_Akku : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + LDHLSP : out std_logic; + ADDSPdd : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + ExchangeWH : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + I_MULUB : out std_logic; + I_MULU : out std_logic; + SetWZ : out std_logic_vector(1 downto 0); + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + R800_mode : in std_logic; + No_PC : out std_logic; + XYbit_undoc : out std_logic + ); + end component; + + component T80_ALU + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + WZ : in std_logic_vector(15 downto 0); + XY_State : in std_logic_vector(1 downto 0); + ALU_Op : in std_logic_vector(3 downto 0); + Rot_Akku : in std_logic; + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/rtl/T80/T80_Reg.vhd b/rtl/T80/T80_Reg.vhd index 3d0c5a9..e7e8645 100644 --- a/rtl/T80/T80_Reg.vhd +++ b/rtl/T80/T80_Reg.vhd @@ -1,13 +1,13 @@ --------------------------------------------------------------------------------- --- **** --- T80(c) core. Attempt to finish all undocumented features and provide --- accurate timings. --- Version 350. --- Copyright (c) 2018 Sorgelig --- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr --- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as --- correct implementation is still unclear. --- +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- -- **** -- T80(b) core. In an effort to merge and maintain bug fixes .... -- @@ -89,7 +89,9 @@ entity T80_Reg is DOBL : out std_logic_vector(7 downto 0); DOCH : out std_logic_vector(7 downto 0); DOCL : out std_logic_vector(7 downto 0); - DOR : out std_logic_vector(127 downto 0) + DOR : out std_logic_vector(127 downto 0); + DIRSet : in std_logic; + DIR : in std_logic_vector(127 downto 0) ); end T80_Reg; @@ -104,7 +106,31 @@ begin process (Clk) begin if rising_edge(Clk) then - if CEN = '1' then + if DIRSet = '1' then + RegsL(0) <= DIR( 7 downto 0); + RegsH(0) <= DIR( 15 downto 8); + + RegsL(1) <= DIR( 23 downto 16); + RegsH(1) <= DIR( 31 downto 24); + + RegsL(2) <= DIR( 39 downto 32); + RegsH(2) <= DIR( 47 downto 40); + + RegsL(3) <= DIR( 55 downto 48); + RegsH(3) <= DIR( 63 downto 56); + + RegsL(4) <= DIR( 71 downto 64); + RegsH(4) <= DIR( 79 downto 72); + + RegsL(5) <= DIR( 87 downto 80); + RegsH(5) <= DIR( 95 downto 88); + + RegsL(6) <= DIR(103 downto 96); + RegsH(6) <= DIR(111 downto 104); + + RegsL(7) <= DIR(119 downto 112); + RegsH(7) <= DIR(127 downto 120); + elsif CEN = '1' then if WEH = '1' then RegsH(to_integer(unsigned(AddrA))) <= DIH; end if; diff --git a/rtl/T80/T80a.vhd b/rtl/T80/T80a.vhd new file mode 100644 index 0000000..468b690 --- /dev/null +++ b/rtl/T80/T80a.vhd @@ -0,0 +1,342 @@ +-- **** +-- 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 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- 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/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed interrupt cycle +-- +-- 0235 : Updated for T80 interface change +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : 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 +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +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 + ); + port( + RESET_n : in std_logic; + R800_mode : 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; + A : out std_logic_vector(15 downto 0); + D : inout std_logic_vector(7 downto 0) + ); +end T80a; + +architecture rtl of T80a is + + signal CEN : std_logic; + signal Reset_s : std_logic; + signal IntCycle_n : std_logic; + signal IORQ : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal MREQ : std_logic; + signal MReq_Inhibit : std_logic; + 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 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 Wait_s : std_logic; + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + CEN <= '1'; + + 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 + + MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; + IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; + RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; + WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z'; + 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'); + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + Reset_s <= '0'; + elsif CLK_n'event and CLK_n = '1' then + Reset_s <= '1'; + end if; + end process; + + u0 : T80 + generic map( + Mode => Mode, + IOWait => IOWait) + port map( + R800_mode => R800_mode, + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n_i, + HALT_n => HALT_n, + WAIT_n => Wait_s, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => Reset_s, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n_i, + CLK_n => CLK_n, + A => A_i, + DInst => D, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (CLK_n) + begin + if CLK_n'event and CLK_n = '0' then + Wait_s <= WAIT_n; + if TState = "011" and BUSAK_n_i = '1' then + DI_Reg <= to_x01(D); + end if; + end if; + end process; + +-- 30/10/19 Charlie Ingley - Generate WR_t2 to correct MREQ/WR timing + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then + WR_t2 <= '0'; + elsif CLK_n'event and CLK_n = '0' then + if MCycle /= "001" then + if TState = "010" then -- WR starts on falling edge of T2 for MREQ + WR_t2 <= Write; + end if; + end if; + if TState = "011" then -- end WR + WR_t2 <= '0'; + 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 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 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 + elsif CLK_n'event and CLK_n = '0' then + if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n + MReq_Inhibit <= '0'; + else + MReq_Inhibit <= '1'; + end if; + end if; + end process; + +-- Generate RD for MREQ + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + RD <= '0'; + MREQ <= '0'; + elsif CLK_n'event and CLK_n = '0' then + if MCycle = "001" then + if TState = "001" then + RD <= IntCycle_n; + MREQ <= IntCycle_n; + end if; + if TState = "011" then + RD <= '0'; + MREQ <= '1'; + end if; + if TState = "100" then + MREQ <= '0'; + end if; + else + if TState = "001" and NoRead = '0' then + RD <= not Write; + MREQ <= not IORQ; + end if; + if TState = "011" then + RD <= '0'; + MREQ <= '0'; + end if; + end if; + 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 MCycle = "001" then + if TState = "001" then + IORQ_int <= not IntCycle_n; + end if; + if TState = "010" and Wait_s = '1' then + IORQ_int <= '0'; + 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 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 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 TState = "001" then + IORQ_t1 <= not IntCycle_n; + end if; + if TState = "011" then + IORQ_t1 <= '1'; + 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 + IORQ_t2 <= IORQ_t1; + end if; + end process; + +end; diff --git a/rtl/T80/T80as.vhd b/rtl/T80/T80as.vhd new file mode 100644 index 0000000..9a34c64 --- /dev/null +++ b/rtl/T80/T80as.vhd @@ -0,0 +1,289 @@ +------------------------------------------------------------------------------ +-- 2004.10.18 WR_n active was changed from T2 to T3. +-- modification by Katsumi Degawa +------------------------------------------------------------------------------ +-- t80as.vhd : The non-tristate signal edition of t80a.vhd +-- +-- 2003.2.7 non-tristate modification by Tatsuyuki Satoh +-- +-- 1.separate 'D' to 'DO' and 'DI'. +-- 2.added 'DOE' to 'DO' enable signal.(data direction) +-- 3.MREQ_n,IORQ_n,RD_n,WR_n,RFSH_n,A doesn't become the condition of 'Z'. +-- +-- There is a mark of "--AS" in all the change points. +-- +------------------------------------------------------------------------------ + +-- +-- Z80 compatible microprocessor core, asynchronous top level +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- 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/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed interrupt cycle +-- +-- 0235 : Updated for T80 interface change +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- +-- 0247 : Fixed bus req/ack cycle +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80as is + generic( + Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); + port( + 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; + A : out std_logic_vector(15 downto 0); +--AS-- D : inout std_logic_vector(7 downto 0) +--AS>> + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + DOE : out std_logic +--< 'Z'); +--AS-- D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); +--AS>> + MREQ_n <= MREQ_n_i; + IORQ_n <= IORQ_n_i; + RD_n <= RD_n_i; + WR_n <= WR_n_i; + RFSH_n <= RFSH_n_i; + A <= A_i; + DOE <= Write when BUSAK_n_i = '1' else '0'; +--< Mode, + IOWait => 1) + port map( + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n_i, + HALT_n => HALT_n, + WAIT_n => Wait_s, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => Reset_s, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n_i, + CLK_n => CLK_n, + A => A_i, +-- DInst => D, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (CLK_n) + begin + if CLK_n'event and CLK_n = '0' then + Wait_s <= WAIT_n; + if TState = "011" and BUSAK_n_i = '1' then +--AS-- DI_Reg <= to_x01(D); +--AS>> + DI_Reg <= to_x01(DI); +--< Z80, 1 => Fast Z80, 2 => 8080, 3 => GB - ); - port( - RESET_n : in std_logic; - CLK : in std_logic; - CEN_p : in std_logic := '1'; - CEN_n : in std_logic := '1'; - WAIT_n : in std_logic := '1'; - INT_n : in std_logic := '1'; - NMI_n : in std_logic := '1'; - BUSRQ_n : in std_logic := '1'; - 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; - OUT0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 - A : out std_logic_vector(15 downto 0); - DI : in std_logic_vector(7 downto 0); - DO : out std_logic_vector(7 downto 0); - REG : out std_logic_vector(207 downto 0) -- IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A - ); -end T80pa; - -architecture rtl of T80pa is - - signal IntCycle_n : std_logic; - signal IntCycleD_n : std_logic_vector(1 downto 0); - signal IORQ : std_logic; - signal NoRead : std_logic; - signal Write : std_logic; - signal BUSAK : std_logic; - signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser - signal MCycle : std_logic_vector(2 downto 0); - signal TState : std_logic_vector(2 downto 0); - signal CEN_pol : std_logic; - signal A_int : std_logic_vector(15 downto 0); - signal A_last : std_logic_vector(15 downto 0); - -begin - - A <= A_int when NoRead = '0' or Write = '1' else A_last; - - BUSAK_n <= BUSAK; - - u0 : work.T80 - generic map( - Mode => Mode, - IOWait => 1 - ) - port map( - CEN => CEN_p and not CEN_pol, - M1_n => M1_n, - IORQ => IORQ, - NoRead => NoRead, - Write => Write, - RFSH_n => RFSH_n, - HALT_n => HALT_n, - WAIT_n => '1', - INT_n => INT_n, - NMI_n => NMI_n, - RESET_n => RESET_n, - BUSRQ_n => BUSRQ_n, - BUSAK_n => BUSAK, - CLK_n => CLK, - A => A_int, - DInst => DI, -- valid at beginning of T3 - DI => DI_Reg, -- latched at middle of T3 - DO => DO, - REG => REG, - MC => MCycle, - TS => TState, - OUT0 => OUT0, - IntCycle_n => IntCycle_n - ); - - process(CLK) - begin - if rising_edge(CLK) then - if RESET_n = '0' then - WR_n <= '1'; - RD_n <= '1'; - IORQ_n <= '1'; - MREQ_n <= '1'; - DI_Reg <= "00000000"; - CEN_pol <= '0'; - elsif CEN_p = '1' and CEN_pol = '0' then - CEN_pol <= '1'; - if MCycle = "001" then - if TState = "010" then - IORQ_n <= '1'; - MREQ_n <= '1'; - RD_n <= '1'; - end if; - else - if TState = "001" and IORQ = '1' then - WR_n <= not Write; - RD_n <= Write; - IORQ_n <= '0'; - end if; - end if; - elsif CEN_n = '1' and CEN_pol = '1' then - if TState = "010" then - CEN_pol <= not WAIT_n; - else - CEN_pol <= '0'; - end if; - if TState = "011" and BUSAK = '1' then - DI_Reg <= DI; - end if; - if MCycle = "001" then - if TState = "001" then - IntCycleD_n <= IntCycleD_n(0) & IntCycle_n; - RD_n <= not IntCycle_n; - MREQ_n <= not IntCycle_n; - IORQ_n <= IntCycleD_n(1); - A_last <= A_int; - end if; - if TState = "011" then - IntCycleD_n <= "11"; - RD_n <= '1'; - MREQ_n <= '0'; - end if; - if TState = "100" then - MREQ_n <= '1'; - end if; - else - if NoRead = '0' and IORQ = '0' then - if TState = "001" then - RD_n <= Write; - MREQ_n <= '0'; - A_last <= A_int; - end if; - end if; - if TState = "010" then - WR_n <= not Write; - end if; - if TState = "011" then - WR_n <= '1'; - RD_n <= '1'; - IORQ_n <= '1'; - MREQ_n <= '1'; - end if; - end if; - end if; - end if; - end process; -end; +-- v2.4: Use the fixed WAIT_n in T80.vhd +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80pa is + generic( + Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); + port( + RESET_n : in std_logic; + CLK : in std_logic; + CEN_p : in std_logic := '1'; + CEN_n : in std_logic := '1'; + WAIT_n : in std_logic := '1'; + INT_n : in std_logic := '1'; + NMI_n : in std_logic := '1'; + BUSRQ_n : in std_logic := '1'; + 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; + OUT0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + A : out std_logic_vector(15 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + R800_mode : in std_logic := '0'; + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + ); +end T80pa; + +architecture rtl of T80pa is + + signal IntCycle_n : std_logic; + signal IntCycleD_n : std_logic_vector(1 downto 0); + signal IORQ : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal BUSAK : std_logic; + signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + signal CEN_pol : std_logic; + signal CEN : std_logic; + signal Wait_s : std_logic; +begin + + CEN <= CEN_p and not CEN_pol; + BUSAK_n <= BUSAK; + + u0 : T80 + generic map( + Mode => Mode, + IOWait => 1 + ) + port map( + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + WAIT_n => Wait_s, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK, + CLK_n => CLK, + A => A, + DInst => DI, -- valid at beginning of T3 + DI => DI_Reg, -- latched at middle of T3 + DO => DO, + REG => REG, + MC => MCycle, + TS => TState, + OUT0 => OUT0, + R800_mode => R800_mode, + IntCycle_n => IntCycle_n, + DIRSet => DIRSet, + DIR => DIR + ); + + process(CLK) + begin + if rising_edge(CLK) then + if RESET_n = '0' then + WR_n <= '1'; + RD_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + CEN_pol <= '0'; + elsif CEN_p = '1' and CEN_pol = '0' then + CEN_pol <= '1'; + if WAIT_s = '1' or TState /= "010" then + if MCycle = "001" then + if TState = "010" then + IORQ_n <= '1'; + MREQ_n <= '1'; + RD_n <= '1'; + end if; + else + if TState = "001" and IORQ = '1' then + WR_n <= not Write; + RD_n <= Write; + IORQ_n <= '0'; + end if; + end if; + end if; + elsif CEN_n = '1' and CEN_pol = '1' then + Wait_s <= Wait_n; + CEN_pol <= '0'; + if TState = "011" and BUSAK = '1' then + DI_Reg <= DI; + end if; + if MCycle = "001" then + if TState = "001" then + IntCycleD_n <= IntCycleD_n(0) & IntCycle_n; + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + IORQ_n <= IntCycleD_n(1); + end if; + if TState = "011" then + IntCycleD_n <= "11"; + RD_n <= '1'; + MREQ_n <= '0'; + end if; + if TState = "100" then + MREQ_n <= '1'; + end if; + else + if NoRead = '0' and IORQ = '0' then + if TState = "001" then + RD_n <= Write; + MREQ_n <= '0'; + end if; + end if; + if TState = "010" then + WR_n <= not Write; + end if; + if TState = "011" then + WR_n <= '1'; + RD_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + end if; + end if; + end if; + end if; + end process; +end; diff --git a/rtl/T80/T80s.vhd b/rtl/T80/T80s.vhd index 8c82f69..6967292 100644 --- a/rtl/T80/T80s.vhd +++ b/rtl/T80/T80s.vhd @@ -69,6 +69,7 @@ library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use IEEE.STD_LOGIC_UNSIGNED.all; +use work.T80_Pack.all; entity T80s is generic( @@ -111,7 +112,7 @@ architecture rtl of T80s is begin - u0 : work.T80 + u0 : T80 generic map( Mode => Mode, IOWait => IOWait) diff --git a/rtl/T80/T80se.vhd b/rtl/T80/T80se.vhd new file mode 100644 index 0000000..1b0cb9b --- /dev/null +++ b/rtl/T80/T80se.vhd @@ -0,0 +1,192 @@ +-- **** +-- 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, synchronous top level with clock enable +-- Different timing than the original z80 +-- Inputs needs to be synchronous and outputs may glitch +-- +-- Version : 0240 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- 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/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0235 : First release +-- +-- 0236 : Added T2Write generic +-- +-- 0237 : Fixed T2Write with wait state +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80se is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 + IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CLKEN : 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); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T80se; + +architecture rtl of T80se is + + signal IntCycle_n : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal IORQ : std_logic; + signal DI_Reg : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + u0 : T80 + generic map( + Mode => Mode, + IOWait => IOWait) + port map( + CEN => CLKEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + WAIT_n => Wait_n, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n, + CLK_n => CLK_n, + A => A, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + elsif CLK_n'event and CLK_n = '1' then + if CLKEN = '1' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + if MCycle = "001" then + if TState = "001" or (TState = "010" and Wait_n = '0') then + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + IORQ_n <= IntCycle_n; + end if; + if TState = "011" then + MREQ_n <= '0'; + end if; + else + if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then + RD_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + if T2Write = 0 then + if TState = "010" and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + else + if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + end if; + end if; + if TState = "010" and Wait_n = '1' then + DI_Reg <= DI; + end if; + end if; + end if; + end process; + +end; diff --git a/rtl/T80/T80sed.vhd b/rtl/T80/T80sed.vhd new file mode 100644 index 0000000..0c28ec2 --- /dev/null +++ b/rtl/T80/T80sed.vhd @@ -0,0 +1,179 @@ +-- **** +-- 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) +-- +-- **** +-- ** CUSTOM 2 CLOCK MEMORY ACCESS FOR PACMAN, MIKEJ ** +-- +-- Z80 compatible microprocessor core, synchronous top level with clock enable +-- Different timing than the original z80 +-- Inputs needs to be synchronous and outputs may glitch +-- +-- Version : 0238 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- 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/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0235 : First release +-- +-- 0236 : Added T2Write generic +-- +-- 0237 : Fixed T2Write with wait state +-- +-- 0238 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80sed is + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CLKEN : 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); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T80sed; + +architecture rtl of T80sed is + + signal IntCycle_n : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal IORQ : std_logic; + signal DI_Reg : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + u0 : T80 + generic map( + Mode => 0, + IOWait => 1) + port map( + CEN => CLKEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + WAIT_n => Wait_n, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n, + CLK_n => CLK_n, + A => A, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + elsif CLK_n'event and CLK_n = '1' then + if CLKEN = '1' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + if MCycle = "001" then + if TState = "001" or (TState = "010" and Wait_n = '0') then + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + IORQ_n <= IntCycle_n; + end if; + if TState = "011" then + MREQ_n <= '0'; + end if; + else + if (TState = "001" or TState = "010") and NoRead = '0' and Write = '0' then + RD_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + if ((TState = "001") or (TState = "010")) and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + end if; + if TState = "010" and Wait_n = '1' then + DI_Reg <= DI; + end if; + end if; + end if; + end process; + +end;