⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t80_mcode.vhd

📁 t80 vhdl source code
💻 VHD
📖 第 1 页 / 共 4 页
字号:
--
-- 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 + -