-- **** -- T80(b) core. In an effort to merge and maintain bug fixes .... -- -- -- Ver 300 started tidyup. Rmoved some auto_wait bits from 0247 which caused problems -- -- 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 -- 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 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; 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 Flag_C : integer := 0; Flag_N : integer := 1; Flag_P : integer := 2; Flag_X : integer := 3; Flag_H : integer := 4; Flag_Y : integer := 5; Flag_Z : integer := 6; Flag_S : integer := 7 ); port( 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 ); 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); signal I : std_logic_vector(7 downto 0); signal R : unsigned(7 downto 0); signal SP, PC : unsigned(15 downto 0); signal RegDIH : std_logic_vector(7 downto 0); signal RegDIL : std_logic_vector(7 downto 0); signal RegBusA : std_logic_vector(15 downto 0); signal RegBusB : std_logic_vector(15 downto 0); signal RegBusC : std_logic_vector(15 downto 0); signal RegAddrA_r : std_logic_vector(2 downto 0); signal RegAddrA : std_logic_vector(2 downto 0); signal RegAddrB_r : std_logic_vector(2 downto 0); signal RegAddrB : std_logic_vector(2 downto 0); signal RegAddrC : std_logic_vector(2 downto 0); signal RegWEH : std_logic; signal RegWEL : std_logic; signal Alternate : std_logic; -- Help Registers signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register signal IR : std_logic_vector(7 downto 0); -- Instruction register signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector signal RegBusA_r : std_logic_vector(15 downto 0); signal ID16 : signed(15 downto 0); signal Save_Mux : std_logic_vector(7 downto 0); signal TState : unsigned(2 downto 0); signal MCycle : std_logic_vector(2 downto 0); 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 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); signal T_Res : std_logic; signal XY_State : std_logic_vector(1 downto 0); signal Pre_XY_F_M : std_logic_vector(2 downto 0); signal NextIs_XY_Fetch : std_logic; signal XY_Ind : std_logic; signal No_BTR : std_logic; signal BTR_r : std_logic; signal Auto_Wait : std_logic; signal Auto_Wait_t1 : std_logic; signal Auto_Wait_t2 : std_logic; signal IncDecZ : std_logic; -- ALU signals signal BusB : std_logic_vector(7 downto 0); signal BusA : std_logic_vector(7 downto 0); signal ALU_Q : std_logic_vector(7 downto 0); signal F_Out : std_logic_vector(7 downto 0); -- Registered micro code outputs signal Read_To_Reg_r : std_logic_vector(4 downto 0); signal Arith16_r : std_logic; signal Z16_r : std_logic; signal ALU_Op_r : std_logic_vector(3 downto 0); signal Save_ALU_r : std_logic; signal PreserveC_r : std_logic; signal MCycles : std_logic_vector(2 downto 0); -- Micro code outputs signal MCycles_d : std_logic_vector(2 downto 0); signal TStates : std_logic_vector(2 downto 0); signal IntCycle : std_logic; signal NMICycle : std_logic; signal Inc_PC : std_logic; signal Inc_WZ : std_logic; signal IncDec_16 : std_logic_vector(3 downto 0); signal Prefix : std_logic_vector(1 downto 0); signal Read_To_Acc : std_logic; signal Read_To_Reg : std_logic; signal Set_BusB_To : std_logic_vector(3 downto 0); signal Set_BusA_To : std_logic_vector(3 downto 0); signal ALU_Op : std_logic_vector(3 downto 0); signal Save_ALU : std_logic; signal PreserveC : std_logic; signal Arith16 : std_logic; signal Set_Addr_To : std_logic_vector(2 downto 0); signal Jump : std_logic; signal JumpE : std_logic; signal JumpXY : std_logic; signal Call : std_logic; signal RstP : std_logic; signal LDZ : std_logic; signal LDW : std_logic; signal LDSPHL : std_logic; signal IORQ_i : std_logic; signal Special_LD : std_logic_vector(2 downto 0); signal ExchangeDH : std_logic; signal ExchangeRp : std_logic; signal ExchangeAF : std_logic; signal ExchangeRS : std_logic; signal I_DJNZ : std_logic; signal I_CPL : std_logic; signal I_CCF : std_logic; signal I_SCF : std_logic; signal I_RETN : std_logic; signal I_BT : std_logic; signal I_BC : std_logic; signal I_BTR : std_logic; signal I_RLD : std_logic; signal I_RRD : std_logic; signal I_INRC : std_logic; signal SetDI : std_logic; signal SetEI : std_logic; signal IMode : std_logic_vector(1 downto 0); signal Halt : std_logic; begin mcode : T80_MCode generic map( Mode => Mode, Flag_C => Flag_C, Flag_N => Flag_N, Flag_P => Flag_P, Flag_X => Flag_X, Flag_H => Flag_H, Flag_Y => Flag_Y, Flag_Z => Flag_Z, Flag_S => Flag_S) port map( IR => IR, ISet => ISet, MCycle => MCycle, F => F, NMICycle => NMICycle, IntCycle => IntCycle, MCycles => MCycles_d, TStates => TStates, Prefix => Prefix, Inc_PC => Inc_PC, Inc_WZ => Inc_WZ, IncDec_16 => IncDec_16, Read_To_Acc => Read_To_Acc, Read_To_Reg => Read_To_Reg, Set_BusB_To => Set_BusB_To, Set_BusA_To => Set_BusA_To, ALU_Op => ALU_Op, Save_ALU => Save_ALU, PreserveC => PreserveC, Arith16 => Arith16, Set_Addr_To => Set_Addr_To, IORQ => IORQ_i, Jump => Jump, JumpE => JumpE, JumpXY => JumpXY, Call => Call, RstP => RstP, LDZ => LDZ, LDW => LDW, LDSPHL => LDSPHL, Special_LD => Special_LD, ExchangeDH => ExchangeDH, ExchangeRp => ExchangeRp, ExchangeAF => ExchangeAF, ExchangeRS => ExchangeRS, I_DJNZ => I_DJNZ, I_CPL => I_CPL, I_CCF => I_CCF, I_SCF => I_SCF, I_RETN => I_RETN, I_BT => I_BT, I_BC => I_BC, I_BTR => I_BTR, I_RLD => I_RLD, I_RRD => I_RRD, I_INRC => I_INRC, SetDI => SetDI, SetEI => SetEI, IMode => IMode, Halt => Halt, NoRead => NoRead, Write => Write); alu : T80_ALU generic map( Mode => Mode, Flag_C => Flag_C, Flag_N => Flag_N, Flag_P => Flag_P, Flag_X => Flag_X, Flag_H => Flag_H, Flag_Y => Flag_Y, Flag_Z => Flag_Z, Flag_S => Flag_S) port map( Arith16 => Arith16_r, Z16 => Z16_r, ALU_Op => ALU_Op_r, IR => IR(5 downto 0), ISet => ISet, BusA => BusA, BusB => BusB, F_In => F, Q => ALU_Q, F_Out => F_Out); ClkEn <= CEN and not BusAck; T_Res <= '1' when TState = unsigned(TStates) else '0'; NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and ((Set_Addr_To = aXY) or (MCycle = "001" and IR = "11001011") or (MCycle = "001" and IR = "00110110")) else '0'; Save_Mux <= BusB when ExchangeRp = '1' else DI_Reg when Save_ALU_r = '0' else ALU_Q; process (RESET_n, CLK_n) begin if RESET_n = '0' then PC <= (others => '0'); -- Program Counter A <= (others => '0'); TmpAddr <= (others => '0'); IR <= "00000000"; ISet <= "00"; XY_State <= "00"; IStatus <= "00"; MCycles <= "000"; DO <= "00000000"; ACC <= (others => '1'); F <= (others => '1'); Ap <= (others => '1'); Fp <= (others => '1'); I <= (others => '0'); R <= (others => '0'); SP <= (others => '1'); Alternate <= '0'; Read_To_Reg_r <= "00000"; F <= (others => '1'); Arith16_r <= '0'; BTR_r <= '0'; Z16_r <= '0'; ALU_Op_r <= "0000"; Save_ALU_r <= '0'; PreserveC_r <= '0'; XY_Ind <= '0'; elsif CLK_n'event and CLK_n = '1' then if ClkEn = '1' then ALU_Op_r <= "0000"; Save_ALU_r <= '0'; Read_To_Reg_r <= "00000"; MCycles <= MCycles_d; 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; 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 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; 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 if Prefix = "10" then XY_State <= "00"; XY_Ind <= '0'; end if; ISet <= Prefix; end if; else XY_State <= "00"; XY_Ind <= '0'; end if; 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) <= 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'; 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; end if; if TState = 3 and MCycle = "110" then TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); 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; 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'; 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; end if; end if; end if; end process; --------------------------------------------------------------------------- -- -- BC('), DE('), HL('), IX and IY -- --------------------------------------------------------------------------- process (CLK_n) begin if CLK_n'event and CLK_n = '1' then if ClkEn = '1' then -- Bus A / Write RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then RegAddrA_r <= XY_State(1) & "11"; end if; -- Bus B RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1); if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then RegAddrB_r <= XY_State(1) & "11"; end if; -- Address from register RegAddrC <= Alternate & Set_Addr_To(1 downto 0); -- Jump (HL), LD SP,HL if (JumpXY = '1' or LDSPHL = '1') then RegAddrC <= Alternate & "10"; end if; if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then RegAddrC <= XY_State(1) & "11"; end if; if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then IncDecZ <= F_Out(Flag_Z); end if; if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then if ID16 = 0 then IncDecZ <= '0'; else IncDecZ <= '1'; end if; end if; RegBusA_r <= RegBusA; end if; end if; end process; RegAddrA <= -- 16 bit increment/decrement Alternate & IncDec_16(1 downto 0) when (TState = 2 or (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else XY_State(1) & "11" when (TState = 2 or (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else -- EX HL,DL Alternate & "10" when ExchangeDH = '1' and TState = 3 else Alternate & "01" when ExchangeDH = '1' and TState = 4 else -- Bus A / Write RegAddrA_r; RegAddrB <= -- EX HL,DL Alternate & "01" when ExchangeDH = '1' and TState = 3 else -- Bus B RegAddrB_r; ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else signed(RegBusA) + 1; process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, ExchangeDH, IncDec_16, MCycle, TState, Wait_n) begin RegWEH <= '0'; RegWEL <= '0'; 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 "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => RegWEH <= not Read_To_Reg_r(0); RegWEL <= Read_To_Reg_r(0); when others => end case; end if; if ExchangeDH = '1' and (TState = 3 or TState = 4) then RegWEH <= '1'; RegWEL <= '1'; end if; if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then case IncDec_16(1 downto 0) is when "00" | "01" | "10" => RegWEH <= '1'; RegWEL <= '1'; when others => end case; end if; end process; process (Save_Mux, RegBusB, RegBusA_r, ID16, ExchangeDH, IncDec_16, MCycle, TState, Wait_n) begin RegDIH <= Save_Mux; RegDIL <= Save_Mux; if ExchangeDH = '1' and TState = 3 then RegDIH <= RegBusB(15 downto 8); RegDIL <= RegBusB(7 downto 0); end if; if ExchangeDH = '1' and TState = 4 then RegDIH <= RegBusA_r(15 downto 8); RegDIL <= RegBusA_r(7 downto 0); end if; if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then RegDIH <= std_logic_vector(ID16(15 downto 8)); RegDIL <= std_logic_vector(ID16(7 downto 0)); end if; end process; Regs : T80_Reg port map( Clk => CLK_n, CEN => ClkEn, WEH => RegWEH, WEL => RegWEL, AddrA => RegAddrA, AddrB => RegAddrB, AddrC => RegAddrC, DIH => RegDIH, DIL => RegDIL, DOAH => RegBusA(15 downto 8), DOAL => RegBusA(7 downto 0), DOBH => RegBusB(15 downto 8), DOBL => RegBusB(7 downto 0), DOCH => RegBusC(15 downto 8), DOCL => RegBusC(7 downto 0)); --------------------------------------------------------------------------- -- -- Buses -- --------------------------------------------------------------------------- process (CLK_n) begin if CLK_n'event and CLK_n = '1' 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_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 => BusB <= "--------"; end case; end if; end if; end process; --------------------------------------------------------------------------- -- -- Generate external control signals -- --------------------------------------------------------------------------- process (RESET_n,CLK_n) 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; end if; end if; end process; MC <= std_logic_vector(MCycle); TS <= std_logic_vector(TState); DI_Reg <= DI; HALT_n <= not Halt_FF; BUSAK_n <= not BusAck; IntCycle_n <= not IntCycle; IntE <= IntE_FF1; IORQ <= IORQ_i; Stop <= I_DJNZ; ------------------------------------------------------------------------- -- -- Syncronise inputs -- ------------------------------------------------------------------------- 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'; NMICycle <= '0'; IntCycle <= '0'; IntE_FF1 <= '0'; IntE_FF2 <= '0'; No_BTR <= '0'; 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 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 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); end if; end if; else if Auto_Wait = '1' nand Auto_Wait_t2 = '0' then TState <= TState + 1; 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; end;