T80: Sync with latest version.

This commit is contained in:
sorgelig
2018-08-21 23:21:12 +08:00
parent 7aaa1db5e3
commit 75557d8fd3
15 changed files with 1002 additions and 1378 deletions

View File

@ -355,12 +355,7 @@ set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl"
set_global_assignment -name CDF_FILE jtag.cdf set_global_assignment -name CDF_FILE jtag.cdf
set_global_assignment -name QIP_FILE sys/sys.qip set_global_assignment -name QIP_FILE sys/sys.qip
set_global_assignment -name VHDL_FILE src/t80/T80_Reg.vhd set_global_assignment -name QIP_FILE src/t80/T80.qip
set_global_assignment -name VHDL_FILE src/t80/T80_Pack.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_MCode.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_ALU.vhd
set_global_assignment -name VHDL_FILE src/t80/T80.vhd
set_global_assignment -name VHDL_FILE src/t80/T80s.vhd
set_global_assignment -name VERILOG_FILE src/cpu/zsignals.v set_global_assignment -name VERILOG_FILE src/cpu/zsignals.v
set_global_assignment -name VERILOG_FILE src/cpu/zports.v set_global_assignment -name VERILOG_FILE src/cpu/zports.v
set_global_assignment -name VERILOG_FILE src/cpu/zmem.v set_global_assignment -name VERILOG_FILE src/cpu/zmem.v

View File

@ -119,7 +119,7 @@ localparam CONF_STR = {
"O8,CPU Cache,On,Off;", "O8,CPU Cache,On,Off;",
"O9A,#7FFD span,128K,128K Auto,1024K,512K;", "O9A,#7FFD span,128K,128K Auto,1024K,512K;",
"OLN,ZX Palette,Default,B.black,Light,Pale,Dark,Grayscale,Custom;", "OLN,ZX Palette,Default,B.black,Light,Pale,Dark,Grayscale,Custom;",
"OPR,INT Offset,2,3,4,5,6,7,0,1;", "OPR,INT Offset,3,4,5,6,7,0,1,2;",
"-;", "-;",
"OBD,F11 Reset,boot.$C,sys.rom,ROM;", "OBD,F11 Reset,boot.$C,sys.rom,ROM;",
"OEF, bank,TR-DOS,Basic 48,Basic 128,SYS;", "OEF, bank,TR-DOS,Basic 48,Basic 128,SYS;",
@ -144,7 +144,7 @@ assign CMOSCfg[18:16]= (status[18:16]) ? status[18:16] + 3'd2 : 3'd0;
assign CMOSCfg[20:19]= status[20:19] + 2'd2; assign CMOSCfg[20:19]= status[20:19] + 2'd2;
assign CMOSCfg[23:21]= status[23:21]; assign CMOSCfg[23:21]= status[23:21];
assign CMOSCfg[24] = 0; assign CMOSCfg[24] = 0;
assign CMOSCfg[27:25]= status[27:25] + 3'd2; assign CMOSCfg[27:25]= status[27:25] + 3'd3;
//////////////////// CLOCKS /////////////////// //////////////////// CLOCKS ///////////////////

View File

@ -103,15 +103,12 @@ wire cpu_wr_n;
wire [15:0] cpu_a_bus; wire [15:0] cpu_a_bus;
wire [7:0] cpu_do_bus; wire [7:0] cpu_do_bus;
T80s cpu T80pa cpu
( (
.RESET_n(~RESET), .RESET_n(~RESET),
.CLK_n(CLK), .CLK(CLK),
.CEN(CE & ~MEM_WAIT), .CEN_p(CE & ~MEM_WAIT),
.WAIT_n(1),
.INT_n(int_n), .INT_n(int_n),
.NMI_n(1),
.BUSRQ_n(1),
.M1_n(cpu_m1_n), .M1_n(cpu_m1_n),
.MREQ_n(cpu_mreq_n), .MREQ_n(cpu_mreq_n),
.IORQ_n(cpu_iorq_n), .IORQ_n(cpu_iorq_n),

7
src/t80/T80.qip Normal file
View File

@ -0,0 +1,7 @@
set_global_assignment -name VHDL_FILE src/t80/T80_Reg.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_Pack.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_MCode.vhd
set_global_assignment -name VHDL_FILE src/t80/T80_ALU.vhd
set_global_assignment -name VHDL_FILE src/t80/T80.vhd
set_global_assignment -name VHDL_FILE src/t80/T80pa.vhd
set_global_assignment -name VHDL_FILE src/t80/T80s.vhd

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,10 +1,26 @@
--------------------------------------------------------------------------------
-- ****
-- T80(c) core. Attempt to finish all undocumented features and provide
-- accurate timings.
-- Version 350.
-- Copyright (c) 2018 Sorgelig
-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr
-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as
-- correct implementation is still unclear.
--
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
-- --
-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
-- Z80 compatible microprocessor core -- Z80 compatible microprocessor core
-- --
-- Version : 0247 -- Version : 0247
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved -- All rights reserved
-- --
-- Redistribution and use in source and synthezised forms, with or without -- Redistribution and use in source and synthezised forms, with or without
@ -38,21 +54,17 @@
-- 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 :
-- --
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test -- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
-- -- 0238 : Fixed zero flag for 16 bit SBC and ADC
-- 0238 : Fixed zero flag for 16 bit SBC and ADC -- 0240 : Added GB operations
-- -- 0242 : Cleanup
-- 0240 : Added GB operations -- 0247 : Cleanup
--
-- 0242 : Cleanup
--
-- 0247 : Cleanup
-- --
library IEEE; library IEEE;
@ -72,68 +84,81 @@ entity T80_ALU is
Flag_S : integer := 7 Flag_S : integer := 7
); );
port( port(
Arith16 : in std_logic; Arith16 : in std_logic;
Z16 : in std_logic; Z16 : in std_logic;
ALU_Op : in std_logic_vector(3 downto 0); WZ : in std_logic_vector(15 downto 0);
IR : in std_logic_vector(5 downto 0); XY_State : in std_logic_vector(1 downto 0);
ISet : in std_logic_vector(1 downto 0); ALU_Op : in std_logic_vector(3 downto 0);
BusA : in std_logic_vector(7 downto 0); IR : in std_logic_vector(5 downto 0);
BusB : in std_logic_vector(7 downto 0); ISet : in std_logic_vector(1 downto 0);
F_In : in std_logic_vector(7 downto 0); BusA : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0); BusB : in std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0) F_In : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0)
); );
end T80_ALU; end T80_ALU;
architecture rtl of T80_ALU is architecture rtl of T80_ALU is
procedure AddSub(A : std_logic_vector; procedure AddSub(A : std_logic_vector;
B : std_logic_vector; B : std_logic_vector;
Sub : std_logic; Sub : std_logic;
Carry_In : std_logic; Carry_In : std_logic;
signal Res : out std_logic_vector; signal Res : out std_logic_vector;
signal Carry : out std_logic) is signal Carry : out std_logic) is
variable B_i : unsigned(A'length - 1 downto 0);
variable Res_i : unsigned(A'length + 1 downto 0); variable B_i : unsigned(A'length - 1 downto 0);
variable Res_i : unsigned(A'length + 1 downto 0);
begin begin
if Sub = '1' then if Sub = '1' then
B_i := not unsigned(B); B_i := not unsigned(B);
else else
B_i := unsigned(B); B_i := unsigned(B);
end if; end if;
Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1"); Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
Carry <= Res_i(A'length + 1); Carry <= Res_i(A'length + 1);
Res <= std_logic_vector(Res_i(A'length downto 1)); Res <= std_logic_vector(Res_i(A'length downto 1));
end; end;
-- AddSub variables (temporary signals) -- AddSub variables (temporary signals)
signal UseCarry : std_logic; signal UseCarry : std_logic;
signal Carry7_v : std_logic; signal Carry7_v : std_logic;
signal Overflow_v : std_logic; signal Overflow_v : std_logic;
signal HalfCarry_v : std_logic; signal HalfCarry_v : std_logic;
signal Carry_v : std_logic; signal Carry_v : std_logic;
signal Q_v : std_logic_vector(7 downto 0); signal Q_v : std_logic_vector(7 downto 0);
signal BitMask : std_logic_vector(7 downto 0); signal BitMask : std_logic_vector(7 downto 0);
begin begin
with IR(5 downto 3) select BitMask <= "00000001" when "000", with IR(5 downto 3) select BitMask <= "00000001" when "000",
"00000010" when "001", "00000010" when "001",
"00000100" when "010", "00000100" when "010",
"00001000" when "011", "00001000" when "011",
"00010000" when "100", "00010000" when "100",
"00100000" when "101", "00100000" when "101",
"01000000" when "110", "01000000" when "110",
"10000000" when others; "10000000" when others;
UseCarry <= not ALU_Op(2) and ALU_Op(0); UseCarry <= not ALU_Op(2) and ALU_Op(0);
AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v); AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v); AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v); AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
OverFlow_v <= Carry_v xor Carry7_v;
process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) -- bug fix - parity flag is just parity for 8080, also overflow for Z80
process (Carry_v, Carry7_v, Q_v)
begin
if(Mode=2) then
OverFlow_v <= not (Q_v(0) xor Q_v(1) xor Q_v(2) xor Q_v(3) xor
Q_v(4) xor Q_v(5) xor Q_v(6) xor Q_v(7)); else
OverFlow_v <= Carry_v xor Carry7_v;
end if;
end process;
process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, WZ, XY_State)
variable Q_t : std_logic_vector(7 downto 0); variable Q_t : std_logic_vector(7 downto 0);
variable DAA_Q : unsigned(8 downto 0); variable DAA_Q : unsigned(8 downto 0);
begin begin
@ -176,7 +201,7 @@ begin
if Q_t(7 downto 0) = "00000000" then if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1'; F_Out(Flag_Z) <= '1';
if Z16 = '1' then if Z16 = '1' then
F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC
end if; end if;
else else
F_Out(Flag_Z) <= '0'; F_Out(Flag_Z) <= '0';
@ -271,11 +296,12 @@ begin
end if; end if;
F_Out(Flag_H) <= '1'; F_Out(Flag_H) <= '1';
F_Out(Flag_N) <= '0'; F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= '0'; if IR(2 downto 0) = "110" or XY_State /= "00" then
F_Out(Flag_Y) <= '0'; F_Out(Flag_X) <= WZ(11);
if IR(2 downto 0) /= "110" then F_Out(Flag_Y) <= WZ(13);
F_Out(Flag_X) <= BusB(3); else
F_Out(Flag_Y) <= BusB(5); F_Out(Flag_X) <= BusB(3);
F_Out(Flag_Y) <= BusB(5);
end if; end if;
when "1010" => when "1010" =>
-- SET -- SET
@ -347,5 +373,4 @@ begin
end case; end case;
Q <= Q_t; Q <= Q_t;
end process; end process;
end; end;

View File

@ -1,10 +1,26 @@
--------------------------------------------------------------------------------
-- ****
-- T80(c) core. Attempt to finish all undocumented features and provide
-- accurate timings.
-- Version 350.
-- Copyright (c) 2018 Sorgelig
-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr
-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as
-- correct implementation is still unclear.
--
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
-- --
-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
-- Z80 compatible microprocessor core -- Z80 compatible microprocessor core
-- --
-- Version : 0242 -- Version : 0242
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved -- All rights reserved
-- --
-- Redistribution and use in source and synthezised forms, with or without -- Redistribution and use in source and synthezised forms, with or without
@ -38,36 +54,31 @@
-- 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 IM 1
-- 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
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test -- 0238 : Added NoRead signal
-- -- 0238b: Fixed instruction timing for POP and DJNZ
-- 0235 : Added IM 2 fix by Mike Johnson -- 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
-- 0238 : Added NoRead signal -- 0242 : Fixed I/O instruction timing, cleanup
--
-- 0238b: Fixed instruction timing for POP and DJNZ
--
-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes
--
-- 0242 : Fixed I/O instruction timing, cleanup
-- --
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 work.T80_Pack.all;
entity T80_MCode is entity T80_MCode is
generic( generic(
Mode : integer := 0; Mode : integer := 0;
Flag_C : integer := 0; Flag_C : integer := 0;
Flag_N : integer := 1; Flag_N : integer := 1;
Flag_P : integer := 2; Flag_P : integer := 2;
@ -78,80 +89,74 @@ entity T80_MCode is
Flag_S : integer := 7 Flag_S : integer := 7
); );
port( port(
IR : in std_logic_vector(7 downto 0); IR : in std_logic_vector(7 downto 0);
ISet : in std_logic_vector(1 downto 0); ISet : in std_logic_vector(1 downto 0);
MCycle : in std_logic_vector(2 downto 0); MCycle : in std_logic_vector(2 downto 0);
F : in std_logic_vector(7 downto 0); F : in std_logic_vector(7 downto 0);
NMICycle : in std_logic; NMICycle : in std_logic;
IntCycle : in std_logic; IntCycle : in std_logic;
XY_State : in std_logic_vector(1 downto 0); XY_State : in std_logic_vector(1 downto 0);
MCycles : out std_logic_vector(2 downto 0); MCycles : out std_logic_vector(2 downto 0);
TStates : 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 Prefix : out std_logic_vector(1 downto 0); -- None,CB,ED,DD/FD
Inc_PC : out std_logic; Inc_PC : out std_logic;
Inc_WZ : out std_logic; Inc_WZ : out std_logic;
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
Read_To_Reg : out std_logic; Read_To_Reg : out std_logic;
Read_To_Acc : 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_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 Set_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); 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;
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
IORQ : out std_logic; IORQ : out std_logic;
Jump : out std_logic; Jump : out std_logic;
JumpE : out std_logic; JumpE : out std_logic;
JumpXY : out std_logic; JumpXY : out std_logic;
Call : out std_logic; Call : out std_logic;
RstP : out std_logic; RstP : out std_logic;
LDZ : out std_logic; LDZ : out std_logic;
LDW : out std_logic; LDW : out std_logic;
LDSPHL : 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 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;
ExchangeAF : out std_logic; ExchangeAF : out std_logic;
ExchangeRS : out std_logic; ExchangeRS : out std_logic;
I_DJNZ : out std_logic; I_DJNZ : out std_logic;
I_CPL : out std_logic; I_CPL : out std_logic;
I_CCF : out std_logic; I_CCF : out std_logic;
I_SCF : out std_logic; I_SCF : out std_logic;
I_RETN : out std_logic; I_RETN : out std_logic;
I_BT : out std_logic; I_BT : out std_logic;
I_BC : out std_logic; I_BC : out std_logic;
I_BTR : out std_logic; I_BTR : out std_logic;
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;
SetDI : out std_logic; SetWZ : out std_logic_vector(1 downto 0);
SetEI : out std_logic; SetDI : out std_logic;
IMode : out std_logic_vector(1 downto 0); SetEI : out std_logic;
Halt : out std_logic; IMode : out std_logic_vector(1 downto 0);
NoRead : out std_logic; Halt : out std_logic;
Write : out std_logic; NoRead : out std_logic;
XYbit_undoc : out std_logic Write : out std_logic;
); XYbit_undoc : out std_logic
);
end T80_MCode; end T80_MCode;
architecture rtl of T80_MCode is architecture rtl of T80_MCode is
constant aNone : std_logic_vector(2 downto 0) := "111"; constant aNone : std_logic_vector(2 downto 0) := "111";
constant aBC : std_logic_vector(2 downto 0) := "000"; constant aBC : std_logic_vector(2 downto 0) := "000";
constant aDE : std_logic_vector(2 downto 0) := "001"; constant aDE : std_logic_vector(2 downto 0) := "001";
constant aXY : std_logic_vector(2 downto 0) := "010"; constant aXY : std_logic_vector(2 downto 0) := "010";
constant aIOA : std_logic_vector(2 downto 0) := "100"; constant aIOA : std_logic_vector(2 downto 0) := "100";
constant aSP : std_logic_vector(2 downto 0) := "101"; constant aSP : std_logic_vector(2 downto 0) := "101";
constant aZI : std_logic_vector(2 downto 0) := "110"; constant aZI : std_logic_vector(2 downto 0) := "110";
-- constant aNone : std_logic_vector(2 downto 0) := "000";
-- constant aXY : std_logic_vector(2 downto 0) := "001";
-- constant aIOA : std_logic_vector(2 downto 0) := "010";
-- constant aSP : std_logic_vector(2 downto 0) := "011";
-- constant aBC : std_logic_vector(2 downto 0) := "100";
-- constant aDE : std_logic_vector(2 downto 0) := "101";
-- constant aZI : std_logic_vector(2 downto 0) := "110";
function is_cc_true( function is_cc_true(
F : std_logic_vector(7 downto 0); F : std_logic_vector(7 downto 0);
@ -160,10 +165,10 @@ architecture rtl of T80_MCode is
begin begin
if Mode = 3 then if Mode = 3 then
case cc is case cc is
when "000" => return F(7) = '0'; -- NZ when "000" => return F(Flag_S) = '0'; -- NZ
when "001" => return F(7) = '1'; -- Z when "001" => return F(Flag_S) = '1'; -- Z
when "010" => return F(4) = '0'; -- NC when "010" => return F(Flag_H) = '0'; -- NC
when "011" => return F(4) = '1'; -- C when "011" => return F(Flag_H) = '1'; -- C
when "100" => return false; when "100" => return false;
when "101" => return false; when "101" => return false;
when "110" => return false; when "110" => return false;
@ -171,14 +176,14 @@ architecture rtl of T80_MCode is
end case; end case;
else else
case cc is case cc is
when "000" => return F(6) = '0'; -- NZ when "000" => return F(Flag_Z) = '0'; -- NZ
when "001" => return F(6) = '1'; -- Z when "001" => return F(Flag_Z) = '1'; -- Z
when "010" => return F(0) = '0'; -- NC when "010" => return F(Flag_C) = '0'; -- NC
when "011" => return F(0) = '1'; -- C when "011" => return F(Flag_C) = '1'; -- C
when "100" => return F(2) = '0'; -- PO when "100" => return F(Flag_P) = '0'; -- PO
when "101" => return F(2) = '1'; -- PE when "101" => return F(Flag_P) = '1'; -- PE
when "110" => return F(7) = '0'; -- P when "110" => return F(Flag_S) = '0'; -- P
when "111" => return F(7) = '1'; -- M when "111" => return F(Flag_S) = '1'; -- M
end case; end case;
end if; end if;
end; end;
@ -186,10 +191,10 @@ architecture rtl of T80_MCode is
begin begin
process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State) process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State)
variable DDD : std_logic_vector(2 downto 0); variable DDD : std_logic_vector(2 downto 0);
variable SSS : std_logic_vector(2 downto 0); variable SSS : std_logic_vector(2 downto 0);
variable DPair : std_logic_vector(1 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 begin
DDD := IR(5 downto 3); DDD := IR(5 downto 3);
SSS := IR(2 downto 0); SSS := IR(2 downto 0);
@ -245,8 +250,9 @@ begin
IMode <= "11"; IMode <= "11";
Halt <= '0'; Halt <= '0';
NoRead <= '0'; NoRead <= '0';
Write <= '0'; Write <= '0';
XYbit_undoc <= '0'; XYbit_undoc <= '0';
SetWZ <= "00";
case ISet is case ISet is
when "00" => when "00" =>
@ -371,6 +377,7 @@ begin
when 1 => when 1 =>
Set_Addr_To <= aBC; Set_Addr_To <= aBC;
Set_BusB_To <= "0111"; Set_BusB_To <= "0111";
SetWZ <= "10";
when 2 => when 2 =>
Write <= '1'; Write <= '1';
when others => null; when others => null;
@ -382,6 +389,7 @@ begin
when 1 => when 1 =>
Set_Addr_To <= aDE; Set_Addr_To <= aDE;
Set_BusB_To <= "0111"; Set_BusB_To <= "0111";
SetWZ <= "10";
when 2 => when 2 =>
Write <= '1'; Write <= '1';
when others => null; when others => null;
@ -407,7 +415,8 @@ begin
Inc_PC <= '1'; Inc_PC <= '1';
LDZ <= '1'; LDZ <= '1';
when 3 => when 3 =>
Set_Addr_To <= aZI; Set_Addr_To <= aZI;
SetWZ <= "10";
Inc_PC <= '1'; Inc_PC <= '1';
Set_BusB_To <= "0111"; Set_BusB_To <= "0111";
when 4 => when 4 =>
@ -637,7 +646,8 @@ begin
Read_To_Reg <= '1'; Read_To_Reg <= '1';
Set_BusA_To <= "0101"; Set_BusA_To <= "0101";
Set_BusB_To <= "0101"; Set_BusB_To <= "0101";
Set_Addr_To <= aSP; Set_Addr_To <= aSP;
LDZ <= '1';
when 3 => when 3 =>
IncDec_16 <= "0111"; IncDec_16 <= "0111";
Set_Addr_To <= aSP; Set_Addr_To <= aSP;
@ -648,6 +658,7 @@ begin
Set_BusA_To <= "0100"; Set_BusA_To <= "0100";
Set_BusB_To <= "0100"; Set_BusB_To <= "0100";
Set_Addr_To <= aSP; Set_Addr_To <= aSP;
LDW <= '1';
when 5 => when 5 =>
IncDec_16 <= "1111"; IncDec_16 <= "1111";
TStates <= "101"; TStates <= "101";
@ -864,7 +875,8 @@ begin
Set_BusB_To <= "1000"; Set_BusB_To <= "1000";
end case; end case;
TStates <= "100"; TStates <= "100";
Arith16 <= '1'; Arith16 <= '1';
SetWZ <= "11";
when 3 => when 3 =>
NoRead <= '1'; NoRead <= '1';
Read_To_Reg <= '1'; Read_To_Reg <= '1';
@ -916,6 +928,7 @@ begin
when 3 => when 3 =>
Inc_PC <= '1'; Inc_PC <= '1';
Jump <= '1'; Jump <= '1';
LDW <= '1';
when others => null; when others => null;
end case; end case;
when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" =>
@ -982,6 +995,7 @@ begin
Inc_PC <= '1'; Inc_PC <= '1';
LDZ <= '1'; LDZ <= '1';
when 3 => when 3 =>
LDW <= '1';
Inc_PC <= '1'; Inc_PC <= '1';
if is_cc_true(F, to_bitvector(IR(5 downto 3))) then if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
Jump <= '1'; Jump <= '1';
@ -1363,7 +1377,7 @@ begin
-- SRL r -- SRL r
-- SLL r (Undocumented) / SWAP r -- SLL r (Undocumented) / SWAP r
if XY_State="00" then if XY_State="00" then
if MCycle = "001" or MCycle = "111" then if MCycle = "001" then
ALU_Op <= "1000"; ALU_Op <= "1000";
Read_To_Reg <= '1'; Read_To_Reg <= '1';
Save_ALU <= '1'; Save_ALU <= '1';
@ -1420,7 +1434,7 @@ begin
|"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" =>
-- BIT b,r -- BIT b,r
if XY_State="00" then if XY_State="00" then
if MCycle = "001" or MCycle = "111" then if MCycle = "001" then
Set_BusB_To(2 downto 0) <= IR(2 downto 0); Set_BusB_To(2 downto 0) <= IR(2 downto 0);
ALU_Op <= "1001"; ALU_Op <= "1001";
end if; end if;
@ -1463,24 +1477,6 @@ begin
ALU_Op <= "1010"; ALU_Op <= "1010";
Read_To_Reg <= '1'; Read_To_Reg <= '1';
Save_ALU <= '1'; Save_ALU <= '1';
else
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 7 =>
Set_Addr_To <= aXY;
when 2 =>
Set_BusB_To(2 downto 0) <= "110";
ALU_Op <= "1010";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_Addr_To <= aXY;
TStates <= "100";
when 3 =>
Set_Addr_To <= aXY;
when 4 =>
Write <= '1';
when others => null;
end case;
end if; end if;
else else
-- SET b,(IX+d),Reg, undocumented -- SET b,(IX+d),Reg, undocumented
@ -1531,24 +1527,6 @@ begin
ALU_Op <= "1011"; ALU_Op <= "1011";
Read_To_Reg <= '1'; Read_To_Reg <= '1';
Save_ALU <= '1'; Save_ALU <= '1';
else
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 7 =>
Set_Addr_To <= aXY;
when 2 =>
Set_BusB_To(2 downto 0) <= "110";
ALU_Op <= "1011";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_Addr_To <= aXY;
TStates <= "100";
when 3 =>
Set_Addr_To <= aXY;
when 4 =>
Write <= '1';
when others => null;
end case;
end if; end if;
else else
-- RES b,(IX+d),Reg, undocumented -- RES b,(IX+d),Reg, undocumented
@ -1709,7 +1687,7 @@ begin
when others => null; when others => null;
end case; end case;
when "10100000" | "10101000" | "10110000" | "10111000" => when "10100000" | "10101000" | "10110000" | "10111000" =>
-- LDI, LDD, LDIR, LDDR -- LDI, LDD, LDIR, LDDR
MCycles <= "100"; MCycles <= "100";
case to_integer(unsigned(MCycle)) is case to_integer(unsigned(MCycle)) is
when 1 => when 1 =>
@ -1796,11 +1774,12 @@ begin
case to_integer(unsigned(IR(5 downto 4))) is case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 => when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4); Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '1'; Set_BusB_To(0) <= '1';
when others => when others =>
Set_BusB_To <= "1000"; Set_BusB_To <= "1000";
end case; end case;
TStates <= "100"; TStates <= "100";
SetWZ <= "11";
when 3 => when 3 =>
NoRead <= '1'; NoRead <= '1';
Read_To_Reg <= '1'; Read_To_Reg <= '1';
@ -1834,6 +1813,7 @@ begin
Set_BusB_To <= "1000"; Set_BusB_To <= "1000";
end case; end case;
TStates <= "100"; TStates <= "100";
SetWZ <= "11";
when 3 => when 3 =>
NoRead <= '1'; NoRead <= '1';
ALU_Op <= "0011"; ALU_Op <= "0011";
@ -1849,46 +1829,49 @@ begin
when others => when others =>
end case; end case;
when "01101111" => when "01101111" =>
-- RLD -- RLD -- Read in M2, not M3! fixed by Sorgelig
MCycles <= "100"; MCycles <= "100";
case to_integer(unsigned(MCycle)) is case to_integer(unsigned(MCycle)) is
when 2 => when 1 =>
NoRead <= '1';
Set_Addr_To <= aXY; Set_Addr_To <= aXY;
when 3 => when 2 =>
Read_To_Reg <= '1'; Read_To_Reg <= '1';
Set_BusB_To(2 downto 0) <= "110"; Set_BusB_To(2 downto 0) <= "110";
Set_BusA_To(2 downto 0) <= "111"; Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "1101"; ALU_Op <= "1101";
TStates <= "100";
Set_Addr_To <= aXY;
Save_ALU <= '1'; Save_ALU <= '1';
when 4 => when 3 =>
TStates <= "100";
I_RLD <= '1'; I_RLD <= '1';
NoRead <= '1';
Set_Addr_To <= aXY;
when 4 =>
Write <= '1'; Write <= '1';
when others => when others =>
end case; end case;
when "01100111" => when "01100111" =>
-- RRD -- RRD -- Read in M2, not M3! fixed by Sorgelig
MCycles <= "100"; MCycles <= "100";
case to_integer(unsigned(MCycle)) is case to_integer(unsigned(MCycle)) is
when 2 => when 1 =>
Set_Addr_To <= aXY; Set_Addr_To <= aXY;
when 3 => when 2 =>
Read_To_Reg <= '1'; Read_To_Reg <= '1';
Set_BusB_To(2 downto 0) <= "110"; Set_BusB_To(2 downto 0) <= "110";
Set_BusA_To(2 downto 0) <= "111"; Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "1110"; ALU_Op <= "1110";
TStates <= "100";
Set_Addr_To <= aXY;
Save_ALU <= '1'; Save_ALU <= '1';
when 4 => when 3 =>
TStates <= "100";
I_RRD <= '1'; I_RRD <= '1';
NoRead <= '1';
Set_Addr_To <= aXY;
when 4 =>
Write <= '1'; Write <= '1';
when others => when others =>
end case; end case;
when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" => when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" =>
-- RETI, RETN -- RETI/RETN
MCycles <= "011"; MCycles <= "011";
case to_integer(unsigned(MCycle)) is case to_integer(unsigned(MCycle)) is
when 1 => when 1 =>
@ -1899,7 +1882,8 @@ begin
LDZ <= '1'; LDZ <= '1';
when 3 => when 3 =>
Jump <= '1'; Jump <= '1';
IncDec_16 <= "0111"; IncDec_16 <= "0111";
LDW <= '1';
I_RETN <= '1'; I_RETN <= '1';
when others => null; when others => null;
end case; end case;
@ -1908,7 +1892,8 @@ begin
MCycles <= "010"; MCycles <= "010";
case to_integer(unsigned(MCycle)) is case to_integer(unsigned(MCycle)) is
when 1 => when 1 =>
Set_Addr_To <= aBC; Set_Addr_To <= aBC;
SetWZ <= "01";
when 2 => when 2 =>
IORQ <= '1'; IORQ <= '1';
if IR(5 downto 3) /= "110" then if IR(5 downto 3) /= "110" then
@ -1925,6 +1910,7 @@ begin
case to_integer(unsigned(MCycle)) is case to_integer(unsigned(MCycle)) is
when 1 => when 1 =>
Set_Addr_To <= aBC; Set_Addr_To <= aBC;
SetWZ <= "01";
Set_BusB_To(2 downto 0) <= IR(5 downto 3); Set_BusB_To(2 downto 0) <= IR(5 downto 3);
if IR(5 downto 3) = "110" then if IR(5 downto 3) = "110" then
Set_BusB_To(3) <= '1'; Set_BusB_To(3) <= '1';
@ -1939,12 +1925,15 @@ begin
MCycles <= "100"; MCycles <= "100";
case to_integer(unsigned(MCycle)) is case to_integer(unsigned(MCycle)) is
when 1 => when 1 =>
TStates <= "101";
Set_Addr_To <= aBC; Set_Addr_To <= aBC;
Set_BusB_To <= "1010"; Set_BusB_To <= "1010";
Set_BusA_To <= "0000"; Set_BusA_To <= "0000";
Read_To_Reg <= '1'; Read_To_Reg <= '1';
Save_ALU <= '1'; Save_ALU <= '1';
ALU_Op <= "0010"; ALU_Op <= "0010";
SetWZ <= "11";
IncDec_16(3) <= IR(3);
when 2 => when 2 =>
IORQ <= '1'; IORQ <= '1';
Set_BusB_To <= "0110"; Set_BusB_To <= "0110";
@ -1955,7 +1944,6 @@ begin
else else
IncDec_16 <= "1110"; IncDec_16 <= "1110";
end if; end if;
TStates <= "100";
Write <= '1'; Write <= '1';
I_BTR <= '1'; I_BTR <= '1';
when 4 => when 4 =>
@ -1978,6 +1966,8 @@ begin
when 2 => when 2 =>
Set_BusB_To <= "0110"; Set_BusB_To <= "0110";
Set_Addr_To <= aBC; Set_Addr_To <= aBC;
SetWZ <= "11";
IncDec_16(3) <= IR(3);
when 3 => when 3 =>
if IR(3) = '0' then if IR(3) = '0' then
IncDec_16 <= "0110"; IncDec_16 <= "0110";

View File

@ -1,3 +1,23 @@
--------------------------------------------------------------------------------
-- ****
-- T80(c) core. Attempt to finish all undocumented features and provide
-- accurate timings.
-- Version 350.
-- Copyright (c) 2018 Sorgelig
-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr
-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as
-- correct implementation is still unclear.
--
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
-- --
-- Z80 compatible microprocessor core -- Z80 compatible microprocessor core
-- --
@ -52,8 +72,8 @@ package T80_Pack is
component T80 component T80
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 := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle
Flag_C : integer := 0; Flag_C : integer := 0;
Flag_N : integer := 1; Flag_N : integer := 1;
Flag_P : integer := 2; Flag_P : integer := 2;
@ -64,62 +84,57 @@ package T80_Pack is
Flag_S : integer := 7 Flag_S : integer := 7
); );
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;
BUSRQ_n : in std_logic; BUSRQ_n : in std_logic;
M1_n : out std_logic; M1_n : out std_logic;
IORQ : out std_logic; IORQ : out std_logic;
NoRead : out std_logic; NoRead : out std_logic;
Write : out std_logic; Write : out std_logic;
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;
IntE : out std_logic; IntE : out std_logic;
Stop : out std_logic; Stop : out std_logic;
REG : out std_logic_vector(207 downto 0) -- IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A
SavePC : out std_logic_vector(15 downto 0);
SaveINT : out std_logic_vector(7 downto 0);
RestorePC : in std_logic_vector(15 downto 0);
RestoreINT : in std_logic_vector(7 downto 0);
RestorePC_n : in std_logic
); );
end component; end component;
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)
); );
end component; end component;
component T80_MCode component T80_MCode
generic( generic(
Mode : integer := 0; Mode : integer := 0;
Flag_C : integer := 0; Flag_C : integer := 0;
Flag_N : integer := 1; Flag_N : integer := 1;
Flag_P : integer := 2; Flag_P : integer := 2;
@ -130,12 +145,12 @@ package T80_Pack is
Flag_S : integer := 7 Flag_S : integer := 7
); );
port( port(
IR : in std_logic_vector(7 downto 0); IR : in std_logic_vector(7 downto 0);
ISet : in std_logic_vector(1 downto 0); ISet : in std_logic_vector(1 downto 0);
MCycle : in std_logic_vector(2 downto 0); MCycle : in std_logic_vector(2 downto 0);
F : in std_logic_vector(7 downto 0); F : in std_logic_vector(7 downto 0);
NMICycle : in std_logic; NMICycle : in std_logic;
IntCycle : in std_logic; IntCycle : in std_logic;
XY_State : in std_logic_vector(1 downto 0); XY_State : in std_logic_vector(1 downto 0);
MCycles : out std_logic_vector(2 downto 0); MCycles : out std_logic_vector(2 downto 0);
TStates : out std_logic_vector(2 downto 0); TStates : out std_logic_vector(2 downto 0);
@ -145,8 +160,8 @@ package T80_Pack is
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
Read_To_Reg : out std_logic; Read_To_Reg : out std_logic;
Read_To_Acc : 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_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 Set_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); 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;
@ -178,6 +193,7 @@ 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;
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);
@ -190,7 +206,7 @@ package T80_Pack is
component T80_ALU component T80_ALU
generic( generic(
Mode : integer := 0; Mode : integer := 0;
Flag_C : integer := 0; Flag_C : integer := 0;
Flag_N : integer := 1; Flag_N : integer := 1;
Flag_P : integer := 2; Flag_P : integer := 2;
@ -201,16 +217,18 @@ package T80_Pack is
Flag_S : integer := 7 Flag_S : integer := 7
); );
port( port(
Arith16 : in std_logic; Arith16 : in std_logic;
Z16 : in std_logic; Z16 : in std_logic;
ALU_Op : in std_logic_vector(3 downto 0); WZ : in std_logic_vector(15 downto 0);
IR : in std_logic_vector(5 downto 0); XY_State : in std_logic_vector(1 downto 0);
ISet : in std_logic_vector(1 downto 0); ALU_Op : in std_logic_vector(3 downto 0);
BusA : in std_logic_vector(7 downto 0); IR : in std_logic_vector(5 downto 0);
BusB : in std_logic_vector(7 downto 0); ISet : in std_logic_vector(1 downto 0);
F_In : in std_logic_vector(7 downto 0); BusA : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0); BusB : in std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0) F_In : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0)
); );
end component; end component;

View File

@ -1,3 +1,22 @@
--------------------------------------------------------------------------------
-- ****
-- T80(c) core. Attempt to finish all undocumented features and provide
-- accurate timings.
-- Version 350.
-- Copyright (c) 2018 Sorgelig
-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr
-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as
-- correct implementation is still unclear.
--
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
-- --
-- T80 Registers, technology independent -- T80 Registers, technology independent
-- --
@ -55,35 +74,36 @@ use IEEE.numeric_std.all;
entity T80_Reg is entity T80_Reg is
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)
); );
end T80_Reg; end T80_Reg;
architecture rtl of T80_Reg is architecture rtl of T80_Reg is
type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0);
signal RegsH : Register_Image(0 to 7); signal RegsH : Register_Image(0 to 7);
signal RegsL : Register_Image(0 to 7); signal RegsL : Register_Image(0 to 7);
begin begin
process (Clk) process (Clk)
begin begin
if Clk'event and Clk = '1' then if rising_edge(Clk) then
if CEN = '1' then if CEN = '1' then
if WEH = '1' then if WEH = '1' then
RegsH(to_integer(unsigned(AddrA))) <= DIH; RegsH(to_integer(unsigned(AddrA))) <= DIH;
@ -101,5 +121,6 @@ begin
DOBL <= RegsL(to_integer(unsigned(AddrB))); DOBL <= RegsL(to_integer(unsigned(AddrB)));
DOCH <= RegsH(to_integer(unsigned(AddrC))); DOCH <= RegsH(to_integer(unsigned(AddrC)));
DOCL <= RegsL(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; end;

View File

@ -1,268 +0,0 @@
--
-- Z80 compatible microprocessor core, asynchronous top level
--
-- Version : 0247
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
-- 0208 : First complete release
--
-- 0211 : Fixed interrupt cycle
--
-- 0235 : Updated for T80 interface change
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
-- 0247 : Fixed bus req/ack cycle
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
entity T80a is
generic(
Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
);
port(
RESET_n : in std_logic;
CLK_n : in std_logic;
WAIT_n : in std_logic;
INT_n : in std_logic;
NMI_n : in std_logic;
BUSRQ_n : in std_logic;
M1_n : out std_logic;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : out std_logic;
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
A : out std_logic_vector(15 downto 0);
D : inout std_logic_vector(7 downto 0);
SavePC : out std_logic_vector(15 downto 0);
SaveINT : out std_logic_vector(7 downto 0);
RestorePC : in std_logic_vector(15 downto 0);
RestoreINT : in std_logic_vector(7 downto 0);
RestorePC_n : in std_logic
);
end T80a;
architecture rtl of T80a is
signal CEN : std_logic;
signal Reset_s : std_logic;
signal IntCycle_n : std_logic;
signal IORQ : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal MREQ : std_logic;
signal MReq_Inhibit : std_logic;
signal Req_Inhibit : std_logic;
signal RD : std_logic;
signal MREQ_n_i : std_logic;
signal IORQ_n_i : std_logic;
signal RD_n_i : std_logic;
signal WR_n_i : std_logic;
signal RFSH_n_i : std_logic;
signal BUSAK_n_i : std_logic;
signal A_i : std_logic_vector(15 downto 0);
signal DO : std_logic_vector(7 downto 0);
signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser
signal Wait_s : std_logic;
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
begin
CEN <= '1';
BUSAK_n <= BUSAK_n_i;
MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit);
RD_n_i <= not RD or Req_Inhibit;
MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z';
IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z';
RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z';
WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z';
RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z';
A <= A_i when BUSAK_n_i = '1' else (others => 'Z');
D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z');
process (RESET_n, CLK_n)
begin
if RESET_n = '0' then
Reset_s <= '0';
elsif CLK_n'event and CLK_n = '1' then
Reset_s <= '1';
end if;
end process;
u0 : T80
generic map(
Mode => Mode,
IOWait => 1)
port map(
CEN => CEN,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n_i,
HALT_n => HALT_n,
WAIT_n => Wait_s,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => Reset_s,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK_n_i,
CLK_n => CLK_n,
A => A_i,
DInst => D,
DI => DI_Reg,
DO => DO,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n,
SavePC => SavePC,
SaveINT => SaveINT,
RestorePC => RestorePC,
RestoreINT => RestoreINT,
RestorePC_n => RestorePC_n );
process (CLK_n)
begin
if CLK_n'event and CLK_n = '0' then
Wait_s <= WAIT_n;
if TState = "011" and BUSAK_n_i = '1' then
DI_Reg <= to_x01(D);
end if;
end if;
end process;
process (Reset_s,CLK_n)
begin
if Reset_s = '0' then
WR_n_i <= '1';
elsif CLK_n'event and CLK_n = '1' then
WR_n_i <= '1';
if TState = "001" then -- To short for IO writes !!!!!!!!!!!!!!!!!!!
WR_n_i <= not Write;
end if;
end if;
end process;
process (Reset_s,CLK_n)
begin
if Reset_s = '0' then
Req_Inhibit <= '0';
elsif CLK_n'event and CLK_n = '1' then
if MCycle = "001" and TState = "010" then
Req_Inhibit <= '1';
else
Req_Inhibit <= '0';
end if;
end if;
end process;
process (Reset_s,CLK_n)
begin
if Reset_s = '0' then
MReq_Inhibit <= '0';
elsif CLK_n'event and CLK_n = '0' then
if MCycle = "001" and TState = "010" then
MReq_Inhibit <= '1';
else
MReq_Inhibit <= '0';
end if;
end if;
end process;
process(Reset_s,CLK_n)
begin
if Reset_s = '0' then
RD <= '0';
IORQ_n_i <= '1';
MREQ <= '0';
elsif CLK_n'event and CLK_n = '0' then
if MCycle = "001" then
if TState = "001" then
RD <= IntCycle_n;
MREQ <= IntCycle_n;
IORQ_n_i <= IntCycle_n;
end if;
if TState = "011" then
RD <= '0';
IORQ_n_i <= '1';
MREQ <= '1';
end if;
if TState = "100" then
MREQ <= '0';
end if;
else
if TState = "001" and NoRead = '0' then
RD <= not Write;
IORQ_n_i <= not IORQ;
MREQ <= not IORQ;
end if;
if TState = "011" then
RD <= '0';
IORQ_n_i <= '1';
MREQ <= '0';
end if;
end if;
end if;
end process;
end;

211
src/t80/T80pa.vhd Normal file
View File

@ -0,0 +1,211 @@
--
-- Z80 compatible microprocessor core, preudo-asynchronous top level (by Sorgelig)
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- File history :
--
-- v1.0: convert to preudo-asynchronous model with original Z80 timings.
--
-- v2.0: rewritten for more precise timings.
-- support for both CEN_n and CEN_p set to 1. Effective clock will be CLK/2.
--
-- v2.1: Output Address 0 during non-bus MCycle (fix ZX contention)
--
-- v2.2: Interrupt acknowledge cycle has been corrected
-- WAIT_n is broken in T80.vhd. Simulate correct WAIT_n locally.
--
-- v2.3: Output last used Address during non-bus MCycle seems more correct.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
entity T80pa is
generic(
Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
);
port(
RESET_n : in std_logic;
CLK : in std_logic;
CEN_p : in std_logic := '1';
CEN_n : in std_logic := '1';
WAIT_n : in std_logic := '1';
INT_n : in std_logic := '1';
NMI_n : in std_logic := '1';
BUSRQ_n : in std_logic := '1';
M1_n : out std_logic;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : out std_logic;
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
A : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
REG : out std_logic_vector(207 downto 0) -- IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A
);
end T80pa;
architecture rtl of T80pa is
signal IntCycle_n : std_logic;
signal IntCycleD_n : std_logic_vector(1 downto 0);
signal IORQ : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal BUSAK : std_logic;
signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
signal CEN_pol : std_logic;
signal A_int : std_logic_vector(15 downto 0);
signal A_last : std_logic_vector(15 downto 0);
begin
A <= A_int when NoRead = '0' or Write = '1' else A_last;
BUSAK_n <= BUSAK;
u0 : T80
generic map(
Mode => Mode,
IOWait => 1
)
port map(
CEN => CEN_p and not CEN_pol,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => '1',
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK,
CLK_n => CLK,
A => A_int,
DInst => DI, -- valid at beginning of T3
DI => DI_Reg, -- latched at middle of T3
DO => DO,
REG => REG,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n
);
process(CLK)
begin
if rising_edge(CLK) then
if RESET_n = '0' then
WR_n <= '1';
RD_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
DI_Reg <= "00000000";
CEN_pol <= '0';
elsif CEN_p = '1' and CEN_pol = '0' then
CEN_pol <= '1';
if MCycle = "001" then
if TState = "010" then
IORQ_n <= '1';
MREQ_n <= '1';
RD_n <= '1';
end if;
else
if TState = "001" and IORQ = '1' then
WR_n <= not Write;
RD_n <= Write;
IORQ_n <= '0';
end if;
end if;
elsif CEN_n = '1' and CEN_pol = '1' then
if TState = "010" then
CEN_pol <= not WAIT_n;
else
CEN_pol <= '0';
end if;
if TState = "011" and BUSAK = '1' then
DI_Reg <= DI;
end if;
if MCycle = "001" then
if TState = "001" then
IntCycleD_n <= IntCycleD_n(0) & IntCycle_n;
RD_n <= not IntCycle_n;
MREQ_n <= not IntCycle_n;
IORQ_n <= IntCycleD_n(1);
A_last <= A_int;
end if;
if TState = "011" then
IntCycleD_n <= "11";
RD_n <= '1';
MREQ_n <= '0';
end if;
if TState = "100" then
MREQ_n <= '1';
end if;
else
if NoRead = '0' and IORQ = '0' then
if TState = "001" then
RD_n <= Write;
MREQ_n <= '0';
A_last <= A_int;
end if;
end if;
if TState = "010" then
WR_n <= not Write;
end if;
if TState = "011" then
WR_n <= '1';
RD_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
end if;
end if;
end if;
end if;
end process;
end;

View File

@ -79,11 +79,11 @@ entity T80s 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 := '1';
WAIT_n : in std_logic; WAIT_n : in std_logic := '1';
INT_n : in std_logic; INT_n : in std_logic := '1';
NMI_n : in std_logic; NMI_n : in std_logic := '1';
BUSRQ_n : in std_logic; BUSRQ_n : in std_logic := '1';
M1_n : out std_logic; M1_n : out std_logic;
MREQ_n : out std_logic; MREQ_n : out std_logic;
IORQ_n : out std_logic; IORQ_n : out std_logic;
@ -135,14 +135,8 @@ begin
DO => DO, DO => DO,
MC => MCycle, MC => MCycle,
TS => TState, TS => TState,
IntCycle_n => IntCycle_n, IntCycle_n => IntCycle_n
);
SavePC => open,
SaveINT => open,
RestorePC => (others => '1'),
RestoreINT => (others => '1'),
RestorePC_n => '1' );
process (RESET_n, CLK_n) process (RESET_n, CLK_n)
begin begin
@ -152,7 +146,7 @@ begin
IORQ_n <= '1'; IORQ_n <= '1';
MREQ_n <= '1'; MREQ_n <= '1';
DI_Reg <= "00000000"; DI_Reg <= "00000000";
elsif CLK_n'event and CLK_n = '1' then elsif rising_edge(CLK_n) then
if CEN = '1' then if CEN = '1' then
RD_n <= '1'; RD_n <= '1';
WR_n <= '1'; WR_n <= '1';
@ -193,5 +187,4 @@ begin
end if; end if;
end if; end if;
end process; end process;
end; end;

View File

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

View File

@ -329,24 +329,20 @@ zclock TS02
.turbo(turbo) .turbo(turbo)
); );
T80s #(.mode(0), .t2write(1), .iowait(1)) z80_unit T80s CPU
( (
.reset_n((~reset)), .RESET_n(~reset),
.clk_n(zclk), .CLK_n(zclk),
.cen(1), .INT_n(cpu_int_n_TS),
.wait_n(1), .M1_n(cpu_m1_n),
.int_n(cpu_int_n_TS), .MREQ_n(cpu_mreq_n),
.nmi_n(1), .IORQ_n(cpu_iorq_n),
.busrq_n(1), .RD_n(cpu_rd_n),
.m1_n(cpu_m1_n), .WR_n(cpu_wr_n),
.mreq_n(cpu_mreq_n), .RFSH_n(cpu_rfsh_n),
.iorq_n(cpu_iorq_n), .A(cpu_a_bus),
.rd_n(cpu_rd_n), .DI(cpu_di_bus),
.wr_n(cpu_wr_n), .DO(cpu_do_bus)
.rfsh_n(cpu_rfsh_n),
.a(cpu_a_bus),
.di(cpu_di_bus),
.do(cpu_do_bus)
); );
zsignals TS04 zsignals TS04