--------------------------------------------------------------------------------- -- -- Entity: decode -- Filename: decode.vhd -- Description: the Instruction Decode (ID) unit for -- the TUD MB-Lite implementation -- -- Author: Huib Lincklaen Arriens -- Delft University of Technology -- Faculty EEMCS, Department ME&CE, Circuits and Systems -- Date: September, 2010 -- June, 2011: added code for MUL and BARREL (Huib) -- Modified: -- Remarks: -- -------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE WORK.mbl_Pkg.all; -------------------------------------------------------------------------------- ENTITY decode IS -------------------------------------------------------------------------------- GENERIC ( USE_HW_MUL_g : BOOLEAN := FALSE; USE_BARREL_g : BOOLEAN := FALSE ); PORT ( IF2ID_i : IN IF2ID_Type; imem_data_i : IN STD_LOGIC_VECTOR (31 DOWNTO 0); -- ID2GPRF_o : OUT ID2GPRF_Type; ID2EX_o : OUT ID2EX_Type; -- INT_CTRL_i : IN INT_CTRL_Type; ID2CTRL_o : OUT ID2CTRL_Type; -- noLiteOpc_s : OUT STD_LOGIC ); END ENTITY decode; -------------------------------------------------------------------------------- ARCHITECTURE rtl OF decode IS -------------------------------------------------------------------------------- BEGIN p_decode: PROCESS (IF2ID_i, imem_data_i, INT_CTRL_i) IS VARIABLE prog_counter_v : STD_LOGIC_VECTOR (31 DOWNTO 0); VARIABLE opcIx_v : STD_LOGIC_VECTOR ( 5 DOWNTO 0); VARIABLE instruction_v : STD_LOGIC_VECTOR (31 DOWNTO 0); VARIABLE rD_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); VARIABLE rA_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); VARIABLE rB_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); VARIABLE IMM16_v : STD_LOGIC_VECTOR (15 DOWNTO 0); VARIABLE FSL_Mode_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); VARIABLE code_x26_v : STD_LOGIC_VECTOR ( 2 DOWNTO 0); VARIABLE IMM_Lock_v : STD_LOGIC; VARIABLE alu_Action_v : ALU_ACTION_Type; VARIABLE alu_Op1_v : ALU_IN1_Type; VARIABLE alu_Op2_v : ALU_IN2_Type; VARIABLE alu_Cin_v : ALU_CIN_Type; VARIABLE msr_Action_v : MSR_ACTION_Type; VARIABLE branch_Action_v : BRANCH_ACTION_Type; VARIABLE delayBit_v : STD_LOGIC; VARIABLE mem_Action_v : MEM_ACTION_Type; VARIABLE transfer_Size_v : TRANSFER_SIZE_Type; VARIABLE wrb_Action_v : WRB_ACTION_Type; VARIABLE int_busy_v : STD_LOGIC; BEGIN prog_counter_v := IF2ID_i.program_counter; instruction_v := imem_data_i; opcIx_v := instruction_v (31 DOWNTO 26); rD_v := instruction_v (25 DOWNTO 21); rA_v := instruction_v (20 DOWNTO 16); rB_v := instruction_v (15 DOWNTO 11); IMM16_v := instruction_v (15 DOWNTO 0); IMM_Lock_v := '0'; delayBit_v := '0'; alu_Cin_v := CIN_ZERO; alu_Action_v := A_NOP; msr_Action_v := KEEP_CARRY; branch_Action_v := NO_BR; mem_Action_v := NO_MEM; transfer_Size_v := WORD; wrb_Action_v := WRB_EX; FSL_Mode_v := "01010"; -- for decoding SEXT16, SEXT8, SRC, SRC or SRL code_x26_v := instruction_v(6) & instruction_v(5) & instruction_v(0); int_busy_v := INT_CTRL_i.int_busy; -- for debugging purposes noLiteOpc_s <= '0'; IF (INT_CTRL_i.setup_int = '1') THEN alu_Op1_v := ALU_IN_ZERO; alu_Op2_v := ALU_IN_IMM; IMM16_v := X"0010"; -- address of _interrupt_handler vector prog_counter_v := INT_CTRL_i.rti_target; -- delayed program counter alu_Action_v := A_ADD; rD_v := "01110"; -- r14 reserved for storing program_counter rA_v := (OTHERS => '0'); -- also set rA and rB to avoid possible ... rB_v := (OTHERS => '0'); -- ... erronuous hazard detection in exeq module int_busy_v := '1'; branch_Action_v := BRL; ELSE alu_Op1_v := ALU_IN_REGA; IF (opcIx_v(3) = '0') THEN alu_Op2_v := ALU_IN_REGB; ELSE alu_Op2_v := ALU_IN_IMM; END IF; CASE opcIx_v (5 DOWNTO 4) IS WHEN "00" => -- ADD / RSUB / CMP IF (opcIx_v(0) = '1') THEN -- RSUB / CMP alu_Op1_v := ALU_IN_NOT_REGA; END IF; IF (opcIx_v(1) = '0') THEN -- xxx IF (opcIx_v(0) = '0') THEN alu_Cin_v := CIN_ZERO; ELSE alu_Cin_v := CIN_ONE; END IF; ELSE -- xxxC alu_Cin_v := FROM_MSR; END IF; IF ((opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN -- special CMP(U) and not RSUB(I)K IF (IMM16_v(1) = '1') THEN -- U-bit set, CMPU alu_Action_v := A_CMPU; ELSE alu_Action_v := A_CMP; END IF; ELSE alu_Action_v := A_ADD; IF (opcIx_v(2) = '0') THEN msr_Action_v := UPDATE_CARRY; END IF; END IF; WHEN "01" => -- MUL / BS / FSL CASE opcIx_v (2 DOWNTO 0) IS WHEN "000" => -- MUL IF (USE_HW_MUL_g = TRUE) THEN alu_Action_v := A_MUL; ELSE noLiteOpc_s <= '1'; END IF; WHEN "001" => -- BS IF (USE_BARREL_g = TRUE) THEN IF (instruction_v(10) = '1') THEN alu_Action_v := A_BSLL; ELSE IF (instruction_v(9) = '1') THEN alu_Action_v := A_BSRA; ELSE alu_Action_v := A_BSRL; END IF; END IF; ELSE noLiteOpc_s <= '1'; END IF; WHEN "011" => -- FSL IF (opcIx_v(3) = '0') THEN FSL_Mode_v := instruction_v(10 DOWNTO 6); ELSE FSL_Mode_v := instruction_v(15 DOWNTO 11); END IF; IF (FSL_Mode_v(4) = '0') THEN alu_Action_v := A_FSL_GET; wrb_Action_v := WRB_FSL; ELSE alu_Action_v := A_FSL_PUT; wrb_Action_v := NO_WRB; END IF; msr_Action_v := UPDATE_CARRY; WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; WHEN "10" => IF (opcIx_v (3 DOWNTO 0) = "0100") THEN CASE code_x26_v IS WHEN "001" | "011" | "101" => CASE code_x26_v(2 DOWNTO 1) IS WHEN "00" => -- SRA alu_Cin_v := FROM_IN1; WHEN "01" => -- SRC alu_Cin_v := FROM_MSR; WHEN "10" => -- SRL alu_Cin_v := CIN_ZERO; WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; alu_Action_v := A_SHIFT; msr_Action_v := UPDATE_CARRY; WHEN "110" => -- SEXT8 alu_Action_v := A_SEXT8; WHEN "111" => -- SEXT16 alu_Action_v := A_SEXT16; WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; ELSIF (opcIx_v (3 DOWNTO 0) = "1100") THEN -- IMM IMM_Lock_v := '1'; -- always: IMM_LOCK_o.IMM16 <= IMM16_v; alu_Action_v := A_NOP; wrb_Action_v := NO_WRB; ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN CASE rD_v IS WHEN "10001" => -- RTID int_busy_v := '0'; WHEN "10000" => -- RTSD -- WHEN "10010" => -- RTBD -- WHEN "10100" => -- RTED WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; alu_Action_v := A_ADD; branch_Action_v := BR; wrb_Action_v := NO_WRB; delayBit_v := '1'; ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN CASE IMM16_v IS WHEN X"8001" => -- MFS (MSR only) alu_Action_v := A_MFS; WHEN X"C001" => -- MTS (MSR only) alu_Action_v := A_MTS; wrb_Action_v := NO_WRB; WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; rB_v := (OTHERS => '0'); -- in order to prevent occasional hazards (r16, r24) ELSE CASE opcIx_v (2 DOWNTO 0) IS WHEN "000" => alu_Action_v := A_OR; WHEN "001" => alu_Action_v := A_AND; WHEN "010" => alu_Action_v := A_XOR; WHEN "011" => alu_Action_v := A_AND; IF (opcIx_v(3) = '0') THEN alu_Op2_v := ALU_IN_NOT_REGB; ELSE alu_Op2_v := ALU_IN_NOT_IMM; END IF; WHEN "110" => -- BR(I) IF (rA_v(2) = '1') THEN branch_Action_v := BRL; ELSE branch_Action_v := BR; wrb_Action_v := NO_WRB; END IF; IF (rA_v(3) = '1') THEN alu_Op1_v := ALU_IN_ZERO; ELSE alu_Op1_v := ALU_IN_PC; END IF; IF (rA_v(4) = '1') THEN delayBit_v := '1'; END IF; alu_Action_v := A_ADD; WHEN "111" => CASE rD_v(3 DOWNTO 0) IS WHEN "0000" => -- BEQ branch_Action_v := BEQ; WHEN "0001" => -- BNE branch_Action_v := BNE; WHEN "0010" => -- BLT branch_Action_v := BLT; WHEN "0011" => -- BLE branch_Action_v := BLE; WHEN "0100" => -- BGT branch_Action_v := BGT; WHEN "0101" => -- BGE branch_Action_v := BGE; WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; alu_Action_v := A_ADD; alu_Op1_v := ALU_IN_PC; delayBit_v := rD_v(4); wrb_Action_v := NO_WRB; -- evaluate and update/overwrite in exeq WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; END IF; WHEN "11" => alu_Action_v := A_ADD; CASE opcIx_v (1 DOWNTO 0) IS WHEN "00" => transfer_Size_v := BYTE; WHEN "01" => transfer_Size_v := HALFWORD; WHEN "10" => transfer_Size_v := WORD; WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; IF (opcIx_v(2) = '0') THEN mem_Action_v := RD_MEM; wrb_Action_v := WRB_MEM; ELSE mem_Action_v := WR_MEM; wrb_Action_v := NO_WRB; END IF; WHEN OTHERS => noLiteOpc_s <= '1'; END CASE; END IF; -- interrupt test ID2GPRF_o.rdix_rA <= rA_v; ID2GPRF_o.rdix_rB <= rB_v; ID2GPRF_o.rdix_rD <= rD_v; ID2EX_o.program_counter <= prog_counter_v; ID2EX_o.rdix_rA <= rA_v; ID2EX_o.rdix_rB <= rB_v; ID2EX_o.curr_rD <= rD_v; ID2EX_o.alu_Action <= alu_Action_v; ID2EX_o.alu_Op1 <= alu_Op1_v; ID2EX_o.alu_Op2 <= alu_Op2_v; ID2EX_o.alu_Cin <= alu_Cin_v; ID2EX_o.IMM16 <= IMM16_v; ID2EX_o.IMM_Lock <= IMM_Lock_v; ID2EX_o.msr_Action <= msr_Action_v; ID2EX_o.branch_Action <= branch_Action_v; ID2EX_o.mem_Action <= mem_Action_v; ID2EX_o.transfer_Size <= transfer_Size_v; ID2EX_o.wrb_Action <= wrb_Action_v; ID2EX_o.FSL_Non_blocking <= FSL_Mode_v(3); ID2EX_o.FSL_Control <= FSL_Mode_v(2); ID2EX_o.FSL_Test <= FSL_Mode_v(1); ID2EX_o.FSL_Atomic <= FSL_Mode_v(0); -- ID2CTRL_o.delayBit <= delayBit_v; ID2CTRL_o.int_busy <= int_busy_v; END PROCESS; END ARCHITECTURE rtl;