Top secrets sources NedoPC pentevo

Rev

Rev 4 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

-- ****
-- 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;
                ResetPC         : in  std_logic_vector(15 downto 0);
                ResetSP         : in  std_logic_vector(15 downto 0)
        );
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 <= unsigned(ResetPC);
                        -- (others => '0')  -- Program Counter
                        A <= ResetPC; -- (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 <= unsigned(ResetSP);
                        -- (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;