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

📄 opcode_decoder.vhd

📁 用vhdl语用实现简单的16位cpu功能
💻 VHD
📖 第 1 页 / 共 3 页
字号:
library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;--  Uncomment the following lines to use the declarations that are--  provided for instantiating Xilinx primitive components.--library UNISIM;--use UNISIM.VComponents.all;use work.cpu_pack.ALL;entity opcode_decoder is	PORT(	CLK_I  : IN  std_logic;			T2     : IN  std_logic;			CLR    : IN  std_logic;			CE     : IN  std_logic;			OPCODE : IN  std_logic_vector(7 downto 0);			OP_CYC : IN  cycle;					-- current cycle (M1, M2, ...)			INT    : IN  std_logic;				-- interrupt			RRZ    : IN  std_logic;				-- RR is zero			OP_CAT : OUT op_category;			-- select signals			D_SX    : out std_logic_vector(1 downto 0);		-- ALU select X			D_SY    : out std_logic_vector(3 downto 0);		-- ALU select Y			D_OP    : out std_logic_vector(4 downto 0);		-- ALU operation			D_SA    : out std_logic_vector(4 downto 0);		-- select address			D_SMQ   : out std_logic;			-- write enable/select signal			D_WE_RR  : out std_logic;			D_WE_LL  : out std_logic;			D_WE_SP  : out SP_OP;			D_RD_O   : out std_logic;			D_WE_O   : out std_logic;			D_LOCK   : out std_logic;			-- input/output			D_IO     : out std_logic;			PC_OP  : out std_logic_vector(2 downto 0);			LAST_M : out std_logic;		-- last M cycle of an opcode			HLT    : out std_logic		);end opcode_decoder;architecture Behavioral of opcode_decoder is	function pc(A : std_logic;				OP : std_logic_vector(2 downto 0)) return std_logic_vector is	begin		if (A = '1') then	return OP;		else				return PC_NEXT;		end if;	end;	function hadr(	A   : std_logic;					ADR : std_logic_vector(4 downto 0)) return std_logic_vector is	begin		return ADR(4 downto 1) & A;	end;	function mix(A : std_logic) return std_logic_vector is	begin		if (A = '1') then	return ALU_X_MIX_Y;		else				return ALU_MOVE_Y;		end if;	end;	function sp(A : std_logic;				OP : SP_OP) return SP_OP is	begin		if (A = '1') then	return OP;		else				return SP_NOP;		end if;	end;	signal LAST         : cycle;	signal ENABLE_INT   : std_logic;	signal DISABLE_INT  : std_logic;	signal DISABLE_CNT  : std_logic_vector(3 downto 0);	signal HALT_REQ     : std_logic;	signal UNHALT_REQ   : std_logic;	signal HALTED       : std_logic;	signal INT_M1       : std_logic;	signal INT_M2       : std_logic;begin	LAST_M <= '1' when (OP_CYC = LAST) else '0';	HLT    <= HALTED;	-- show when CPU is halted	-- HLT    <= '1' when DISABLE_CNT = 0 else '0';	-- show when ints enabled	process(CLK_I, CLR)	begin		if (CLR = '1') then			DISABLE_CNT <= "0001";	-- 1 x disabled			INT_M2      <= '0';			HALTED      <= '0';		elsif ((rising_edge(CLK_I) and T2 = '1') and CE = '1' ) then			if (DISABLE_INT = '1') then				DISABLE_CNT <= DISABLE_CNT + 1;			elsif (ENABLE_INT  = '1' and DISABLE_CNT /= 0) then				DISABLE_CNT <= DISABLE_CNT - 1;			end if;			if (UNHALT_REQ = '1') then				HALTED <= '0';			elsif (HALT_REQ = '1') then				HALTED <= '1';			end if;			INT_M2 <= INT_M1;		end if;	end process;	process(OPCODE, OP_CYC, INT, RRZ, INT_M2, DISABLE_CNT, HALTED)		variable	IS_M1			: std_logic;		variable	IS_M2, IS_M1_M2	: std_logic;		variable	IS_M3, IS_M2_M3	: std_logic;		variable	IS_M4, IS_M3_M4	: std_logic;		variable	IS_M5			: std_logic;	begin		if (OP_CYC = M1) then	IS_M1 := '1';	else	IS_M1 := '0';	end if;		if (OP_CYC = M2) then	IS_M2 := '1';	else	IS_M2 := '0';	end if;		if (OP_CYC = M3) then	IS_M3 := '1';	else	IS_M3 := '0';	end if;		if (OP_CYC = M4) then	IS_M4 := '1';	else	IS_M4 := '0';	end if;		if (OP_CYC = M5) then	IS_M5 := '1';	else	IS_M5 := '0';	end if;		IS_M1_M2		:= IS_M1 or IS_M2;		IS_M2_M3		:=          IS_M2 or IS_M3;		IS_M3_M4		:=                   IS_M3 or IS_M4;		-- default: NOP		--		OP_CAT      <= undef;		D_SX        <= SX_ANY;		D_SY        <= SY_ANY;		D_OP        <= "00000";		D_SA        <= "00000";		D_SMQ       <= '0';		D_WE_RR     <= '0';		D_WE_LL     <= '0';		D_WE_SP     <= SP_NOP;		D_WE_O      <= '0';		D_RD_O      <= '0';		D_LOCK      <= '0';		D_IO        <= '0';		PC_OP       <= PC_NEXT;		LAST        <= M1;			-- default: single cycle opcode (M1 only)		ENABLE_INT  <= '0';		DISABLE_INT <= '0';		HALT_REQ    <= '0';		UNHALT_REQ  <= '0';		INT_M1      <= '0';		if ((IS_M1 = '1' and INT = '1' and DISABLE_CNT = "0000")	-- new INT or			or INT_M2 = '1' ) then							-- continue INT			OP_CAT      <= INTR;			LAST        <= M2;			INT_M1      <= IS_M1;			D_OP        <= ALU_X_ADD_Y;			D_SX        <= SX_PC;			D_SY        <= SY_SY0;		-- PC + 0 (current PC)			D_SA        <= ADR_dSP;			D_WE_O      <= IS_M1_M2;			D_LOCK      <= IS_M1;			PC_OP       <= pc(IS_M1, PC_INT);			D_SMQ       <= IS_M1;			D_WE_SP     <= sp(IS_M1_M2, SP_LOAD);			DISABLE_INT <= IS_M1;			UNHALT_REQ  <= '1';		elsif (HALTED = '1') then			OP_CAT      <= HALT_WAIT;			LAST        <= M2;			PC_OP       <= PC_WAIT;		elsif (OPCODE(7) = '1') then			case OPCODE(6 downto 4) is				when "010" =>					OP_CAT  <= ADD_RR_I;					D_OP    <= ALU_X_ADD_Y;					D_SX    <= SX_RR;					D_SY    <= SY_UQ;					D_WE_RR <= IS_M1;				when "011" =>					OP_CAT  <= SUB_RR_I;					D_OP    <= ALU_X_SUB_Y;					D_SX    <= SX_RR;					D_SY    <= SY_UQ;					D_WE_RR <= IS_M1;				when "100" =>					OP_CAT  <= MOVE_I_RR;					D_OP    <= ALU_MOVE_Y;					D_SX    <= SX_ANY;					D_SY    <= SY_SQ;					D_WE_RR <= IS_M1;				when "101" =>					OP_CAT  <= SEQ_LL_I;					D_OP    <= ALU_X_EQ_Y;					D_SX    <= SX_LL;					D_SY    <= SY_SQ;					D_WE_RR <= IS_M1;		-- !! RR				when "110" =>					OP_CAT  <= MOVE_I_LL;					D_OP    <= ALU_MOVE_Y;					D_SX    <= SX_ANY;					D_SY    <= SY_UQ;					D_WE_LL <= IS_M1;				when "111" =>					case OPCODE(3 downto 0) is						when "0100" =>							OP_CAT  <= ADD_RR_I;							D_OP    <= ALU_X_ADD_Y;							D_SX    <= SX_RR;							D_SY    <= SY_I16;							LAST    <= M3;							D_WE_RR <= IS_M3;							when "0101" =>							OP_CAT  <= ADD_RR_I;							D_OP    <= ALU_X_ADD_Y;							D_SX    <= SX_RR;							D_SY    <= SY_UI8;							LAST    <= M2;							D_WE_RR <= IS_M2;							when "0110" =>							OP_CAT  <= SUB_RR_I;							D_OP    <= ALU_X_SUB_Y;							D_SX    <= SX_RR;							D_SY    <= SY_I16;							LAST    <= M3;							D_WE_RR <= IS_M3;						when "0111" =>							OP_CAT  <= SUB_RR_I;							D_OP    <= ALU_X_SUB_Y;							D_SX    <= SX_RR;							D_SY    <= SY_UI8;							LAST    <= M2;							D_WE_RR <= IS_M2;						when "1000" =>							OP_CAT <= MOVE_I_RR;							D_OP   <= ALU_MOVE_Y;							D_SX   <= SX_ANY;							D_SY   <= SY_I16;							LAST    <= M3;							D_WE_RR <= IS_M3;						when "1001" =>							OP_CAT  <= MOVE_I_RR;							D_OP    <= ALU_MOVE_Y;							D_SX    <= SX_ANY;							D_SY    <= SY_SI8;							LAST    <= M2;							D_WE_RR <= IS_M2;						when "1010" =>							OP_CAT <= SEQ_LL_I;							D_OP   <= ALU_X_EQ_Y;							D_SX   <= SX_LL;							D_SY   <= SY_I16;							LAST    <= M3;							D_WE_RR <= IS_M3;			-- SEQ sets RR !						when "1011" =>							OP_CAT  <= SEQ_LL_I;							D_OP    <= ALU_X_EQ_Y;							D_SX    <= SX_LL;							D_SY    <= SY_SI8;							LAST    <= M2;							D_WE_RR <= IS_M2;			-- SEQ sets RR !						when "1100" =>							OP_CAT <= MOVE_I_LL;							D_OP   <= ALU_MOVE_Y;							D_SX   <= SX_ANY;							D_SY   <= SY_I16;							LAST    <= M3;							D_WE_LL <= IS_M3;						when "1101" =>							OP_CAT  <= MOVE_I_LL;							D_OP    <= ALU_MOVE_Y;							D_SX    <= SX_ANY;							D_SY    <= SY_SI8;							LAST    <= M2;							D_WE_LL <= IS_M2;					when others =>	-- undefined				end case;				when others =>	-- undefined			end case;		else			case OPCODE(6 downto 0) is				-- 00000000000000000000000000000000000000000000000000000000000000000000				when "0000000" =>					OP_CAT   <= HALT;					HALT_REQ <= '1';					PC_OP    <= PC_WAIT;				when "0000001" =>					OP_CAT <= NOP;				when "0000010" =>					OP_CAT <= JMP_i;					LAST   <= M3;					PC_OP  <= pc(IS_M2, PC_JMP);				when "0000011" =>					OP_CAT <= JMP_RRNZ_i;					LAST   <= M3;					PC_OP  <= pc(IS_M2 and not RRZ, PC_JMP);				when "0000100" =>					OP_CAT <= JMP_RRZ_i;					LAST   <= M3;					PC_OP  <= pc(IS_M2 and RRZ, PC_JMP);				when "0000101" =>					OP_CAT  <= CALL_i;					LAST    <= M3;					D_OP    <= ALU_X_ADD_Y;					D_SX    <= SX_PC;					D_SY    <= SY_SY3;		-- PC + 3					D_SA    <= ADR_dSP;					D_WE_O  <= IS_M1_M2;					D_LOCK  <= IS_M1;					PC_OP   <= pc(IS_M2, PC_JMP);					D_SMQ   <= IS_M1;					D_WE_SP <= sp(IS_M1_M2, SP_LOAD);				when "0000110" =>					OP_CAT  <= CALL_RR;					LAST    <= M2;					D_OP    <= ALU_X_ADD_Y;					D_SX    <= SX_PC;					D_SY    <= SY_SY1;		-- PC + 1					D_SA    <= ADR_dSP;					D_WE_O  <= IS_M1_M2;					D_LOCK  <= IS_M1;					PC_OP   <= pc(IS_M1, PC_JPRR);					D_SMQ   <= IS_M1;					D_WE_SP <= sp(IS_M1_M2, SP_LOAD);				when "0000111" | "1111000" =>					if (OPCODE(0) = '1') then						OP_CAT      <= RET;					else						OP_CAT      <= RETI;						ENABLE_INT  <= IS_M1;					end if;					LAST    <= M5;					D_SA    <= ADR_SPi;		-- read address: (SP)+					D_RD_O  <= IS_M1_M2;					D_LOCK  <= IS_M1;					D_WE_SP <= sp(IS_M1_M2, SP_INC);					case OP_CYC is						when M1 =>	PC_OP   <= PC_WAIT;						when M2 =>	PC_OP   <= PC_WAIT;						when M3 =>	PC_OP   <= PC_RETL;						when M4 =>	PC_OP   <= PC_RETH;						when others =>					end case;				when "0001000" =>					OP_CAT  <= MOVE_SPi_RR;					D_SX    <= SX_RR;					D_SY    <= SY_UM;					D_SA    <= ADR_SPi;					D_RD_O  <= IS_M1_M2;					D_LOCK  <= IS_M1;					LAST    <= M3;					PC_OP   <= pc(IS_M1_M2, PC_WAIT);					D_WE_RR <= IS_M2_M3;					D_WE_SP <= sp(IS_M1_M2, SP_INC);					D_OP    <= mix(IS_M3);				when "0001001" =>					OP_CAT  <= MOVE_SPi_RS;					LAST    <= M2;					D_OP    <= ALU_MOVE_Y;					D_SX    <= SX_ANY;					D_SY    <= SY_SM;					D_SA    <= ADR_SPi;					D_RD_O  <= IS_M1;					D_WE_RR <= IS_M2;					PC_OP   <= pc(IS_M1, PC_WAIT);					D_WE_SP <= sp(IS_M1, SP_INC);				when "0001010" =>					OP_CAT  <= MOVE_SPi_RU;					LAST    <= M2;					D_OP    <= ALU_MOVE_Y;					D_SX    <= SX_ANY;					D_SY    <= SY_UM;					D_SA    <= ADR_SPi;					D_RD_O  <= IS_M1;					PC_OP   <= pc(IS_M1, PC_WAIT);					D_WE_SP <= sp(IS_M1, SP_INC);					D_WE_RR <= IS_M2;				when "0001011" =>					OP_CAT  <= MOVE_SPi_LL;					LAST    <= M3;					D_SX    <= SX_LL;					D_SY    <= SY_UM;					D_SA    <= ADR_SPi;					D_RD_O  <= IS_M1_M2;					D_LOCK  <= IS_M1;					PC_OP   <= pc(IS_M1_M2, PC_WAIT);					D_WE_SP <= sp(IS_M1_M2, SP_INC);					D_WE_LL <= IS_M2_M3;					D_OP    <= mix(IS_M3);				when "0001100" =>					OP_CAT  <= MOVE_SPi_LS;					LAST    <= M2;					D_OP    <= ALU_MOVE_Y;					D_SX    <= SX_ANY;					D_SY    <= SY_SM;					D_SA    <= ADR_SPi;					D_RD_O  <= IS_M1;					PC_OP   <= pc(IS_M1, PC_WAIT);					D_WE_SP <= sp(IS_M1, SP_INC);					D_WE_LL <= IS_M2;				when "0001101" =>					OP_CAT  <= MOVE_SPi_LU;					LAST    <= M2;					D_OP    <= ALU_MOVE_Y;					D_SX    <= SX_ANY;					D_SY    <= SY_UM;					D_SA    <= ADR_SPi;					D_RD_O  <= IS_M1;					PC_OP   <= pc(IS_M1, PC_WAIT);					D_WE_SP <= sp(IS_M1, SP_INC);					D_WE_LL <= IS_M2;				when "0001110" =>					OP_CAT  <= MOVE_RR_dSP;					LAST    <= M2;					D_OP    <= ALU_X_OR_Y;					D_SX    <= SX_RR;					D_SY    <= SY_SY0;					D_SA    <= ADR_dSP;					D_WE_O  <= IS_M1_M2;					D_LOCK  <= IS_M1;					PC_OP   <= pc(IS_M1, PC_WAIT);					D_WE_SP <= sp(IS_M1_M2, SP_LOAD);					D_SMQ   <= IS_M1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -