📄 t80_mcode.vhd
字号:
--
-- 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
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
-- 0208 : First complete release
--
-- 0211 : Fixed 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
--
-- 0242 : Fixed I/O instruction timing, cleanup
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity T80_MCode is
generic(
Mode : integer := 0;
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(
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
);
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";
function is_cc_true(
F : std_logic_vector(7 downto 0);
cc : bit_vector(2 downto 0)
) return boolean 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 "100" => return false;
when "101" => return false;
when "110" => return false;
when "111" => return false;
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
end case;
end if;
end;
begin
process (IR, ISet, MCycle, F, NMICycle, IntCycle)
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);
begin
DDD := IR(5 downto 3);
SSS := IR(2 downto 0);
DPair := IR(5 downto 4);
IRB := to_bitvector(IR);
MCycles <= "001";
if MCycle = "001" then
TStates <= "100";
else
TStates <= "011";
end if;
Prefix <= "00";
Inc_PC <= '0';
Inc_WZ <= '0';
IncDec_16 <= "0000";
Read_To_Acc <= '0';
Read_To_Reg <= '0';
Set_BusB_To <= "0000";
Set_BusA_To <= "0000";
ALU_Op <= "0" & IR(5 downto 3);
Save_ALU <= '0';
PreserveC <= '0';
Arith16 <= '0';
IORQ <= '0';
Set_Addr_To <= aNone;
Jump <= '0';
JumpE <= '0';
JumpXY <= '0';
Call <= '0';
RstP <= '0';
LDZ <= '0';
LDW <= '0';
LDSPHL <= '0';
Special_LD <= "000";
ExchangeDH <= '0';
ExchangeRp <= '0';
ExchangeAF <= '0';
ExchangeRS <= '0';
I_DJNZ <= '0';
I_CPL <= '0';
I_CCF <= '0';
I_SCF <= '0';
I_RETN <= '0';
I_BT <= '0';
I_BC <= '0';
I_BTR <= '0';
I_RLD <= '0';
I_RRD <= '0';
I_INRC <= '0';
SetDI <= '0';
SetEI <= '0';
IMode <= "11";
Halt <= '0';
NoRead <= '0';
Write <= '0';
case ISet is
when "00" =>
------------------------------------------------------------------------------
--
-- Unprefixed instructions
--
------------------------------------------------------------------------------
case IRB is
-- 8 BIT LOAD GROUP
when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111"
|"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111"
|"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111"
|"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111"
|"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111"
|"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111"
|"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" =>
-- LD r,r'
Set_BusB_To(2 downto 0) <= SSS;
ExchangeRp <= '1';
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" =>
-- LD r,n
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
when others => null;
end case;
when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" =>
-- LD r,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
when others => null;
end case;
when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" =>
-- LD (HL),r
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
Set_BusB_To(2 downto 0) <= SSS;
Set_BusB_To(3) <= '0';
when 2 =>
Write <= '1';
when others => null;
end case;
when "00110110" =>
-- LD (HL),n
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aXY;
Set_BusB_To(2 downto 0) <= SSS;
Set_BusB_To(3) <= '0';
when 3 =>
Write <= '1';
when others => null;
end case;
when "00001010" =>
-- LD A,(BC)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
when 2 =>
Read_To_Acc <= '1';
when others => null;
end case;
when "00011010" =>
-- LD A,(DE)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aDE;
when 2 =>
Read_To_Acc <= '1';
when others => null;
end case;
when "00111010" =>
if Mode = 3 then
-- LDD A,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
Read_To_Acc <= '1';
IncDec_16 <= "1110";
when others => null;
end case;
else
-- LD A,(nn)
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
when 4 =>
Read_To_Acc <= '1';
when others => null;
end case;
end if;
when "00000010" =>
-- LD (BC),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
when others => null;
end case;
when "00010010" =>
-- LD (DE),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aDE;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
when others => null;
end case;
when "00110010" =>
if Mode = 3 then
-- LDD (HL),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
IncDec_16 <= "1110";
when others => null;
end case;
else
-- LD (nn),A
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
Set_BusB_To <= "0111";
when 4 =>
Write <= '1';
when others => null;
end case;
end if;
-- 16 BIT LOAD GROUP
when "00000001"|"00010001"|"00100001"|"00110001" =>
-- LD dd,nn
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Read_To_Reg <= '1';
if DPAIR = "11" then
Set_BusA_To(3 downto 0) <= "1000";
else
Set_BusA_To(2 downto 1) <= DPAIR;
Set_BusA_To(0) <= '1';
end if;
when 3 =>
Inc_PC <= '1';
Read_To_Reg <= '1';
if DPAIR = "11" then
Set_BusA_To(3 downto 0) <= "1001";
else
Set_BusA_To(2 downto 1) <= DPAIR;
Set_BusA_To(0) <= '0';
end if;
when others => null;
end case;
when "00101010" =>
if Mode = 3 then
-- LDI A,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
Read_To_Acc <= '1';
IncDec_16 <= "0110";
when others => null;
end case;
else
-- LD HL,(nn)
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
LDW <= '1';
when 4 =>
Set_BusA_To(2 downto 0) <= "101"; -- L
Read_To_Reg <= '1';
Inc_WZ <= '1';
Set_Addr_To <= aZI;
when 5 =>
Set_BusA_To(2 downto 0) <= "100"; -- H
Read_To_Reg <= '1';
when others => null;
end case;
end if;
when "00100010" =>
if Mode = 3 then
-- LDI (HL),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -