From 8a2196c4fc97945ce6c64ffe693d508011415c32 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Fri, 31 May 2019 00:18:50 +0200 Subject: [PATCH] Moon Patrol: update T80 --- .../MoonPatrol_MIST/mpatrol.qsf | 6 +- .../MoonPatrol_MIST/src/t80/T80.vhd | 1119 +++++++++-------- .../MoonPatrol_MIST/src/t80/T80_ALU.vhd | 29 +- .../MoonPatrol_MIST/src/t80/T80_MCode.vhd | 305 ++--- .../MoonPatrol_MIST/src/t80/T80_Reg.vhd | 82 +- .../MoonPatrol_MIST/src/t80/T80s.vhd | 192 +++ .../MoonPatrol_MIST/src/t80/T80se.vhd | 192 --- .../MoonPatrol_MIST/src/t80/Z80.vhd | 14 +- 8 files changed, 1040 insertions(+), 899 deletions(-) create mode 100644 Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80s.vhd delete mode 100644 Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80se.vhd diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf index f595a1cd..0fb971ee 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf @@ -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 \ No newline at end of file +set_global_assignment -name VHDL_FILE src/build_id.vhd \ No newline at end of file diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80.vhd index 1ea66542..2fd8f9f5 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80.vhd @@ -1,23 +1,28 @@ +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- -- **** -- T80(b) core. In an effort to merge and maintain bug fixes .... -- --- -- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010 --- Ver 302 fixed IO cycle timing, tested thanks to Alessandro. -- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle --- Ver 300 started tidyup. Rmoved some auto_wait bits from 0247 which caused problems +-- 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 @@ -58,37 +63,27 @@ -- File history : -- -- 0208 : First complete release --- -- 0210 : Fixed wait and halt --- -- 0211 : Fixed Refresh addition and IM 1 --- -- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test --- -- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson --- -- 0235 : Added clock enable and IM 2 fix by Mike Johnson --- -- 0237 : Changed 8080 I/O address output, added IntE output --- -- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag --- -- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode --- -- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM --- -- 0247 : Fixed bus req/ack cycle -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; -use work.T80_Pack.all; +use IEEE.STD_LOGIC_UNSIGNED.all; entity T80 is generic( Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB - IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; @@ -99,34 +94,47 @@ entity T80 is Flag_S : integer := 7 ); port( - RESET_n : in std_logic; - CLK_n : in std_logic; - CEN : in std_logic; - WAIT_n : in std_logic; - INT_n : in std_logic; - NMI_n : in std_logic; - BUSRQ_n : in std_logic; - M1_n : out std_logic; - IORQ : out std_logic; - NoRead : out std_logic; - Write : out std_logic; - RFSH_n : out std_logic; - HALT_n : out std_logic; - BUSAK_n : out std_logic; - A : out std_logic_vector(15 downto 0); - DInst : in std_logic_vector(7 downto 0); - DI : in std_logic_vector(7 downto 0); - DO : out std_logic_vector(7 downto 0); - MC : out std_logic_vector(2 downto 0); - TS : out std_logic_vector(2 downto 0); - IntCycle_n : out std_logic; - IntE : out std_logic; - Stop : out std_logic + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic; + out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A ); end T80; architecture rtl of T80 is + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + -- Registers signal ACC, F : std_logic_vector(7 downto 0); signal Ap, Fp : std_logic_vector(7 downto 0); @@ -149,7 +157,7 @@ architecture rtl of T80 is signal Alternate : std_logic; -- Help Registers - signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register + signal WZ : std_logic_vector(15 downto 0); -- MEMPTR register signal IR : std_logic_vector(7 downto 0); -- Instruction register signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector signal RegBusA_r : std_logic_vector(15 downto 0); @@ -162,11 +170,10 @@ architecture rtl of T80 is signal IntE_FF1 : std_logic; signal IntE_FF2 : std_logic; signal Halt_FF : std_logic; - signal BusReq_s : std_logic; - signal BusAck : std_logic; + signal BusReq_s : std_logic := '0'; + signal BusAck : std_logic := '0'; signal ClkEn : std_logic; signal NMI_s : std_logic; - signal INT_s : std_logic; signal IStatus : std_logic_vector(1 downto 0); signal DI_Reg : std_logic_vector(7 downto 0); @@ -239,17 +246,23 @@ architecture rtl of T80 is signal I_BTR : std_logic; signal I_RLD : std_logic; signal I_RRD : std_logic; + signal I_RXDD : std_logic; signal I_INRC : std_logic; + signal SetWZ : std_logic_vector(1 downto 0); signal SetDI : std_logic; signal SetEI : std_logic; signal IMode : std_logic_vector(1 downto 0); signal Halt : std_logic; signal XYbit_undoc : std_logic; - + signal DOR : std_logic_vector(127 downto 0); begin - mcode : T80_MCode + REG <= IntE_FF2 & IntE_FF1 & IStatus & DOR & std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC when Alternate = '0' + else IntE_FF2 & IntE_FF1 & IStatus & DOR(127 downto 112) & DOR(47 downto 0) & DOR(63 downto 48) & DOR(111 downto 64) & + std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC; + + mcode : work.T80_MCode generic map( Mode => Mode, Flag_C => Flag_C, @@ -308,6 +321,7 @@ begin I_RLD => I_RLD, I_RRD => I_RRD, I_INRC => I_INRC, + SetWZ => SetWZ, SetDI => SetDI, SetEI => SetEI, IMode => IMode, @@ -316,7 +330,7 @@ begin Write => Write, XYbit_undoc => XYbit_undoc); - alu : T80_ALU + alu : work.T80_ALU generic map( Mode => Mode, Flag_C => Flag_C, @@ -330,6 +344,8 @@ begin port map( Arith16 => Arith16_r, Z16 => Z16_r, + WZ => WZ, + XY_State=> XY_State, ALU_Op => ALU_Op_r, IR => IR(5 downto 0), ISet => ISet, @@ -353,11 +369,13 @@ begin ALU_Q; process (RESET_n, CLK_n) + variable n : std_logic_vector(7 downto 0); + variable ioq : std_logic_vector(8 downto 0); begin if RESET_n = '0' then PC <= (others => '0'); -- Program Counter A <= (others => '0'); - TmpAddr <= (others => '0'); + WZ <= (others => '0'); IR <= "00000000"; ISet <= "00"; XY_State <= "00"; @@ -375,7 +393,6 @@ begin Alternate <= '0'; Read_To_Reg_r <= "00000"; - F <= (others => '1'); Arith16_r <= '0'; BTR_r <= '0'; Z16_r <= '0'; @@ -383,333 +400,414 @@ begin Save_ALU_r <= '0'; PreserveC_r <= '0'; XY_Ind <= '0'; + I_RXDD <= '0'; - elsif CLK_n'event and CLK_n = '1' then + elsif rising_edge(CLK_n) then - if ClkEn = '1' then + if DIRSet = '1' then + ACC <= DIR( 7 downto 0); + F <= DIR(15 downto 8); + Ap <= DIR(23 downto 16); + Fp <= DIR(31 downto 24); + I <= DIR(39 downto 32); + R <= unsigned(DIR(47 downto 40)); + SP <= unsigned(DIR(63 downto 48)); + PC <= unsigned(DIR(79 downto 64)); + A <= DIR(79 downto 64); + IStatus <= DIR(209 downto 208); - ALU_Op_r <= "0000"; - Save_ALU_r <= '0'; - Read_To_Reg_r <= "00000"; + elsif ClkEn = '1' then + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + Read_To_Reg_r <= "00000"; - MCycles <= MCycles_d; + MCycles <= MCycles_d; - if Mode = 3 then - IStatus <= "10"; - elsif IMode /= "11" then - IStatus <= IMode; - end if; + if IMode /= "11" then + IStatus <= IMode; + end if; - Arith16_r <= Arith16; - PreserveC_r <= PreserveC; - if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then - Z16_r <= '1'; - else - Z16_r <= '0'; - end if; + Arith16_r <= Arith16; + PreserveC_r <= PreserveC; + if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then + Z16_r <= '1'; + else + Z16_r <= '0'; + end if; - if MCycle = "001" and TState(2) = '0' then - -- MCycle = 1 and TState = 1, 2, or 3 + if MCycle = "001" and TState(2) = '0' then + -- MCycle = 1 and TState = 1, 2, or 3 - if TState = 2 and Wait_n = '1' then - if Mode < 2 then - A(7 downto 0) <= std_logic_vector(R); - A(15 downto 8) <= I; - R(6 downto 0) <= R(6 downto 0) + 1; - end if; + if TState = 2 and Wait_n = '1' then + if Mode < 2 then + A(7 downto 0) <= std_logic_vector(R); + A(15 downto 8) <= I; + R(6 downto 0) <= R(6 downto 0) + 1; + end if; - if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then - PC <= PC + 1; - end if; + if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then + PC <= PC + 1; + end if; - if IntCycle = '1' and IStatus = "01" then - IR <= "11111111"; - elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then - IR <= "00000000"; - else - IR <= DInst; - end if; + if IntCycle = '1' and IStatus = "01" then + IR <= "11111111"; + elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DInst; + end if; - ISet <= "00"; - if Prefix /= "00" then - if Prefix = "11" then - if IR(5) = '1' then - XY_State <= "10"; + ISet <= "00"; + if Prefix /= "00" then + if Prefix = "11" then + if IR(5) = '1' then + XY_State <= "10"; + else + XY_State <= "01"; + end if; else - XY_State <= "01"; + if Prefix = "10" then + XY_State <= "00"; + XY_Ind <= '0'; + end if; + ISet <= Prefix; end if; else - if Prefix = "10" then - XY_State <= "00"; - XY_Ind <= '0'; - end if; - ISet <= Prefix; + XY_State <= "00"; + XY_Ind <= '0'; end if; - else - XY_State <= "00"; - XY_Ind <= '0'; + end if; + + else + -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + + if MCycle = "110" then + XY_Ind <= '1'; + if Prefix = "01" then + ISet <= "01"; + end if; + end if; + + if T_Res = '1' then + BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; + if Jump = '1' then + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= WZ(7 downto 0); + PC(15 downto 8) <= unsigned(DI_Reg); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); + elsif JumpXY = '1' then + A <= RegBusC; + PC <= unsigned(RegBusC); + elsif Call = '1' or RstP = '1' then + A <= WZ; + PC <= unsigned(WZ); + elsif MCycle = MCycles and NMICycle = '1' then + A <= "0000000001100110"; + PC <= "0000000001100110"; + elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then + A(15 downto 8) <= I; + A(7 downto 0) <= WZ(7 downto 0); + PC(15 downto 8) <= unsigned(I); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); + else + case Set_Addr_To is + when aXY => + if XY_State = "00" then + A <= RegBusC; + else + if NextIs_XY_Fetch = '1' then + A <= std_logic_vector(PC); + else + A <= WZ; + end if; + end if; + when aIOA => + if Mode = 3 then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + elsif Mode = 2 then + -- Duplicate I/O address on 8080 + A(15 downto 8) <= DI_Reg; + else + A(15 downto 8) <= ACC; + end if; + A(7 downto 0) <= DI_Reg; + WZ <= (ACC & DI_Reg) + "1"; + when aSP => + A <= std_logic_vector(SP); + when aBC => + if Mode = 3 and IORQ_i = '1' then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + A(7 downto 0) <= RegBusC(7 downto 0); + else + A <= RegBusC; + if SetWZ = "01" then + WZ <= RegBusC + "1"; + end if; + if SetWZ = "10" then + WZ(7 downto 0) <= RegBusC(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; + end if; + when aDE => + A <= RegBusC; + if SetWZ = "10" then + WZ(7 downto 0) <= RegBusC(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; + when aZI => + if Inc_WZ = '1' then + A <= std_logic_vector(unsigned(WZ) + 1); + else + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= WZ(7 downto 0); + if SetWZ = "10" then + WZ(7 downto 0) <= WZ(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; + end if; + when others => + A <= std_logic_vector(PC); + end case; + end if; + + if SetWZ = "11" then + WZ <= std_logic_vector(ID16); + end if; + + Save_ALU_r <= Save_ALU; + ALU_Op_r <= ALU_Op; + + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + end if; + + if (TState = 2 and I_BTR = '1' and IR(0) = '1') or (TState = 1 and I_BTR = '1' and IR(0) = '0') then + ioq := ('0' & DI_Reg) + ('0' & std_logic_vector(ID16(7 downto 0))); + F(Flag_N) <= DI_Reg(7); + F(Flag_C) <= ioq(8); + F(Flag_H) <= ioq(8); + ioq := (ioq and x"7") xor ('0'&BusA); + F(Flag_P) <= not (ioq(0) xor ioq(1) xor ioq(2) xor ioq(3) xor ioq(4) xor ioq(5) xor ioq(6) xor ioq(7)); + end if; + + if TState = 2 and Wait_n = '1' then + if ISet = "01" and MCycle = "111" then + IR <= DInst; + end if; + if JumpE = '1' then + PC <= unsigned(signed(PC) + signed(DI_Reg)); + WZ <= std_logic_vector(signed(PC) + signed(DI_Reg)); + elsif Inc_PC = '1' then + PC <= PC + 1; + end if; + if BTR_r = '1' then + PC <= PC - 2; + end if; + if RstP = '1' then + WZ <= (others =>'0'); + WZ(5 downto 3) <= IR(5 downto 3); + end if; + end if; + if TState = 3 and MCycle = "110" then + WZ <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + end if; + + if MCycle = "011" and TState = 4 and No_BTR = '0' then + if I_BT = '1' or I_BC = '1' then + WZ <= std_logic_vector(PC)-"1"; + end if; + end if; + + if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then + if IncDec_16(2 downto 0) = "111" then + if IncDec_16(3) = '1' then + SP <= SP - 1; + else + SP <= SP + 1; + end if; + end if; + end if; + + if LDSPHL = '1' then + SP <= unsigned(RegBusC); + end if; + if ExchangeAF = '1' then + Ap <= ACC; + ACC <= Ap; + Fp <= F; + F <= Fp; + end if; + if ExchangeRS = '1' then + Alternate <= not Alternate; end if; end if; - else - -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + if TState = 3 then + if LDZ = '1' then + WZ(7 downto 0) <= DI_Reg; + end if; + if LDW = '1' then + WZ(15 downto 8) <= DI_Reg; + end if; - if MCycle = "110" then - XY_Ind <= '1'; - if Prefix = "01" then - ISet <= "01"; + if Special_LD(2) = '1' then + case Special_LD(1 downto 0) is + when "00" => + ACC <= I; + F(Flag_P) <= IntE_FF2; + F(Flag_S) <= I(7); + + if I = x"00" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + + F(Flag_Y) <= I(5); + F(Flag_H) <= '0'; + F(Flag_X) <= I(3); + F(Flag_N) <= '0'; + + + when "01" => + ACC <= std_logic_vector(R); + F(Flag_P) <= IntE_FF2; + F(Flag_S) <= R(7); + + if R = x"00" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + + F(Flag_Y) <= R(5); + F(Flag_H) <= '0'; + F(Flag_X) <= R(3); + F(Flag_N) <= '0'; + + when "10" => + I <= ACC; + when others => + R <= unsigned(ACC); + end case; + end if; + end if; + + if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then + if Mode = 3 then + F(6) <= F_Out(6); + F(5) <= F_Out(5); + F(7) <= F_Out(7); + if PreserveC_r = '0' then + F(4) <= F_Out(4); + end if; + else + F(7 downto 1) <= F_Out(7 downto 1); + if PreserveC_r = '0' then + F(Flag_C) <= F_Out(0); + end if; + end if; + end if; + if T_Res = '1' and I_INRC = '1' then + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + F(Flag_X) <= DI_Reg(3); + F(Flag_Y) <= DI_Reg(5); + if DI_Reg(7 downto 0) = "00000000" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + F(Flag_S) <= DI_Reg(7); + F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor + DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); + end if; + + if TState = 1 and Auto_Wait_t1 = '0' then + -- Keep D0 from M3 for RLD/RRD (Sorgelig) + I_RXDD <= I_RLD or I_RRD; + if I_RXDD='0' then + DO <= BusB; + end if; + if I_RLD = '1' then + DO(3 downto 0) <= BusA(3 downto 0); + DO(7 downto 4) <= BusB(3 downto 0); + end if; + if I_RRD = '1' then + DO(3 downto 0) <= BusB(7 downto 4); + DO(7 downto 4) <= BusA(3 downto 0); end if; end if; if T_Res = '1' then - BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; - if Jump = '1' then - A(15 downto 8) <= DI_Reg; - A(7 downto 0) <= TmpAddr(7 downto 0); - PC(15 downto 8) <= unsigned(DI_Reg); - PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); - elsif JumpXY = '1' then - A <= RegBusC; - PC <= unsigned(RegBusC); - elsif Call = '1' or RstP = '1' then - A <= TmpAddr; - PC <= unsigned(TmpAddr); - elsif MCycle = MCycles and NMICycle = '1' then - A <= "0000000001100110"; - PC <= "0000000001100110"; - elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then - A(15 downto 8) <= I; - A(7 downto 0) <= TmpAddr(7 downto 0); - PC(15 downto 8) <= unsigned(I); - PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); - else - case Set_Addr_To is - when aXY => - if XY_State = "00" then - A <= RegBusC; - else - if NextIs_XY_Fetch = '1' then - A <= std_logic_vector(PC); - else - A <= TmpAddr; - end if; - end if; - when aIOA => - if Mode = 3 then - -- Memory map I/O on GBZ80 - A(15 downto 8) <= (others => '1'); - elsif Mode = 2 then - -- Duplicate I/O address on 8080 - A(15 downto 8) <= DI_Reg; - else - A(15 downto 8) <= ACC; - end if; - A(7 downto 0) <= DI_Reg; - when aSP => - A <= std_logic_vector(SP); - when aBC => - if Mode = 3 and IORQ_i = '1' then - -- Memory map I/O on GBZ80 - A(15 downto 8) <= (others => '1'); - A(7 downto 0) <= RegBusC(7 downto 0); - else - A <= RegBusC; - end if; - when aDE => - A <= RegBusC; - when aZI => - if Inc_WZ = '1' then - A <= std_logic_vector(unsigned(TmpAddr) + 1); - else - A(15 downto 8) <= DI_Reg; - A(7 downto 0) <= TmpAddr(7 downto 0); - end if; - when others => - A <= std_logic_vector(PC); - end case; - end if; - - Save_ALU_r <= Save_ALU; - ALU_Op_r <= ALU_Op; - - if I_CPL = '1' then - -- CPL - ACC <= not ACC; - F(Flag_Y) <= not ACC(5); - F(Flag_H) <= '1'; - F(Flag_X) <= not ACC(3); - F(Flag_N) <= '1'; - end if; - if I_CCF = '1' then - -- CCF - F(Flag_C) <= not F(Flag_C); - F(Flag_Y) <= ACC(5); - F(Flag_H) <= F(Flag_C); - F(Flag_X) <= ACC(3); - F(Flag_N) <= '0'; - end if; - if I_SCF = '1' then - -- SCF - F(Flag_C) <= '1'; - F(Flag_Y) <= ACC(5); - F(Flag_H) <= '0'; - F(Flag_X) <= ACC(3); - F(Flag_N) <= '0'; + Read_To_Reg_r(3 downto 0) <= Set_BusA_To; + Read_To_Reg_r(4) <= Read_To_Reg; + if Read_To_Acc = '1' then + Read_To_Reg_r(3 downto 0) <= "0111"; + Read_To_Reg_r(4) <= '1'; end if; end if; - if TState = 2 and Wait_n = '1' then - if ISet = "01" and MCycle = "111" then - IR <= DInst; - end if; - if JumpE = '1' then - PC <= unsigned(signed(PC) + signed(DI_Reg)); - elsif Inc_PC = '1' then - PC <= PC + 1; - end if; - if BTR_r = '1' then - PC <= PC - 2; - end if; - if RstP = '1' then - TmpAddr <= (others =>'0'); - TmpAddr(5 downto 3) <= IR(5 downto 3); - end if; + if TState = 1 and I_BT = '1' then + F(Flag_X) <= ALU_Q(3); + F(Flag_Y) <= ALU_Q(1); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; end if; - if TState = 3 and MCycle = "110" then - TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + if TState = 1 and I_BC = '1' then + n := ALU_Q - ("0000000" & F_Out(Flag_H)); + F(Flag_X) <= n(3); + F(Flag_Y) <= n(1); + end if; + if I_BC = '1' or I_BT = '1' then + F(Flag_P) <= IncDecZ; end if; - if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then - if IncDec_16(2 downto 0) = "111" then - if IncDec_16(3) = '1' then - SP <= SP - 1; - else - SP <= SP + 1; - end if; - end if; - end if; - - if LDSPHL = '1' then - SP <= unsigned(RegBusC); - end if; - if ExchangeAF = '1' then - Ap <= ACC; - ACC <= Ap; - Fp <= F; - F <= Fp; - end if; - if ExchangeRS = '1' then - Alternate <= not Alternate; - end if; - end if; - - if TState = 3 then - if LDZ = '1' then - TmpAddr(7 downto 0) <= DI_Reg; - end if; - if LDW = '1' then - TmpAddr(15 downto 8) <= DI_Reg; - end if; - - if Special_LD(2) = '1' then - case Special_LD(1 downto 0) is - when "00" => - ACC <= I; - F(Flag_P) <= IntE_FF2; - when "01" => - ACC <= std_logic_vector(R); - F(Flag_P) <= IntE_FF2; - when "10" => - I <= ACC; + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10111" => + ACC <= Save_Mux; + when "10110" => + DO <= Save_Mux; + when "11000" => + SP(7 downto 0) <= unsigned(Save_Mux); + when "11001" => + SP(15 downto 8) <= unsigned(Save_Mux); + when "11011" => + F <= Save_Mux; when others => - R <= unsigned(ACC); end case; - end if; - end if; - - if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then - if Mode = 3 then - F(6) <= F_Out(6); - F(5) <= F_Out(5); - F(7) <= F_Out(7); - if PreserveC_r = '0' then - F(4) <= F_Out(4); - end if; - else - F(7 downto 1) <= F_Out(7 downto 1); - if PreserveC_r = '0' then - F(Flag_C) <= F_Out(0); + if XYbit_undoc='1' then + DO <= ALU_Q; end if; end if; end if; - if T_Res = '1' and I_INRC = '1' then - F(Flag_H) <= '0'; - F(Flag_N) <= '0'; - if DI_Reg(7 downto 0) = "00000000" then - F(Flag_Z) <= '1'; - else - F(Flag_Z) <= '0'; - end if; - F(Flag_S) <= DI_Reg(7); - F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor - DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); - end if; - - if TState = 1 then - DO <= BusB; - if I_RLD = '1' then - DO(3 downto 0) <= BusA(3 downto 0); - DO(7 downto 4) <= BusB(3 downto 0); - end if; - if I_RRD = '1' then - DO(3 downto 0) <= BusB(7 downto 4); - DO(7 downto 4) <= BusA(3 downto 0); - end if; - end if; - - if T_Res = '1' then - Read_To_Reg_r(3 downto 0) <= Set_BusA_To; - Read_To_Reg_r(4) <= Read_To_Reg; - if Read_To_Acc = '1' then - Read_To_Reg_r(3 downto 0) <= "0111"; - Read_To_Reg_r(4) <= '1'; - end if; - end if; - - if TState = 1 and I_BT = '1' then - F(Flag_X) <= ALU_Q(3); - F(Flag_Y) <= ALU_Q(1); - F(Flag_H) <= '0'; - F(Flag_N) <= '0'; - end if; - if I_BC = '1' or I_BT = '1' then - F(Flag_P) <= IncDecZ; - end if; - - if (TState = 1 and Save_ALU_r = '0') or - (Save_ALU_r = '1' and ALU_OP_r /= "0111") then - case Read_To_Reg_r is - when "10111" => - ACC <= Save_Mux; - when "10110" => - DO <= Save_Mux; - when "11000" => - SP(7 downto 0) <= unsigned(Save_Mux); - when "11001" => - SP(15 downto 8) <= unsigned(Save_Mux); - when "11011" => - F <= Save_Mux; - when others => - end case; - if XYbit_undoc='1' then - DO <= ALU_Q; - end if; - end if; - end if; - - end if; - end process; --------------------------------------------------------------------------- @@ -719,7 +817,7 @@ begin --------------------------------------------------------------------------- process (CLK_n) begin - if CLK_n'event and CLK_n = '1' then + if rising_edge(CLK_n) then if ClkEn = '1' then -- Bus A / Write RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); @@ -785,7 +883,7 @@ begin begin RegWEH <= '0'; RegWEL <= '0'; - if (TState = 1 and Save_ALU_r = '0') or + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or (Save_ALU_r = '1' and ALU_OP_r /= "0111") then case Read_To_Reg_r is when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => @@ -831,7 +929,7 @@ begin end if; end process; - Regs : T80_Reg + Regs : work.T80_Reg port map( Clk => CLK_n, CEN => ClkEn, @@ -847,7 +945,10 @@ begin DOBH => RegBusB(15 downto 8), DOBL => RegBusB(7 downto 0), DOCH => RegBusC(15 downto 8), - DOCL => RegBusC(7 downto 0)); + DOCL => RegBusC(7 downto 0), + DOR => DOR, + DIRSet => DIRSet, + DIR => DIR(207 downto 80)); --------------------------------------------------------------------------- -- @@ -856,61 +957,65 @@ begin --------------------------------------------------------------------------- process (CLK_n) begin - if CLK_n'event and CLK_n = '1' then + if rising_edge(CLK_n) then if ClkEn = '1' then - case Set_BusB_To is - when "0111" => - BusB <= ACC; - when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => - if Set_BusB_To(0) = '1' then - BusB <= RegBusB(7 downto 0); - else - BusB <= RegBusB(15 downto 8); - end if; - when "0110" => - BusB <= DI_Reg; - when "1000" => - BusB <= std_logic_vector(SP(7 downto 0)); - when "1001" => - BusB <= std_logic_vector(SP(15 downto 8)); - when "1010" => - BusB <= "00000001"; - when "1011" => - BusB <= F; - when "1100" => - BusB <= std_logic_vector(PC(7 downto 0)); - when "1101" => - BusB <= std_logic_vector(PC(15 downto 8)); - when "1110" => - BusB <= "00000000"; - when others => - BusB <= "--------"; - end case; + case Set_BusB_To is + when "0111" => + BusB <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusB_To(0) = '1' then + BusB <= RegBusB(7 downto 0); + else + BusB <= RegBusB(15 downto 8); + end if; + when "0110" => + BusB <= DI_Reg; + when "1000" => + BusB <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusB <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusB <= "00000001"; + when "1011" => + BusB <= F; + when "1100" => + BusB <= std_logic_vector(PC(7 downto 0)); + when "1101" => + BusB <= std_logic_vector(PC(15 downto 8)); + when "1110" => + if IR = x"71" and out0 = '1' then + BusB <= "11111111"; + else + BusB <= "00000000"; + end if; + when others => + BusB <= "--------"; + end case; - case Set_BusA_To is - when "0111" => - BusA <= ACC; - when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => - if Set_BusA_To(0) = '1' then - BusA <= RegBusA(7 downto 0); - else - BusA <= RegBusA(15 downto 8); + case Set_BusA_To is + when "0111" => + BusA <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusA_To(0) = '1' then + BusA <= RegBusA(7 downto 0); + else + BusA <= RegBusA(15 downto 8); + end if; + when "0110" => + BusA <= DI_Reg; + when "1000" => + BusA <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusA <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusA <= "00000000"; + when others => + BusA <= "--------"; + end case; + if XYbit_undoc='1' then + BusA <= DI_Reg; + BusB <= DI_Reg; end if; - when "0110" => - BusA <= DI_Reg; - when "1000" => - BusA <= std_logic_vector(SP(7 downto 0)); - when "1001" => - BusA <= std_logic_vector(SP(15 downto 8)); - when "1010" => - BusA <= "00000000"; - when others => - BusA <= "--------"; - end case; - if XYbit_undoc='1' then - BusA <= DI_Reg; - BusB <= DI_Reg; - end if; end if; end if; end process; @@ -924,13 +1029,13 @@ begin begin if RESET_n = '0' then RFSH_n <= '1'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then - RFSH_n <= '0'; - else - RFSH_n <= '1'; - end if; + elsif rising_edge(CLK_n) then + if DIRSet = '0' and CEN = '1' then + if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then + RFSH_n <= '0'; + else + RFSH_n <= '1'; + end if; end if; end if; end process; @@ -939,7 +1044,7 @@ begin TS <= std_logic_vector(TState); DI_Reg <= DI; HALT_n <= not Halt_FF; - BUSAK_n <= not BusAck; + BUSAK_n <= not (BusAck and RESET_n); IntCycle_n <= not IntCycle; IntE <= IntE_FF1; IORQ <= IORQ_i; @@ -947,44 +1052,18 @@ begin ------------------------------------------------------------------------- -- --- Syncronise inputs +-- Main state machine -- ------------------------------------------------------------------------- process (RESET_n, CLK_n) variable OldNMI_n : std_logic; - begin - if RESET_n = '0' then - BusReq_s <= '0'; - INT_s <= '0'; - NMI_s <= '0'; - OldNMI_n := '0'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - BusReq_s <= not BUSRQ_n; - INT_s <= not INT_n; - if NMICycle = '1' then - NMI_s <= '0'; - elsif NMI_n = '0' and OldNMI_n = '1' then - NMI_s <= '1'; - end if; - OldNMI_n := NMI_n; - end if; - end if; - end process; - -------------------------------------------------------------------------- --- --- Main state machine --- -------------------------------------------------------------------------- - process (RESET_n, CLK_n) begin if RESET_n = '0' then MCycle <= "001"; TState <= "000"; Pre_XY_F_M <= "000"; Halt_FF <= '0'; - BusAck <= '0'; + --BusAck <= '0'; NMICycle <= '0'; IntCycle <= '0'; IntE_FF1 <= '0'; @@ -993,96 +1072,104 @@ begin Auto_Wait_t1 <= '0'; Auto_Wait_t2 <= '0'; M1_n <= '1'; - elsif CLK_n'event and CLK_n = '1' then - if CEN = '1' then - Auto_Wait_t1 <= Auto_Wait; - Auto_Wait_t2 <= Auto_Wait_t1; - No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or - (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or - (I_BTR and (not IR(4) or F(Flag_Z))); - if TState = 2 then - if SetEI = '1' then - IntE_FF1 <= '1'; - IntE_FF2 <= '1'; - end if; - if I_RETN = '1' then - IntE_FF1 <= IntE_FF2; - end if; - end if; - if TState = 3 then - if SetDI = '1' then - IntE_FF1 <= '0'; - IntE_FF2 <= '0'; - end if; - end if; - if IntCycle = '1' or NMICycle = '1' then - Halt_FF <= '0'; - end if; - if MCycle = "001" and TState = 2 and Wait_n = '1' then - M1_n <= '1'; - end if; - if BusReq_s = '1' and BusAck = '1' then + --BusReq_s <= '0'; + NMI_s <= '0'; + elsif rising_edge(CLK_n) then + + if DIRSet = '1' then + IntE_FF2 <= DIR(211); + IntE_FF1 <= DIR(210); else - BusAck <= '0'; - if TState = 2 and Wait_n = '0' then - elsif T_Res = '1' then - if Halt = '1' then - Halt_FF <= '1'; - end if; - if BusReq_s = '1' then - BusAck <= '1'; + if NMI_n = '0' and OldNMI_n = '1' then + NMI_s <= '1'; + end if; + OldNMI_n := NMI_n; + + if CEN = '1' then + BusReq_s <= not BUSRQ_n; + Auto_Wait_t2 <= Auto_Wait_t1; + if T_Res = '1' then + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; else - TState <= "001"; - if NextIs_XY_Fetch = '1' then - MCycle <= "110"; - Pre_XY_F_M <= MCycle; - if IR = "00110110" and Mode = 0 then - Pre_XY_F_M <= "010"; - end if; - elsif (MCycle = "111") or - (MCycle = "110" and Mode = 1 and ISet /= "01") then - MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); - elsif (MCycle = MCycles) or - No_BTR = '1' or - (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then - M1_n <= '0'; - MCycle <= "001"; - IntCycle <= '0'; - NMICycle <= '0'; - if NMI_s = '1' and Prefix = "00" then - NMICycle <= '1'; - IntE_FF1 <= '0'; - elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then - IntCycle <= '1'; - IntE_FF1 <= '0'; - IntE_FF2 <= '0'; - end if; - else - MCycle <= std_logic_vector(unsigned(MCycle) + 1); + Auto_Wait_t1 <= Auto_Wait or IORQ_i; + end if; + No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or + (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or + (I_BTR and (not IR(4) or F(Flag_Z))); + if TState = 2 then + if SetEI = '1' then + IntE_FF1 <= '1'; + IntE_FF2 <= '1'; + end if; + if I_RETN = '1' then + IntE_FF1 <= IntE_FF2; end if; end if; - else - if Auto_Wait = '1' nand Auto_Wait_t2 = '0' then - - TState <= TState + 1; + if TState = 3 then + if SetDI = '1' then + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + end if; + if IntCycle = '1' or NMICycle = '1' then + Halt_FF <= '0'; + end if; + if MCycle = "001" and TState = 2 and Wait_n = '1' then + M1_n <= '1'; + end if; + if BusReq_s = '1' and BusAck = '1' then + else + BusAck <= '0'; + if TState = 2 and Wait_n = '0' then + elsif T_Res = '1' then + if Halt = '1' then + Halt_FF <= '1'; + end if; + if BusReq_s = '1' then + BusAck <= '1'; + else + TState <= "001"; + if NextIs_XY_Fetch = '1' then + MCycle <= "110"; + Pre_XY_F_M <= MCycle; + if IR = "00110110" and Mode = 0 then + Pre_XY_F_M <= "010"; + end if; + elsif (MCycle = "111") or (MCycle = "110" and Mode = 1 and ISet /= "01") then + MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); + elsif (MCycle = MCycles) or No_BTR = '1' or (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then + M1_n <= '0'; + MCycle <= "001"; + IntCycle <= '0'; + NMICycle <= '0'; + if NMI_s = '1' and Prefix = "00" then + NMI_s <= '0'; + NMICycle <= '1'; + IntE_FF1 <= '0'; + elsif IntE_FF1 = '1' and INT_n='0' and Prefix = "00" and SetEI = '0' then + IntCycle <= '1'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + end if; + else + if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor + (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then + TState <= TState + 1; + end if; + end if; + end if; + if TState = 0 then + M1_n <= '0'; end if; end if; end if; - if TState = 0 then - M1_n <= '0'; - end if; - end if; - end if; - end process; - - process (IntCycle, NMICycle, MCycle) - begin - Auto_Wait <= '0'; - if IntCycle = '1' or NMICycle = '1' then - if MCycle = "001" then - Auto_Wait <= '1'; - end if; end if; end process; + Auto_Wait <= '1' when IntCycle = '1' and MCycle = "001" else '0'; end; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_ALU.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_ALU.vhd index 95c98dab..a9438aed 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_ALU.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_ALU.vhd @@ -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; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_MCode.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_MCode.vhd index 198dac66..f5312bd6 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_MCode.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_MCode.vhd @@ -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; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_Reg.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_Reg.vhd index 1c0f2638..e7e86454 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_Reg.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80_Reg.vhd @@ -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; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80s.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80s.vhd new file mode 100644 index 00000000..8c82f697 --- /dev/null +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80s.vhd @@ -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; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80se.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80se.vhd deleted file mode 100644 index 1b0cb9b5..00000000 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/T80se.vhd +++ /dev/null @@ -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; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/Z80.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/Z80.vhd index db1ad947..11875a54 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/Z80.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/t80/Z80.vhd @@ -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,