Z80: Update T80 core to latest from Mister on 30/6/2021

Change-Id: I6c007617ab03796dcd864c0f84d5663e0f4bece9
This commit is contained in:
David Banks 2021-06-30 11:53:24 +01:00
parent 246cb88e72
commit 8e83d6e21f
5 changed files with 1027 additions and 754 deletions

View File

@ -21,7 +21,7 @@
-- **** -- ****
-- Z80 compatible microprocessor core -- Z80 compatible microprocessor core
-- --
-- Version : 0247 -- Version : 0250
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
-- All rights reserved -- 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 -- 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 -- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM
-- 0247 : Fixed bus req/ack cycle -- 0247 : Fixed bus req/ack cycle
-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15
-- --
library IEEE; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all; use IEEE.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.all; use IEEE.STD_LOGIC_UNSIGNED.all;
use work.T80_Pack.all;
use work.all;
entity T80 is entity T80 is
generic( generic(
@ -117,9 +117,9 @@ entity T80 is
MC : out std_logic_vector(2 downto 0); MC : out std_logic_vector(2 downto 0);
TS : out std_logic_vector(2 downto 0); TS : out std_logic_vector(2 downto 0);
IntCycle_n : out std_logic; IntCycle_n : out std_logic;
NMICycle_n : out std_logic;
IntE : out std_logic; IntE : out std_logic;
Stop : 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 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 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; end T80;
architecture rtl of T80 is 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 -- Registers
signal ACC, F : std_logic_vector(7 downto 0); signal ACC, F : std_logic_vector(7 downto 0);
@ -283,9 +153,13 @@ architecture rtl of T80 is
-- Help Registers -- Help Registers
signal WZ : std_logic_vector(15 downto 0); -- MEMPTR register 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 IR : std_logic_vector(7 downto 0); -- Instruction register
signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector
signal RegBusA_r : std_logic_vector(15 downto 0); 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 ID16 : signed(15 downto 0);
signal Save_Mux : std_logic_vector(7 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_FF1 : std_logic;
signal IntE_FF2 : std_logic; signal IntE_FF2 : std_logic;
signal Halt_FF : std_logic; signal Halt_FF : std_logic;
signal BusReq_s : std_logic; signal BusReq_s : std_logic := '0';
signal BusAck : std_logic; signal BusAck : std_logic := '0';
signal ClkEn : std_logic; signal ClkEn : std_logic;
signal NMI_s : std_logic; signal NMI_s : std_logic;
signal IStatus : std_logic_vector(1 downto 0); 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 Set_BusA_To : std_logic_vector(3 downto 0);
signal ALU_Op : std_logic_vector(3 downto 0); signal ALU_Op : std_logic_vector(3 downto 0);
signal Save_ALU : std_logic; signal Save_ALU : std_logic;
signal Rot_Akku : std_logic;
signal PreserveC : std_logic; signal PreserveC : std_logic;
signal Arith16 : std_logic; signal Arith16 : std_logic;
signal Set_Addr_To : std_logic_vector(2 downto 0); signal Set_Addr_To : std_logic_vector(2 downto 0);
@ -355,6 +230,8 @@ architecture rtl of T80 is
signal LDZ : std_logic; signal LDZ : std_logic;
signal LDW : std_logic; signal LDW : std_logic;
signal LDSPHL : std_logic; signal LDSPHL : std_logic;
signal LDHLSP : std_logic;
signal ADDSPdd : std_logic;
signal IORQ_i : std_logic; signal IORQ_i : std_logic;
signal Special_LD : std_logic_vector(2 downto 0); signal Special_LD : std_logic_vector(2 downto 0);
signal ExchangeDH : std_logic; signal ExchangeDH : std_logic;
@ -373,14 +250,16 @@ architecture rtl of T80 is
signal I_RRD : std_logic; signal I_RRD : std_logic;
signal I_RXDD : std_logic; signal I_RXDD : std_logic;
signal I_INRC : 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 SetWZ : std_logic_vector(1 downto 0);
signal SetDI : std_logic; signal SetDI : std_logic;
signal SetEI : std_logic; signal SetEI : std_logic;
signal IMode : std_logic_vector(1 downto 0); signal IMode : std_logic_vector(1 downto 0);
signal Halt : std_logic; signal Halt : std_logic;
signal XYbit_undoc : std_logic; signal XYbit_undoc : std_logic;
signal No_PC : std_logic;
signal DOR : std_logic_vector(127 downto 0); signal DOR : std_logic_vector(127 downto 0);
signal IVector : std_logic_vector(7 downto 0);
begin begin
@ -419,6 +298,7 @@ begin
Set_BusA_To => Set_BusA_To, Set_BusA_To => Set_BusA_To,
ALU_Op => ALU_Op, ALU_Op => ALU_Op,
Save_ALU => Save_ALU, Save_ALU => Save_ALU,
Rot_Akku => Rot_Akku,
PreserveC => PreserveC, PreserveC => PreserveC,
Arith16 => Arith16, Arith16 => Arith16,
Set_Addr_To => Set_Addr_To, Set_Addr_To => Set_Addr_To,
@ -431,6 +311,8 @@ begin
LDZ => LDZ, LDZ => LDZ,
LDW => LDW, LDW => LDW,
LDSPHL => LDSPHL, LDSPHL => LDSPHL,
LDHLSP => LDHLSP,
ADDSPdd => ADDSPdd,
Special_LD => Special_LD, Special_LD => Special_LD,
ExchangeDH => ExchangeDH, ExchangeDH => ExchangeDH,
ExchangeRp => ExchangeRp, ExchangeRp => ExchangeRp,
@ -447,6 +329,8 @@ begin
I_RLD => I_RLD, I_RLD => I_RLD,
I_RRD => I_RRD, I_RRD => I_RRD,
I_INRC => I_INRC, I_INRC => I_INRC,
I_MULUB => I_MULUB,
I_MULU => I_MULU,
SetWZ => SetWZ, SetWZ => SetWZ,
SetDI => SetDI, SetDI => SetDI,
SetEI => SetEI, SetEI => SetEI,
@ -454,6 +338,8 @@ begin
Halt => Halt, Halt => Halt,
NoRead => NoRead, NoRead => NoRead,
Write => Write, Write => Write,
R800_mode => R800_mode,
No_PC => No_PC,
XYbit_undoc => XYbit_undoc); XYbit_undoc => XYbit_undoc);
alu : T80_ALU alu : T80_ALU
@ -473,6 +359,7 @@ begin
WZ => WZ, WZ => WZ,
XY_State=> XY_State, XY_State=> XY_State,
ALU_Op => ALU_Op_r, ALU_Op => ALU_Op_r,
Rot_Akku => Rot_Akku,
IR => IR(5 downto 0), IR => IR(5 downto 0),
ISet => ISet, ISet => ISet,
BusA => BusA, BusA => BusA,
@ -497,6 +384,8 @@ begin
process (RESET_n, CLK_n) process (RESET_n, CLK_n)
variable n : std_logic_vector(7 downto 0); variable n : std_logic_vector(7 downto 0);
variable ioq : std_logic_vector(8 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 begin
if RESET_n = '0' then if RESET_n = '0' then
PC <= (others => '0'); -- Program Counter PC <= (others => '0'); -- Program Counter
@ -511,6 +400,11 @@ begin
ACC <= (others => '1'); ACC <= (others => '1');
F <= (others => '1'); F <= (others => '1');
if Mode = 3 then
ACC <= (others => '0');
F <= "11110000";
end if;
Ap <= (others => '1'); Ap <= (others => '1');
Fp <= (others => '1'); Fp <= (others => '1');
I <= (others => '0'); I <= (others => '0');
@ -539,7 +433,7 @@ begin
R <= unsigned(DIR(47 downto 40)); R <= unsigned(DIR(47 downto 40));
SP <= unsigned(DIR(63 downto 48)); SP <= unsigned(DIR(63 downto 48));
PC <= unsigned(DIR(79 downto 64)); PC <= unsigned(DIR(79 downto 64));
A <= DIR(79 downto 64); A <= DIR(79 downto 64);
IStatus <= DIR(209 downto 208); IStatus <= DIR(209 downto 208);
elsif ClkEn = '1' then elsif ClkEn = '1' then
@ -549,7 +443,27 @@ begin
MCycles <= MCycles_d; 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; IStatus <= IMode;
end if; end if;
@ -579,16 +493,15 @@ begin
IR <= "11111111"; IR <= "11111111";
elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then
IR <= "00000000"; 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 else
IR <= DInst; IR <= DInst;
end if; 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"; ISet <= "00";
if Prefix /= "00" then if Prefix /= "00" then
if Prefix = "11" then if Prefix = "11" then
@ -636,11 +549,12 @@ begin
elsif MCycle = MCycles and NMICycle = '1' then elsif MCycle = MCycles and NMICycle = '1' then
A <= "0000000001100110"; A <= "0000000001100110";
PC <= "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(15 downto 8) <= I;
A(7 downto 0) <= IVector; A(7 downto 0) <= WZ(7 downto 0);
PC(15 downto 8) <= unsigned(I); PC(15 downto 8) <= unsigned(I);
PC(7 downto 0) <= unsigned(IVector); PC(7 downto 0) <= unsigned(WZ(7 downto 0));
else else
case Set_Addr_To is case Set_Addr_To is
when aXY => when aXY =>
@ -700,7 +614,12 @@ begin
end if; end if;
end if; end if;
when others => 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 case;
end if; end if;
@ -711,29 +630,50 @@ begin
Save_ALU_r <= Save_ALU; Save_ALU_r <= Save_ALU;
ALU_Op_r <= ALU_Op; ALU_Op_r <= ALU_Op;
if I_CPL = '1' then if Mode = 3 then
-- CPL if I_CPL = '1' then
ACC <= not ACC; -- CPL
F(Flag_Y) <= not ACC(5); ACC <= not ACC;
F(Flag_H) <= '1'; F(Flag_H) <= '1';
F(Flag_X) <= not ACC(3); F(Flag_N) <= '1';
F(Flag_N) <= '1'; end if;
end if; if I_CCF = '1' then
if I_CCF = '1' then -- CCF
-- CCF F(Flag_C) <= not F(Flag_C);
F(Flag_C) <= not F(Flag_C); F(Flag_H) <= '0';
F(Flag_Y) <= ACC(5); F(Flag_N) <= '0';
F(Flag_H) <= F(Flag_C); end if;
F(Flag_X) <= ACC(3); if I_SCF = '1' then
F(Flag_N) <= '0'; -- SCF
end if; F(Flag_C) <= '1';
if I_SCF = '1' then F(Flag_H) <= '0';
-- SCF F(Flag_N) <= '0';
F(Flag_C) <= '1'; end if;
F(Flag_Y) <= ACC(5); else
F(Flag_H) <= '0'; if I_CPL = '1' then
F(Flag_X) <= ACC(3); -- CPL
F(Flag_N) <= '0'; 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;
end if; end if;
@ -742,7 +682,7 @@ begin
F(Flag_N) <= DI_Reg(7); F(Flag_N) <= DI_Reg(7);
F(Flag_C) <= ioq(8); F(Flag_C) <= ioq(8);
F(Flag_H) <= 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)); 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; end if;
@ -784,6 +724,11 @@ begin
end if; end if;
end if; end if;
if ADDSPdd = '1' and TState = 2 then
WZ <= std_logic_vector(SP);
SP <= unsigned(signed(SP)+signed(Save_Mux));
end if;
if LDSPHL = '1' then if LDSPHL = '1' then
SP <= unsigned(RegBusC); SP <= unsigned(RegBusC);
end if; end if;
@ -931,7 +876,12 @@ begin
when "11001" => when "11001" =>
SP(15 downto 8) <= unsigned(Save_Mux); SP(15 downto 8) <= unsigned(Save_Mux);
when "11011" => 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 => when others =>
end case; end case;
if XYbit_undoc='1' then if XYbit_undoc='1' then
@ -942,6 +892,42 @@ begin
end if; end if;
end process; 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 -- 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 (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else
-- EX HL,DL -- EX HL,DL
Alternate & "10" when ExchangeDH = '1' and TState = 3 else 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 -- Bus A / Write
RegAddrA_r; RegAddrA_r;
@ -1010,8 +998,8 @@ begin
ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else
signed(RegBusA) + 1; signed(RegBusA) + 1;
process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, 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) ExchangeDH, IncDec_16, MCycle, TState, Wait_n, LDHLSP)
begin begin
RegWEH <= '0'; RegWEH <= '0';
RegWEL <= '0'; RegWEL <= '0';
@ -1025,11 +1013,21 @@ begin
end case; end case;
end if; 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 if ExchangeDH = '1' and (TState = 3 or TState = 4) then
RegWEH <= '1'; RegWEH <= '1';
RegWEL <= '1'; RegWEL <= '1';
end if; 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 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 case IncDec_16(1 downto 0) is
when "00" | "01" | "10" => when "00" | "01" | "10" =>
@ -1040,12 +1038,29 @@ begin
end if; end if;
end process; end process;
process (Save_Mux, RegBusB, RegBusA_r, ID16, TmpAddr2 <= std_logic_vector(unsigned(signed(SP) + signed(Save_Mux)));
ExchangeDH, IncDec_16, MCycle, TState, Wait_n)
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 begin
RegDIH <= Save_Mux; RegDIH <= Save_Mux;
RegDIL <= 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 if ExchangeDH = '1' and TState = 3 then
RegDIH <= RegBusB(15 downto 8); RegDIH <= RegBusB(15 downto 8);
RegDIL <= RegBusB(7 downto 0); RegDIL <= RegBusB(7 downto 0);
@ -1176,13 +1191,11 @@ begin
TS <= std_logic_vector(TState); TS <= std_logic_vector(TState);
DI_Reg <= DI; DI_Reg <= DI;
HALT_n <= not Halt_FF; HALT_n <= not Halt_FF;
BUSAK_n <= not BusAck; BUSAK_n <= not (BusAck and RESET_n);
IntCycle_n <= not IntCycle; IntCycle_n <= not IntCycle;
NMICycle_n <= not NMICycle;
IntE <= IntE_FF1; IntE <= IntE_FF1;
IORQ <= IORQ_i; IORQ <= IORQ_i;
Stop <= I_DJNZ; Stop <= I_DJNZ;
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- --
-- Main state machine -- Main state machine
@ -1196,7 +1209,7 @@ begin
TState <= "000"; TState <= "000";
Pre_XY_F_M <= "000"; Pre_XY_F_M <= "000";
Halt_FF <= '0'; Halt_FF <= '0';
BusAck <= '0'; --BusAck <= '0';
NMICycle <= '0'; NMICycle <= '0';
IntCycle <= '0'; IntCycle <= '0';
IntE_FF1 <= '0'; IntE_FF1 <= '0';
@ -1205,10 +1218,9 @@ begin
Auto_Wait_t1 <= '0'; Auto_Wait_t1 <= '0';
Auto_Wait_t2 <= '0'; Auto_Wait_t2 <= '0';
M1_n <= '1'; M1_n <= '1';
BusReq_s <= '0'; --BusReq_s <= '0';
NMI_s <= '0'; NMI_s <= '0';
elsif rising_edge(CLK_n) then elsif rising_edge(CLK_n) then
if DIRSet = '1' then if DIRSet = '1' then
IntE_FF2 <= DIR(211); IntE_FF2 <= DIR(211);
IntE_FF1 <= DIR(210); IntE_FF1 <= DIR(210);
@ -1256,13 +1268,20 @@ begin
BusAck <= '0'; BusAck <= '0';
if TState = 2 and Wait_n = '0' then if TState = 2 and Wait_n = '0' then
elsif T_Res = '1' 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'; Halt_FF <= '1';
end if; end if;
if BusReq_s = '1' then if BusReq_s = '1' then
BusAck <= '1'; BusAck <= '1';
else else
TState <= "001"; 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 if NextIs_XY_Fetch = '1' then
MCycle <= "110"; MCycle <= "110";
Pre_XY_F_M <= MCycle; Pre_XY_F_M <= MCycle;
@ -1284,6 +1303,8 @@ begin
IntCycle <= '1'; IntCycle <= '1';
IntE_FF1 <= '0'; IntE_FF1 <= '0';
IntE_FF2 <= '0'; IntE_FF2 <= '0';
elsif (Halt_FF = '1' and INT_n = '0' and Mode = 3) then
Halt_FF <= '0';
end if; end if;
else else
MCycle <= std_logic_vector(unsigned(MCycle) + 1); MCycle <= std_logic_vector(unsigned(MCycle) + 1);

View File

@ -89,6 +89,7 @@ entity T80_ALU is
WZ : in std_logic_vector(15 downto 0); WZ : in std_logic_vector(15 downto 0);
XY_State : in std_logic_vector(1 downto 0); XY_State : in std_logic_vector(1 downto 0);
ALU_Op : in std_logic_vector(3 downto 0); ALU_Op : in std_logic_vector(3 downto 0);
Rot_Akku : in std_logic;
IR : in std_logic_vector(5 downto 0); IR : in std_logic_vector(5 downto 0);
ISet : in std_logic_vector(1 downto 0); ISet : in std_logic_vector(1 downto 0);
BusA : in std_logic_vector(7 downto 0); BusA : in std_logic_vector(7 downto 0);
@ -158,7 +159,7 @@ begin
end if; end if;
end process; 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 Q_t : std_logic_vector(7 downto 0);
variable DAA_Q : unsigned(8 downto 0); variable DAA_Q : unsigned(8 downto 0);
begin begin
@ -220,35 +221,64 @@ begin
end if; end if;
when "1100" => when "1100" =>
-- DAA -- DAA
F_Out(Flag_H) <= F_In(Flag_H); if Mode = 3 then
F_Out(Flag_C) <= F_In(Flag_C); F_Out(Flag_H) <= '0';
DAA_Q(7 downto 0) := unsigned(BusA); F_Out(Flag_C) <= F_In(Flag_C);
DAA_Q(8) := '0'; DAA_Q(7 downto 0) := unsigned(BusA);
if F_In(Flag_N) = '0' then DAA_Q(8) := '0';
-- After addition if F_In(Flag_N) = '0' then
-- Alow > 9 or H = 1 -- After addition
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then -- Alow > 9 or H = 1
if (DAA_Q(3 downto 0) > 9) then if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
F_Out(Flag_H) <= '1'; DAA_Q := DAA_Q + 6;
else end if;
F_Out(Flag_H) <= '0'; -- 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; 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; end if;
else else
-- After subtraction F_Out(Flag_H) <= F_In(Flag_H);
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then F_Out(Flag_C) <= F_In(Flag_C);
if DAA_Q(3 downto 0) > 5 then DAA_Q(7 downto 0) := unsigned(BusA);
F_Out(Flag_H) <= '0'; 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; 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;
end if; end if;
F_Out(Flag_X) <= DAA_Q(3); F_Out(Flag_X) <= DAA_Q(3);
@ -368,6 +398,9 @@ begin
F_Out(Flag_S) <= F_In(Flag_S); F_Out(Flag_S) <= F_In(Flag_S);
F_Out(Flag_Z) <= F_In(Flag_Z); F_Out(Flag_Z) <= F_In(Flag_Z);
end if; end if;
if Mode = 3 and Rot_Akku = '1' then
F_Out(Flag_Z) <= '0';
end if;
when others => when others =>
null; null;
end case; end case;

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@
-- --
-- Z80 compatible microprocessor core -- Z80 compatible microprocessor core
-- --
-- Version : 0242 -- Version : 0250
-- --
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
-- --
@ -84,7 +84,7 @@ package T80_Pack is
port( port(
RESET_n : in std_logic; RESET_n : in std_logic;
CLK_n : in std_logic; CLK_n : in std_logic;
CEN : in std_logic; CEN : in std_logic;
WAIT_n : in std_logic; WAIT_n : in std_logic;
INT_n : in std_logic; INT_n : in std_logic;
NMI_n : in std_logic; NMI_n : in std_logic;
@ -96,16 +96,17 @@ package T80_Pack is
RFSH_n : out std_logic; RFSH_n : out std_logic;
HALT_n : out std_logic; HALT_n : out std_logic;
BUSAK_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); DInst : in std_logic_vector(7 downto 0);
DI : in std_logic_vector(7 downto 0); DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0); DO : out std_logic_vector(7 downto 0);
MC : out std_logic_vector(2 downto 0); MC : out std_logic_vector(2 downto 0);
TS : out std_logic_vector(2 downto 0); TS : out std_logic_vector(2 downto 0);
IntCycle_n : out std_logic; IntCycle_n : out std_logic;
NMICycle_n : out std_logic;
IntE : out std_logic; IntE : out std_logic;
Stop : 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 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'; 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 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 component T80_Reg
port( port(
Clk : in std_logic; Clk : in std_logic;
CEN : in std_logic; CEN : in std_logic;
WEH : in std_logic; WEH : in std_logic;
WEL : in std_logic; WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0); AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0); AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0); AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0); DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0); DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0); DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0); DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0); DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0); DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0); DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0); DOCL : out std_logic_vector(7 downto 0);
DOR : out std_logic_vector(127 downto 0); DOR : out std_logic_vector(127 downto 0);
DIRSet : in std_logic; DIRSet : in std_logic;
DIR : in std_logic_vector(127 downto 0) DIR : in std_logic_vector(127 downto 0)
); );
end component; end component;
@ -168,6 +169,7 @@ package T80_Pack is
ALU_Op : out std_logic_vector(3 downto 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 -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
Save_ALU : out std_logic; Save_ALU : out std_logic;
Rot_Akku : out std_logic;
PreserveC : out std_logic; PreserveC : out std_logic;
Arith16 : out std_logic; Arith16 : out std_logic;
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI 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; LDW : out std_logic;
LDSPHL : out std_logic; LDSPHL : out std_logic;
LDHLSP : 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 Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
ExchangeDH : out std_logic; ExchangeDH : out std_logic;
ExchangeRp : out std_logic; ExchangeRp : out std_logic;
@ -198,12 +200,17 @@ package T80_Pack is
I_RLD : out std_logic; I_RLD : out std_logic;
I_RRD : out std_logic; I_RRD : out std_logic;
I_INRC : out std_logic; I_INRC : out std_logic;
I_MULUB : out std_logic;
I_MULU : out std_logic;
SetWZ : out std_logic_vector(1 downto 0);
SetDI : out std_logic; SetDI : out std_logic;
SetEI : out std_logic; SetEI : out std_logic;
IMode : out std_logic_vector(1 downto 0); IMode : out std_logic_vector(1 downto 0);
Halt : out std_logic; Halt : out std_logic;
NoRead : out std_logic; NoRead : out std_logic;
Write : out std_logic; Write : out std_logic;
R800_mode : in std_logic;
No_PC : out std_logic;
XYbit_undoc : out std_logic XYbit_undoc : out std_logic
); );
end component; end component;
@ -223,7 +230,10 @@ package T80_Pack is
port( port(
Arith16 : in std_logic; Arith16 : in std_logic;
Z16 : 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); ALU_Op : in std_logic_vector(3 downto 0);
Rot_Akku : in std_logic;
IR : in std_logic_vector(5 downto 0); IR : in std_logic_vector(5 downto 0);
ISet : in std_logic_vector(1 downto 0); ISet : in std_logic_vector(1 downto 0);
BusA : in std_logic_vector(7 downto 0); BusA : in std_logic_vector(7 downto 0);

View File

@ -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 -- Z80 compatible microprocessor core, asynchronous top level
-- --
-- Version : 0247a -- Version : 0250
-- --
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
-- --
@ -38,28 +47,32 @@
-- you have the latest version of this file. -- you have the latest version of this file.
-- --
-- The latest version of this file can be found at: -- 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 : -- Limitations :
-- --
-- File history : -- 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; library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
@ -67,269 +80,263 @@ use IEEE.numeric_std.all;
use work.T80_Pack.all; use work.T80_Pack.all;
entity T80a is entity T80a is
generic( generic(
Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB 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( );
-- Additions port(
TS : out std_logic_vector(2 downto 0); RESET_n : in std_logic;
Regs : out std_logic_vector(255 downto 0); R800_mode : in std_logic;
PdcData : out std_logic_vector(7 downto 0); CLK_n : in std_logic;
-- Original Signals WAIT_n : in std_logic;
RESET_n : in std_logic; INT_n : in std_logic;
CLK_n : in std_logic; NMI_n : in std_logic;
CEN : in std_logic; BUSRQ_n : in std_logic;
WAIT_n : in std_logic; M1_n : out std_logic;
INT_n : in std_logic; MREQ_n : out std_logic;
NMI_n : in std_logic; IORQ_n : out std_logic;
BUSRQ_n : in std_logic; RD_n : out std_logic;
M1_n : out std_logic; WR_n : out std_logic;
MREQ_n : out std_logic; RFSH_n : out std_logic;
IORQ_n : out std_logic; HALT_n : out std_logic;
RD_n : out std_logic; BUSAK_n : out std_logic;
WR_n : out std_logic; A : out std_logic_vector(15 downto 0);
RFSH_n : out std_logic; D : inout std_logic_vector(7 downto 0)
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; end T80a;
architecture rtl of T80a is architecture rtl of T80a is
signal Reset_s : std_logic; signal CEN : std_logic;
signal IntCycle_n : std_logic; signal Reset_s : std_logic;
signal NMICycle_n : std_logic; signal IntCycle_n : std_logic;
signal IORQ : std_logic; signal IORQ : std_logic;
signal NoRead : std_logic; signal NoRead : std_logic;
signal Write : std_logic; signal Write : std_logic;
signal MREQ : std_logic; signal MREQ : std_logic;
signal MReq_Inhibit : std_logic; signal MReq_Inhibit : std_logic;
signal IReq_Inhibit : std_logic; -- 0247a signal Req_Inhibit : std_logic;
signal Req_Inhibit : std_logic; signal RD : std_logic;
signal RD : std_logic; signal MREQ_n_i : 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_n_i : std_logic;
signal RD_n_i : std_logic; signal IORQ_t1 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control
signal WR_n_i : std_logic; signal IORQ_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control
signal WR_n_j : std_logic; -- 0247a signal IORQ_rw : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ control
signal RFSH_n_i : std_logic; signal IORQ_int : std_logic; -- 30/10/19 Charlie Ingley-- add IORQ interrupt control
signal BUSAK_n_i : std_logic; signal IORQ_int_inhibit : std_logic_vector(2 downto 0);
signal A_i : std_logic_vector(15 downto 0); signal RD_n_i : std_logic;
signal DO : std_logic_vector(7 downto 0); signal WR_n_i : std_logic;
signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser signal WR_t2 : std_logic; -- 30/10/19 Charlie Ingley-- add WR control
signal Wait_s : std_logic; signal RFSH_n_i : std_logic;
signal MCycle : std_logic_vector(2 downto 0); signal BUSAK_n_i : std_logic;
signal TState : std_logic_vector(2 downto 0); signal A_i : std_logic_vector(15 downto 0);
signal HALT_n_int : std_logic; signal DO : std_logic_vector(7 downto 0);
signal iack1 : std_logic; signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser
signal iack2 : std_logic; signal Wait_s : std_logic;
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
begin begin
CEN <= '1';
BUSAK_n <= BUSAK_n_i; BUSAK_n <= BUSAK_n_i; -- 30/10/19 Charlie Ingley - IORQ/RD/WR changes
MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit); MREQ_rw <= MREQ and (Req_Inhibit or MReq_Inhibit); -- added MREQ timing control
RD_n_i <= not RD or (IORQ and IReq_Inhibit) or Req_Inhibit; -- DMB MREQ_n_i <= not MREQ_rw; -- changed MREQ generation
WR_n_j <= WR_n_i or (IORQ and IReq_Inhibit); -- DMB IORQ_rw <= IORQ and not (IORQ_t1 or IORQ_t2); -- added IORQ generation timing control
HALT_n <= HALT_n_int; 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 process (RESET_n, CLK_n)
--MREQ_n <= MREQ_n_i; when BUSAK_n_i = '1' else 'Z'; begin
--IORQ_n <= IORQ_n_i or IReq_Inhibit when BUSAK_n_i = '1' else 'Z'; -- 0247a if RESET_n = '0' then
--RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; Reset_s <= '0';
--WR_n <= WR_n_j when BUSAK_n_i = '1' else 'Z'; -- 0247a elsif CLK_n'event and CLK_n = '1' then
--RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; Reset_s <= '1';
--A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); end if;
end process;
MREQ_n <= MREQ_n_i; u0 : T80
IORQ_n <= IORQ_n_i or IReq_Inhibit or Req_inhibit; --DMB generic map(
RD_n <= RD_n_i; Mode => Mode,
WR_n <= WR_n_j; -- 0247a IOWait => IOWait)
RFSH_n <= RFSH_n_i; port map(
A <= A_i; 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; process (CLK_n)
Den <= Write and BUSAK_n_i; 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) -- 30/10/19 Charlie Ingley - Generate WR_t2 to correct MREQ/WR timing
begin process (Reset_s,CLK_n)
if RESET_n = '0' then begin
Reset_s <= '0'; if Reset_s = '0' then
elsif CLK_n'event and CLK_n = '1' then WR_t2 <= '0';
Reset_s <= '1'; elsif CLK_n'event and CLK_n = '0' then
end if; if MCycle /= "001" then
end process; 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 -- Generate Req_Inhibit
generic map( process (Reset_s,CLK_n)
Mode => Mode, begin
IOWait => 1) if Reset_s = '0' then
port map( Req_Inhibit <= '1'; -- Charlie Ingley 30/10/19 - changed Req_Inhibit polarity
CEN => CEN, elsif CLK_n'event and CLK_n = '1' then
M1_n => M1_n, if MCycle = "001" and TState = "010" and WAIT_n = '1' then -- by Fabio Belavenuto - fix behavior of Wait_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
Req_Inhibit <= '0'; Req_Inhibit <= '0';
elsif CLK_n'event and CLK_n = '1' then else
if CEN = '1' then Req_Inhibit <= '1';
if MCycle = "001" and TState = "010" and wait_s = '1' then end if;
Req_Inhibit <= '1'; end if;
else end process;
Req_Inhibit <= '0';
end if;
end if;
end if;
end process;
process (Reset_s,CLK_n) -- Generate MReq_Inhibit
begin process (Reset_s, CLK_n)
if Reset_s = '0' then 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'; MReq_Inhibit <= '0';
elsif CLK_n'event and CLK_n = '0' then else
if CEN = '1' then MReq_Inhibit <= '1';
if MCycle = "001" and TState = "010" then end if;
MReq_Inhibit <= '1'; end if;
else end process;
MReq_Inhibit <= '0';
end if; -- 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 if; if TState = "011" then
end process; RD <= '0';
MREQ <= '1';
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;
end if; end if;
end if; if TState = "100" then
end process; 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; end;