📄 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 + -