From 75557d8fd39ef385c53111f9e516a17e1552d89f Mon Sep 17 00:00:00 2001 From: sorgelig Date: Tue, 21 Aug 2018 23:21:12 +0800 Subject: [PATCH] T80: Sync with latest version. --- TSConf-lite.qsf | 7 +- TSConf.sv | 4 +- src/sound/gs.v | 9 +- src/t80/T80.qip | 7 + src/t80/T80.vhd | 768 ++++++++++++++++++++++-------------------- src/t80/T8080se.vhd | 185 ---------- src/t80/T80_ALU.vhd | 133 +++++--- src/t80/T80_MCode.vhd | 326 +++++++++--------- src/t80/T80_Pack.vhd | 152 +++++---- src/t80/T80_Reg.vhd | 57 +++- src/t80/T80a.vhd | 268 --------------- src/t80/T80pa.vhd | 211 ++++++++++++ src/t80/T80s.vhd | 23 +- src/t80/T80se.vhd | 200 ----------- src/tsconf.v | 30 +- 15 files changed, 1002 insertions(+), 1378 deletions(-) create mode 100644 src/t80/T80.qip delete mode 100644 src/t80/T8080se.vhd delete mode 100644 src/t80/T80a.vhd create mode 100644 src/t80/T80pa.vhd delete mode 100644 src/t80/T80se.vhd diff --git a/TSConf-lite.qsf b/TSConf-lite.qsf index 0153fbb..904fb9b 100644 --- a/TSConf-lite.qsf +++ b/TSConf-lite.qsf @@ -355,12 +355,7 @@ set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl" set_global_assignment -name CDF_FILE jtag.cdf set_global_assignment -name QIP_FILE sys/sys.qip -set_global_assignment -name VHDL_FILE src/t80/T80_Reg.vhd -set_global_assignment -name VHDL_FILE src/t80/T80_Pack.vhd -set_global_assignment -name VHDL_FILE src/t80/T80_MCode.vhd -set_global_assignment -name VHDL_FILE src/t80/T80_ALU.vhd -set_global_assignment -name VHDL_FILE src/t80/T80.vhd -set_global_assignment -name VHDL_FILE src/t80/T80s.vhd +set_global_assignment -name QIP_FILE src/t80/T80.qip set_global_assignment -name VERILOG_FILE src/cpu/zsignals.v set_global_assignment -name VERILOG_FILE src/cpu/zports.v set_global_assignment -name VERILOG_FILE src/cpu/zmem.v diff --git a/TSConf.sv b/TSConf.sv index e8568c0..a5dd447 100644 --- a/TSConf.sv +++ b/TSConf.sv @@ -119,7 +119,7 @@ localparam CONF_STR = { "O8,CPU Cache,On,Off;", "O9A,#7FFD span,128K,128K Auto,1024K,512K;", "OLN,ZX Palette,Default,B.black,Light,Pale,Dark,Grayscale,Custom;", - "OPR,INT Offset,2,3,4,5,6,7,0,1;", + "OPR,INT Offset,3,4,5,6,7,0,1,2;", "-;", "OBD,F11 Reset,boot.$C,sys.rom,ROM;", "OEF, bank,TR-DOS,Basic 48,Basic 128,SYS;", @@ -144,7 +144,7 @@ assign CMOSCfg[18:16]= (status[18:16]) ? status[18:16] + 3'd2 : 3'd0; assign CMOSCfg[20:19]= status[20:19] + 2'd2; assign CMOSCfg[23:21]= status[23:21]; assign CMOSCfg[24] = 0; -assign CMOSCfg[27:25]= status[27:25] + 3'd2; +assign CMOSCfg[27:25]= status[27:25] + 3'd3; //////////////////// CLOCKS /////////////////// diff --git a/src/sound/gs.v b/src/sound/gs.v index 52fefe5..bbf09c9 100644 --- a/src/sound/gs.v +++ b/src/sound/gs.v @@ -103,15 +103,12 @@ wire cpu_wr_n; wire [15:0] cpu_a_bus; wire [7:0] cpu_do_bus; -T80s cpu +T80pa cpu ( .RESET_n(~RESET), - .CLK_n(CLK), - .CEN(CE & ~MEM_WAIT), - .WAIT_n(1), + .CLK(CLK), + .CEN_p(CE & ~MEM_WAIT), .INT_n(int_n), - .NMI_n(1), - .BUSRQ_n(1), .M1_n(cpu_m1_n), .MREQ_n(cpu_mreq_n), .IORQ_n(cpu_iorq_n), diff --git a/src/t80/T80.qip b/src/t80/T80.qip new file mode 100644 index 0000000..1c5d369 --- /dev/null +++ b/src/t80/T80.qip @@ -0,0 +1,7 @@ +set_global_assignment -name VHDL_FILE src/t80/T80_Reg.vhd +set_global_assignment -name VHDL_FILE src/t80/T80_Pack.vhd +set_global_assignment -name VHDL_FILE src/t80/T80_MCode.vhd +set_global_assignment -name VHDL_FILE src/t80/T80_ALU.vhd +set_global_assignment -name VHDL_FILE src/t80/T80.vhd +set_global_assignment -name VHDL_FILE src/t80/T80pa.vhd +set_global_assignment -name VHDL_FILE src/t80/T80s.vhd diff --git a/src/t80/T80.vhd b/src/t80/T80.vhd index 3335d96..e6db89f 100644 --- a/src/t80/T80.vhd +++ b/src/t80/T80.vhd @@ -1,10 +1,28 @@ +-------------------------------------------------------------------------------- +-- **** +-- 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 .... -- +-- 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 : 0247 --- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) --- -- All rights reserved -- -- Redistribution and use in source and synthezised forms, with or without @@ -38,44 +56,35 @@ -- you have the latest version of this file. -- -- The latest version of this file can be found at: --- http://www.opencores.org/cvsweb.shtml/t80/ +-- http://www.opencores.org/cvsweb.shtml/t80/ -- -- Limitations : -- -- File history : -- --- 0208 : First complete release --- --- 0210 : Fixed wait and halt --- --- 0211 : Fixed Refresh addition and IM 1 --- --- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test --- --- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson --- --- 0235 : Added clock enable and IM 2 fix by Mike Johnson --- --- 0237 : Changed 8080 I/O address output, added IntE output --- --- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag --- --- 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 +-- 0208 : First complete release +-- 0210 : Fixed wait and halt +-- 0211 : Fixed Refresh addition and IM 1 +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson +-- 0235 : Added clock enable and IM 2 fix by Mike Johnson +-- 0237 : Changed 8080 I/O address output, added IntE output +-- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag +-- 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 -- 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; -- 1 => Single cycle I/O, 1 => Std I/O cycle + 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 Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; @@ -86,172 +95,173 @@ entity T80 is 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; - - SavePC : out std_logic_vector(15 downto 0); - SaveINT : out std_logic_vector(7 downto 0); - RestorePC : in std_logic_vector(15 downto 0); - RestoreINT : in std_logic_vector(7 downto 0); - - RestorePC_n : in std_logic + 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; + 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 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"; + 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); - signal I : std_logic_vector(7 downto 0); - signal R : unsigned(7 downto 0); - signal SP, PC : unsigned(15 downto 0); - signal RegDIH : std_logic_vector(7 downto 0); - signal RegDIL : std_logic_vector(7 downto 0); - signal RegBusA : std_logic_vector(15 downto 0); - signal RegBusB : std_logic_vector(15 downto 0); - signal RegBusC : std_logic_vector(15 downto 0); - signal RegAddrA_r : std_logic_vector(2 downto 0); - signal RegAddrA : std_logic_vector(2 downto 0); - signal RegAddrB_r : std_logic_vector(2 downto 0); - signal RegAddrB : std_logic_vector(2 downto 0); - signal RegAddrC : std_logic_vector(2 downto 0); - signal RegWEH : std_logic; - signal RegWEL : std_logic; - signal Alternate : std_logic; + signal ACC, F : std_logic_vector(7 downto 0); + signal Ap, Fp : std_logic_vector(7 downto 0); + signal I : std_logic_vector(7 downto 0); + signal R : unsigned(7 downto 0); + signal SP, PC : unsigned(15 downto 0); + + signal RegDIH : std_logic_vector(7 downto 0); + signal RegDIL : std_logic_vector(7 downto 0); + signal RegBusA : std_logic_vector(15 downto 0); + signal RegBusB : std_logic_vector(15 downto 0); + signal RegBusC : std_logic_vector(15 downto 0); + signal RegAddrA_r : std_logic_vector(2 downto 0); + signal RegAddrA : std_logic_vector(2 downto 0); + signal RegAddrB_r : std_logic_vector(2 downto 0); + signal RegAddrB : std_logic_vector(2 downto 0); + signal RegAddrC : std_logic_vector(2 downto 0); + signal RegWEH : std_logic; + signal RegWEL : std_logic; + signal Alternate : std_logic; -- Help Registers - signal TmpAddr : 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 WZ : std_logic_vector(15 downto 0); -- MEMPTR 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 ID16 : signed(15 downto 0); - signal Save_Mux : std_logic_vector(7 downto 0); + signal ID16 : signed(15 downto 0); + signal Save_Mux : std_logic_vector(7 downto 0); - signal TState : unsigned(2 downto 0); - signal MCycle : std_logic_vector(2 downto 0); - 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 ClkEn : std_logic; - signal NMI_s : std_logic; - signal INT_s : std_logic; - signal IStatus : std_logic_vector(1 downto 0); + signal TState : unsigned(2 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + 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 ClkEn : std_logic; + signal NMI_s : std_logic; + signal IStatus : std_logic_vector(1 downto 0); - signal DI_Reg : std_logic_vector(7 downto 0); - signal T_Res : std_logic; - signal XY_State : std_logic_vector(1 downto 0); - signal Pre_XY_F_M : std_logic_vector(2 downto 0); - signal NextIs_XY_Fetch : std_logic; - signal XY_Ind : std_logic; - signal No_BTR : std_logic; - signal BTR_r : std_logic; - signal Auto_Wait : std_logic; - signal Auto_Wait_t1 : std_logic; - signal Auto_Wait_t2 : std_logic; - signal IncDecZ : std_logic; + signal DI_Reg : std_logic_vector(7 downto 0); + signal T_Res : std_logic; + signal XY_State : std_logic_vector(1 downto 0); + signal Pre_XY_F_M : std_logic_vector(2 downto 0); + signal NextIs_XY_Fetch : std_logic; + signal XY_Ind : std_logic; + signal No_BTR : std_logic; + signal BTR_r : std_logic; + signal Auto_Wait : std_logic; + signal Auto_Wait_t1 : std_logic; + signal Auto_Wait_t2 : std_logic; + signal IncDecZ : std_logic; -- ALU signals - signal BusB : std_logic_vector(7 downto 0); - signal BusA : std_logic_vector(7 downto 0); - signal ALU_Q : std_logic_vector(7 downto 0); - signal F_Out : std_logic_vector(7 downto 0); + signal BusB : std_logic_vector(7 downto 0); + signal BusA : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal F_Out : std_logic_vector(7 downto 0); -- Registered micro code outputs - signal Read_To_Reg_r : std_logic_vector(4 downto 0); - signal Arith16_r : std_logic; - signal Z16_r : std_logic; - signal ALU_Op_r : std_logic_vector(3 downto 0); - signal Save_ALU_r : std_logic; - signal PreserveC_r : std_logic; - signal MCycles : std_logic_vector(2 downto 0); + signal Read_To_Reg_r : std_logic_vector(4 downto 0); + signal Arith16_r : std_logic; + signal Z16_r : std_logic; + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Save_ALU_r : std_logic; + signal PreserveC_r : std_logic; + signal MCycles : std_logic_vector(2 downto 0); -- Micro code outputs - signal MCycles_d : std_logic_vector(2 downto 0); - signal TStates : std_logic_vector(2 downto 0); - signal IntCycle : std_logic; - signal NMICycle : std_logic; - signal Inc_PC : std_logic; - signal Inc_WZ : std_logic; - signal IncDec_16 : std_logic_vector(3 downto 0); - signal Prefix : std_logic_vector(1 downto 0); - signal Read_To_Acc : std_logic; - signal Read_To_Reg : std_logic; - signal Set_BusB_To : std_logic_vector(3 downto 0); - 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 PreserveC : std_logic; - signal Arith16 : std_logic; - signal Set_Addr_To : std_logic_vector(2 downto 0); - signal Jump : std_logic; - signal JumpE : std_logic; - signal JumpXY : std_logic; - signal Call : std_logic; - signal RstP : std_logic; - signal LDZ : std_logic; - signal LDW : std_logic; - signal LDSPHL : std_logic; - signal IORQ_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 I_DJNZ : std_logic; - signal I_CPL : std_logic; - signal I_CCF : std_logic; - signal I_SCF : std_logic; - signal I_RETN : std_logic; - signal I_BT : std_logic; - signal I_BC : std_logic; - signal I_BTR : std_logic; - signal I_RLD : std_logic; - signal I_RRD : std_logic; - signal I_INRC : std_logic; - 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 MCycles_d : std_logic_vector(2 downto 0); + signal TStates : std_logic_vector(2 downto 0); + signal IntCycle : std_logic; + signal NMICycle : std_logic; + signal Inc_PC : std_logic; + signal Inc_WZ : std_logic; + signal IncDec_16 : std_logic_vector(3 downto 0); + signal Prefix : std_logic_vector(1 downto 0); + signal Read_To_Acc : std_logic; + signal Read_To_Reg : std_logic; + signal Set_BusB_To : std_logic_vector(3 downto 0); + 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 PreserveC : std_logic; + signal Arith16 : std_logic; + signal Set_Addr_To : std_logic_vector(2 downto 0); + signal Jump : std_logic; + signal JumpE : std_logic; + signal JumpXY : std_logic; + signal Call : std_logic; + signal RstP : std_logic; + signal LDZ : std_logic; + signal LDW : std_logic; + signal LDSPHL : std_logic; + signal IORQ_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 I_DJNZ : std_logic; + signal I_CPL : std_logic; + signal I_CCF : std_logic; + signal I_SCF : std_logic; + signal I_RETN : std_logic; + signal I_BT : std_logic; + signal I_BC : std_logic; + signal I_BTR : std_logic; + signal I_RLD : std_logic; + signal I_RRD : std_logic; + signal I_RXDD : std_logic; + signal I_INRC : 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 DOR : std_logic_vector(127 downto 0); 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) & + std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC; + mcode : T80_MCode generic map( - Mode => Mode, + Mode => Mode, Flag_C => Flag_C, Flag_N => Flag_N, Flag_P => Flag_P, @@ -261,64 +271,65 @@ begin Flag_Z => Flag_Z, Flag_S => Flag_S) port map( - IR => IR, - ISet => ISet, - MCycle => MCycle, - F => F, - NMICycle => NMICycle, - IntCycle => IntCycle, - XY_State => XY_State, - MCycles => MCycles_d, - TStates => TStates, - Prefix => Prefix, - Inc_PC => Inc_PC, - Inc_WZ => Inc_WZ, - IncDec_16 => IncDec_16, + IR => IR, + ISet => ISet, + MCycle => MCycle, + F => F, + NMICycle => NMICycle, + IntCycle => IntCycle, + XY_State => XY_State, + MCycles => MCycles_d, + TStates => TStates, + Prefix => Prefix, + Inc_PC => Inc_PC, + Inc_WZ => Inc_WZ, + IncDec_16 => IncDec_16, Read_To_Acc => Read_To_Acc, Read_To_Reg => Read_To_Reg, Set_BusB_To => Set_BusB_To, Set_BusA_To => Set_BusA_To, - ALU_Op => ALU_Op, - Save_ALU => Save_ALU, - PreserveC => PreserveC, - Arith16 => Arith16, + ALU_Op => ALU_Op, + Save_ALU => Save_ALU, + PreserveC => PreserveC, + Arith16 => Arith16, Set_Addr_To => Set_Addr_To, - IORQ => IORQ_i, - Jump => Jump, - JumpE => JumpE, - JumpXY => JumpXY, - Call => Call, - RstP => RstP, - LDZ => LDZ, - LDW => LDW, - LDSPHL => LDSPHL, - Special_LD => Special_LD, - ExchangeDH => ExchangeDH, - ExchangeRp => ExchangeRp, - ExchangeAF => ExchangeAF, - ExchangeRS => ExchangeRS, - I_DJNZ => I_DJNZ, - I_CPL => I_CPL, - I_CCF => I_CCF, - I_SCF => I_SCF, - I_RETN => I_RETN, - I_BT => I_BT, - I_BC => I_BC, - I_BTR => I_BTR, - I_RLD => I_RLD, - I_RRD => I_RRD, - I_INRC => I_INRC, - SetDI => SetDI, - SetEI => SetEI, - IMode => IMode, - Halt => Halt, - NoRead => NoRead, - Write => Write, + IORQ => IORQ_i, + Jump => Jump, + JumpE => JumpE, + JumpXY => JumpXY, + Call => Call, + RstP => RstP, + LDZ => LDZ, + LDW => LDW, + LDSPHL => LDSPHL, + Special_LD => Special_LD, + ExchangeDH => ExchangeDH, + ExchangeRp => ExchangeRp, + ExchangeAF => ExchangeAF, + ExchangeRS => ExchangeRS, + I_DJNZ => I_DJNZ, + I_CPL => I_CPL, + I_CCF => I_CCF, + I_SCF => I_SCF, + I_RETN => I_RETN, + I_BT => I_BT, + I_BC => I_BC, + I_BTR => I_BTR, + I_RLD => I_RLD, + I_RRD => I_RRD, + I_INRC => I_INRC, + SetWZ => SetWZ, + SetDI => SetDI, + SetEI => SetEI, + IMode => IMode, + Halt => Halt, + NoRead => NoRead, + Write => Write, XYbit_undoc => XYbit_undoc); alu : T80_ALU generic map( - Mode => Mode, + Mode => Mode, Flag_C => Flag_C, Flag_N => Flag_N, Flag_P => Flag_P, @@ -329,15 +340,17 @@ begin Flag_S => Flag_S) port map( Arith16 => Arith16_r, - Z16 => Z16_r, - ALU_Op => ALU_Op_r, - IR => IR(5 downto 0), - ISet => ISet, - BusA => BusA, - BusB => BusB, - F_In => F, - Q => ALU_Q, - F_Out => F_Out); + Z16 => Z16_r, + WZ => WZ, + XY_State=> XY_State, + ALU_Op => ALU_Op_r, + IR => IR(5 downto 0), + ISet => ISet, + BusA => BusA, + BusB => BusB, + F_In => F, + Q => ALU_Q, + F_Out => F_Out); ClkEn <= CEN and not BusAck; @@ -352,47 +365,44 @@ begin DI_Reg when Save_ALU_r = '0' else ALU_Q; - process (RESET_n, RestorePC_n, CLK_n) + process (RESET_n, CLK_n) + variable n : std_logic_vector(7 downto 0); + variable ioq : std_logic_vector(8 downto 0); begin - - if CLK_n'event and CLK_n = '1' then + if RESET_n = '0' then + PC <= (others => '0'); -- Program Counter + A <= (others => '0'); + WZ <= (others => '0'); + IR <= "00000000"; + ISet <= "00"; + XY_State <= "00"; + IStatus <= "00"; + MCycles <= "000"; + DO <= "00000000"; - if RESET_n = '0' then - PC <= (others => '0'); -- Program Counter - A <= (others => '0'); - TmpAddr <= (others => '0'); - IR <= "00000000"; - ISet <= "00"; - XY_State <= "00"; - IStatus <= "00"; - MCycles <= "000"; - DO <= "00000000"; + ACC <= (others => '1'); + F <= (others => '1'); + Ap <= (others => '1'); + Fp <= (others => '1'); + I <= (others => '0'); + R <= (others => '0'); + SP <= (others => '1'); + Alternate <= '0'; - ACC <= (others => '1'); - F <= (others => '1'); - Ap <= (others => '1'); - Fp <= (others => '1'); - I <= (others => '0'); - R <= (others => '0'); - SP <= (others => '1'); - Alternate <= '0'; + Read_To_Reg_r <= "00000"; + F <= (others => '1'); + Arith16_r <= '0'; + BTR_r <= '0'; + Z16_r <= '0'; + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + PreserveC_r <= '0'; + XY_Ind <= '0'; + I_RXDD <= '0'; - Read_To_Reg_r <= "00000"; - F <= (others => '1'); - Arith16_r <= '0'; - BTR_r <= '0'; - Z16_r <= '0'; - ALU_Op_r <= "0000"; - Save_ALU_r <= '0'; - PreserveC_r <= '0'; - XY_Ind <= '0'; + elsif rising_edge(CLK_n) then - elsif RestorePC_n = '0' then - PC <= unsigned( RestorePC ); - A <= RestorePC; - IStatus <= RestoreInt(1 downto 0); - - elsif ClkEn = '1' then + if ClkEn = '1' then ALU_Op_r <= "0000"; Save_ALU_r <= '0'; @@ -469,23 +479,23 @@ begin 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) <= TmpAddr(7 downto 0); + A(7 downto 0) <= WZ(7 downto 0); PC(15 downto 8) <= unsigned(DI_Reg); - PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + 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 <= TmpAddr; - PC <= unsigned(TmpAddr); + 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) <= TmpAddr(7 downto 0); + A(7 downto 0) <= WZ(7 downto 0); PC(15 downto 8) <= unsigned(I); - PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); else case Set_Addr_To is when aXY => @@ -495,7 +505,7 @@ begin if NextIs_XY_Fetch = '1' then A <= std_logic_vector(PC); else - A <= TmpAddr; + A <= WZ; end if; end if; when aIOA => @@ -509,6 +519,7 @@ begin 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 => @@ -518,20 +529,39 @@ begin 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 = "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(TmpAddr) + 1); + A <= std_logic_vector(unsigned(WZ) + 1); else A(15 downto 8) <= DI_Reg; - A(7 downto 0) <= TmpAddr(7 downto 0); + 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 => A <= std_logic_vector(PC); 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; @@ -561,6 +591,15 @@ begin 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 @@ -568,6 +607,7 @@ begin 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; @@ -575,12 +615,18 @@ begin PC <= PC - 2; end if; if RstP = '1' then - TmpAddr <= (others =>'0'); - TmpAddr(5 downto 3) <= IR(5 downto 3); + WZ <= (others =>'0'); + WZ(5 downto 3) <= IR(5 downto 3); end if; end if; if TState = 3 and MCycle = "110" then - TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + 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 @@ -609,10 +655,10 @@ begin if TState = 3 then if LDZ = '1' then - TmpAddr(7 downto 0) <= DI_Reg; + WZ(7 downto 0) <= DI_Reg; end if; if LDW = '1' then - TmpAddr(15 downto 8) <= DI_Reg; + WZ(15 downto 8) <= DI_Reg; end if; if Special_LD(2) = '1' then @@ -628,6 +674,12 @@ begin 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; @@ -639,6 +691,11 @@ begin 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 => @@ -665,6 +722,8 @@ begin 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 @@ -676,7 +735,11 @@ begin end if; if TState = 1 and Auto_Wait_t1 = '0' then - DO <= BusB; + -- 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); @@ -702,6 +765,11 @@ begin 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; @@ -739,7 +807,7 @@ begin --------------------------------------------------------------------------- process (CLK_n) begin - if CLK_n'event and CLK_n = '1' then + if rising_edge(CLK_n) then if ClkEn = '1' then -- Bus A / Write RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); @@ -781,10 +849,10 @@ begin RegAddrA <= -- 16 bit increment/decrement - XY_State(1) & "11" when (TState = 2 or - (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" and XY_State /= "00" else Alternate & IncDec_16(1 downto 0) when (TState = 2 or - (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) else + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else + XY_State(1) & "11" when (TState = 2 or + (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 @@ -867,7 +935,8 @@ begin DOBH => RegBusB(15 downto 8), DOBL => RegBusB(7 downto 0), DOCH => RegBusC(15 downto 8), - DOCL => RegBusC(7 downto 0)); + DOCL => RegBusC(7 downto 0), + DOR => DOR); --------------------------------------------------------------------------- -- @@ -876,7 +945,7 @@ begin --------------------------------------------------------------------------- process (CLK_n) begin - if CLK_n'event and CLK_n = '1' then + if rising_edge(CLK_n) then if ClkEn = '1' then case Set_BusB_To is when "0111" => @@ -925,7 +994,7 @@ begin when "1010" => BusA <= "00000000"; when others => - BusB <= "--------"; + BusA <= "--------"; end case; if XYbit_undoc='1' then BusA <= DI_Reg; @@ -942,16 +1011,15 @@ begin --------------------------------------------------------------------------- process (RESET_n,CLK_n) begin - if CLK_n'event and CLK_n = '1' then - if RESET_n = '0' then + 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'; - - elsif 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 if; end process; @@ -966,86 +1034,46 @@ begin IORQ <= IORQ_i; Stop <= I_DJNZ; - SavePC <= std_logic_vector( PC ); - SaveINT <= "0000" & IntE_FF2 & IntE_FF1 & IStatus when MCycle = "001" and TState = "001" and Prefix = "00" and IntCycle = '0' and NMICycle = '0' else - "1111" & IntE_FF2 & IntE_FF1 & IStatus; - -------------------------------------------------------------------------- --- --- Syncronise inputs --- -------------------------------------------------------------------------- - process (RESET_n, CLK_n) - variable OldNMI_n : std_logic; - begin - if CLK_n'event and CLK_n = '1' then - - if RESET_n = '0' then - BusReq_s <= '0'; - INT_s <= '0'; - NMI_s <= '0'; - OldNMI_n := '0'; - - elsif CEN = '1' then - BusReq_s <= not BUSRQ_n; - INT_s <= not INT_n; - if NMICycle = '1' then - NMI_s <= '0'; - elsif NMI_n = '0' and OldNMI_n = '1' then - NMI_s <= '1'; - end if; - OldNMI_n := NMI_n; - end if; - - end if; - end process; - ------------------------------------------------------------------------- -- -- Main state machine -- ------------------------------------------------------------------------- - process (RESET_n, RestorePC_n, CLK_n) + process (RESET_n, CLK_n) + variable OldNMI_n : std_logic; begin - - if CLK_n'event and CLK_n = '1' then - if RESET_n = '0' then - MCycle <= "001"; - TState <= "000"; - Pre_XY_F_M <= "000"; - Halt_FF <= '0'; - BusAck <= '0'; - NMICycle <= '0'; - IntCycle <= '0'; - IntE_FF1 <= '0'; - IntE_FF2 <= '0'; - No_BTR <= '0'; - Auto_Wait_t1 <= '0'; - Auto_Wait_t2 <= '0'; - M1_n <= '1'; + if RESET_n = '0' then + MCycle <= "001"; + TState <= "000"; + Pre_XY_F_M <= "000"; + Halt_FF <= '0'; + BusAck <= '0'; + NMICycle <= '0'; + IntCycle <= '0'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + No_BTR <= '0'; + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + M1_n <= '1'; + BusReq_s <= '0'; + NMI_s <= '0'; + elsif rising_edge(CLK_n) then - elsif RestorePC_n = '0' then - MCycle <= "001"; - TState <= "001"; - NMICycle <= '0'; - IntCycle <= '0'; - IntE_FF1 <= RestoreINT(2); - IntE_FF2 <= RestoreINT(3); - - Pre_XY_F_M <= "000"; - Halt_FF <= '0'; - BusAck <= '0'; - No_BTR <= '0'; - Auto_Wait_t1 <= '0'; - Auto_Wait_t2 <= '0'; - - elsif CEN = '1' 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; end if; - Auto_Wait_t2 <= Auto_Wait_t1; 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))); @@ -1082,32 +1110,28 @@ begin 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 = MCycles) or - No_BTR = '1' or - (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') or - ( MCycle = "111" and MCycles= "001" and Pre_XY_F_M = "001" ) then + 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 + if NMI_s = '1' and Prefix = "00" then + NMI_s <= '0'; NMICycle <= '1'; IntE_FF1 <= '0'; - elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then + 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; - elsif (MCycle = "111") or - (MCycle = "110" and Mode = 1 and ISet /= "01") then - MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); else MCycle <= std_logic_vector(unsigned(MCycle) + 1); end if; diff --git a/src/t80/T8080se.vhd b/src/t80/T8080se.vhd deleted file mode 100644 index 2b6d28f..0000000 --- a/src/t80/T8080se.vhd +++ /dev/null @@ -1,185 +0,0 @@ --- --- 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/src/t80/T80_ALU.vhd b/src/t80/T80_ALU.vhd index 86fddce..3e881ee 100644 --- a/src/t80/T80_ALU.vhd +++ b/src/t80/T80_ALU.vhd @@ -1,10 +1,26 @@ +-------------------------------------------------------------------------------- +-- **** +-- 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 .... -- +-- 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 : 0247 --- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) --- -- All rights reserved -- -- Redistribution and use in source and synthezised forms, with or without @@ -38,21 +54,17 @@ -- you have the latest version of this file. -- -- The latest version of this file can be found at: --- http://www.opencores.org/cvsweb.shtml/t80/ +-- http://www.opencores.org/cvsweb.shtml/t80/ -- -- Limitations : -- -- File history : -- --- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test --- --- 0238 : Fixed zero flag for 16 bit SBC and ADC --- --- 0240 : Added GB operations --- --- 0242 : Cleanup --- --- 0247 : Cleanup +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- 0238 : Fixed zero flag for 16 bit SBC and ADC +-- 0240 : Added GB operations +-- 0242 : Cleanup +-- 0247 : Cleanup -- library IEEE; @@ -72,68 +84,81 @@ entity T80_ALU is Flag_S : integer := 7 ); port( - Arith16 : in std_logic; - Z16 : in std_logic; - ALU_Op : in std_logic_vector(3 downto 0); - 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) + 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); + 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 T80_ALU; architecture rtl of T80_ALU is - procedure AddSub(A : std_logic_vector; - B : std_logic_vector; - Sub : std_logic; - Carry_In : std_logic; - signal Res : out std_logic_vector; - signal Carry : out std_logic) is - variable B_i : unsigned(A'length - 1 downto 0); - variable Res_i : unsigned(A'length + 1 downto 0); + procedure AddSub(A : std_logic_vector; + B : std_logic_vector; + Sub : std_logic; + Carry_In : std_logic; + signal Res : out std_logic_vector; + signal Carry : out std_logic) is + + variable B_i : unsigned(A'length - 1 downto 0); + variable Res_i : unsigned(A'length + 1 downto 0); begin if Sub = '1' then B_i := not unsigned(B); else - B_i := unsigned(B); + B_i := unsigned(B); end if; + Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1"); Carry <= Res_i(A'length + 1); Res <= std_logic_vector(Res_i(A'length downto 1)); end; -- AddSub variables (temporary signals) - signal UseCarry : std_logic; - signal Carry7_v : std_logic; - signal Overflow_v : std_logic; - signal HalfCarry_v : std_logic; - signal Carry_v : std_logic; - signal Q_v : std_logic_vector(7 downto 0); + signal UseCarry : std_logic; + signal Carry7_v : std_logic; + signal Overflow_v : std_logic; + signal HalfCarry_v : std_logic; + signal Carry_v : std_logic; + signal Q_v : std_logic_vector(7 downto 0); - signal BitMask : std_logic_vector(7 downto 0); + signal BitMask : std_logic_vector(7 downto 0); begin with IR(5 downto 3) select BitMask <= "00000001" when "000", - "00000010" when "001", - "00000100" when "010", - "00001000" when "011", - "00010000" when "100", - "00100000" when "101", - "01000000" when "110", - "10000000" when others; + "00000010" when "001", + "00000100" when "010", + "00001000" when "011", + "00010000" when "100", + "00100000" when "101", + "01000000" when "110", + "10000000" when others; UseCarry <= not ALU_Op(2) and ALU_Op(0); AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v); AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v); AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v); - OverFlow_v <= Carry_v xor Carry7_v; - process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) + -- bug fix - parity flag is just parity for 8080, also overflow for Z80 + process (Carry_v, Carry7_v, Q_v) + begin + if(Mode=2) then + OverFlow_v <= not (Q_v(0) xor Q_v(1) xor Q_v(2) xor Q_v(3) xor + Q_v(4) xor Q_v(5) xor Q_v(6) xor Q_v(7)); else + OverFlow_v <= Carry_v xor Carry7_v; + 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) variable Q_t : std_logic_vector(7 downto 0); variable DAA_Q : unsigned(8 downto 0); begin @@ -176,7 +201,7 @@ begin if Q_t(7 downto 0) = "00000000" then F_Out(Flag_Z) <= '1'; if Z16 = '1' then - F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC + F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC end if; else F_Out(Flag_Z) <= '0'; @@ -271,11 +296,12 @@ begin end if; F_Out(Flag_H) <= '1'; F_Out(Flag_N) <= '0'; - F_Out(Flag_X) <= '0'; - F_Out(Flag_Y) <= '0'; - if IR(2 downto 0) /= "110" then - F_Out(Flag_X) <= BusB(3); - F_Out(Flag_Y) <= BusB(5); + 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); end if; when "1010" => -- SET @@ -347,5 +373,4 @@ begin end case; Q <= Q_t; end process; - end; diff --git a/src/t80/T80_MCode.vhd b/src/t80/T80_MCode.vhd index 36c8b15..6b43ef4 100644 --- a/src/t80/T80_MCode.vhd +++ b/src/t80/T80_MCode.vhd @@ -1,10 +1,26 @@ +-------------------------------------------------------------------------------- +-- **** +-- 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 .... -- +-- 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 : 0242 --- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) --- -- All rights reserved -- -- Redistribution and use in source and synthezised forms, with or without @@ -38,36 +54,31 @@ -- you have the latest version of this file. -- -- The latest version of this file can be found at: --- http://www.opencores.org/cvsweb.shtml/t80/ +-- http://www.opencores.org/cvsweb.shtml/t80/ -- -- Limitations : -- -- File history : -- --- 0208 : First complete release --- --- 0211 : Fixed IM 1 --- --- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test --- --- 0235 : Added IM 2 fix by Mike Johnson --- --- 0238 : Added NoRead signal --- --- 0238b: Fixed instruction timing for POP and DJNZ --- --- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes --- --- 0242 : Fixed I/O instruction timing, cleanup +-- 0208 : First complete release +-- 0211 : Fixed IM 1 +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- 0235 : Added IM 2 fix by Mike Johnson +-- 0238 : Added NoRead signal +-- 0238b: Fixed instruction timing for POP and DJNZ +-- 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 -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +use work.T80_Pack.all; entity T80_MCode is generic( - Mode : integer := 0; + Mode : integer := 0; Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; @@ -78,80 +89,74 @@ entity T80_MCode is 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,CB,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; - 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; - 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; - 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; - 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; - XYbit_undoc : out std_logic - ); + 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,CB,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; + 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; + 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; + 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; + 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; + 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"; --- constant aNone : std_logic_vector(2 downto 0) := "000"; --- constant aXY : std_logic_vector(2 downto 0) := "001"; --- constant aIOA : std_logic_vector(2 downto 0) := "010"; --- constant aSP : std_logic_vector(2 downto 0) := "011"; --- constant aBC : std_logic_vector(2 downto 0) := "100"; --- constant aDE : std_logic_vector(2 downto 0) := "101"; --- constant aZI : std_logic_vector(2 downto 0) := "110"; + 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); @@ -160,10 +165,10 @@ architecture rtl of T80_MCode is begin if Mode = 3 then case cc is - when "000" => return F(7) = '0'; -- NZ - when "001" => return F(7) = '1'; -- Z - when "010" => return F(4) = '0'; -- NC - when "011" => return F(4) = '1'; -- C + 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 "100" => return false; when "101" => return false; when "110" => return false; @@ -171,14 +176,14 @@ architecture rtl of T80_MCode is end case; else case cc is - when "000" => return F(6) = '0'; -- NZ - when "001" => return F(6) = '1'; -- Z - when "010" => return F(0) = '0'; -- NC - when "011" => return F(0) = '1'; -- C - when "100" => return F(2) = '0'; -- PO - when "101" => return F(2) = '1'; -- PE - when "110" => return F(7) = '0'; -- P - when "111" => return F(7) = '1'; -- M + 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 F(Flag_P) = '0'; -- PO + when "101" => return F(Flag_P) = '1'; -- PE + when "110" => return F(Flag_S) = '0'; -- P + when "111" => return F(Flag_S) = '1'; -- M end case; end if; end; @@ -186,10 +191,10 @@ architecture rtl of T80_MCode is begin process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State) - variable DDD : std_logic_vector(2 downto 0); - variable SSS : std_logic_vector(2 downto 0); + variable DDD : std_logic_vector(2 downto 0); + variable SSS : std_logic_vector(2 downto 0); variable DPair : std_logic_vector(1 downto 0); - variable IRB : bit_vector(7 downto 0); + variable IRB : bit_vector(7 downto 0); begin DDD := IR(5 downto 3); SSS := IR(2 downto 0); @@ -245,8 +250,9 @@ begin IMode <= "11"; Halt <= '0'; NoRead <= '0'; - Write <= '0'; - XYbit_undoc <= '0'; + Write <= '0'; + XYbit_undoc <= '0'; + SetWZ <= "00"; case ISet is when "00" => @@ -371,6 +377,7 @@ begin when 1 => Set_Addr_To <= aBC; Set_BusB_To <= "0111"; + SetWZ <= "10"; when 2 => Write <= '1'; when others => null; @@ -382,6 +389,7 @@ begin when 1 => Set_Addr_To <= aDE; Set_BusB_To <= "0111"; + SetWZ <= "10"; when 2 => Write <= '1'; when others => null; @@ -407,7 +415,8 @@ 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"; when 4 => @@ -637,7 +646,8 @@ begin Read_To_Reg <= '1'; Set_BusA_To <= "0101"; Set_BusB_To <= "0101"; - Set_Addr_To <= aSP; + Set_Addr_To <= aSP; + LDZ <= '1'; when 3 => IncDec_16 <= "0111"; Set_Addr_To <= aSP; @@ -648,6 +658,7 @@ begin Set_BusA_To <= "0100"; Set_BusB_To <= "0100"; Set_Addr_To <= aSP; + LDW <= '1'; when 5 => IncDec_16 <= "1111"; TStates <= "101"; @@ -864,7 +875,8 @@ begin Set_BusB_To <= "1000"; end case; TStates <= "100"; - Arith16 <= '1'; + Arith16 <= '1'; + SetWZ <= "11"; when 3 => NoRead <= '1'; Read_To_Reg <= '1'; @@ -916,6 +928,7 @@ begin when 3 => Inc_PC <= '1'; Jump <= '1'; + LDW <= '1'; when others => null; end case; when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => @@ -982,6 +995,7 @@ begin Inc_PC <= '1'; LDZ <= '1'; when 3 => + LDW <= '1'; Inc_PC <= '1'; if is_cc_true(F, to_bitvector(IR(5 downto 3))) then Jump <= '1'; @@ -1363,7 +1377,7 @@ begin -- SRL r -- SLL r (Undocumented) / SWAP r if XY_State="00" then - if MCycle = "001" or MCycle = "111" then + if MCycle = "001" then ALU_Op <= "1000"; Read_To_Reg <= '1'; Save_ALU <= '1'; @@ -1420,7 +1434,7 @@ begin |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => -- BIT b,r if XY_State="00" then - if MCycle = "001" or MCycle = "111" then + if MCycle = "001" then Set_BusB_To(2 downto 0) <= IR(2 downto 0); ALU_Op <= "1001"; end if; @@ -1463,24 +1477,6 @@ begin ALU_Op <= "1010"; Read_To_Reg <= '1'; Save_ALU <= '1'; - else - MCycles <= "100"; - case to_integer(unsigned(MCycle)) is - when 7 => - Set_Addr_To <= aXY; - when 2 => - Set_BusB_To(2 downto 0) <= "110"; - ALU_Op <= "1010"; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - Set_Addr_To <= aXY; - TStates <= "100"; - when 3 => - Set_Addr_To <= aXY; - when 4 => - Write <= '1'; - when others => null; - end case; end if; else -- SET b,(IX+d),Reg, undocumented @@ -1531,24 +1527,6 @@ begin ALU_Op <= "1011"; Read_To_Reg <= '1'; Save_ALU <= '1'; - else - MCycles <= "100"; - case to_integer(unsigned(MCycle)) is - when 7 => - Set_Addr_To <= aXY; - when 2 => - Set_BusB_To(2 downto 0) <= "110"; - ALU_Op <= "1011"; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - Set_Addr_To <= aXY; - TStates <= "100"; - when 3 => - Set_Addr_To <= aXY; - when 4 => - Write <= '1'; - when others => null; - end case; end if; else -- RES b,(IX+d),Reg, undocumented @@ -1709,7 +1687,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 => @@ -1796,11 +1774,12 @@ begin 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(0) <= '1'; + when others => Set_BusB_To <= "1000"; end case; TStates <= "100"; + SetWZ <= "11"; when 3 => NoRead <= '1'; Read_To_Reg <= '1'; @@ -1834,6 +1813,7 @@ begin Set_BusB_To <= "1000"; end case; TStates <= "100"; + SetWZ <= "11"; when 3 => NoRead <= '1'; ALU_Op <= "0011"; @@ -1849,46 +1829,49 @@ begin when others => end case; when "01101111" => - -- RLD + -- RLD -- Read in M2, not M3! fixed by Sorgelig MCycles <= "100"; case to_integer(unsigned(MCycle)) is - when 2 => - NoRead <= '1'; + when 1 => Set_Addr_To <= aXY; - when 3 => + when 2 => Read_To_Reg <= '1'; Set_BusB_To(2 downto 0) <= "110"; Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1101"; - TStates <= "100"; - Set_Addr_To <= aXY; Save_ALU <= '1'; - when 4 => + when 3 => + TStates <= "100"; I_RLD <= '1'; + NoRead <= '1'; + Set_Addr_To <= aXY; + when 4 => Write <= '1'; when others => end case; when "01100111" => - -- RRD + -- RRD -- Read in M2, not M3! fixed by Sorgelig MCycles <= "100"; case to_integer(unsigned(MCycle)) is - when 2 => + when 1 => Set_Addr_To <= aXY; - when 3 => + when 2 => Read_To_Reg <= '1'; Set_BusB_To(2 downto 0) <= "110"; Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1110"; - TStates <= "100"; - Set_Addr_To <= aXY; Save_ALU <= '1'; - when 4 => + when 3 => + TStates <= "100"; I_RRD <= '1'; + NoRead <= '1'; + Set_Addr_To <= aXY; + when 4 => Write <= '1'; when others => end case; when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" => - -- RETI, RETN + -- RETI/RETN MCycles <= "011"; case to_integer(unsigned(MCycle)) is when 1 => @@ -1899,7 +1882,8 @@ begin LDZ <= '1'; when 3 => Jump <= '1'; - IncDec_16 <= "0111"; + IncDec_16 <= "0111"; + LDW <= '1'; I_RETN <= '1'; when others => null; end case; @@ -1908,7 +1892,8 @@ 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'; if IR(5 downto 3) /= "110" then @@ -1925,6 +1910,7 @@ begin case to_integer(unsigned(MCycle)) is when 1 => Set_Addr_To <= aBC; + SetWZ <= "01"; Set_BusB_To(2 downto 0) <= IR(5 downto 3); if IR(5 downto 3) = "110" then Set_BusB_To(3) <= '1'; @@ -1939,12 +1925,15 @@ begin MCycles <= "100"; case to_integer(unsigned(MCycle)) is when 1 => + TStates <= "101"; Set_Addr_To <= aBC; Set_BusB_To <= "1010"; Set_BusA_To <= "0000"; Read_To_Reg <= '1'; Save_ALU <= '1'; - ALU_Op <= "0010"; + ALU_Op <= "0010"; + SetWZ <= "11"; + IncDec_16(3) <= IR(3); when 2 => IORQ <= '1'; Set_BusB_To <= "0110"; @@ -1955,7 +1944,6 @@ begin else IncDec_16 <= "1110"; end if; - TStates <= "100"; Write <= '1'; I_BTR <= '1'; when 4 => @@ -1978,6 +1966,8 @@ begin when 2 => Set_BusB_To <= "0110"; Set_Addr_To <= aBC; + SetWZ <= "11"; + IncDec_16(3) <= IR(3); when 3 => if IR(3) = '0' then IncDec_16 <= "0110"; diff --git a/src/t80/T80_Pack.vhd b/src/t80/T80_Pack.vhd index ca18e3a..7c73e4a 100644 --- a/src/t80/T80_Pack.vhd +++ b/src/t80/T80_Pack.vhd @@ -1,3 +1,23 @@ +-------------------------------------------------------------------------------- +-- **** +-- 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 .... +-- +-- +-- 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 -- @@ -52,8 +72,8 @@ package T80_Pack is 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 + 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 Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; @@ -64,62 +84,57 @@ package T80_Pack is 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; - - SavePC : out std_logic_vector(15 downto 0); - SaveINT : out std_logic_vector(7 downto 0); - RestorePC : in std_logic_vector(15 downto 0); - RestoreINT : in std_logic_vector(7 downto 0); - - RestorePC_n : in std_logic + 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; + 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 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) + 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) ); end component; component T80_MCode generic( - Mode : integer := 0; + Mode : integer := 0; Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; @@ -130,12 +145,12 @@ package T80_Pack is 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; + 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); @@ -145,8 +160,8 @@ package T80_Pack is 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 + 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; @@ -178,6 +193,7 @@ package T80_Pack is I_RLD : out std_logic; I_RRD : out std_logic; I_INRC : 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); @@ -190,7 +206,7 @@ package T80_Pack is component T80_ALU generic( - Mode : integer := 0; + Mode : integer := 0; Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; @@ -201,16 +217,18 @@ package T80_Pack is Flag_S : integer := 7 ); port( - Arith16 : in std_logic; - Z16 : in std_logic; - ALU_Op : in std_logic_vector(3 downto 0); - 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) + 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); + 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; diff --git a/src/t80/T80_Reg.vhd b/src/t80/T80_Reg.vhd index 828485f..3d0c5a9 100644 --- a/src/t80/T80_Reg.vhd +++ b/src/t80/T80_Reg.vhd @@ -1,3 +1,22 @@ +-------------------------------------------------------------------------------- +-- **** +-- 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 .... +-- +-- +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** -- -- T80 Registers, technology independent -- @@ -55,35 +74,36 @@ use IEEE.numeric_std.all; entity T80_Reg is 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) + 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) ); end T80_Reg; architecture rtl of T80_Reg is type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); - signal RegsH : Register_Image(0 to 7); - signal RegsL : Register_Image(0 to 7); + signal RegsH : Register_Image(0 to 7); + signal RegsL : Register_Image(0 to 7); begin process (Clk) begin - if Clk'event and Clk = '1' then + if rising_edge(Clk) then if CEN = '1' then if WEH = '1' then RegsH(to_integer(unsigned(AddrA))) <= DIH; @@ -101,5 +121,6 @@ begin DOBL <= RegsL(to_integer(unsigned(AddrB))); DOCH <= RegsH(to_integer(unsigned(AddrC))); DOCL <= RegsL(to_integer(unsigned(AddrC))); + DOR <= RegsH(7) & RegsL(7) & RegsH(6) & RegsL(6) & RegsH(5) & RegsL(5) & RegsH(4) & RegsL(4) & RegsH(3) & RegsL(3) & RegsH(2) & RegsL(2) & RegsH(1) & RegsL(1) & RegsH(0) & RegsL(0); end; diff --git a/src/t80/T80a.vhd b/src/t80/T80a.vhd deleted file mode 100644 index 414e590..0000000 --- a/src/t80/T80a.vhd +++ /dev/null @@ -1,268 +0,0 @@ --- --- 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 T80a 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); - D : inout std_logic_vector(7 downto 0); - - SavePC : out std_logic_vector(15 downto 0); - SaveINT : out std_logic_vector(7 downto 0); - RestorePC : in std_logic_vector(15 downto 0); - RestoreINT : in std_logic_vector(7 downto 0); - - RestorePC_n : in std_logic - - ); -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 IORQ_n_i : std_logic; - signal RD_n_i : std_logic; - signal WR_n_i : std_logic; - 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; - MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit); - RD_n_i <= not RD or Req_Inhibit; - - 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 => 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, - DI => DI_Reg, - DO => DO, - MC => MCycle, - TS => TState, - IntCycle_n => IntCycle_n, - - SavePC => SavePC, - SaveINT => SaveINT, - RestorePC => RestorePC, - RestoreINT => RestoreINT, - - RestorePC_n => RestorePC_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; - - process (Reset_s,CLK_n) - begin - if Reset_s = '0' then - WR_n_i <= '1'; - elsif CLK_n'event and CLK_n = '1' then - WR_n_i <= '1'; - if TState = "001" then -- To short for IO writes !!!!!!!!!!!!!!!!!!! - WR_n_i <= not Write; - end if; - end if; - end process; - - process (Reset_s,CLK_n) - begin - if Reset_s = '0' then - Req_Inhibit <= '0'; - elsif CLK_n'event and CLK_n = '1' then - if MCycle = "001" and TState = "010" then - Req_Inhibit <= '1'; - else - Req_Inhibit <= '0'; - end if; - end if; - end process; - - process (Reset_s,CLK_n) - begin - if Reset_s = '0' then - MReq_Inhibit <= '0'; - elsif CLK_n'event and CLK_n = '0' then - if MCycle = "001" and TState = "010" then - MReq_Inhibit <= '1'; - else - MReq_Inhibit <= '0'; - end if; - end if; - end process; - - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - RD <= '0'; - IORQ_n_i <= '1'; - 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; - IORQ_n_i <= IntCycle_n; - end if; - if TState = "011" then - RD <= '0'; - IORQ_n_i <= '1'; - MREQ <= '1'; - end if; - if TState = "100" then - MREQ <= '0'; - end if; - else - if TState = "001" and NoRead = '0' then - RD <= not Write; - IORQ_n_i <= not IORQ; - MREQ <= not IORQ; - end if; - if TState = "011" then - RD <= '0'; - IORQ_n_i <= '1'; - MREQ <= '0'; - end if; - end if; - end if; - end process; - -end; diff --git a/src/t80/T80pa.vhd b/src/t80/T80pa.vhd new file mode 100644 index 0000000..cb3d146 --- /dev/null +++ b/src/t80/T80pa.vhd @@ -0,0 +1,211 @@ +-- +-- Z80 compatible microprocessor core, preudo-asynchronous top level (by Sorgelig) +-- +-- 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/ +-- +-- File history : +-- +-- v1.0: convert to preudo-asynchronous model with original Z80 timings. +-- +-- v2.0: rewritten for more precise timings. +-- support for both CEN_n and CEN_p set to 1. Effective clock will be CLK/2. +-- +-- v2.1: Output Address 0 during non-bus MCycle (fix ZX contention) +-- +-- v2.2: Interrupt acknowledge cycle has been corrected +-- WAIT_n is broken in T80.vhd. Simulate correct WAIT_n locally. +-- +-- v2.3: Output last used Address during non-bus MCycle seems more correct. +-- + +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; + 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 : 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, + 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; diff --git a/src/t80/T80s.vhd b/src/t80/T80s.vhd index faa2e1d..1f45aa0 100644 --- a/src/t80/T80s.vhd +++ b/src/t80/T80s.vhd @@ -79,11 +79,11 @@ entity T80s is 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; + CEN : 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; @@ -135,14 +135,8 @@ begin DO => DO, MC => MCycle, TS => TState, - IntCycle_n => IntCycle_n, - - SavePC => open, - SaveINT => open, - RestorePC => (others => '1'), - RestoreINT => (others => '1'), - - RestorePC_n => '1' ); + IntCycle_n => IntCycle_n + ); process (RESET_n, CLK_n) begin @@ -152,7 +146,7 @@ begin IORQ_n <= '1'; MREQ_n <= '1'; DI_Reg <= "00000000"; - elsif CLK_n'event and CLK_n = '1' then + elsif rising_edge(CLK_n) then if CEN = '1' then RD_n <= '1'; WR_n <= '1'; @@ -193,5 +187,4 @@ begin end if; end if; end process; - end; diff --git a/src/t80/T80se.vhd b/src/t80/T80se.vhd deleted file mode 100644 index c47a56e..0000000 --- a/src/t80/T80se.vhd +++ /dev/null @@ -1,200 +0,0 @@ --- --- 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 : 0242 --- --- 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 := 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; - A : out std_logic_vector(15 downto 0); - DI : in std_logic_vector(7 downto 0); - DO : out std_logic_vector(7 downto 0); - - SavePC : out std_logic_vector(15 downto 0); - SaveINT : out std_logic_vector(7 downto 0); - RestorePC : in std_logic_vector(15 downto 0); - RestoreINT : in std_logic_vector(7 downto 0); - - RestorePC_n : in std_logic - ); -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, - - SavePC => SavePC, - SaveINT => SaveINT, - RestorePC => RestorePC, - RestoreINT => RestoreINT, - - RestorePC_n => RestorePC_n ); - - - process (CLK_n) - begin - if CLK_n'event and CLK_n = '1' then - if RESET_n = '0' then - RD_n <= '1'; - WR_n <= '1'; - IORQ_n <= '1'; - MREQ_n <= '1'; - DI_Reg <= "00000000"; - elsif 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" 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 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 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/src/tsconf.v b/src/tsconf.v index 92c4399..b989fd2 100644 --- a/src/tsconf.v +++ b/src/tsconf.v @@ -329,24 +329,20 @@ zclock TS02 .turbo(turbo) ); -T80s #(.mode(0), .t2write(1), .iowait(1)) z80_unit +T80s CPU ( - .reset_n((~reset)), - .clk_n(zclk), - .cen(1), - .wait_n(1), - .int_n(cpu_int_n_TS), - .nmi_n(1), - .busrq_n(1), - .m1_n(cpu_m1_n), - .mreq_n(cpu_mreq_n), - .iorq_n(cpu_iorq_n), - .rd_n(cpu_rd_n), - .wr_n(cpu_wr_n), - .rfsh_n(cpu_rfsh_n), - .a(cpu_a_bus), - .di(cpu_di_bus), - .do(cpu_do_bus) + .RESET_n(~reset), + .CLK_n(zclk), + .INT_n(cpu_int_n_TS), + .M1_n(cpu_m1_n), + .MREQ_n(cpu_mreq_n), + .IORQ_n(cpu_iorq_n), + .RD_n(cpu_rd_n), + .WR_n(cpu_wr_n), + .RFSH_n(cpu_rfsh_n), + .A(cpu_a_bus), + .DI(cpu_di_bus), + .DO(cpu_do_bus) ); zsignals TS04