?? opcode_decoder.vhd
字號:
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 + -