From 8e83d6e21f525734da545cb4e7e63442c0771654 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 30 Jun 2021 11:53:24 +0100 Subject: [PATCH 1/9] Z80: Update T80 core to latest from Mister on 30/6/2021 Change-Id: I6c007617ab03796dcd864c0f84d5663e0f4bece9 --- src/T80/T80.vhd | 393 ++++++++++++----------- src/T80/T80_ALU.vhd | 85 +++-- src/T80/T80_MCode.vhd | 724 +++++++++++++++++++++++++++--------------- src/T80/T80_Pack.vhd | 64 ++-- src/T80/T80a.vhd | 515 +++++++++++++++--------------- 5 files changed, 1027 insertions(+), 754 deletions(-) diff --git a/src/T80/T80.vhd b/src/T80/T80.vhd index ed57ca6..5ad3e90 100644 --- a/src/T80/T80.vhd +++ b/src/T80/T80.vhd @@ -21,7 +21,7 @@ -- **** -- Z80 compatible microprocessor core -- --- Version : 0247 +-- Version : 0250 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- All rights reserved -- @@ -73,14 +73,14 @@ -- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode -- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM -- 0247 : Fixed bus req/ack cycle +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use IEEE.STD_LOGIC_UNSIGNED.all; - -use work.all; +use work.T80_Pack.all; entity T80 is generic( @@ -117,9 +117,9 @@ entity T80 is MC : out std_logic_vector(2 downto 0); TS : out std_logic_vector(2 downto 0); IntCycle_n : out std_logic; - NMICycle_n : out std_logic; IntE : out std_logic; Stop : out std_logic; + R800_mode : in std_logic := '0'; out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A @@ -129,136 +129,6 @@ entity T80 is end T80; architecture rtl of T80 is - component T80_MCode - generic( - Mode : integer := 0; - Flag_C : integer := 0; - Flag_N : integer := 1; - Flag_P : integer := 2; - Flag_X : integer := 3; - Flag_H : integer := 4; - Flag_Y : integer := 5; - Flag_Z : integer := 6; - Flag_S : integer := 7 - ); - port( - IR : in std_logic_vector(7 downto 0); - ISet : in std_logic_vector(1 downto 0); - MCycle : in std_logic_vector(2 downto 0); - F : in std_logic_vector(7 downto 0); - NMICycle : in std_logic; - IntCycle : in std_logic; - XY_State : in std_logic_vector(1 downto 0); - MCycles : out std_logic_vector(2 downto 0); - TStates : out std_logic_vector(2 downto 0); - Prefix : out std_logic_vector(1 downto 0); -- None,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 component; - - component T80_ALU - generic( - Mode : integer := 0; - Flag_C : integer := 0; - Flag_N : integer := 1; - Flag_P : integer := 2; - Flag_X : integer := 3; - Flag_H : integer := 4; - Flag_Y : integer := 5; - Flag_Z : integer := 6; - Flag_S : integer := 7 - ); - port( - Arith16 : in std_logic; - Z16 : in std_logic; - WZ : in std_logic_vector(15 downto 0); - XY_State : in std_logic_vector(1 downto 0); - ALU_Op : in std_logic_vector(3 downto 0); - 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; - - component T80_Reg - port( - Clk : in std_logic; - CEN : in std_logic; - WEH : in std_logic; - WEL : in std_logic; - AddrA : in std_logic_vector(2 downto 0); - AddrB : in std_logic_vector(2 downto 0); - AddrC : in std_logic_vector(2 downto 0); - DIH : in std_logic_vector(7 downto 0); - DIL : in std_logic_vector(7 downto 0); - DOAH : out std_logic_vector(7 downto 0); - DOAL : out std_logic_vector(7 downto 0); - DOBH : out std_logic_vector(7 downto 0); - DOBL : out std_logic_vector(7 downto 0); - DOCH : out std_logic_vector(7 downto 0); - DOCL : out std_logic_vector(7 downto 0); - DOR : out std_logic_vector(127 downto 0); - DIRSet : in std_logic; - DIR : in std_logic_vector(127 downto 0) - ); - end component; - - 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); @@ -283,9 +153,13 @@ architecture rtl of T80 is -- Help Registers signal WZ : std_logic_vector(15 downto 0); -- MEMPTR register + signal TmpAddr2 : std_logic_vector(15 downto 0); -- Temporary address register signal IR : std_logic_vector(7 downto 0); -- Instruction register signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector signal RegBusA_r : std_logic_vector(15 downto 0); + signal MULU_Prod32 : std_logic_vector(31 downto 0); + signal MULU_tmp : std_logic_vector(31 downto 0); + signal MULU_Fakt1 : std_logic_vector(15 downto 0); signal ID16 : signed(15 downto 0); signal Save_Mux : std_logic_vector(7 downto 0); @@ -295,8 +169,8 @@ architecture rtl of T80 is signal IntE_FF1 : std_logic; signal IntE_FF2 : std_logic; signal Halt_FF : std_logic; - signal BusReq_s : std_logic; - signal BusAck : std_logic; + signal BusReq_s : std_logic := '0'; + signal BusAck : std_logic := '0'; signal ClkEn : std_logic; signal NMI_s : std_logic; signal IStatus : std_logic_vector(1 downto 0); @@ -344,6 +218,7 @@ architecture rtl of T80 is signal Set_BusA_To : std_logic_vector(3 downto 0); signal ALU_Op : std_logic_vector(3 downto 0); signal Save_ALU : std_logic; + signal Rot_Akku : std_logic; signal PreserveC : std_logic; signal Arith16 : std_logic; signal Set_Addr_To : std_logic_vector(2 downto 0); @@ -355,6 +230,8 @@ architecture rtl of T80 is signal LDZ : std_logic; signal LDW : std_logic; signal LDSPHL : std_logic; + signal LDHLSP : std_logic; + signal ADDSPdd : std_logic; signal IORQ_i : std_logic; signal Special_LD : std_logic_vector(2 downto 0); signal ExchangeDH : std_logic; @@ -373,14 +250,16 @@ architecture rtl of T80 is signal I_RRD : std_logic; signal I_RXDD : std_logic; signal I_INRC : std_logic; + signal I_MULUB : std_logic; + signal I_MULU : std_logic; signal SetWZ : std_logic_vector(1 downto 0); signal SetDI : std_logic; signal SetEI : std_logic; signal IMode : std_logic_vector(1 downto 0); signal Halt : std_logic; signal XYbit_undoc : std_logic; + signal No_PC : std_logic; signal DOR : std_logic_vector(127 downto 0); - signal IVector : std_logic_vector(7 downto 0); begin @@ -419,6 +298,7 @@ begin Set_BusA_To => Set_BusA_To, ALU_Op => ALU_Op, Save_ALU => Save_ALU, + Rot_Akku => Rot_Akku, PreserveC => PreserveC, Arith16 => Arith16, Set_Addr_To => Set_Addr_To, @@ -431,6 +311,8 @@ begin LDZ => LDZ, LDW => LDW, LDSPHL => LDSPHL, + LDHLSP => LDHLSP, + ADDSPdd => ADDSPdd, Special_LD => Special_LD, ExchangeDH => ExchangeDH, ExchangeRp => ExchangeRp, @@ -447,6 +329,8 @@ begin I_RLD => I_RLD, I_RRD => I_RRD, I_INRC => I_INRC, + I_MULUB => I_MULUB, + I_MULU => I_MULU, SetWZ => SetWZ, SetDI => SetDI, SetEI => SetEI, @@ -454,6 +338,8 @@ begin Halt => Halt, NoRead => NoRead, Write => Write, + R800_mode => R800_mode, + No_PC => No_PC, XYbit_undoc => XYbit_undoc); alu : T80_ALU @@ -473,6 +359,7 @@ begin WZ => WZ, XY_State=> XY_State, ALU_Op => ALU_Op_r, + Rot_Akku => Rot_Akku, IR => IR(5 downto 0), ISet => ISet, BusA => BusA, @@ -497,6 +384,8 @@ begin process (RESET_n, CLK_n) variable n : std_logic_vector(7 downto 0); variable ioq : std_logic_vector(8 downto 0); + variable temp_c : unsigned(8 downto 0); + variable temp_h : unsigned(4 downto 0); begin if RESET_n = '0' then PC <= (others => '0'); -- Program Counter @@ -511,6 +400,11 @@ begin ACC <= (others => '1'); F <= (others => '1'); + if Mode = 3 then + ACC <= (others => '0'); + F <= "11110000"; + end if; + Ap <= (others => '1'); Fp <= (others => '1'); I <= (others => '0'); @@ -539,7 +433,7 @@ begin R <= unsigned(DIR(47 downto 40)); SP <= unsigned(DIR(63 downto 48)); PC <= unsigned(DIR(79 downto 64)); - A <= DIR(79 downto 64); + A <= DIR(79 downto 64); IStatus <= DIR(209 downto 208); elsif ClkEn = '1' then @@ -549,7 +443,27 @@ begin MCycles <= MCycles_d; - if IMode /= "11" then + if LDHLSP = '1' and MCycle = "011" and TState = 1 then + temp_c := unsigned('0'&SP(7 downto 0))+unsigned('0'&Save_Mux); + temp_h := unsigned('0'&SP(3 downto 0))+unsigned('0'&Save_Mux(3 downto 0)); + F(Flag_Z) <= '0'; + F(Flag_N) <= '0'; + F(Flag_H) <= temp_h(4); + F(Flag_C) <= temp_c(8); + end if; + + if ADDSPdd = '1' and TState = 1 then + temp_c := unsigned('0'&SP(7 downto 0))+unsigned('0'&Save_Mux); + temp_h := unsigned('0'&SP(3 downto 0))+unsigned('0'&Save_Mux(3 downto 0)); + F(Flag_Z) <= '0'; + F(Flag_N) <= '0'; + F(Flag_H) <= temp_h(4); + F(Flag_C) <= temp_c(8); + end if; + + if Mode = 3 then + IStatus <= "10"; + elsif IMode /= "11" then IStatus <= IMode; end if; @@ -579,16 +493,15 @@ begin IR <= "11111111"; elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then IR <= "00000000"; - -- DMB: It's important to catch the interrupt vector at - -- the start of T3, not the middle as the old code - -- (using WZ) did. This caused a issue with the Z80 - -- Second Processor on the GODIL due to the pullups - -- (esp on D0) - IVector <= DInst; else IR <= DInst; end if; + if Mode <= 1 and IntCycle = '1' and IStatus = "10" then + -- IM2 vector address low byte from bus + WZ(7 downto 0) <= DInst; + end if; + ISet <= "00"; if Prefix /= "00" then if Prefix = "11" then @@ -636,11 +549,12 @@ begin elsif MCycle = MCycles and NMICycle = '1' then A <= "0000000001100110"; PC <= "0000000001100110"; - elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then + elsif ((Mode /= 3 and MCycle = "011") or (Mode = 3 and MCycle = "100")) + and IntCycle = '1' and IStatus = "10" then A(15 downto 8) <= I; - A(7 downto 0) <= IVector; + A(7 downto 0) <= WZ(7 downto 0); PC(15 downto 8) <= unsigned(I); - PC(7 downto 0) <= unsigned(IVector); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); else case Set_Addr_To is when aXY => @@ -700,7 +614,12 @@ begin end if; end if; when others => - A <= std_logic_vector(PC); + if ISet = "10" and IR(7 downto 4) = x"B" and IR(2 downto 1) = "01" and MCycle = 3 and No_BTR = '0' then + -- INIR, INDR, OTIR, OTDR + A <= RegBusA_r; + elsif No_PC = '0' or No_BTR = '1' or (I_DJNZ = '1' and IncDecZ = '1') or Mode > 1 then + A <= std_logic_vector(PC); + end if; end case; end if; @@ -711,29 +630,50 @@ begin Save_ALU_r <= Save_ALU; ALU_Op_r <= ALU_Op; - if I_CPL = '1' then - -- CPL - ACC <= not ACC; - F(Flag_Y) <= not ACC(5); - F(Flag_H) <= '1'; - F(Flag_X) <= not ACC(3); - F(Flag_N) <= '1'; - end if; - if I_CCF = '1' then - -- CCF - F(Flag_C) <= not F(Flag_C); - F(Flag_Y) <= ACC(5); - F(Flag_H) <= F(Flag_C); - F(Flag_X) <= ACC(3); - F(Flag_N) <= '0'; - end if; - if I_SCF = '1' then - -- SCF - F(Flag_C) <= '1'; - F(Flag_Y) <= ACC(5); - F(Flag_H) <= '0'; - F(Flag_X) <= ACC(3); - F(Flag_N) <= '0'; + if Mode = 3 then + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_H) <= '1'; + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + else + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; end if; end if; @@ -742,7 +682,7 @@ begin F(Flag_N) <= DI_Reg(7); F(Flag_C) <= ioq(8); F(Flag_H) <= ioq(8); - ioq := (ioq and ('0'&x"07")) xor ('0'&BusA); + 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; @@ -784,6 +724,11 @@ begin end if; end if; + if ADDSPdd = '1' and TState = 2 then + WZ <= std_logic_vector(SP); + SP <= unsigned(signed(SP)+signed(Save_Mux)); + end if; + if LDSPHL = '1' then SP <= unsigned(RegBusC); end if; @@ -931,7 +876,12 @@ begin when "11001" => SP(15 downto 8) <= unsigned(Save_Mux); when "11011" => - F <= Save_Mux; + if Mode = 3 then + F(7 downto 4) <= Save_Mux(7 downto 4); + F(3 downto 0) <= "0000"; -- bit 3 to 0 always return 0 + else + F <= Save_Mux; + end if; when others => end case; if XYbit_undoc='1' then @@ -942,6 +892,42 @@ begin end if; end process; +--------------------------------------------------------------------------- +-- +-- Multiply +-- +--------------------------------------------------------------------------- + process (CLK_n, ACC, RegBusB, MULU_tmp, MULU_Fakt1, MULU_Prod32) + begin + + MULU_tmp(31 downto 12) <= std_logic_vector((unsigned(MULU_Fakt1)*unsigned(MULU_Prod32(3 downto 0)))+unsigned("0000"&MULU_Prod32(31 downto 16))); + MULU_tmp(11 downto 0) <= MULU_Prod32(15 downto 4); + + if rising_edge(CLK_n) then + if ClkEn = '1' then + if T_Res='1' then + if I_MULUB='1' then + MULU_Prod32(7 downto 0) <= ACC; + MULU_Prod32(15 downto 8) <= "--------"; + MULU_Prod32(31 downto 16) <= X"0000"; + MULU_Fakt1(7 downto 0) <= "00000000"; + if Set_BusB_To(0) = '1' then + MULU_Fakt1(15 downto 8) <= RegBusB(7 downto 0); + else + MULU_Fakt1(15 downto 8) <= RegBusB(15 downto 8); + end if; + else + MULU_Prod32(15 downto 0) <= RegBusA; + MULU_Prod32(31 downto 16) <= X"0000"; + MULU_Fakt1 <= RegBusB; + end if; + else + MULU_Prod32 <= MULU_tmp; + end if; + end if; + end if; + end process; + --------------------------------------------------------------------------- -- -- BC('), DE('), HL('), IX and IY @@ -997,7 +983,9 @@ begin (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else -- EX HL,DL Alternate & "10" when ExchangeDH = '1' and TState = 3 else - Alternate & "01" when ExchangeDH = '1' and TState = 4 else + Alternate & "01" when (ExchangeDH = '1' or I_MULU = '1') and TState = 4 else + -- LDHLSP + "010" when LDHLSP = '1' and TState = 4 else -- Bus A / Write RegAddrA_r; @@ -1010,8 +998,8 @@ begin ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else signed(RegBusA) + 1; - process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, - ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, I_MULU, T_Res, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n, LDHLSP) begin RegWEH <= '0'; RegWEL <= '0'; @@ -1025,11 +1013,21 @@ begin end case; end if; + if I_MULU = '1' and (T_Res = '1' or TState = 4) then -- TState = 4 DE write + RegWEH <= '1'; + RegWEL <= '1'; + end if; + if ExchangeDH = '1' and (TState = 3 or TState = 4) then RegWEH <= '1'; RegWEL <= '1'; end if; + if LDHLSP = '1' and MCycle = "010" and TState = 4 then + RegWEH <= '1'; + RegWEL <= '1'; + end if; + if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then case IncDec_16(1 downto 0) is when "00" | "01" | "10" => @@ -1040,12 +1038,29 @@ begin end if; end process; - process (Save_Mux, RegBusB, RegBusA_r, ID16, - ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + TmpAddr2 <= std_logic_vector(unsigned(signed(SP) + signed(Save_Mux))); + + process (Save_Mux, RegBusB, RegBusA_r, ID16, I_MULU, MULU_Prod32, MULU_tmp, T_Res, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n, LDHLSP, TmpAddr2) begin RegDIH <= Save_Mux; RegDIL <= Save_Mux; + if I_MULU = '1' then + if T_Res = '1' then + RegDIH <= MULU_Prod32(31 downto 24); + RegDIL <= MULU_Prod32(23 downto 16); + else + RegDIH <= MULU_tmp(15 downto 8); -- TState = 4 DE write + RegDIL <= MULU_tmp(7 downto 0); + end if; + end if; + + if LDHLSP = '1' and MCycle = "010" and TState = 4 then + RegDIH <= TmpAddr2(15 downto 8); + RegDIL <= TmpAddr2(7 downto 0); + end if; + if ExchangeDH = '1' and TState = 3 then RegDIH <= RegBusB(15 downto 8); RegDIL <= RegBusB(7 downto 0); @@ -1176,13 +1191,11 @@ begin TS <= std_logic_vector(TState); DI_Reg <= DI; HALT_n <= not Halt_FF; - BUSAK_n <= not BusAck; + BUSAK_n <= not (BusAck and RESET_n); IntCycle_n <= not IntCycle; - NMICycle_n <= not NMICycle; IntE <= IntE_FF1; IORQ <= IORQ_i; Stop <= I_DJNZ; - ------------------------------------------------------------------------- -- -- Main state machine @@ -1196,7 +1209,7 @@ begin TState <= "000"; Pre_XY_F_M <= "000"; Halt_FF <= '0'; - BusAck <= '0'; + --BusAck <= '0'; NMICycle <= '0'; IntCycle <= '0'; IntE_FF1 <= '0'; @@ -1205,10 +1218,9 @@ begin Auto_Wait_t1 <= '0'; Auto_Wait_t2 <= '0'; M1_n <= '1'; - BusReq_s <= '0'; + --BusReq_s <= '0'; NMI_s <= '0'; elsif rising_edge(CLK_n) then - if DIRSet = '1' then IntE_FF2 <= DIR(211); IntE_FF1 <= DIR(210); @@ -1256,13 +1268,20 @@ begin BusAck <= '0'; if TState = 2 and Wait_n = '0' then elsif T_Res = '1' then - if Halt = '1' then + if Halt = '1' and ( not(Mode = 3 and INT_n = '0' and IntE_FF1 = '0')) then -- halt bug when Mode = 3 , INT_n = '0' and IME=0 Halt_FF <= '1'; end if; if BusReq_s = '1' then BusAck <= '1'; else TState <= "001"; + if (IntCycle = '1' and Mode = 3) then -- GB: read interrupt at MCycle 3 + if (MCycle = "010") then + M1_n <= '0'; + else + M1_n <= '1'; + end if; + end if; if NextIs_XY_Fetch = '1' then MCycle <= "110"; Pre_XY_F_M <= MCycle; @@ -1284,6 +1303,8 @@ begin IntCycle <= '1'; IntE_FF1 <= '0'; IntE_FF2 <= '0'; + elsif (Halt_FF = '1' and INT_n = '0' and Mode = 3) then + Halt_FF <= '0'; end if; else MCycle <= std_logic_vector(unsigned(MCycle) + 1); diff --git a/src/T80/T80_ALU.vhd b/src/T80/T80_ALU.vhd index a9438ae..1192e0b 100644 --- a/src/T80/T80_ALU.vhd +++ b/src/T80/T80_ALU.vhd @@ -89,6 +89,7 @@ entity T80_ALU is WZ : in std_logic_vector(15 downto 0); XY_State : in std_logic_vector(1 downto 0); ALU_Op : in std_logic_vector(3 downto 0); + Rot_Akku : in std_logic; IR : in std_logic_vector(5 downto 0); ISet : in std_logic_vector(1 downto 0); BusA : in std_logic_vector(7 downto 0); @@ -158,7 +159,7 @@ begin end if; end process; - process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, WZ, XY_State) + process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, Rot_Akku, WZ, XY_State) variable Q_t : std_logic_vector(7 downto 0); variable DAA_Q : unsigned(8 downto 0); begin @@ -220,35 +221,64 @@ begin end if; when "1100" => -- DAA - F_Out(Flag_H) <= F_In(Flag_H); - F_Out(Flag_C) <= F_In(Flag_C); - DAA_Q(7 downto 0) := unsigned(BusA); - DAA_Q(8) := '0'; - if F_In(Flag_N) = '0' then - -- After addition - -- Alow > 9 or H = 1 - if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then - if (DAA_Q(3 downto 0) > 9) then - F_Out(Flag_H) <= '1'; - else - F_Out(Flag_H) <= '0'; + if Mode = 3 then + F_Out(Flag_H) <= '0'; + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if F_In(Flag_H) = '1' then + DAA_Q := DAA_Q - 6; + if F_In(Flag_C) = '0' then + DAA_Q(8) := '0'; + end if; + end if; + if F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 96; -- 0x60 end if; - DAA_Q := DAA_Q + 6; - end if; - -- new Ahigh > 9 or C = 1 - if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then - DAA_Q := DAA_Q + 96; -- 0x60 end if; else - -- After subtraction - if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then - if DAA_Q(3 downto 0) > 5 then - F_Out(Flag_H) <= '0'; + F_Out(Flag_H) <= F_In(Flag_H); + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if (DAA_Q(3 downto 0) > 9) then + F_Out(Flag_H) <= '1'; + else + F_Out(Flag_H) <= '0'; + end if; + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if DAA_Q(3 downto 0) > 5 then + F_Out(Flag_H) <= '0'; + end if; + DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; + end if; + if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 352; -- 0x160 end if; - DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; - end if; - if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then - DAA_Q := DAA_Q - 352; -- 0x160 end if; end if; F_Out(Flag_X) <= DAA_Q(3); @@ -368,6 +398,9 @@ begin F_Out(Flag_S) <= F_In(Flag_S); F_Out(Flag_Z) <= F_In(Flag_Z); end if; + if Mode = 3 and Rot_Akku = '1' then + F_Out(Flag_Z) <= '0'; + end if; when others => null; end case; diff --git a/src/T80/T80_MCode.vhd b/src/T80/T80_MCode.vhd index 0d1fbab..eadf1af 100644 --- a/src/T80/T80_MCode.vhd +++ b/src/T80/T80_MCode.vhd @@ -19,7 +19,7 @@ -- **** -- Z80 compatible microprocessor core -- --- Version : 0242 +-- Version : 0250 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- All rights reserved -- @@ -69,11 +69,13 @@ -- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes -- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR -- 0242 : Fixed I/O instruction timing, cleanup +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +use work.T80_Pack.all; entity T80_MCode is generic( @@ -108,6 +110,7 @@ entity T80_MCode is ALU_Op : out std_logic_vector(3 downto 0); -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None Save_ALU : out std_logic; + Rot_Akku : out std_logic; PreserveC : out std_logic; Arith16 : out std_logic; Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI @@ -120,6 +123,8 @@ entity T80_MCode is LDZ : out std_logic; LDW : out std_logic; LDSPHL : out std_logic; + LDHLSP : out std_logic; + ADDSPdd : out std_logic; Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None ExchangeDH : out std_logic; ExchangeRp : out std_logic; @@ -136,6 +141,8 @@ entity T80_MCode is I_RLD : out std_logic; I_RRD : out std_logic; I_INRC : out std_logic; + I_MULUB : out std_logic; + I_MULU : out std_logic; SetWZ : out std_logic_vector(1 downto 0); SetDI : out std_logic; SetEI : out std_logic; @@ -143,20 +150,14 @@ entity T80_MCode is Halt : out std_logic; NoRead : out std_logic; Write : out std_logic; + R800_mode : in std_logic; + No_PC : out std_logic; XYbit_undoc : out std_logic ); end T80_MCode; architecture rtl of T80_MCode is - constant aNone : std_logic_vector(2 downto 0) := "111"; - constant aBC : std_logic_vector(2 downto 0) := "000"; - constant aDE : std_logic_vector(2 downto 0) := "001"; - constant aXY : std_logic_vector(2 downto 0) := "010"; - constant aIOA : std_logic_vector(2 downto 0) := "100"; - constant aSP : std_logic_vector(2 downto 0) := "101"; - constant aZI : std_logic_vector(2 downto 0) := "110"; - function is_cc_true( F : std_logic_vector(7 downto 0); cc : bit_vector(2 downto 0) @@ -164,10 +165,10 @@ architecture rtl of T80_MCode is begin if Mode = 3 then case cc is - when "000" => return F(Flag_S) = '0'; -- NZ - when "001" => return F(Flag_S) = '1'; -- Z - when "010" => return F(Flag_H) = '0'; -- NC - when "011" => return F(Flag_H) = '1'; -- C + when "000" => return F(Flag_Z) = '0'; -- NZ + when "001" => return F(Flag_Z) = '1'; -- Z + when "010" => return F(Flag_C) = '0'; -- NC + when "011" => return F(Flag_C) = '1'; -- C when "100" => return false; when "101" => return false; when "110" => return false; @@ -189,7 +190,7 @@ architecture rtl of T80_MCode is begin - process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State) + process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State, R800_mode) variable DDD : std_logic_vector(2 downto 0); variable SSS : std_logic_vector(2 downto 0); variable DPair : std_logic_vector(1 downto 0); @@ -216,6 +217,7 @@ begin Set_BusA_To <= "0000"; ALU_Op <= "0" & IR(5 downto 3); Save_ALU <= '0'; + Rot_Akku <= '0'; PreserveC <= '0'; Arith16 <= '0'; IORQ <= '0'; @@ -228,6 +230,8 @@ begin LDZ <= '0'; LDW <= '0'; LDSPHL <= '0'; + LDHLSP <= '0'; + ADDSPdd <= '0'; Special_LD <= "000"; ExchangeDH <= '0'; ExchangeRp <= '0'; @@ -244,12 +248,15 @@ begin I_RLD <= '0'; I_RRD <= '0'; I_INRC <= '0'; + I_MULUB <= '0'; + I_MULU <= '0'; SetDI <= '0'; SetEI <= '0'; IMode <= "11"; Halt <= '0'; NoRead <= '0'; Write <= '0'; + No_PC <= '0'; XYbit_undoc <= '0'; SetWZ <= "00"; @@ -520,38 +527,76 @@ begin end if; when "11111001" => -- LD SP,HL - TStates <= "110"; - LDSPHL <= '1'; + if Mode = 3 then + MCycles <= "010"; + if MCycle = "010" then + LDSPHL <= '1'; + end if; + else + TStates <= "110"; + LDSPHL <= '1'; + end if; when "11000101"|"11010101"|"11100101"|"11110101" => -- PUSH qq - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_TO <= aSP; - if DPAIR = "11" then - Set_BusB_To <= "0111"; - else - Set_BusB_To(2 downto 1) <= DPAIR; - Set_BusB_To(0) <= '0'; - Set_BusB_To(3) <= '0'; - end if; - when 2 => - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - if DPAIR = "11" then - Set_BusB_To <= "1011"; - else - Set_BusB_To(2 downto 1) <= DPAIR; - Set_BusB_To(0) <= '1'; - Set_BusB_To(3) <= '0'; - end if; - Write <= '1'; - when 3 => - Write <= '1'; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 3 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 4 => + Write <= '1'; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 2 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; when "11000001"|"11010001"|"11100001"|"11110001" => -- POP qq MCycles <= "011"; @@ -615,7 +660,7 @@ begin when "11011001" => if Mode = 3 then -- RETI - MCycles <= "011"; + MCycles <= "100"; case to_integer(unsigned(MCycle)) is when 1 => Set_Addr_TO <= aSP; @@ -626,7 +671,7 @@ begin when 3 => Jump <= '1'; IncDec_16 <= "0111"; - I_RETN <= '1'; + --I_RETN <= '1'; SetEI <= '1'; when others => null; end case; @@ -643,81 +688,28 @@ begin Set_Addr_To <= aSP; when 2 => Read_To_Reg <= '1'; - Set_BusA_To <= "0101"; -- L, target of Read_To_Reg - Set_BusB_To <= "0101"; -- L, input of ALU + Set_BusA_To <= "0101"; + Set_BusB_To <= "0101"; Set_Addr_To <= aSP; - LDZ <= '1'; -- also load Z + LDZ <= '1'; when 3 => - IncDec_16 <= "0111"; -- Increment SP + IncDec_16 <= "0111"; Set_Addr_To <= aSP; TStates <= "100"; Write <= '1'; when 4 => Read_To_Reg <= '1'; - Set_BusA_To <= "0100"; -- H, target of Read_To_Reg - Set_BusB_To <= "0100"; -- H, input of ALU + Set_BusA_To <= "0100"; + Set_BusB_To <= "0100"; Set_Addr_To <= aSP; - LDW <= '1'; -- also load Z + LDW <= '1'; when 5 => - IncDec_16 <= "1111"; -- Decrement SP + IncDec_16 <= "1111"; TStates <= "101"; Write <= '1'; when others => null; end case; - end if; - --- The T80 implementation does: --- --- (4) M1 fetch --- (3) M2 Read (SP) -> L, Z --- L -> ALU --- (4) M3 Write ALU result -> (SP) --- SP++ --- (3) M4 Read (SP) -> H, W --- H -> ALU --- (5) M5 Write ALU result -> (SP) --- SP-- --- --- The Z80 does --- (4) M1 fetch --- (3) M2 Read (SP) -> Z --- SP++ --- (4) M3 Read (SP) -> W --- (3) M4 Write H -> (SP) --- SP-- --- (5) M5 Write L -> (SP) --- --- and somehow WZ -> HL at the end! --- --- Attempt at a new version. --- --- case to_integer(unsigned(MCycle)) is --- when 1 => --- Set_Addr_To <= aSP; --- when 2 => --- IncDec_16 <= "0111"; --- Read_To_Reg <= '1'; --- Set_BusA_To <= "0101"; --- Set_BusB_To <= "0101"; --- Set_Addr_To <= aSP; --- LDZ <= '1'; --- when 3 => --- Read_To_Reg <= '1'; --- Set_BusA_To <= "0100"; --- Set_BusB_To <= "0100"; --- Set_Addr_To <= aSP; --- TStates <= "100"; --- LDW <= '1'; --- when 4 => --- IncDec_16 <= "1111"; --- Set_Addr_To <= aSP; --- Write <= '1'; --- when 5 => --- TStates <= "101"; --- Write <= '1'; --- when others => null; --- end case; --- end if; + end if; -- 8 BIT ARITHMETIC AND LOGICAL GROUP when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" @@ -869,30 +861,50 @@ begin end case; elsif IntCycle = '1' then -- INT (IM 2) - MCycles <= "101"; - case to_integer(unsigned(MCycle)) is - when 1 => - LDZ <= '1'; - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1101"; - when 2 => - --TStates <= "100"; - Write <= '1'; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1100"; - when 3 => - --TStates <= "100"; - Write <= '1'; - when 4 => - Inc_PC <= '1'; - LDZ <= '1'; - when 5 => - Jump <= '1'; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "110"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + when 3 => -- GB: interrupt is acknowledged on MCycle 3 + LDZ <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 4 => + Write <= '1'; + when others => null; + end case; + else + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + --TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + --TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + end if; else -- NOP end if; @@ -909,49 +921,108 @@ begin -- 16 BIT ARITHMETIC GROUP when "00001001"|"00011001"|"00101001"|"00111001" => -- ADD HL,ss - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 2 => - NoRead <= '1'; - ALU_Op <= "0000"; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - Set_BusA_To(2 downto 0) <= "101"; - case to_integer(unsigned(IR(5 downto 4))) is - when 0|1|2 => - Set_BusB_To(2 downto 1) <= IR(5 downto 4); - Set_BusB_To(0) <= '1'; + if Mode = 3 then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + SetWZ <= "11"; + when 2 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; when others => - Set_BusB_To <= "1000"; end case; - TStates <= "100"; - Arith16 <= '1'; - SetWZ <= "11"; - when 3 => - NoRead <= '1'; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - ALU_Op <= "0001"; - Set_BusA_To(2 downto 0) <= "100"; - case to_integer(unsigned(IR(5 downto 4))) is - when 0|1|2 => - Set_BusB_To(2 downto 1) <= IR(5 downto 4); + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + No_PC <= '1'; + when 2 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + SetWZ <= "11"; + No_PC <= '1'; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; when others => - Set_BusB_To <= "1001"; end case; - Arith16 <= '1'; - when others => - end case; + end if; when "00000011"|"00010011"|"00100011"|"00110011" => -- INC ss - TStates <= "110"; - IncDec_16(3 downto 2) <= "01"; - IncDec_16(1 downto 0) <= DPair; + if Mode = 3 then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + when others => + end case; + else + TStates <= "110"; + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + end if; when "00001011"|"00011011"|"00101011"|"00111011" => -- DEC ss - TStates <= "110"; - IncDec_16(3 downto 2) <= "11"; - IncDec_16(1 downto 0) <= DPair; + if Mode = 3 then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + when others => + end case; + else + TStates <= "110"; + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + end if; -- ROTATE AND SHIFT GROUP when "00000111" @@ -965,12 +1036,17 @@ begin Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1000"; Read_To_Reg <= '1'; + Rot_Akku <= '1'; Save_ALU <= '1'; -- JUMP GROUP when "11000011" => -- JP nn - MCycles <= "011"; + if Mode = 3 then + MCycles <= "100"; + else + MCycles <= "011"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; @@ -978,7 +1054,9 @@ begin when 3 => Inc_PC <= '1'; Jump <= '1'; - LDW <= '1'; + if Mode /= 3 then + LDW <= '1'; + end if; when others => null; end case; when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => @@ -991,9 +1069,9 @@ begin when 1 => Set_Addr_To <= aBC; Set_BusB_To <= "0111"; + IORQ <= '1'; --TH must be earlier to be stable when address is generated when 2 => Write <= '1'; - IORQ <= '1'; when others => end case; when "01" => @@ -1017,9 +1095,9 @@ begin case to_integer(unsigned(MCycle)) is when 1 => Set_Addr_To <= aBC; + IORQ <= '1'; --TH must be earlier to be stable when address is generated when 2 => Read_To_Acc <= '1'; - IORQ <= '1'; when others => end case; when "11" => @@ -1039,16 +1117,24 @@ begin end case; else -- JP cc,nn - MCycles <= "011"; + if Mode = 3 then + MCycles <= "100"; + else + MCycles <= "011"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; LDZ <= '1'; when 3 => - LDW <= '1'; + if Mode /= 3 then + LDW <= '1'; + end if; Inc_PC <= '1'; if is_cc_true(F, to_bitvector(IR(5 downto 3))) then Jump <= '1'; + elsif Mode = 3 then + MCycles <= "011"; end if; when others => null; end case; @@ -1060,6 +1146,7 @@ begin case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; + No_PC <= '1'; when 3 => NoRead <= '1'; JumpE <= '1'; @@ -1076,6 +1163,8 @@ begin Inc_PC <= '1'; if F(Flag_C) = '0' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1093,6 +1182,8 @@ begin Inc_PC <= '1'; if F(Flag_C) = '1' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1110,6 +1201,8 @@ begin Inc_PC <= '1'; if F(Flag_Z) = '0' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1127,6 +1220,8 @@ begin Inc_PC <= '1'; if F(Flag_Z) = '1' then MCycles <= "010"; + else + No_PC <= '1'; end if; when 3 => NoRead <= '1'; @@ -1138,9 +1233,15 @@ begin when "11101001" => -- JP (HL) JumpXY <= '1'; - when "00010000" => - if Mode = 3 then + when "00010000" => + if Mode = 3 then -- STOP and skip next byte + MCycles <= "010"; I_DJNZ <= '1'; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + when others => null; + end case; elsif Mode < 2 then -- DJNZ,e MCycles <= "011"; @@ -1156,6 +1257,7 @@ begin when 2 => I_DJNZ <= '1'; Inc_PC <= '1'; + No_PC <= '1'; when 3 => NoRead <= '1'; JumpE <= '1'; @@ -1167,7 +1269,11 @@ begin -- CALL AND RETURN GROUP when "11001101" => -- CALL nn - MCycles <= "101"; + if Mode = 3 then + MCycles <= "110"; + else + MCycles <= "101"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; @@ -1192,7 +1298,11 @@ begin when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" => if IR(5) = '0' or Mode /= 3 then -- CALL cc,nn - MCycles <= "101"; + if Mode = 3 then + MCycles <= "110"; + else + MCycles <= "101"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; @@ -1221,20 +1331,36 @@ begin end if; when "11001001" => -- RET - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - --TStates <= "101"; - Set_Addr_TO <= aSP; - when 2 => - IncDec_16 <= "0111"; - Set_Addr_To <= aSP; - LDZ <= '1'; - when 3 => - Jump <= '1'; - IncDec_16 <= "0111"; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Set_Addr_TO <= aSP; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 4 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + --TStates <= "101"; + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" => if IR(5) = '1' and Mode = 3 then case IRB(4 downto 3) is @@ -1252,22 +1378,11 @@ begin end case; when "01" => -- ADD SP,n - MCycles <= "011"; + MCycles <= "100"; case to_integer(unsigned(MCycle)) is - when 2 => - ALU_Op <= "0000"; - Inc_PC <= '1'; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - Set_BusA_To <= "1000"; - Set_BusB_To <= "0110"; when 3 => - NoRead <= '1'; - Read_To_Reg <= '1'; - Save_ALU <= '1'; - ALU_Op <= "0001"; - Set_BusA_To <= "1001"; - Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + Inc_PC <= '1'; + ADDSPdd <= '1'; when others => end case; when "10" => @@ -1282,67 +1397,100 @@ begin when others => null; end case; when "11" => - -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! - MCycles <= "101"; + -- LD HL,SP+n + MCycles <= "011"; case to_integer(unsigned(MCycle)) is + when 1 => + Inc_PC <= '1'; when 2 => + LDHLSP <= '1'; Inc_PC <= '1'; - LDZ <= '1'; when 3 => - Set_Addr_To <= aZI; - Inc_PC <= '1'; - LDW <= '1'; - when 4 => - Set_BusA_To(2 downto 0) <= "101"; -- L - Read_To_Reg <= '1'; - Inc_WZ <= '1'; - Set_Addr_To <= aZI; - when 5 => - Set_BusA_To(2 downto 0) <= "100"; -- H - Read_To_Reg <= '1'; + LDHLSP <= '1'; when others => null; end case; end case; else -- RET cc - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - if is_cc_true(F, to_bitvector(IR(5 downto 3))) then - Set_Addr_TO <= aSP; - else - MCycles <= "001"; - end if; - TStates <= "101"; - when 2 => - IncDec_16 <= "0111"; - Set_Addr_To <= aSP; - LDZ <= '1'; - when 3 => - Jump <= '1'; - IncDec_16 <= "0111"; - when others => null; - end case; + if Mode = 3 then + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "010"; + end if; + TStates <= "101"; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 4 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "001"; + end if; + TStates <= "101"; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; end if; when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" => -- RST p - MCycles <= "011"; - case to_integer(unsigned(MCycle)) is - when 1 => - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1101"; - when 2 => - Write <= '1'; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1100"; - when 3 => - Write <= '1'; - RstP <= '1'; - when others => null; - end case; + if Mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 3 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 4 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + else + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + end if; -- INPUT AND OUTPUT GROUP when "11011011" => @@ -1642,16 +1790,16 @@ begin | "10101100"|"10101101"|"10101110"|"10101111" | "10110100"|"10110101"|"10110110"|"10110111" | "10111100"|"10111101"|"10111110"|"10111111" - |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" - |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" - |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" - |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11000000"| "11000010" |"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"| "11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"| "11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"| "11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" - |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11110000"|"11110001"|"11110010" |"11110100"|"11110101"|"11110110"|"11110111" |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => null; -- NOP, undocumented - when "01111110"|"01111111" => + when "01110111"|"01111111" => -- NOP, undocumented null; -- 8 BIT LOAD GROUP @@ -1762,6 +1910,7 @@ begin else IncDec_16 <= "1101"; end if; + No_PC <= '1'; when 4 => NoRead <= '1'; TStates <= "101"; @@ -1785,10 +1934,12 @@ begin else IncDec_16 <= "1110"; end if; + No_PC <= '1'; when 3 => NoRead <= '1'; I_BC <= '1'; TStates <= "101"; + No_PC <= '1'; when 4 => NoRead <= '1'; TStates <= "101"; @@ -1807,7 +1958,7 @@ begin when "01010110"|"01110110" => -- IM 1 IMode <= "01"; - when "01011110"|"01110111" => + when "01011110"|"01111110" => -- IM 2 IMode <= "10"; -- 16 bit arithmetic @@ -1815,6 +1966,8 @@ begin -- ADC HL,ss MCycles <= "011"; case to_integer(unsigned(MCycle)) is + when 1 => + No_PC <= '1'; when 2 => NoRead <= '1'; ALU_Op <= "0001"; @@ -1830,6 +1983,7 @@ begin end case; TStates <= "100"; SetWZ <= "11"; + No_PC <= '1'; when 3 => NoRead <= '1'; Read_To_Reg <= '1'; @@ -1849,6 +2003,8 @@ begin -- SBC HL,ss MCycles <= "011"; case to_integer(unsigned(MCycle)) is + when 1 => + No_PC <= '1'; when 2 => NoRead <= '1'; ALU_Op <= "0011"; @@ -1864,6 +2020,7 @@ begin end case; TStates <= "100"; SetWZ <= "11"; + No_PC <= '1'; when 3 => NoRead <= '1'; ALU_Op <= "0011"; @@ -1890,6 +2047,7 @@ begin Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1101"; Save_ALU <= '1'; + No_PC <= '1'; when 3 => TStates <= "100"; I_RLD <= '1'; @@ -1911,6 +2069,7 @@ begin Set_BusA_To(2 downto 0) <= "111"; ALU_Op <= "1110"; Save_ALU <= '1'; + No_PC <= '1'; when 3 => TStates <= "100"; I_RRD <= '1'; @@ -2032,6 +2191,46 @@ begin TStates <= "101"; when others => null; end case; + when "11000001"|"11001001"|"11010001"|"11011001" => + --R800 MULUB + if R800_mode = '1' then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + I_MULUB <= '1'; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + Set_BusB_To(3) <= '0'; + when 2 => + NoRead <= '1'; + I_MULU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + when others => null; + end case; + end if; + when "11000011"|"11110011" => + --R800 MULUW + if R800_mode = '1' then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + if DPAIR = "11" then + Set_BusB_To(3 downto 0) <= "1000"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + Set_BusA_To(2 downto 0) <= "100"; + when 2 => + TStates <= "101"; + NoRead <= '1'; + I_MULU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + when others => null; + end case; + end if; end case; end case; @@ -2064,6 +2263,9 @@ begin if IRB = "00110110" or IRB = "11001011" then Set_Addr_To <= aNone; end if; + if not (IRB = "00110110" or ISet = "01") then + No_PC <= '1'; + end if; end if; if MCycle = "111" then if Mode = 0 then diff --git a/src/T80/T80_Pack.vhd b/src/T80/T80_Pack.vhd index 0b2cfa9..fc1407a 100644 --- a/src/T80/T80_Pack.vhd +++ b/src/T80/T80_Pack.vhd @@ -11,7 +11,7 @@ -- -- Z80 compatible microprocessor core -- --- Version : 0242 +-- Version : 0250 -- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- @@ -84,7 +84,7 @@ package T80_Pack is port( RESET_n : in std_logic; CLK_n : in std_logic; - CEN : in std_logic; + CEN : in std_logic; WAIT_n : in std_logic; INT_n : in std_logic; NMI_n : in std_logic; @@ -96,16 +96,17 @@ package T80_Pack is RFSH_n : out std_logic; HALT_n : out std_logic; BUSAK_n : out std_logic; - A : out std_logic_vector(15 downto 0); + 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); + 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; - NMICycle_n : out std_logic; IntE : out std_logic; Stop : out std_logic; + R800_mode : in std_logic := '0'; + out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A DIRSet : in std_logic := '0'; DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A @@ -114,24 +115,24 @@ package T80_Pack is component T80_Reg port( - Clk : in std_logic; - CEN : in std_logic; - WEH : in std_logic; - WEL : in std_logic; - AddrA : in std_logic_vector(2 downto 0); - AddrB : in std_logic_vector(2 downto 0); - AddrC : in std_logic_vector(2 downto 0); - DIH : in std_logic_vector(7 downto 0); - DIL : in std_logic_vector(7 downto 0); - DOAH : out std_logic_vector(7 downto 0); - DOAL : out std_logic_vector(7 downto 0); - DOBH : out std_logic_vector(7 downto 0); - DOBL : out std_logic_vector(7 downto 0); - DOCH : out std_logic_vector(7 downto 0); - DOCL : out std_logic_vector(7 downto 0); - DOR : out std_logic_vector(127 downto 0); - DIRSet : in std_logic; - DIR : in std_logic_vector(127 downto 0) + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0); + DOR : out std_logic_vector(127 downto 0); + DIRSet : in std_logic; + DIR : in std_logic_vector(127 downto 0) ); end component; @@ -168,6 +169,7 @@ package T80_Pack is ALU_Op : out std_logic_vector(3 downto 0); -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None Save_ALU : out std_logic; + Rot_Akku : out std_logic; PreserveC : out std_logic; Arith16 : out std_logic; Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI @@ -181,7 +183,7 @@ package T80_Pack is LDW : out std_logic; LDSPHL : out std_logic; LDHLSP : out std_logic; - ADDSPdd : out std_logic; + ADDSPdd : out std_logic; Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None ExchangeDH : out std_logic; ExchangeRp : out std_logic; @@ -198,12 +200,17 @@ package T80_Pack is I_RLD : out std_logic; I_RRD : out std_logic; I_INRC : out std_logic; + I_MULUB : out std_logic; + I_MULU : out std_logic; + SetWZ : out std_logic_vector(1 downto 0); SetDI : out std_logic; SetEI : out std_logic; IMode : out std_logic_vector(1 downto 0); Halt : out std_logic; NoRead : out std_logic; Write : out std_logic; + R800_mode : in std_logic; + No_PC : out std_logic; XYbit_undoc : out std_logic ); end component; @@ -223,7 +230,10 @@ package T80_Pack is port( Arith16 : in std_logic; Z16 : in std_logic; + WZ : in std_logic_vector(15 downto 0); + XY_State : in std_logic_vector(1 downto 0); ALU_Op : in std_logic_vector(3 downto 0); + Rot_Akku : in std_logic; IR : in std_logic_vector(5 downto 0); ISet : in std_logic_vector(1 downto 0); BusA : in std_logic_vector(7 downto 0); diff --git a/src/T80/T80a.vhd b/src/T80/T80a.vhd index f225df2..fdd84d1 100644 --- a/src/T80/T80a.vhd +++ b/src/T80/T80a.vhd @@ -1,7 +1,16 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** -- -- Z80 compatible microprocessor core, asynchronous top level -- --- Version : 0247a +-- Version : 0250 -- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- @@ -38,28 +47,32 @@ -- you have the latest version of this file. -- -- The latest version of this file can be found at: --- http://www.opencores.org/cvsweb.shtml/t80/ +-- http://www.opencores.org/cvsweb.shtml/t80/ -- -- Limitations : -- -- File history : -- --- 0208 : First complete release +-- 0208 : First complete release -- --- 0211 : Fixed interrupt cycle +-- 0211 : Fixed interrupt cycle -- --- 0235 : Updated for T80 interface change +-- 0235 : Updated for T80 interface change -- --- 0238 : Updated for T80 interface change +-- 0238 : Updated for T80 interface change -- --- 0240 : Updated for T80 interface change +-- 0240 : Updated for T80 interface change -- --- 0242 : Updated for T80 interface change +-- 0242 : Updated for T80 interface change -- --- 0247 : Fixed bus req/ack cycle +-- 0247 : Fixed bus req/ack cycle +-- +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 +-- +-- Bus signal logic changes from the ZX Spectrum Next were made by: +-- +-- Fabio Belavenuto, Charlie Ingley -- --- 0247a: 7th of September, 2003 by Kazuhiro Tsujikawa (tujikawa@hat.hi-ho.ne.jp) --- Fixed IORQ_n, RD_n, WR_n bus timing library IEEE; use IEEE.std_logic_1164.all; @@ -67,269 +80,263 @@ 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( - -- Additions - TS : out std_logic_vector(2 downto 0); - Regs : out std_logic_vector(255 downto 0); - PdcData : out std_logic_vector(7 downto 0); - -- Original Signals - RESET_n : in std_logic; - CLK_n : in std_logic; - CEN : in std_logic; - WAIT_n : in std_logic; - INT_n : in std_logic; - NMI_n : in std_logic; - BUSRQ_n : in std_logic; - M1_n : out std_logic; - MREQ_n : out std_logic; - IORQ_n : out std_logic; - RD_n : out std_logic; - WR_n : out std_logic; - RFSH_n : out std_logic; - HALT_n : out std_logic; - BUSAK_n : out std_logic; - A : out std_logic_vector(15 downto 0); - Din : in std_logic_vector(7 downto 0); - Dout : out std_logic_vector(7 downto 0); - Den : out std_logic - ); + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle + ); + port( + RESET_n : in std_logic; + R800_mode : in std_logic; + CLK_n : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + D : inout std_logic_vector(7 downto 0) + ); end T80a; architecture rtl of T80a is - signal Reset_s : std_logic; - signal IntCycle_n : std_logic; - signal NMICycle_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 IReq_Inhibit : std_logic; -- 0247a - 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 WR_n_j : std_logic; -- 0247a - signal RFSH_n_i : std_logic; - signal BUSAK_n_i : std_logic; - signal A_i : std_logic_vector(15 downto 0); - signal DO : std_logic_vector(7 downto 0); - signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser - signal Wait_s : std_logic; - signal MCycle : std_logic_vector(2 downto 0); - signal TState : std_logic_vector(2 downto 0); - signal HALT_n_int : std_logic; - signal iack1 : std_logic; - signal iack2 : std_logic; + signal CEN : std_logic; + signal Reset_s : std_logic; + signal IntCycle_n : std_logic; + signal IORQ : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal MREQ : std_logic; + signal MReq_Inhibit : std_logic; + signal Req_Inhibit : std_logic; + signal RD : std_logic; + signal MREQ_n_i : std_logic; + signal MREQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add MREQ control + signal IORQ_n_i : std_logic; + signal IORQ_t1 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control + signal IORQ_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control + signal IORQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control + signal IORQ_int : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ interrupt control + signal IORQ_int_inhibit : std_logic_vector(2 downto 0); + signal RD_n_i : std_logic; + signal WR_n_i : std_logic; + signal WR_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add WR control + signal RFSH_n_i : std_logic; + signal BUSAK_n_i : std_logic; + signal A_i : std_logic_vector(15 downto 0); + signal DO : std_logic_vector(7 downto 0); + signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser + signal Wait_s : std_logic; + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); begin + CEN <= '1'; - BUSAK_n <= BUSAK_n_i; - MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit); - RD_n_i <= not RD or (IORQ and IReq_Inhibit) or Req_Inhibit; -- DMB - WR_n_j <= WR_n_i or (IORQ and IReq_Inhibit); -- DMB - HALT_n <= HALT_n_int; + BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes + MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control + MREQ_n_i <= not MREQ_rw; -- changed MREQ generation + IORQ_rw <= IORQ and not (IORQ_t1 or IORQ_t2); -- added IORQ generation timing control + IORQ_n_i <= not ((IORQ_int and not IORQ_int_inhibit(2)) or IORQ_rw); -- changed IORQ generation + RD_n_i <= not (RD and (MREQ_rw or IORQ_rw)); -- changed RD/IORQ generation + WR_n_i <= not (Write and ((WR_t2 and MREQ_rw) or IORQ_rw)); -- added WR/IORQ timing control + MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; + IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; + RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; + WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z'; + RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; + A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); + D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); - --Remove tristate as in ICE-Z80 this is implmeneted in Z80CpuMon - --MREQ_n <= MREQ_n_i; when BUSAK_n_i = '1' else 'Z'; - --IORQ_n <= IORQ_n_i or IReq_Inhibit when BUSAK_n_i = '1' else 'Z'; -- 0247a - --RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; - --WR_n <= WR_n_j when BUSAK_n_i = '1' else 'Z'; -- 0247a - --RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; - --A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); + 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; - MREQ_n <= MREQ_n_i; - IORQ_n <= IORQ_n_i or IReq_Inhibit or Req_inhibit; --DMB - RD_n <= RD_n_i; - WR_n <= WR_n_j; -- 0247a - RFSH_n <= RFSH_n_i; - A <= A_i; + u0 : T80 + generic map( + Mode => Mode, + IOWait => IOWait) + port map( + R800_mode => R800_mode, + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n_i, + HALT_n => HALT_n, + WAIT_n => Wait_s, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => Reset_s, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n_i, + CLK_n => CLK_n, + A => A_i, + DInst => D, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); - Dout <= DO; - Den <= Write and BUSAK_n_i; + 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_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; +-- 30/10/19 Charlie Ingley - Generate WR_t2 to correct MREQ/WR timing + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then + WR_t2 <= '0'; + elsif CLK_n'event and CLK_n = '0' then + if MCycle /= "001" then + if TState = "010" then -- WR starts on falling edge of T2 for MREQ + WR_t2 <= Write; + end if; + end if; + if TState = "011" then -- end WR + WR_t2 <= '0'; + end if; + end if; + end process; - 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_int, - 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 => Din, - DI => DI_Reg, - DO => DO, - MC => MCycle, - TS => TState, - IntCycle_n => IntCycle_n, - NMICycle_n => NMICycle_n, - REG => Regs(211 downto 0), - DIRSet => '0', - DIR => (others => '0') - ); - - Regs(255 downto 212) <= (others => '0'); - - process (CLK_n) - begin - if CLK_n'event and CLK_n = '0' then - if CEN = '1' then - Wait_s <= WAIT_n; - if TState = "011" and BUSAK_n_i = '1' then - DI_Reg <= to_x01(Din); - end if; - end if; - end if; - end process; - - process (CLK_n) -- 0247a - begin - if CLK_n'event and CLK_n = '1' then - IReq_Inhibit <= (not IORQ) and IntCycle_n; - end if; - end process; - - process (Reset_s,CLK_n) -- 0247a - begin - if Reset_s = '0' then - WR_n_i <= '1'; - elsif CLK_n'event and CLK_n = '0' then - if CEN = '1' then - if (IORQ = '0') then - if TState = "010" then - WR_n_i <= not Write; - elsif Tstate = "011" then - WR_n_i <= '1'; - end if; - else - if TState = "001" then -- DMB - WR_n_i <= not Write; - elsif Tstate = "011" then - WR_n_i <= '1'; - end if; - end if; - end if; - end if; - end process; - - process (Reset_s,CLK_n) -- 0247a - begin - if Reset_s = '0' then +-- Generate Req_Inhibit + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then + Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity + elsif CLK_n'event and CLK_n = '1' then + if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n Req_Inhibit <= '0'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - if MCycle = "001" and TState = "010" and wait_s = '1' then - Req_Inhibit <= '1'; - else - Req_Inhibit <= '0'; - end if; - end if; - end if; - end process; + else + Req_Inhibit <= '1'; + end if; + end if; + end process; - process (Reset_s,CLK_n) - begin - if Reset_s = '0' then +-- Generate MReq_Inhibit + process (Reset_s, CLK_n) + begin + if Reset_s = '0' then + MReq_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity + elsif CLK_n'event and CLK_n = '0' then + if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n MReq_Inhibit <= '0'; - elsif CLK_n'event and CLK_n = '0' then - if CEN = '1' then - if MCycle = "001" and TState = "010" then - MReq_Inhibit <= '1'; - else - MReq_Inhibit <= '0'; - end if; + else + MReq_Inhibit <= '1'; + end if; + end if; + end process; + +-- Generate RD for MREQ + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + RD <= '0'; + MREQ <= '0'; + elsif CLK_n'event and CLK_n = '0' then + if MCycle = "001" then + if TState = "001" then + RD <= IntCycle_n; + MREQ <= IntCycle_n; end if; - end if; - end process; - - process(Reset_s,CLK_n) -- 0247a - begin - if Reset_s = '0' then - RD <= '0'; - IORQ_n_i <= '1'; - MREQ <= '0'; - iack1 <= '0'; - iack2 <= '0'; - elsif CLK_n'event and CLK_n = '0' then - if CEN = '1' then - if MCycle = "001" then - if IntCycle_n = '1' then - -- Normal M1 Cycle - if TState = "001" then - RD <= '1'; - MREQ <= '1'; - IORQ_n_i <= '1'; - end if; - else - -- Interupt Ack Cycle - -- 5 T-states: T1 T1 (auto wait) T1 (auto wait) T2 T3 - -- Assert IORQ in middle of third T1 - if TState = "001" then - iack1 <= '1'; - iack2 <= iack1; - else - iack1 <= '0'; - iack2 <= '0'; - end if; - if iack2 = '1' then - IORQ_n_i <= '0'; - end if; - end if; - if TState = "011" then - RD <= '0'; - IORQ_n_i <= '1'; - MREQ <= '1'; - end if; - if TState = "100" then - MREQ <= '0'; - end if; - else - if TState = "001" and NoRead = '0' then - IORQ_n_i <= not IORQ; - MREQ <= not IORQ; - RD <= not Write; -- DMB - end if; - if TState = "011" then - RD <= '0'; - IORQ_n_i <= '1'; - MREQ <= '0'; - end if; - end if; + if TState = "011" then + RD <= '0'; + MREQ <= '1'; end if; - end if; - end process; + if TState = "100" then + MREQ <= '0'; + end if; + else + if TState = "001" and NoRead = '0' then + RD <= not Write; + MREQ <= not IORQ; + end if; + if TState = "011" then + RD <= '0'; + MREQ <= '0'; + end if; + end if; + end if; + end process; - TS <= TState; + -- 30/10/19 Charlie Ingley - Generate IORQ_int for IORQ interrupt timing control + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + IORQ_int <= '0'; + elsif CLK_n'event and CLK_n = '1' then + if MCycle = "001" then + if TState = "001" then + IORQ_int <= not IntCycle_n; + end if; + if TState = "010" then + IORQ_int <= '0'; + end if; + end if; + end if; + end process; - PdcData <= (not HALT_n_int) & (not NMICycle_n) & (not IntCycle_n) & "00000"; + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + IORQ_int_inhibit <= "111"; + elsif CLK_n'event and CLK_n = '0' then + if IntCycle_n = '0' then + if MCycle = "001" then + IORQ_int_inhibit <= IORQ_int_inhibit(1 downto 0) & '0'; + end if; + if MCycle = "010" then + IORQ_int_inhibit <= "111"; + end if; + end if; + end if; + end process; + +-- 30/10/19 Charlie Ingley - Generate IORQ_t1 for IORQ timing control + process(Reset_s, CLK_n) + begin + if Reset_s = '0' then + IORQ_t1 <= '1'; + elsif CLK_n'event and CLK_n = '0' then + if TState = "001" then + IORQ_t1 <= not IntCycle_n; + end if; + if TState = "011" then + IORQ_t1 <= '1'; + end if; + end if; + end process; + +-- 30/10/19 Charlie Ingley - Generate IORQ_t2 for IORQ timing control + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + IORQ_t2 <= '1'; + elsif CLK_n'event and CLK_n = '1' then + IORQ_t2 <= IORQ_t1; + end if; + end process; end; From 670328574b026b740b4dd52e910a64a3ae7beced Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 30 Jun 2021 12:46:22 +0100 Subject: [PATCH 2/9] Z80: T80: whitespace Change-Id: If8617f1a93dd9bb0fc1ff94b2d72924f6db34483 --- src/T80/T80a.vhd | 458 +++++++++++++++++++++++------------------------ 1 file changed, 229 insertions(+), 229 deletions(-) diff --git a/src/T80/T80a.vhd b/src/T80/T80a.vhd index fdd84d1..e6e87ea 100644 --- a/src/T80/T80a.vhd +++ b/src/T80/T80a.vhd @@ -80,263 +80,263 @@ use IEEE.numeric_std.all; use work.T80_Pack.all; entity T80a is - generic( - Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB - IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle - ); - port( - RESET_n : in std_logic; - R800_mode : in std_logic; - CLK_n : in std_logic; - WAIT_n : in std_logic; - INT_n : in std_logic; - NMI_n : in std_logic; - BUSRQ_n : in std_logic; - M1_n : out std_logic; - MREQ_n : out std_logic; - IORQ_n : out std_logic; - RD_n : out std_logic; - WR_n : out std_logic; - RFSH_n : out std_logic; - HALT_n : out std_logic; - BUSAK_n : out std_logic; - A : out std_logic_vector(15 downto 0); - D : inout std_logic_vector(7 downto 0) - ); + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle + ); + port( + RESET_n : in std_logic; + R800_mode : in std_logic; + CLK_n : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + D : inout std_logic_vector(7 downto 0) + ); end T80a; architecture rtl of T80a is - signal CEN : std_logic; - signal Reset_s : std_logic; - signal IntCycle_n : std_logic; - signal IORQ : std_logic; - signal NoRead : std_logic; - signal Write : std_logic; - signal MREQ : std_logic; - signal MReq_Inhibit : std_logic; - signal Req_Inhibit : std_logic; - signal RD : std_logic; - signal MREQ_n_i : std_logic; - signal MREQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add MREQ control - signal IORQ_n_i : std_logic; - signal IORQ_t1 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_int : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ interrupt control - signal IORQ_int_inhibit : std_logic_vector(2 downto 0); - signal RD_n_i : std_logic; - signal WR_n_i : std_logic; - signal WR_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add WR control - signal RFSH_n_i : std_logic; - signal BUSAK_n_i : std_logic; - signal A_i : std_logic_vector(15 downto 0); - signal DO : std_logic_vector(7 downto 0); - signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser - signal Wait_s : std_logic; - signal MCycle : std_logic_vector(2 downto 0); - signal TState : std_logic_vector(2 downto 0); + signal CEN : std_logic; + signal Reset_s : std_logic; + signal IntCycle_n : std_logic; + signal IORQ : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal MREQ : std_logic; + signal MReq_Inhibit : std_logic; + signal Req_Inhibit : std_logic; + signal RD : std_logic; + signal MREQ_n_i : std_logic; + signal MREQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add MREQ control + signal IORQ_n_i : std_logic; + signal IORQ_t1 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control + signal IORQ_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control + signal IORQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control + signal IORQ_int : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ interrupt control + signal IORQ_int_inhibit : std_logic_vector(2 downto 0); + signal RD_n_i : std_logic; + signal WR_n_i : std_logic; + signal WR_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add WR control + signal RFSH_n_i : std_logic; + signal BUSAK_n_i : std_logic; + signal A_i : std_logic_vector(15 downto 0); + signal DO : std_logic_vector(7 downto 0); + signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser + signal Wait_s : std_logic; + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); begin - CEN <= '1'; + CEN <= '1'; - BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes - MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control - MREQ_n_i <= not MREQ_rw; -- changed MREQ generation - IORQ_rw <= IORQ and not (IORQ_t1 or IORQ_t2); -- added IORQ generation timing control - IORQ_n_i <= not ((IORQ_int and not IORQ_int_inhibit(2)) or IORQ_rw); -- changed IORQ generation - RD_n_i <= not (RD and (MREQ_rw or IORQ_rw)); -- changed RD/IORQ generation - WR_n_i <= not (Write and ((WR_t2 and MREQ_rw) or IORQ_rw)); -- added WR/IORQ timing control + BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes + MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control + MREQ_n_i <= not MREQ_rw; -- changed MREQ generation + IORQ_rw <= IORQ and not (IORQ_t1 or IORQ_t2); -- added IORQ generation timing control + IORQ_n_i <= not ((IORQ_int and not IORQ_int_inhibit(2)) or IORQ_rw); -- changed IORQ generation + RD_n_i <= not (RD and (MREQ_rw or IORQ_rw)); -- changed RD/IORQ generation + WR_n_i <= not (Write and ((WR_t2 and MREQ_rw) or IORQ_rw)); -- added WR/IORQ timing control - MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; - IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; - RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; - WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z'; - RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; - A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); - D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); + 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; + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + Reset_s <= '0'; + elsif CLK_n'event and CLK_n = '1' then + Reset_s <= '1'; + end if; + end process; - u0 : T80 - generic map( - Mode => Mode, - IOWait => IOWait) - port map( - R800_mode => R800_mode, - CEN => CEN, - M1_n => M1_n, - IORQ => IORQ, - NoRead => NoRead, - Write => Write, - RFSH_n => RFSH_n_i, - HALT_n => HALT_n, - WAIT_n => Wait_s, - INT_n => INT_n, - NMI_n => NMI_n, - RESET_n => Reset_s, - BUSRQ_n => BUSRQ_n, - BUSAK_n => BUSAK_n_i, - CLK_n => CLK_n, - A => A_i, - DInst => D, - DI => DI_Reg, - DO => DO, - MC => MCycle, - TS => TState, - IntCycle_n => IntCycle_n); + u0 : T80 + generic map( + Mode => Mode, + IOWait => IOWait) + port map( + R800_mode => R800_mode, + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n_i, + HALT_n => HALT_n, + WAIT_n => Wait_s, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => Reset_s, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n_i, + CLK_n => CLK_n, + A => A_i, + DInst => D, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); - process (CLK_n) - begin - if CLK_n'event and CLK_n = '0' then - Wait_s <= WAIT_n; - if TState = "011" and BUSAK_n_i = '1' then - DI_Reg <= to_x01(D); - end if; - end if; - end process; + process (CLK_n) + begin + if CLK_n'event and CLK_n = '0' then + Wait_s <= WAIT_n; + if TState = "011" and BUSAK_n_i = '1' then + DI_Reg <= to_x01(D); + end if; + end if; + end process; -- 30/10/19 Charlie Ingley - Generate WR_t2 to correct MREQ/WR timing - process (Reset_s,CLK_n) - begin - if Reset_s = '0' then - WR_t2 <= '0'; - elsif CLK_n'event and CLK_n = '0' then - if MCycle /= "001" then - if TState = "010" then -- WR starts on falling edge of T2 for MREQ - WR_t2 <= Write; - end if; - end if; - if TState = "011" then -- end WR + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then WR_t2 <= '0'; - end if; - end if; - end process; + elsif CLK_n'event and CLK_n = '0' then + if MCycle /= "001" then + if TState = "010" then -- WR starts on falling edge of T2 for MREQ + WR_t2 <= Write; + end if; + end if; + if TState = "011" then -- end WR + WR_t2 <= '0'; + end if; + end if; + end process; -- Generate Req_Inhibit - process (Reset_s,CLK_n) - begin - if Reset_s = '0' then - Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity - elsif CLK_n'event and CLK_n = '1' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - Req_Inhibit <= '0'; - else - Req_Inhibit <= '1'; - end if; - end if; - end process; + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then + Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity + elsif CLK_n'event and CLK_n = '1' then + if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n + Req_Inhibit <= '0'; + else + Req_Inhibit <= '1'; + end if; + end if; + end process; -- Generate MReq_Inhibit - process (Reset_s, CLK_n) - begin - if Reset_s = '0' then - MReq_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity - elsif CLK_n'event and CLK_n = '0' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - MReq_Inhibit <= '0'; - else - MReq_Inhibit <= '1'; - end if; - end if; - end process; + process (Reset_s, CLK_n) + begin + if Reset_s = '0' then + MReq_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity + elsif CLK_n'event and CLK_n = '0' then + if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n + MReq_Inhibit <= '0'; + else + MReq_Inhibit <= '1'; + end if; + end if; + end process; -- Generate RD for MREQ - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - RD <= '0'; - MREQ <= '0'; - elsif CLK_n'event and CLK_n = '0' then - if MCycle = "001" then - if TState = "001" then - RD <= IntCycle_n; - MREQ <= IntCycle_n; - end if; - if TState = "011" then - RD <= '0'; - MREQ <= '1'; - end if; - if TState = "100" then - MREQ <= '0'; - end if; - else - if TState = "001" and NoRead = '0' then - RD <= not Write; - MREQ <= not IORQ; - end if; - if TState = "011" then - RD <= '0'; - MREQ <= '0'; - end if; - end if; - end if; - end process; - - -- 30/10/19 Charlie Ingley - Generate IORQ_int for IORQ interrupt timing control - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - IORQ_int <= '0'; - elsif CLK_n'event and CLK_n = '1' then - if MCycle = "001" then - if TState = "001" then - IORQ_int <= not IntCycle_n; - end if; - if TState = "010" then - IORQ_int <= '0'; - end if; - end if; - end if; - end process; - - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - IORQ_int_inhibit <= "111"; - elsif CLK_n'event and CLK_n = '0' then - if IntCycle_n = '0' then + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + RD <= '0'; + MREQ <= '0'; + elsif CLK_n'event and CLK_n = '0' then if MCycle = "001" then - IORQ_int_inhibit <= IORQ_int_inhibit(1 downto 0) & '0'; + if TState = "001" then + RD <= IntCycle_n; + MREQ <= IntCycle_n; + end if; + if TState = "011" then + RD <= '0'; + MREQ <= '1'; + end if; + if TState = "100" then + MREQ <= '0'; + end if; + else + if TState = "001" and NoRead = '0' then + RD <= not Write; + MREQ <= not IORQ; + end if; + if TState = "011" then + RD <= '0'; + MREQ <= '0'; + end if; end if; - if MCycle = "010" then - IORQ_int_inhibit <= "111"; + end if; + end process; + + -- 30/10/19 Charlie Ingley - Generate IORQ_int for IORQ interrupt timing control + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + IORQ_int <= '0'; + elsif CLK_n'event and CLK_n = '1' then + if MCycle = "001" then + if TState = "001" then + IORQ_int <= not IntCycle_n; + end if; + if TState = "010" then + IORQ_int <= '0'; + end if; end if; - end if; - end if; - end process; + end if; + end process; + + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + IORQ_int_inhibit <= "111"; + elsif CLK_n'event and CLK_n = '0' then + if IntCycle_n = '0' then + if MCycle = "001" then + IORQ_int_inhibit <= IORQ_int_inhibit(1 downto 0) & '0'; + end if; + if MCycle = "010" then + IORQ_int_inhibit <= "111"; + end if; + end if; + end if; + end process; -- 30/10/19 Charlie Ingley - Generate IORQ_t1 for IORQ timing control - process(Reset_s, CLK_n) - begin - if Reset_s = '0' then - IORQ_t1 <= '1'; - elsif CLK_n'event and CLK_n = '0' then - if TState = "001" then - IORQ_t1 <= not IntCycle_n; - end if; - if TState = "011" then + process(Reset_s, CLK_n) + begin + if Reset_s = '0' then IORQ_t1 <= '1'; - end if; - end if; - end process; + elsif CLK_n'event and CLK_n = '0' then + if TState = "001" then + IORQ_t1 <= not IntCycle_n; + end if; + if TState = "011" then + IORQ_t1 <= '1'; + end if; + end if; + end process; -- 30/10/19 Charlie Ingley - Generate IORQ_t2 for IORQ timing control - process (RESET_n, CLK_n) - begin - if RESET_n = '0' then - IORQ_t2 <= '1'; - elsif CLK_n'event and CLK_n = '1' then - IORQ_t2 <= IORQ_t1; - end if; - end process; + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + IORQ_t2 <= '1'; + elsif CLK_n'event and CLK_n = '1' then + IORQ_t2 <= IORQ_t1; + end if; + end process; end; From e65951cfbb64f9897e1d22c7aa45b15d68f4df54 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 30 Jun 2021 13:18:15 +0100 Subject: [PATCH 3/9] Z80: Daves's fixes to T80 for ICE-Z80 Change-Id: Id1530b7c3f433ff2ff2b6f7966e3c93657058761 --- src/T80/T80.vhd | 4 +- src/T80/T80_Pack.vhd | 1 + src/T80/T80a.vhd | 197 +++++++++++++++++++++++++++---------------- 3 files changed, 129 insertions(+), 73 deletions(-) diff --git a/src/T80/T80.vhd b/src/T80/T80.vhd index 5ad3e90..24025a3 100644 --- a/src/T80/T80.vhd +++ b/src/T80/T80.vhd @@ -117,6 +117,7 @@ entity T80 is MC : out std_logic_vector(2 downto 0); TS : out std_logic_vector(2 downto 0); IntCycle_n : out std_logic; + NMICycle_n : out std_logic; IntE : out std_logic; Stop : out std_logic; R800_mode : in std_logic := '0'; @@ -682,7 +683,7 @@ begin F(Flag_N) <= DI_Reg(7); F(Flag_C) <= ioq(8); F(Flag_H) <= ioq(8); - ioq := (ioq and x"7") xor ('0'&BusA); + ioq := (ioq and ('0'&x"07")) 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; @@ -1193,6 +1194,7 @@ begin HALT_n <= not Halt_FF; BUSAK_n <= not (BusAck and RESET_n); IntCycle_n <= not IntCycle; + NMICycle_n <= not NMICycle; IntE <= IntE_FF1; IORQ <= IORQ_i; Stop <= I_DJNZ; diff --git a/src/T80/T80_Pack.vhd b/src/T80/T80_Pack.vhd index fc1407a..e5186ab 100644 --- a/src/T80/T80_Pack.vhd +++ b/src/T80/T80_Pack.vhd @@ -103,6 +103,7 @@ package T80_Pack is MC : out std_logic_vector(2 downto 0); TS : out std_logic_vector(2 downto 0); IntCycle_n : out std_logic; + NMICycle_n : out std_logic; IntE : out std_logic; Stop : out std_logic; R800_mode : in std_logic := '0'; diff --git a/src/T80/T80a.vhd b/src/T80/T80a.vhd index e6e87ea..0eca83f 100644 --- a/src/T80/T80a.vhd +++ b/src/T80/T80a.vhd @@ -85,8 +85,17 @@ entity T80a is IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle ); port( + -- DMB + TS : out std_logic_vector(2 downto 0); + Regs : out std_logic_vector(255 downto 0); + PdcData : out std_logic_vector(7 downto 0); + CEN : in std_logic; + Din : in std_logic_vector(7 downto 0); + Dout : out std_logic_vector(7 downto 0); + Den : out std_logic; + -- Original Signals RESET_n : in std_logic; - R800_mode : in std_logic; + R800_mode : in std_logic := '0'; CLK_n : in std_logic; WAIT_n : in std_logic; INT_n : in std_logic; @@ -100,16 +109,16 @@ entity T80a is 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) + A : out std_logic_vector(15 downto 0) +-- D : inout std_logic_vector(7 downto 0) ); end T80a; architecture rtl of T80a is - signal CEN : std_logic; signal Reset_s : std_logic; signal IntCycle_n : std_logic; + signal NMICycle_n : std_logic; signal IORQ : std_logic; signal NoRead : std_logic; signal Write : std_logic; @@ -136,11 +145,10 @@ architecture rtl of T80a is signal Wait_s : std_logic; signal MCycle : std_logic_vector(2 downto 0); signal TState : std_logic_vector(2 downto 0); + signal HALT_n_int : std_logic; begin - CEN <= '1'; - BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control MREQ_n_i <= not MREQ_rw; -- changed MREQ generation @@ -148,21 +156,34 @@ begin IORQ_n_i <= not ((IORQ_int and not IORQ_int_inhibit(2)) or IORQ_rw); -- changed IORQ generation RD_n_i <= not (RD and (MREQ_rw or IORQ_rw)); -- changed RD/IORQ generation WR_n_i <= not (Write and ((WR_t2 and MREQ_rw) or IORQ_rw)); -- added WR/IORQ timing control + HALT_n <= HALT_n_int; - 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'); + --Remove tristate as in ICE-Z80 this is implmeneted in Z80CpuMon + --MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; + --IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; + --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'); + + MREQ_n <= MREQ_n_i; + IORQ_n <= IORQ_n_i; + RD_n <= RD_n_i; + WR_n <= WR_n_i; + RFSH_n <= RFSH_n_i; + A <= A_i; + Dout <= DO; + Den <= Write and BUSAK_n_i; 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'; + if CEN = '1' then + Reset_s <= '1'; + end if; end if; end process; @@ -178,7 +199,7 @@ begin NoRead => NoRead, Write => Write, RFSH_n => RFSH_n_i, - HALT_n => HALT_n, + HALT_n => HALT_n_int, WAIT_n => Wait_s, INT_n => INT_n, NMI_n => NMI_n, @@ -187,19 +208,29 @@ begin BUSAK_n => BUSAK_n_i, CLK_n => CLK_n, A => A_i, - DInst => D, + DInst => Din, DI => DI_Reg, DO => DO, MC => MCycle, TS => TState, - IntCycle_n => IntCycle_n); + IntCycle_n => IntCycle_n, + -- DMB + NMICycle_n => NMICycle_n, + REG => Regs(211 downto 0), + DIRSet => '0', + DIR => (others => '0') + ); + + Regs(255 downto 212) <= (others => '0'); 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); + if CEN = '1' then + Wait_s <= WAIT_n; + if TState = "011" and BUSAK_n_i = '1' then + DI_Reg <= to_x01(Din); + end if; end if; end if; end process; @@ -210,13 +241,15 @@ begin if Reset_s = '0' then WR_t2 <= '0'; elsif CLK_n'event and CLK_n = '0' then - if MCycle /= "001" then - if TState = "010" then -- WR starts on falling edge of T2 for MREQ - WR_t2 <= Write; + if CEN = '1' then + if MCycle /= "001" then + if TState = "010" then -- WR starts on falling edge of T2 for MREQ + WR_t2 <= Write; + end if; + end if; + if TState = "011" then -- end WR + WR_t2 <= '0'; end if; - end if; - if TState = "011" then -- end WR - WR_t2 <= '0'; end if; end if; end process; @@ -227,10 +260,12 @@ begin if Reset_s = '0' then Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity elsif CLK_n'event and CLK_n = '1' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - Req_Inhibit <= '0'; - else - Req_Inhibit <= '1'; + if CEN = '1' then + if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n + Req_Inhibit <= '0'; + else + Req_Inhibit <= '1'; + end if; end if; end if; end process; @@ -241,10 +276,12 @@ begin if Reset_s = '0' then MReq_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity elsif CLK_n'event and CLK_n = '0' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - MReq_Inhibit <= '0'; - else - MReq_Inhibit <= '1'; + if CEN = '1' then + if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n + MReq_Inhibit <= '0'; + else + MReq_Inhibit <= '1'; + end if; end if; end if; end process; @@ -256,26 +293,28 @@ begin RD <= '0'; MREQ <= '0'; elsif CLK_n'event and CLK_n = '0' then - if MCycle = "001" then - if TState = "001" then - RD <= IntCycle_n; - MREQ <= IntCycle_n; - end if; - if TState = "011" then - RD <= '0'; - MREQ <= '1'; - end if; - if TState = "100" then - MREQ <= '0'; - end if; - else - if TState = "001" and NoRead = '0' then - RD <= not Write; - MREQ <= not IORQ; - end if; - if TState = "011" then - RD <= '0'; - MREQ <= '0'; + if CEN = '1' then + if MCycle = "001" then + if TState = "001" then + RD <= IntCycle_n; + MREQ <= IntCycle_n; + end if; + if TState = "011" then + RD <= '0'; + MREQ <= '1'; + end if; + if TState = "100" then + MREQ <= '0'; + end if; + else + if TState = "001" and NoRead = '0' then + RD <= not Write; + MREQ <= not IORQ; + end if; + if TState = "011" then + RD <= '0'; + MREQ <= '0'; + end if; end if; end if; end if; @@ -287,12 +326,14 @@ begin if Reset_s = '0' then IORQ_int <= '0'; elsif CLK_n'event and CLK_n = '1' then - if MCycle = "001" then - if TState = "001" then - IORQ_int <= not IntCycle_n; - end if; - if TState = "010" then - IORQ_int <= '0'; + if CEN = '1' then + if MCycle = "001" then + if TState = "001" then + IORQ_int <= not IntCycle_n; + end if; + if TState = "010" then + IORQ_int <= '0'; + end if; end if; end if; end if; @@ -303,12 +344,14 @@ begin if Reset_s = '0' then IORQ_int_inhibit <= "111"; elsif CLK_n'event and CLK_n = '0' then - if IntCycle_n = '0' then - if MCycle = "001" then - IORQ_int_inhibit <= IORQ_int_inhibit(1 downto 0) & '0'; - end if; - if MCycle = "010" then - IORQ_int_inhibit <= "111"; + if CEN = '1' then + if IntCycle_n = '0' then + if MCycle = "001" then + IORQ_int_inhibit <= IORQ_int_inhibit(1 downto 0) & '0'; + end if; + if MCycle = "010" then + IORQ_int_inhibit <= "111"; + end if; end if; end if; end if; @@ -320,11 +363,13 @@ begin if Reset_s = '0' then IORQ_t1 <= '1'; elsif CLK_n'event and CLK_n = '0' then - if TState = "001" then - IORQ_t1 <= not IntCycle_n; - end if; - if TState = "011" then - IORQ_t1 <= '1'; + if CEN = '1' then + if TState = "001" then + IORQ_t1 <= not IntCycle_n; + end if; + if TState = "011" then + IORQ_t1 <= '1'; + end if; end if; end if; end process; @@ -335,8 +380,16 @@ begin if RESET_n = '0' then IORQ_t2 <= '1'; elsif CLK_n'event and CLK_n = '1' then - IORQ_t2 <= IORQ_t1; + if CEN = '1' then + IORQ_t2 <= IORQ_t1; + end if; end if; end process; +-- DMB + + TS <= TState; + + PdcData <= (not HALT_n_int) & (not NMICycle_n) & (not IntCycle_n) & "00000"; + end; From 4ecd60065e672f088f60a2d6faaf5713c02093d7 Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 30 Jun 2021 19:44:01 +0100 Subject: [PATCH 4/9] Z80: Revert T80a wrapper to previous version Change-Id: I856a39c51305e99c3d8b32efe5be1f8ed8b2583f --- src/T80/T80a.vhd | 306 +++++++++++++++++++---------------------------- 1 file changed, 123 insertions(+), 183 deletions(-) diff --git a/src/T80/T80a.vhd b/src/T80/T80a.vhd index 0eca83f..f225df2 100644 --- a/src/T80/T80a.vhd +++ b/src/T80/T80a.vhd @@ -1,16 +1,7 @@ --- **** --- T80(b) core. In an effort to merge and maintain bug fixes .... --- --- --- Ver 300 started tidyup --- MikeJ March 2005 --- Latest version from www.fpgaarcade.com (original www.opencores.org) --- --- **** -- -- Z80 compatible microprocessor core, asynchronous top level -- --- Version : 0250 +-- Version : 0247a -- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- @@ -47,32 +38,28 @@ -- you have the latest version of this file. -- -- The latest version of this file can be found at: --- http://www.opencores.org/cvsweb.shtml/t80/ +-- http://www.opencores.org/cvsweb.shtml/t80/ -- -- Limitations : -- -- File history : -- --- 0208 : First complete release +-- 0208 : First complete release -- --- 0211 : Fixed interrupt cycle +-- 0211 : Fixed interrupt cycle -- --- 0235 : Updated for T80 interface change +-- 0235 : Updated for T80 interface change -- --- 0238 : Updated for T80 interface change +-- 0238 : Updated for T80 interface change -- --- 0240 : Updated for T80 interface change +-- 0240 : Updated for T80 interface change -- --- 0242 : Updated for T80 interface change +-- 0242 : Updated for T80 interface change -- --- 0247 : Fixed bus req/ack cycle --- --- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 --- --- Bus signal logic changes from the ZX Spectrum Next were made by: --- --- Fabio Belavenuto, Charlie Ingley +-- 0247 : Fixed bus req/ack cycle -- +-- 0247a: 7th of September, 2003 by Kazuhiro Tsujikawa (tujikawa@hat.hi-ho.ne.jp) +-- Fixed IORQ_n, RD_n, WR_n bus timing library IEEE; use IEEE.std_logic_1164.all; @@ -81,37 +68,34 @@ use work.T80_Pack.all; entity T80a is generic( - Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB - IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle - ); + Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); port( - -- DMB - TS : out std_logic_vector(2 downto 0); - Regs : out std_logic_vector(255 downto 0); - PdcData : out std_logic_vector(7 downto 0); - CEN : in std_logic; - Din : in std_logic_vector(7 downto 0); - Dout : out std_logic_vector(7 downto 0); - Den : out std_logic; + -- Additions + TS : out std_logic_vector(2 downto 0); + Regs : out std_logic_vector(255 downto 0); + PdcData : out std_logic_vector(7 downto 0); -- Original Signals - RESET_n : in std_logic; - R800_mode : in std_logic := '0'; - CLK_n : in std_logic; - WAIT_n : in std_logic; - INT_n : in std_logic; - NMI_n : in std_logic; - BUSRQ_n : in std_logic; - M1_n : out std_logic; - MREQ_n : out std_logic; - IORQ_n : out std_logic; - RD_n : out std_logic; - WR_n : out std_logic; - RFSH_n : out std_logic; - HALT_n : out std_logic; - BUSAK_n : out std_logic; - A : out std_logic_vector(15 downto 0) --- D : inout std_logic_vector(7 downto 0) - ); + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + Din : in std_logic_vector(7 downto 0); + Dout : out std_logic_vector(7 downto 0); + Den : out std_logic + ); end T80a; architecture rtl of T80a is @@ -124,55 +108,51 @@ architecture rtl of T80a is signal Write : std_logic; signal MREQ : std_logic; signal MReq_Inhibit : std_logic; + signal IReq_Inhibit : std_logic; -- 0247a signal Req_Inhibit : std_logic; signal RD : std_logic; signal MREQ_n_i : std_logic; - signal MREQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add MREQ control signal IORQ_n_i : std_logic; - signal IORQ_t1 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control - signal IORQ_int : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ interrupt control - signal IORQ_int_inhibit : std_logic_vector(2 downto 0); signal RD_n_i : std_logic; signal WR_n_i : std_logic; - signal WR_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add WR control + signal WR_n_j : std_logic; -- 0247a signal RFSH_n_i : std_logic; signal BUSAK_n_i : std_logic; signal A_i : std_logic_vector(15 downto 0); signal DO : std_logic_vector(7 downto 0); - signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser + signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser signal Wait_s : std_logic; signal MCycle : std_logic_vector(2 downto 0); signal TState : std_logic_vector(2 downto 0); signal HALT_n_int : std_logic; + signal iack1 : std_logic; + signal iack2 : std_logic; begin - BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes - MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control - MREQ_n_i <= not MREQ_rw; -- changed MREQ generation - IORQ_rw <= IORQ and not (IORQ_t1 or IORQ_t2); -- added IORQ generation timing control - IORQ_n_i <= not ((IORQ_int and not IORQ_int_inhibit(2)) or IORQ_rw); -- changed IORQ generation - RD_n_i <= not (RD and (MREQ_rw or IORQ_rw)); -- changed RD/IORQ generation - WR_n_i <= not (Write and ((WR_t2 and MREQ_rw) or IORQ_rw)); -- added WR/IORQ timing control + + BUSAK_n <= BUSAK_n_i; + MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit); + RD_n_i <= not RD or (IORQ and IReq_Inhibit) or Req_Inhibit; -- DMB + WR_n_j <= WR_n_i or (IORQ and IReq_Inhibit); -- DMB HALT_n <= HALT_n_int; + --Remove tristate as in ICE-Z80 this is implmeneted in Z80CpuMon - --MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; - --IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; + --MREQ_n <= MREQ_n_i; when BUSAK_n_i = '1' else 'Z'; + --IORQ_n <= IORQ_n_i or IReq_Inhibit when BUSAK_n_i = '1' else 'Z'; -- 0247a --RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; - --WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z'; + --WR_n <= WR_n_j when BUSAK_n_i = '1' else 'Z'; -- 0247a --RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; --A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); - --D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); MREQ_n <= MREQ_n_i; - IORQ_n <= IORQ_n_i; + IORQ_n <= IORQ_n_i or IReq_Inhibit or Req_inhibit; --DMB RD_n <= RD_n_i; - WR_n <= WR_n_i; + WR_n <= WR_n_j; -- 0247a RFSH_n <= RFSH_n_i; A <= A_i; + Dout <= DO; Den <= Write and BUSAK_n_i; @@ -181,18 +161,15 @@ begin if RESET_n = '0' then Reset_s <= '0'; elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - Reset_s <= '1'; - end if; + Reset_s <= '1'; end if; end process; u0 : T80 generic map( Mode => Mode, - IOWait => IOWait) + IOWait => 1) port map( - R800_mode => R800_mode, CEN => CEN, M1_n => M1_n, IORQ => IORQ, @@ -214,7 +191,6 @@ begin MC => MCycle, TS => TState, IntCycle_n => IntCycle_n, - -- DMB NMICycle_n => NMICycle_n, REG => Regs(211 downto 0), DIRSet => '0', @@ -235,72 +211,102 @@ begin end if; end process; --- 30/10/19 Charlie Ingley - Generate WR_t2 to correct MREQ/WR timing - process (Reset_s,CLK_n) + process (CLK_n) -- 0247a + begin + if CLK_n'event and CLK_n = '1' then + IReq_Inhibit <= (not IORQ) and IntCycle_n; + end if; + end process; + + process (Reset_s,CLK_n) -- 0247a begin if Reset_s = '0' then - WR_t2 <= '0'; + WR_n_i <= '1'; elsif CLK_n'event and CLK_n = '0' then if CEN = '1' then - if MCycle /= "001" then - if TState = "010" then -- WR starts on falling edge of T2 for MREQ - WR_t2 <= Write; + if (IORQ = '0') then + if TState = "010" then + WR_n_i <= not Write; + elsif Tstate = "011" then + WR_n_i <= '1'; + end if; + else + if TState = "001" then -- DMB + WR_n_i <= not Write; + elsif Tstate = "011" then + WR_n_i <= '1'; end if; end if; - if TState = "011" then -- end WR - WR_t2 <= '0'; + end if; + end if; + end process; + + process (Reset_s,CLK_n) -- 0247a + begin + if Reset_s = '0' then + Req_Inhibit <= '0'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if MCycle = "001" and TState = "010" and wait_s = '1' then + Req_Inhibit <= '1'; + else + Req_Inhibit <= '0'; end if; end if; end if; end process; --- Generate Req_Inhibit process (Reset_s,CLK_n) begin if Reset_s = '0' then - Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - Req_Inhibit <= '0'; - else - Req_Inhibit <= '1'; - end if; - end if; - end if; - end process; - --- Generate MReq_Inhibit - process (Reset_s, CLK_n) - begin - if Reset_s = '0' then - MReq_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity + MReq_Inhibit <= '0'; elsif CLK_n'event and CLK_n = '0' then if CEN = '1' then - if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_n - MReq_Inhibit <= '0'; - else + if MCycle = "001" and TState = "010" then MReq_Inhibit <= '1'; + else + MReq_Inhibit <= '0'; end if; end if; end if; end process; --- Generate RD for MREQ - process(Reset_s,CLK_n) + process(Reset_s,CLK_n) -- 0247a begin if Reset_s = '0' then RD <= '0'; + IORQ_n_i <= '1'; MREQ <= '0'; + iack1 <= '0'; + iack2 <= '0'; elsif CLK_n'event and CLK_n = '0' then if CEN = '1' then if MCycle = "001" then - if TState = "001" then - RD <= IntCycle_n; - MREQ <= IntCycle_n; + if IntCycle_n = '1' then + -- Normal M1 Cycle + if TState = "001" then + RD <= '1'; + MREQ <= '1'; + IORQ_n_i <= '1'; + end if; + else + -- Interupt Ack Cycle + -- 5 T-states: T1 T1 (auto wait) T1 (auto wait) T2 T3 + -- Assert IORQ in middle of third T1 + if TState = "001" then + iack1 <= '1'; + iack2 <= iack1; + else + iack1 <= '0'; + iack2 <= '0'; + end if; + if iack2 = '1' then + IORQ_n_i <= '0'; + end if; end if; if TState = "011" then RD <= '0'; + IORQ_n_i <= '1'; MREQ <= '1'; end if; if TState = "100" then @@ -308,11 +314,13 @@ begin end if; else if TState = "001" and NoRead = '0' then - RD <= not Write; + IORQ_n_i <= not IORQ; MREQ <= not IORQ; + RD <= not Write; -- DMB end if; if TState = "011" then RD <= '0'; + IORQ_n_i <= '1'; MREQ <= '0'; end if; end if; @@ -320,74 +328,6 @@ begin end if; end process; - -- 30/10/19 Charlie Ingley - Generate IORQ_int for IORQ interrupt timing control - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - IORQ_int <= '0'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - if MCycle = "001" then - if TState = "001" then - IORQ_int <= not IntCycle_n; - end if; - if TState = "010" then - IORQ_int <= '0'; - end if; - end if; - end if; - end if; - end process; - - process(Reset_s,CLK_n) - begin - if Reset_s = '0' then - IORQ_int_inhibit <= "111"; - elsif CLK_n'event and CLK_n = '0' then - if CEN = '1' then - if IntCycle_n = '0' then - if MCycle = "001" then - IORQ_int_inhibit <= IORQ_int_inhibit(1 downto 0) & '0'; - end if; - if MCycle = "010" then - IORQ_int_inhibit <= "111"; - end if; - end if; - end if; - end if; - end process; - --- 30/10/19 Charlie Ingley - Generate IORQ_t1 for IORQ timing control - process(Reset_s, CLK_n) - begin - if Reset_s = '0' then - IORQ_t1 <= '1'; - elsif CLK_n'event and CLK_n = '0' then - if CEN = '1' then - if TState = "001" then - IORQ_t1 <= not IntCycle_n; - end if; - if TState = "011" then - IORQ_t1 <= '1'; - end if; - end if; - end if; - end process; - --- 30/10/19 Charlie Ingley - Generate IORQ_t2 for IORQ timing control - process (RESET_n, CLK_n) - begin - if RESET_n = '0' then - IORQ_t2 <= '1'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - IORQ_t2 <= IORQ_t1; - end if; - end if; - end process; - --- DMB - TS <= TState; PdcData <= (not HALT_n_int) & (not NMICycle_n) & (not IntCycle_n) & "00000"; From 785f15c0385362e1b0f89015355f78831563dd3f Mon Sep 17 00:00:00 2001 From: David Banks Date: Wed, 30 Jun 2021 19:44:22 +0100 Subject: [PATCH 5/9] Update firmware version to 0.995 Change-Id: I4f340d876b603fdc27db4b9c9c75280f122705ed --- firmware/AtomBusMon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index 479a953..b5c93b8 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -14,7 +14,7 @@ * VERSION and NAME are used in the start-up message ********************************************************/ -#define VERSION "0.994" +#define VERSION "0.995" #if defined(CPU_Z80) #define NAME "ICE-Z80" From 4b3ed52454133a33aa3a6572944317e4334be30e Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 4 Jul 2021 19:03:52 +0100 Subject: [PATCH 6/9] Z80: Ignore wait during internal machine cycles Change-Id: I2fdeebe9706a868e9757089f1aed544e702146d8 --- src/T80/T80a.vhd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/T80/T80a.vhd b/src/T80/T80a.vhd index f225df2..36f012f 100644 --- a/src/T80/T80a.vhd +++ b/src/T80/T80a.vhd @@ -203,7 +203,7 @@ begin begin if CLK_n'event and CLK_n = '0' then if CEN = '1' then - Wait_s <= WAIT_n; + Wait_s <= WAIT_n or (IORQ_n_i and MREQ_n_i); if TState = "011" and BUSAK_n_i = '1' then DI_Reg <= to_x01(Din); end if; From 0d837de8a6113124478a96edbae76bc3e99ed4d8 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 4 Jul 2021 19:20:25 +0100 Subject: [PATCH 7/9] Z80: fix display of int/nmi/halted state Change-Id: I3e790598d6d2f1520e1ba4df3b79beaf3c8736f2 --- firmware/disz80.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/disz80.c b/firmware/disz80.c index 98ae840..49ef72d 100644 --- a/firmware/disz80.c +++ b/firmware/disz80.c @@ -530,9 +530,9 @@ static const unsigned char cmd_ED40[192] PROGMEM = { NOP,0,0 }; -static const char word_EX_HALT[] PROGMEM = "**HALT**"; -static const char word_EX_INT[] PROGMEM = "**INT**"; -static const char word_EX_NMI[] PROGMEM = "**NMI**"; +static const char msg_HALT[] PROGMEM = "**HALT**\n"; +static const char msg_INT[] PROGMEM = "**INT**\n"; +static const char msg_NMI[] PROGMEM = "**NMI**\n"; unsigned char cmd_halt[] = { HALT,0,0 }; unsigned char cmd_nop[] = { NOP,0,0 }; @@ -906,16 +906,16 @@ addr_t disassemble(addr_t addr) { // Opcode ptr = buffer + 21; if (PDC_DIN & 0x80) { - strcpy_P(ptr, PSTR("**HALT**")); + strcpy_P(ptr, msg_HALT); } else if (PDC_DIN & 0x40) { - strcpy(ptr, PSTR("**NMI**")); + strcpy(ptr, msg_NMI); } else if (PDC_DIN & 0x20) { - strcpy(ptr, PSTR("**INT**")); + strcpy(ptr, msg_INT); } else { ptr = disassem(ptr, &addr2); + *ptr++ = '\n'; + *ptr++ = '\0'; } - *ptr++ = '\n'; - *ptr++ = '\0'; // Hex loadAddr(addr); From 78423708c532bacf95ebc1a4155fe1d43d3d91db Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 4 Jul 2021 19:31:13 +0100 Subject: [PATCH 8/9] Z80: Ignore machine state in disasseble command Change-Id: I28b67a53ec8936bb9172aa10ca6548fe0d9e6460 --- firmware/AtomBusMon.c | 4 ++-- firmware/dis.h | 6 +++++- firmware/dis6502.c | 2 +- firmware/dis65c02.c | 2 +- firmware/dis6809.c | 2 +- firmware/disz80.c | 12 ++++++++---- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index b5c93b8..eb2fcfb 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -922,7 +922,7 @@ void writeIOByteInc() { addr_t disMem(addr_t addr) { loadAddr(addr); - return disassemble(addr); + return disassemble(addr, MODE_NORMAL); } void genericDump(char *params, data_t (*readFunc)()) { @@ -1526,7 +1526,7 @@ void doCmdDis(char *params) { memAddr = startAddr; loadAddr(memAddr); do { - memAddr = disassemble(memAddr); + memAddr = disassemble(memAddr, MODE_DIS_CMD); i++; } while ((!endAddr && i < 10) || (endAddr && memAddr > startAddr && memAddr <= endAddr)); } diff --git a/firmware/dis.h b/firmware/dis.h index 33e42f7..8c60c04 100644 --- a/firmware/dis.h +++ b/firmware/dis.h @@ -6,6 +6,10 @@ #define PDC_DDR DDRA #define PDC_DIN PINA -addr_t disassemble(addr_t addr); +#define MODE_NORMAL 0 +#define MODE_DIS_CMD 1 + +addr_t disassemble(addr_t addr, uint8_t m); + #endif diff --git a/firmware/dis6502.c b/firmware/dis6502.c index 9b0a655..328436e 100644 --- a/firmware/dis6502.c +++ b/firmware/dis6502.c @@ -167,7 +167,7 @@ static const unsigned char dopaddr[256] PROGMEM = /*F0*/ BRA, INDY, IMP, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP }; -addr_t disassemble(addr_t addr) +addr_t disassemble(addr_t addr, uint8_t m) { char buffer[40]; diff --git a/firmware/dis65c02.c b/firmware/dis65c02.c index 2b06f47..d4ad91e 100644 --- a/firmware/dis65c02.c +++ b/firmware/dis65c02.c @@ -187,7 +187,7 @@ static const unsigned char dopaddr[256] PROGMEM = /*F0*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP }; -addr_t disassemble(addr_t addr) +addr_t disassemble(addr_t addr, uint8_t m) { char buffer[40]; diff --git a/firmware/dis6809.c b/firmware/dis6809.c index 31725ce..454b3ce 100644 --- a/firmware/dis6809.c +++ b/firmware/dis6809.c @@ -647,7 +647,7 @@ static char *strcc(char *ptr, uint8_t val) { /* disassemble one instruction at address addr and return the address of the next instruction */ -addr_t disassemble(addr_t addr) { +addr_t disassemble(addr_t addr, uint8_t m) { uint8_t d = get_memb(addr); uint8_t s; int8_t i; diff --git a/firmware/disz80.c b/firmware/disz80.c index 49ef72d..a65dfe5 100644 --- a/firmware/disz80.c +++ b/firmware/disz80.c @@ -887,12 +887,15 @@ char * disassem (char *ptr, unsigned int *ip) { return ptr; } -addr_t disassemble(addr_t addr) { +addr_t disassemble(addr_t addr, uint8_t m) { static char buffer[64]; char *ptr; addr_t addr2 = addr; + // Ignore the current CPU state in the disassemble connamd + uint8_t pdc = (m == MODE_DIS_CMD) ? 0 : PDC_DIN; + // 0123456789012345678901234567890123456789 // AAAA : HH HH HH HH : LD RR,($XXXX) @@ -905,11 +908,12 @@ addr_t disassemble(addr_t addr) { // Opcode ptr = buffer + 21; - if (PDC_DIN & 0x80) { + + if (pdc & 0x80) { strcpy_P(ptr, msg_HALT); - } else if (PDC_DIN & 0x40) { + } else if (pdc & 0x40) { strcpy(ptr, msg_NMI); - } else if (PDC_DIN & 0x20) { + } else if (pdc & 0x20) { strcpy(ptr, msg_INT); } else { ptr = disassem(ptr, &addr2); From ca285abfaf72c7dd0fad56b71ee02d4a114cc615 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 4 Jul 2021 19:31:53 +0100 Subject: [PATCH 9/9] Update firmware version to 0.996 Change-Id: Ibe3fb93ec5f4320c64511649ca25d847ed25fc3a --- firmware/AtomBusMon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index eb2fcfb..313c87a 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -14,7 +14,7 @@ * VERSION and NAME are used in the start-up message ********************************************************/ -#define VERSION "0.995" +#define VERSION "0.996" #if defined(CPU_Z80) #define NAME "ICE-Z80"