+-- ****
+-- 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
--
-- 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/
+-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
--- 0208 : First complete release
+-- 0208 : First complete release
--
--- 0211 : Fixed IM 1
+-- 0211 : Fixed IM 1
--
--- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
+-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
--
--- 0235 : Added IM 2 fix by Mike Johnson
+-- 0235 : Added IM 2 fix by Mike Johnson
--
--- 0238 : Added NoRead signal
+-- 0238 : Added NoRead signal
--
--- 0238b: Fixed instruction timing for POP and DJNZ
+-- 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
+-- 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
+-- 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(
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;
- 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,BC,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);
+ 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;
+ 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,BC,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
+ 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
);
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";
--- constant aNone : std_logic_vector(2 downto 0) := "000";
--- constant aXY : std_logic_vector(2 downto 0) := "001";
--- constant aIOA : std_logic_vector(2 downto 0) := "010";
--- constant aSP : std_logic_vector(2 downto 0) := "011";
--- constant aBC : std_logic_vector(2 downto 0) := "100";
--- constant aDE : std_logic_vector(2 downto 0) := "101";
--- constant aZI : std_logic_vector(2 downto 0) := "110";
+ 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);
------------------------------------------------------------------------------
--
--- Unprefixed instructions
+-- Unprefixed instructions
--
------------------------------------------------------------------------------
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';
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
- Set_BusB_To <= "0111";
+ Set_BusB_To <= "0111";
when 3 =>
Write <= '1';
when others => null;
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" =>
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 =>
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
- Set_BusB_To <= "0111";
+ Set_BusB_To <= "0111";
when 3 =>
Write <= '1';
IORQ <= '1';
------------------------------------------------------------------------------
--
--- CB prefixed instructions
+-- CB prefixed instructions
--
------------------------------------------------------------------------------
-- SRL r
-- SLL r (Undocumented) / SWAP r
if MCycle = "001" then
- ALU_Op <= "1000";
- Read_To_Reg <= '1';
- Save_ALU <= '1';
+ ALU_Op <= "1000";
+ Read_To_Reg <= '1';
+ Save_ALU <= '1';
end if;
when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" =>
-- RLC (HL)
|"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" =>
-- BIT b,r
if MCycle = "001" then
- Set_BusB_To(2 downto 0) <= IR(2 downto 0);
- ALU_Op <= "1001";
+ Set_BusB_To(2 downto 0) <= IR(2 downto 0);
+ ALU_Op <= "1001";
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";
TStates <= "100";
- when others =>
+ when others => null;
end case;
when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111"
|"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111"
|"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" =>
-- SET b,r
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;
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";
TStates <= "100";
when 3 =>
Write <= '1';
- when others =>
+ when others => null;
end case;
when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111"
|"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111"
TStates <= "100";
when 3 =>
Write <= '1';
- when others =>
+ when others => null;
end case;
end case;
------------------------------------------------------------------------------
--
--- ED prefixed instructions
+-- ED prefixed instructions
--
------------------------------------------------------------------------------
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
- Set_BusB_To(2 downto 0) <= IR(5 downto 3);
+ Set_BusB_To(2 downto 0) <= IR(5 downto 3);
if IR(5 downto 3) = "110" then
Set_BusB_To(3) <= '1';
end if;
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 =>
Set_Addr_To <= aXY;
when 3 =>
if IR(3) = '0' then
- IncDec_16 <= "0010";
+ --IncDec_16 <= "0010";
+ IncDec_16 <= "0110";
else
- IncDec_16 <= "1010";
+ --IncDec_16 <= "1010";
+ IncDec_16 <= "1110";
end if;
TStates <= "100";
Write <= '1';
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 =>
Set_Addr_To <= aBC;
when 3 =>
if IR(3) = '0' then
- IncDec_16 <= "0010";
+ IncDec_16 <= "0110"; -- mikej
else
- IncDec_16 <= "1010";
+ IncDec_16 <= "1110"; -- mikej
end if;
IORQ <= '1';
Write <= '1';
if Mode = 1 then
if MCycle = "001" then
--- TStates <= "100";
+-- TStates <= "100";
else
TStates <= "011";
end if;
if Mode = 3 then
if MCycle = "001" then
--- TStates <= "100";
+-- TStates <= "100";
else
TStates <= "100";
end if;