1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-19 01:16:58 +00:00

Moon Patrol: update T80

This commit is contained in:
Gyorgy Szombathelyi 2019-05-31 00:18:50 +02:00
parent b40cd1d3f8
commit 8a2196c4fc
8 changed files with 1040 additions and 899 deletions

View File

@ -187,6 +187,7 @@ set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
set_global_assignment -name VHDL_FILE src/bitmapctl_e.vhd
set_global_assignment -name VHDL_FILE src/tilemapctl_e.vhd
set_global_assignment -name VHDL_FILE src/target_pkg.vhd
@ -208,7 +209,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE src/YM2149.sv
set_global_assignment -name VHDL_FILE src/cpu68.vhd
set_global_assignment -name VHDL_FILE src/tilemapctl.vhd
set_global_assignment -name VHDL_FILE src/t80/Z80.vhd
set_global_assignment -name VHDL_FILE src/t80/T80se.vhd
set_global_assignment -name VHDL_FILE src/t80/T80s.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_Reg.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_Pack.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_MCode.vhd
@ -237,5 +238,4 @@ set_global_assignment -name VERILOG_FILE src/osd.v
set_global_assignment -name VERILOG_FILE src/user_io.v
set_global_assignment -name VHDL_FILE src/sprite_array.vhd
set_global_assignment -name VHDL_FILE src/Clock.vhd
set_global_assignment -name VHDL_FILE src/build_id.vhd
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
set_global_assignment -name VHDL_FILE src/build_id.vhd

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,26 @@
--------------------------------------------------------------------------------
-- ****
-- T80(c) core. Attempt to finish all undocumented features and provide
-- accurate timings.
-- Version 350.
-- Copyright (c) 2018 Sorgelig
-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr
-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as
-- correct implementation is still unclear.
--
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- Z80 compatible microprocessor core
--
-- Version : 0247
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
@ -55,13 +61,9 @@
-- File history :
--
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
--
-- 0238 : Fixed zero flag for 16 bit SBC and ADC
--
-- 0240 : Added GB operations
--
-- 0242 : Cleanup
--
-- 0247 : Cleanup
--
@ -84,6 +86,8 @@ entity T80_ALU is
port(
Arith16 : in std_logic;
Z16 : in std_logic;
WZ : in std_logic_vector(15 downto 0);
XY_State : in std_logic_vector(1 downto 0);
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);
@ -154,7 +158,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)
process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, WZ, XY_State)
variable Q_t : std_logic_vector(7 downto 0);
variable DAA_Q : unsigned(8 downto 0);
begin
@ -292,9 +296,10 @@ begin
end if;
F_Out(Flag_H) <= '1';
F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= '0';
F_Out(Flag_Y) <= '0';
if IR(2 downto 0) /= "110" then
if IR(2 downto 0) = "110" or XY_State /= "00" then
F_Out(Flag_X) <= WZ(11);
F_Out(Flag_Y) <= WZ(13);
else
F_Out(Flag_X) <= BusB(3);
F_Out(Flag_Y) <= BusB(5);
end if;

View File

@ -1,21 +1,26 @@
--------------------------------------------------------------------------------
-- ****
-- T80(c) core. Attempt to finish all undocumented features and provide
-- accurate timings.
-- Version 350.
-- Copyright (c) 2018 Sorgelig
-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr
-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as
-- correct implementation is still unclear.
--
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010
-- Ver 302 fixed IO cycle timing, tested thanks to Alessandro.
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- Z80 compatible microprocessor core
--
-- Version : 0242
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
@ -56,32 +61,23 @@
-- File history :
--
-- 0208 : First complete release
--
-- 0211 : Fixed IM 1
--
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
--
-- 0235 : Added IM 2 fix by Mike Johnson
--
-- 0238 : Added NoRead signal
--
-- 0238b: Fixed instruction timing for POP and DJNZ
--
-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes
-- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR
--
-- 0242 : Fixed I/O instruction timing, cleanup
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
entity T80_MCode is
generic(
Mode : integer := 0;
Mode : integer := 0;
Flag_C : integer := 0;
Flag_N : integer := 1;
Flag_P : integer := 2;
@ -92,66 +88,75 @@ entity T80_MCode is
Flag_S : integer := 7
);
port(
IR : in std_logic_vector(7 downto 0);
ISet : in std_logic_vector(1 downto 0);
MCycle : in std_logic_vector(2 downto 0);
F : in std_logic_vector(7 downto 0);
NMICycle : in std_logic;
IntCycle : in std_logic;
XY_State : in std_logic_vector(1 downto 0);
MCycles : out std_logic_vector(2 downto 0);
TStates : out std_logic_vector(2 downto 0);
Prefix : out std_logic_vector(1 downto 0); -- None,CB,ED,DD/FD
Inc_PC : out std_logic;
Inc_WZ : out std_logic;
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
Read_To_Reg : out std_logic;
Read_To_Acc : out std_logic;
Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
ALU_Op : out std_logic_vector(3 downto 0);
-- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
Save_ALU : out std_logic;
PreserveC : out std_logic;
Arith16 : out std_logic;
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
IORQ : out std_logic;
Jump : out std_logic;
JumpE : out std_logic;
JumpXY : out std_logic;
Call : out std_logic;
RstP : out std_logic;
LDZ : out std_logic;
LDW : out std_logic;
LDSPHL : out std_logic;
Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
ExchangeDH : out std_logic;
ExchangeRp : out std_logic;
ExchangeAF : out std_logic;
ExchangeRS : out std_logic;
I_DJNZ : out std_logic;
I_CPL : out std_logic;
I_CCF : out std_logic;
I_SCF : out std_logic;
I_RETN : out std_logic;
I_BT : out std_logic;
I_BC : out std_logic;
I_BTR : out std_logic;
I_RLD : out std_logic;
I_RRD : out std_logic;
I_INRC : out std_logic;
SetDI : out std_logic;
SetEI : out std_logic;
IMode : out std_logic_vector(1 downto 0);
Halt : out std_logic;
NoRead : out std_logic;
Write : out std_logic;
XYbit_undoc : out std_logic
);
IR : in std_logic_vector(7 downto 0);
ISet : in std_logic_vector(1 downto 0);
MCycle : in std_logic_vector(2 downto 0);
F : in std_logic_vector(7 downto 0);
NMICycle : in std_logic;
IntCycle : in std_logic;
XY_State : in std_logic_vector(1 downto 0);
MCycles : out std_logic_vector(2 downto 0);
TStates : out std_logic_vector(2 downto 0);
Prefix : out std_logic_vector(1 downto 0); -- None,CB,ED,DD/FD
Inc_PC : out std_logic;
Inc_WZ : out std_logic;
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
Read_To_Reg : out std_logic;
Read_To_Acc : out std_logic;
Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
ALU_Op : out std_logic_vector(3 downto 0);
-- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
Save_ALU : out std_logic;
PreserveC : out std_logic;
Arith16 : out std_logic;
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
IORQ : out std_logic;
Jump : out std_logic;
JumpE : out std_logic;
JumpXY : out std_logic;
Call : out std_logic;
RstP : out std_logic;
LDZ : out std_logic;
LDW : out std_logic;
LDSPHL : out std_logic;
Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
ExchangeDH : out std_logic;
ExchangeRp : out std_logic;
ExchangeAF : out std_logic;
ExchangeRS : out std_logic;
I_DJNZ : out std_logic;
I_CPL : out std_logic;
I_CCF : out std_logic;
I_SCF : out std_logic;
I_RETN : out std_logic;
I_BT : out std_logic;
I_BC : out std_logic;
I_BTR : out std_logic;
I_RLD : out std_logic;
I_RRD : out std_logic;
I_INRC : out std_logic;
SetWZ : out std_logic_vector(1 downto 0);
SetDI : out std_logic;
SetEI : out std_logic;
IMode : out std_logic_vector(1 downto 0);
Halt : out std_logic;
NoRead : out std_logic;
Write : out std_logic;
XYbit_undoc : out std_logic
);
end T80_MCode;
architecture rtl of T80_MCode is
constant aNone : std_logic_vector(2 downto 0) := "111";
constant aBC : std_logic_vector(2 downto 0) := "000";
constant aDE : std_logic_vector(2 downto 0) := "001";
constant aXY : std_logic_vector(2 downto 0) := "010";
constant aIOA : std_logic_vector(2 downto 0) := "100";
constant aSP : std_logic_vector(2 downto 0) := "101";
constant aZI : std_logic_vector(2 downto 0) := "110";
function is_cc_true(
F : std_logic_vector(7 downto 0);
cc : bit_vector(2 downto 0)
@ -159,10 +164,10 @@ architecture rtl of T80_MCode is
begin
if Mode = 3 then
case cc is
when "000" => return F(7) = '0'; -- NZ
when "001" => return F(7) = '1'; -- Z
when "010" => return F(4) = '0'; -- NC
when "011" => return F(4) = '1'; -- C
when "000" => return F(Flag_S) = '0'; -- NZ
when "001" => return F(Flag_S) = '1'; -- Z
when "010" => return F(Flag_H) = '0'; -- NC
when "011" => return F(Flag_H) = '1'; -- C
when "100" => return false;
when "101" => return false;
when "110" => return false;
@ -170,14 +175,14 @@ architecture rtl of T80_MCode is
end case;
else
case cc is
when "000" => return F(6) = '0'; -- NZ
when "001" => return F(6) = '1'; -- Z
when "010" => return F(0) = '0'; -- NC
when "011" => return F(0) = '1'; -- C
when "100" => return F(2) = '0'; -- PO
when "101" => return F(2) = '1'; -- PE
when "110" => return F(7) = '0'; -- P
when "111" => return F(7) = '1'; -- M
when "000" => return F(Flag_Z) = '0'; -- NZ
when "001" => return F(Flag_Z) = '1'; -- Z
when "010" => return F(Flag_C) = '0'; -- NC
when "011" => return F(Flag_C) = '1'; -- C
when "100" => return F(Flag_P) = '0'; -- PO
when "101" => return F(Flag_P) = '1'; -- PE
when "110" => return F(Flag_S) = '0'; -- P
when "111" => return F(Flag_S) = '1'; -- M
end case;
end if;
end;
@ -185,10 +190,10 @@ architecture rtl of T80_MCode is
begin
process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State)
variable DDD : std_logic_vector(2 downto 0);
variable SSS : std_logic_vector(2 downto 0);
variable DDD : std_logic_vector(2 downto 0);
variable SSS : std_logic_vector(2 downto 0);
variable DPair : std_logic_vector(1 downto 0);
variable IRB : bit_vector(7 downto 0);
variable IRB : bit_vector(7 downto 0);
begin
DDD := IR(5 downto 3);
SSS := IR(2 downto 0);
@ -246,13 +251,14 @@ begin
NoRead <= '0';
Write <= '0';
XYbit_undoc <= '0';
SetWZ <= "00";
case ISet is
when "00" =>
------------------------------------------------------------------------------
--
-- Unprefixed instructions
-- Unprefixed instructions
--
------------------------------------------------------------------------------
@ -370,6 +376,7 @@ begin
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To <= "0111";
SetWZ <= "10";
when 2 =>
Write <= '1';
when others => null;
@ -381,6 +388,7 @@ begin
when 1 =>
Set_Addr_To <= aDE;
Set_BusB_To <= "0111";
SetWZ <= "10";
when 2 =>
Write <= '1';
when others => null;
@ -407,6 +415,7 @@ begin
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
SetWZ <= "10";
Inc_PC <= '1';
Set_BusB_To <= "0111";
when 4 =>
@ -617,7 +626,7 @@ begin
when 3 =>
Jump <= '1';
IncDec_16 <= "0111";
--I_RETN <= '1';
I_RETN <= '1';
SetEI <= '1';
when others => null;
end case;
@ -637,6 +646,7 @@ begin
Set_BusA_To <= "0101";
Set_BusB_To <= "0101";
Set_Addr_To <= aSP;
LDZ <= '1';
when 3 =>
IncDec_16 <= "0111";
Set_Addr_To <= aSP;
@ -647,6 +657,7 @@ begin
Set_BusA_To <= "0100";
Set_BusB_To <= "0100";
Set_Addr_To <= aSP;
LDW <= '1';
when 5 =>
IncDec_16 <= "1111";
TStates <= "101";
@ -795,23 +806,17 @@ begin
Set_Addr_To <= aSP;
Set_BusB_To <= "1101";
when 2 =>
TStates <= "100";
Write <= '1';
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1100";
when 3 =>
TStates <= "100";
Write <= '1';
when others => null;
end case;
elsif IntCycle = '1' then
-- INT (IM 2)
if mode = 3 then
MCycles <= "011";
else
MCycles <= "101";
end if;
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 1 =>
LDZ <= '1';
@ -820,13 +825,13 @@ begin
Set_Addr_To <= aSP;
Set_BusB_To <= "1101";
when 2 =>
TStates <= "100";
--TStates <= "100";
Write <= '1';
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1100";
when 3 =>
TStates <= "100";
--TStates <= "100";
Write <= '1';
when 4 =>
Inc_PC <= '1';
@ -868,6 +873,7 @@ begin
end case;
TStates <= "100";
Arith16 <= '1';
SetWZ <= "11";
when 3 =>
NoRead <= '1';
Read_To_Reg <= '1';
@ -919,6 +925,7 @@ begin
when 3 =>
Inc_PC <= '1';
Jump <= '1';
LDW <= '1';
when others => null;
end case;
when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" =>
@ -930,7 +937,7 @@ begin
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To <= "0111";
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
IORQ <= '1';
@ -985,6 +992,7 @@ begin
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
LDW <= '1';
Inc_PC <= '1';
if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
Jump <= '1';
@ -1163,6 +1171,7 @@ begin
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
--TStates <= "101";
Set_Addr_TO <= aSP;
when 2 =>
IncDec_16 <= "0111";
@ -1183,7 +1192,7 @@ begin
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
Set_BusB_To <= "0111";
Set_BusB_To <= "0111";
when 3 =>
Write <= '1';
when others => null;
@ -1205,7 +1214,7 @@ begin
Save_ALU <= '1';
ALU_Op <= "0001";
Set_BusA_To <= "1001";
Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!!
Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!!
when others =>
end case;
when "10" =>
@ -1220,7 +1229,7 @@ begin
when others => null;
end case;
when "11" =>
-- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!!
-- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!!
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
@ -1294,7 +1303,6 @@ begin
when 3 =>
Read_To_Acc <= '1';
IORQ <= '1';
TStates <= "100"; -- MIKEJ should be 4 for IO cycle
when others => null;
end case;
end if;
@ -1306,11 +1314,10 @@ begin
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
Set_BusB_To <= "0111";
Set_BusB_To <= "0111";
when 3 =>
Write <= '1';
IORQ <= '1';
TStates <= "100"; -- MIKEJ should be 4 for IO cycle
when others => null;
end case;
end if;
@ -1342,7 +1349,7 @@ begin
------------------------------------------------------------------------------
--
-- CB prefixed instructions
-- CB prefixed instructions
--
------------------------------------------------------------------------------
@ -1391,7 +1398,6 @@ begin
end case;
end if;
when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" =>
-- RLC (HL)
-- RL (HL)
@ -1442,11 +1448,12 @@ begin
when others => null;
end case;
end if;
when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" =>
-- BIT b,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 | 7=>
when 1 | 7 =>
Set_Addr_To <= aXY;
when 2 =>
ALU_Op <= "1001";
@ -1464,9 +1471,9 @@ begin
-- SET b,r
if XY_State="00" then
if MCycle = "001" then
ALU_Op <= "1010";
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "1010";
Read_To_Reg <= '1';
Save_ALU <= '1';
end if;
else
-- SET b,(IX+d),Reg, undocumented
@ -1486,11 +1493,12 @@ begin
when others => null;
end case;
end if;
when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" =>
-- SET b,(HL)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 | 7=>
when 1 | 7 =>
Set_Addr_To <= aXY;
when 2 =>
ALU_Op <= "1010";
@ -1513,9 +1521,9 @@ begin
-- RES b,r
if XY_State="00" then
if MCycle = "001" then
ALU_Op <= "1011";
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "1011";
Read_To_Reg <= '1';
Save_ALU <= '1';
end if;
else
-- RES b,(IX+d),Reg, undocumented
@ -1535,7 +1543,7 @@ begin
when others => null;
end case;
end if;
when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" =>
-- RES b,(HL)
MCycles <= "011";
@ -1558,7 +1566,7 @@ begin
------------------------------------------------------------------------------
--
-- ED prefixed instructions
-- ED prefixed instructions
--
------------------------------------------------------------------------------
@ -1763,11 +1771,12 @@ begin
case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '1';
when others =>
Set_BusB_To(0) <= '1';
when others =>
Set_BusB_To <= "1000";
end case;
TStates <= "100";
SetWZ <= "11";
when 3 =>
NoRead <= '1';
Read_To_Reg <= '1';
@ -1801,6 +1810,7 @@ begin
Set_BusB_To <= "1000";
end case;
TStates <= "100";
SetWZ <= "11";
when 3 =>
NoRead <= '1';
ALU_Op <= "0011";
@ -1816,46 +1826,49 @@ begin
when others =>
end case;
when "01101111" =>
-- RLD
-- RLD -- Read in M2, not M3! fixed by Sorgelig
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
NoRead <= '1';
when 1 =>
Set_Addr_To <= aXY;
when 3 =>
when 2 =>
Read_To_Reg <= '1';
Set_BusB_To(2 downto 0) <= "110";
Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "1101";
TStates <= "100";
Set_Addr_To <= aXY;
Save_ALU <= '1';
when 4 =>
when 3 =>
TStates <= "100";
I_RLD <= '1';
NoRead <= '1';
Set_Addr_To <= aXY;
when 4 =>
Write <= '1';
when others =>
end case;
when "01100111" =>
-- RRD
-- RRD -- Read in M2, not M3! fixed by Sorgelig
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
when 1 =>
Set_Addr_To <= aXY;
when 3 =>
when 2 =>
Read_To_Reg <= '1';
Set_BusB_To(2 downto 0) <= "110";
Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "1110";
TStates <= "100";
Set_Addr_To <= aXY;
Save_ALU <= '1';
when 4 =>
when 3 =>
TStates <= "100";
I_RRD <= '1';
NoRead <= '1';
Set_Addr_To <= aXY;
when 4 =>
Write <= '1';
when others =>
end case;
when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" =>
-- RETI, RETN
-- RETI/RETN
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
@ -1867,6 +1880,7 @@ begin
when 3 =>
Jump <= '1';
IncDec_16 <= "0111";
LDW <= '1';
I_RETN <= '1';
when others => null;
end case;
@ -1876,8 +1890,8 @@ begin
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
SetWZ <= "01";
when 2 =>
TStates <= "100"; -- MIKEJ should be 4 for IO cycle
IORQ <= '1';
if IR(5 downto 3) /= "110" then
Read_To_Reg <= '1';
@ -1893,42 +1907,40 @@ begin
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To(2 downto 0) <= IR(5 downto 3);
SetWZ <= "01";
Set_BusB_To(2 downto 0) <= IR(5 downto 3);
if IR(5 downto 3) = "110" then
Set_BusB_To(3) <= '1';
end if;
when 2 =>
TStates <= "100"; -- MIKEJ should be 4 for IO cycle
Write <= '1';
IORQ <= '1';
when others =>
end case;
when "10100010" | "10101010" | "10110010" | "10111010" =>
-- INI, IND, INIR, INDR
-- note B is decremented AFTER being put on the bus
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 1 =>
TStates <= "101";
Set_Addr_To <= aBC;
Set_BusB_To <= "1010";
Set_BusA_To <= "0000";
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "0010";
SetWZ <= "11";
IncDec_16(3) <= IR(3);
when 2 =>
TStates <= "100"; -- MIKEJ should be 4 for IO cycle
IORQ <= '1';
Set_BusB_To <= "0110";
Set_Addr_To <= aXY;
when 3 =>
if IR(3) = '0' then
--IncDec_16 <= "0010";
IncDec_16 <= "0110";
else
--IncDec_16 <= "1010";
IncDec_16 <= "1110";
end if;
TStates <= "100";
Write <= '1';
I_BTR <= '1';
when 4 =>
@ -1938,8 +1950,6 @@ begin
end case;
when "10100011" | "10101011" | "10110011" | "10111011" =>
-- OUTI, OUTD, OTIR, OTDR
-- note B is decremented BEFORE being put on the bus.
-- mikej fix for hl inc
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 1 =>
@ -1953,13 +1963,14 @@ begin
when 2 =>
Set_BusB_To <= "0110";
Set_Addr_To <= aBC;
SetWZ <= "11";
IncDec_16(3) <= IR(3);
when 3 =>
if IR(3) = '0' then
IncDec_16 <= "0110"; -- mikej
IncDec_16 <= "0110";
else
IncDec_16 <= "1110"; -- mikej
IncDec_16 <= "1110";
end if;
TStates <= "100"; -- MIKEJ should be 4 for IO cycle
IORQ <= '1';
Write <= '1';
I_BTR <= '1';
@ -1974,7 +1985,7 @@ begin
if Mode = 1 then
if MCycle = "001" then
-- TStates <= "100";
-- TStates <= "100";
else
TStates <= "011";
end if;
@ -1982,7 +1993,7 @@ begin
if Mode = 3 then
if MCycle = "001" then
-- TStates <= "100";
-- TStates <= "100";
else
TStates <= "100";
end if;

View File

@ -1,3 +1,13 @@
--------------------------------------------------------------------------------
-- ****
-- T80(c) core. Attempt to finish all undocumented features and provide
-- accurate timings.
-- Version 350.
-- Copyright (c) 2018 Sorgelig
-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr
-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as
-- correct implementation is still unclear.
--
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
@ -47,15 +57,15 @@
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t51/
-- http://www.opencores.org/cvsweb.shtml/t51/
--
-- Limitations :
--
-- File history :
--
-- 0242 : Initial release
-- 0242 : Initial release
--
-- 0244 : Changed to single register file
-- 0244 : Changed to single register file
--
library IEEE;
@ -64,36 +74,63 @@ use IEEE.numeric_std.all;
entity T80_Reg is
port(
Clk : in std_logic;
CEN : in std_logic;
WEH : in std_logic;
WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0)
Clk : in std_logic;
CEN : in std_logic;
WEH : in std_logic;
WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0);
DOR : out std_logic_vector(127 downto 0);
DIRSet : in std_logic;
DIR : in std_logic_vector(127 downto 0)
);
end T80_Reg;
architecture rtl of T80_Reg is
type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0);
signal RegsH : Register_Image(0 to 7);
signal RegsL : Register_Image(0 to 7);
signal RegsH : Register_Image(0 to 7);
signal RegsL : Register_Image(0 to 7);
begin
process (Clk)
begin
if Clk'event and Clk = '1' then
if CEN = '1' then
if rising_edge(Clk) then
if DIRSet = '1' then
RegsL(0) <= DIR( 7 downto 0);
RegsH(0) <= DIR( 15 downto 8);
RegsL(1) <= DIR( 23 downto 16);
RegsH(1) <= DIR( 31 downto 24);
RegsL(2) <= DIR( 39 downto 32);
RegsH(2) <= DIR( 47 downto 40);
RegsL(3) <= DIR( 55 downto 48);
RegsH(3) <= DIR( 63 downto 56);
RegsL(4) <= DIR( 71 downto 64);
RegsH(4) <= DIR( 79 downto 72);
RegsL(5) <= DIR( 87 downto 80);
RegsH(5) <= DIR( 95 downto 88);
RegsL(6) <= DIR(103 downto 96);
RegsH(6) <= DIR(111 downto 104);
RegsL(7) <= DIR(119 downto 112);
RegsH(7) <= DIR(127 downto 120);
elsif CEN = '1' then
if WEH = '1' then
RegsH(to_integer(unsigned(AddrA))) <= DIH;
end if;
@ -110,5 +147,6 @@ begin
DOBL <= RegsL(to_integer(unsigned(AddrB)));
DOCH <= RegsH(to_integer(unsigned(AddrC)));
DOCL <= RegsL(to_integer(unsigned(AddrC)));
DOR <= RegsH(7) & RegsL(7) & RegsH(6) & RegsL(6) & RegsH(5) & RegsL(5) & RegsH(4) & RegsL(4) & RegsH(3) & RegsL(3) & RegsH(2) & RegsL(2) & RegsH(1) & RegsL(1) & RegsH(0) & RegsL(0);
end;

View File

@ -0,0 +1,192 @@
--
-- Z80 compatible microprocessor core, synchronous top level
-- Different timing than the original z80
-- Inputs needs to be synchronous and outputs may glitch
--
-- Version : 0242
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
-- 0208 : First complete release
--
-- 0210 : Fixed read with wait
--
-- 0211 : Fixed interrupt cycle
--
-- 0235 : Updated for T80 interface change
--
-- 0236 : Added T2Write generic
--
-- 0237 : Fixed T2Write with wait state
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity T80s is
generic(
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
T2Write : integer := 1; -- 0 => WR_n active in T3, /=0 => WR_n active in T2
IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle
);
port(
RESET_n : in std_logic;
CLK : in std_logic;
CEN : in std_logic := '1';
WAIT_n : in std_logic := '1';
INT_n : in std_logic := '1';
NMI_n : in std_logic := '1';
BUSRQ_n : in std_logic := '1';
M1_n : out std_logic;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : out std_logic;
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
OUT0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255
A : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end T80s;
architecture rtl of T80s is
signal IntCycle_n : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal IORQ : std_logic;
signal DI_Reg : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
begin
u0 : work.T80
generic map(
Mode => Mode,
IOWait => IOWait)
port map(
CEN => CEN,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => Wait_n,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK_n,
CLK_n => CLK,
A => A,
DInst => DI,
DI => DI_Reg,
DO => DO,
MC => MCycle,
TS => TState,
OUT0 => OUT0,
IntCycle_n => IntCycle_n
);
process (RESET_n, CLK)
begin
if RESET_n = '0' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
DI_Reg <= "00000000";
elsif rising_edge(CLK) then
if CEN = '1' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
if MCycle = 1 then
if TState = 1 or (TState = 2 and Wait_n = '0') then
RD_n <= not IntCycle_n;
MREQ_n <= not IntCycle_n;
IORQ_n <= IntCycle_n;
end if;
if TState = 3 then
MREQ_n <= '0';
end if;
else
if (TState = 1 or (TState = 2 and Wait_n = '0')) and NoRead = '0' and Write = '0' then
RD_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
if T2Write = 0 then
if TState = 2 and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
else
if (TState = 1 or (TState = 2 and Wait_n = '0')) and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
end if;
end if;
if TState = 2 and Wait_n = '1' then
DI_Reg <= DI;
end if;
end if;
end if;
end process;
end;

View File

@ -1,192 +0,0 @@
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- Z80 compatible microprocessor core, synchronous top level with clock enable
-- Different timing than the original z80
-- Inputs needs to be synchronous and outputs may glitch
--
-- Version : 0240
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
-- 0235 : First release
--
-- 0236 : Added T2Write generic
--
-- 0237 : Fixed T2Write with wait state
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
entity T80se is
generic(
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2
IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle
);
port(
RESET_n : in std_logic;
CLK_n : in std_logic;
CLKEN : in std_logic;
WAIT_n : in std_logic;
INT_n : in std_logic;
NMI_n : in std_logic;
BUSRQ_n : in std_logic;
M1_n : out std_logic;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : out std_logic;
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
A : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end T80se;
architecture rtl of T80se is
signal IntCycle_n : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal IORQ : std_logic;
signal DI_Reg : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
begin
u0 : T80
generic map(
Mode => Mode,
IOWait => IOWait)
port map(
CEN => CLKEN,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => Wait_n,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK_n,
CLK_n => CLK_n,
A => A,
DInst => DI,
DI => DI_Reg,
DO => DO,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n);
process (RESET_n, CLK_n)
begin
if RESET_n = '0' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
DI_Reg <= "00000000";
elsif CLK_n'event and CLK_n = '1' then
if CLKEN = '1' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
if MCycle = "001" then
if TState = "001" or (TState = "010" and Wait_n = '0') then
RD_n <= not IntCycle_n;
MREQ_n <= not IntCycle_n;
IORQ_n <= IntCycle_n;
end if;
if TState = "011" then
MREQ_n <= '0';
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then
RD_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
if T2Write = 0 then
if TState = "010" and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
end if;
end if;
if TState = "010" and Wait_n = '1' then
DI_Reg <= DI;
end if;
end if;
end if;
end process;
end;

View File

@ -30,7 +30,7 @@ end Z80;
architecture SYN of Z80 is
component T80se is
component T80s is
generic
(
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
@ -39,8 +39,8 @@ architecture SYN of Z80 is
port
(
RESET_n : in std_logic;
CLK_n : in std_logic;
CLKEN : in std_logic;
CLK : in std_logic;
CEN : in std_logic;
WAIT_n : in std_logic;
INT_n : in std_logic;
NMI_n : in std_logic;
@ -57,7 +57,7 @@ architecture SYN of Z80 is
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end component T80se;
end component T80s;
-- Signal Declarations
@ -105,7 +105,7 @@ architecture SYN of Z80 is
z80_datai <= intvec when ((z80_memrd or z80_iord) = '0') else
datai;
Z80_uP : T80se
Z80_uP : T80s
generic map
(
Mode => 0 -- Z80
@ -113,8 +113,8 @@ architecture SYN of Z80 is
port map
(
RESET_n => reset_n,
CLK_n => clk,
CLKEN => clk_en,
CLK => clk,
CEN => clk_en,
WAIT_n => wait_n,
INT_n => int_n,
NMI_n => nmi_n,