]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blobdiff - hw/decode.vhd
Reformat code and restructure decoder to save LUTs and fit critical path
[fpga/lx-cpu1/tumbl.git] / hw / decode.vhd
index 17c6781f4ab5a9e3c441ee7409cc8f3f18dcec00..cf681e0e33fbad900a932280ce02f7e9da9877b1 100644 (file)
@@ -20,30 +20,30 @@ LIBRARY IEEE;
 USE IEEE.std_logic_1164.all;
 USE WORK.mbl_Pkg.all;
 
-
 --------------------------------------------------------------------------------
 ENTITY decode IS
 --------------------------------------------------------------------------------
-    GENERIC (
-        USE_HW_MUL_g : BOOLEAN := TRUE;
-        USE_BARREL_g : BOOLEAN := TRUE;
-        COMPATIBILITY_MODE_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_o : OUT STD_LOGIC
-        );
+       GENERIC
+       (
+               USE_HW_MUL_g : BOOLEAN := TRUE;
+               USE_BARREL_g : BOOLEAN := TRUE;
+               COMPATIBILITY_MODE_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_o : OUT STD_LOGIC
+       );
 END ENTITY decode;
 
-
 --------------------------------------------------------------------------------
 ARCHITECTURE rtl OF decode IS
 --------------------------------------------------------------------------------
@@ -51,348 +51,365 @@ 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 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;
-        VARIABLE cmp_Cond_v      : CMP_COND_Type;
-        VARIABLE cmp_Cond_Type_v : CMP_COND_TYPE_Type;
-
-    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';
-        IF (COMPATIBILITY_MODE_g = TRUE) THEN
-            delayBit_v      := '0';
-        ELSE
-            cmp_cond_v      := COND_ALL;
-            cmp_cond_type_v := COND_TYPE_ALL;
-        END IF;
-        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;
-        -- 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_o     <= '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
-                    IF (opcIx_v(0) = '1') THEN                          -- RSUB
-                        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 ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
-                    -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode
-                        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
-                    CASE opcIx_v (2 DOWNTO 0) IS
-                        WHEN "000" =>                                   -- MUL
-                            IF (USE_HW_MUL_g = TRUE) THEN
-                                alu_Action_v := A_MUL;
-                            ELSE
-                                noLiteOpc_o <= '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_o <= '1';
-                            END IF;
-                        WHEN "010" =>                                             -- CMP / CMPU / CMPI (new format)
-                            IF (COMPATIBILITY_MODE_g = FALSE) THEN
-                                IF (IMM16_v(5) = '1') THEN   -- U-bit set, CMPU
-                                    alu_Action_v := A_CMPU;
-                                ELSE
-                                    alu_Action_v := A_CMP;
-                                END IF;
-
-                                IF (opcIx_v(3) = '0') THEN   -- IT, ITT, ITE is not available to CMPI
-                                    CASE IMM16_v(4 downto 3) IS
-                                        WHEN "00"   =>
-                                            cmp_Cond_Type_v := COND_TYPE_ALL;
-                                        WHEN "01"   =>
-                                            cmp_Cond_Type_v := COND_TYPE_IF_THEN;
-                                        WHEN "10"   =>
-                                            cmp_Cond_Type_v := COND_TYPE_IF_THEN_THEN;
-                                        WHEN "11"   =>
-                                            cmp_Cond_Type_v := COND_TYPE_IF_THEN_ELSE;
-                                        WHEN OTHERS =>
-                                            NULL;
-                                    END CASE;
-
-                                    CASE IMM16_v(2 downto 0) IS
-                                        WHEN "001"  =>
-                                            cmp_Cond_v := COND_EQ;
-                                        WHEN "010"  =>
-                                            cmp_Cond_v := COND_NE;
-                                        WHEN "011"  =>
-                                            cmp_Cond_v := COND_LT;
-                                        WHEN "100"  =>
-                                            cmp_Cond_v := COND_LE;
-                                        WHEN "101"  =>
-                                            cmp_Cond_v := COND_GT;
-                                        WHEN "110"  =>
-                                            cmp_Cond_v := COND_GE;
-                                        WHEN OTHERS =>
-                                            NULL;
-                                    END CASE;
-                                END IF;
-                            ELSE
-                                noLiteOpc_o <= '1';
-                            END IF;
-                        WHEN OTHERS =>
-                            noLiteOpc_o <= '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_o <= '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_o  <= '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 (3 DOWNTO 0) IS
-                            WHEN "0001" =>                              -- RTI(D)
-                                int_busy_v := '0';
-                            WHEN "0000" =>                              -- RTS(D)
-                            WHEN OTHERS  =>
-                                noLiteOpc_o <= '1';
-                        END CASE;
-                        alu_Action_v    := A_ADD;
-                        branch_Action_v := BR;
-                        wrb_Action_v    := NO_WRB;
-                        IF (COMPATIBILITY_MODE_g = TRUE) THEN
-                            delayBit_v  := rD_v(4);
-                        END IF;
-                    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_o  <= '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)(D)
-                                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;
-                                alu_Action_v    := A_ADD;
-                                IF (COMPATIBILITY_MODE_g = TRUE) THEN
-                                    delayBit_v  := rA_v(4);
-                                END IF;
-                            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_o <= '1';
-                                END CASE;
-                                alu_Action_v := A_ADD;
-                                alu_Op1_v    := ALU_IN_PC;
-                                IF (COMPATIBILITY_MODE_g = TRUE) THEN
-                                    delayBit_v := rD_v(4);
-                                END IF;
-                                wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
-                            WHEN OTHERS =>
-                                noLiteOpc_o  <= '1';
-                        END CASE;
-                    END IF;
-
-                WHEN "11" =>
-                    IF (opcIx_v (3 DOWNTO 0) = "1111") THEN             -- HALT
-                        alu_Action_v :=  A_HALT;
-                        wrb_Action_v := NO_WRB;
-                    ELSE
-                        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_o <= '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;
-                    END IF;
-
-                WHEN OTHERS =>
-                    noLiteOpc_o  <= '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;
-        --
-        IF (COMPATIBILITY_MODE_g = TRUE) THEN
-            ID2CTRL_o.delayBit    <= delayBit_v;
-        ELSE
-            ID2EX_o.cmp_Cond      <= cmp_Cond_v;
-            ID2EX_o.cmp_Cond_Type <= cmp_Cond_Type_v;
-        END IF;
-        ID2CTRL_o.int_busy        <= int_busy_v;
-
-    END PROCESS;
+       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 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 it_Action_v     : IT_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;
+               VARIABLE condition_raw_v : STD_LOGIC_VECTOR ( 2 DOWNTO 0);
+               VARIABLE halt_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';
+               IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                       delayBit_v    := '0';
+               ELSE
+                       it_Action_v   :=  NO_IT;
+               END IF;
+               condition_raw_v := (others => '1');
+               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;
+               halt_v          := '0';
+               -- 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_o     <= '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
+                                       IF (opcIx_v(0) = '1') THEN                          -- RSUB
+                                               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 ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
+                                               -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode
+                                               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
+
+                                       CASE opcIx_v (2 DOWNTO 0) IS
+                                               WHEN "000" =>                                     -- MUL
+                                                       IF (USE_HW_MUL_g = TRUE) THEN
+                                                               alu_Action_v := A_MUL;
+                                                       ELSE
+                                                               noLiteOpc_o <= '1';
+                                                       END IF;
+
+                                               WHEN "001" =>                                     -- BS
+                                                       IF (USE_BARREL_g = TRUE) THEN
+                                                               IF (instruction_v(10) = '1') THEN
+                                                                       alu_Action_v := A_BSLL;
+                                                               ELSIF (instruction_v(9) = '1') THEN
+                                                                       alu_Action_v := A_BSRA;
+                                                               ELSE
+                                                                       alu_Action_v := A_BSRL;
+                                                               END IF;
+                                                       ELSE
+                                                               noLiteOpc_o <= '1';
+                                                       END IF;
+
+                                               WHEN "010" | "011" =>                             -- CMP(U)
+                                                       IF (COMPATIBILITY_MODE_g = FALSE) THEN
+                                                               IF (opcIx_v(0) = '1') THEN
+                                                                       alu_Action_v := A_CMPU;
+                                                               ELSE
+                                                                       alu_Action_v := A_CMP;
+                                                               END IF;
+                                                       ELSE
+                                                               noLiteOpc_o <= '1';
+                                                       END IF;
+
+                                               WHEN "100" | "101" =>                             -- IT(U) / ITT(U) / ITE(U)
+                                                       IF (COMPATIBILITY_MODE_g = FALSE) THEN
+                                                               IF (opcIx_v(0) = '1') THEN
+                                                                       alu_Action_v := A_CMPU;
+                                                               ELSE
+                                                                       alu_Action_v := A_CMP;
+                                                               END IF;
+
+                                                               CASE rD_v(4 downto 3) IS
+                                                                       WHEN "00"   =>
+                                                                               it_Action_v := IT;
+                                                                       WHEN "01"   =>
+                                                                               it_Action_v := ITT;
+                                                                       WHEN "10"   =>
+                                                                               it_Action_v := ITE;
+                                                                       WHEN OTHERS =>
+                                                                               noLiteOpc_o <= '1';
+                                                               END CASE;
+                                                               condition_raw_v := rD_v(2 downto 0);
+                                                               -- IT instruction isn't writing to anything
+                                                               wrb_Action_v := NO_WRB;
+                                                       ELSE
+                                                               noLiteOpc_o <= '1';
+                                                       END IF;
+
+                                               WHEN OTHERS =>
+                                                               noLiteOpc_o <= '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_o <= '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_o  <= '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 (3 DOWNTO 0) IS
+                                                       WHEN "0001" =>                                  -- RTI(D)
+                                                               int_busy_v := '0';
+                                                       WHEN "0000" =>                                  -- RTS(D)
+                                                               WHEN OTHERS  =>
+                                                       noLiteOpc_o <= '1';
+                                               END CASE;
+
+                                               alu_Action_v    := A_ADD;
+                                               branch_Action_v := BR;
+                                               wrb_Action_v    := NO_WRB;
+                                               IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                                                       delayBit_v  := rD_v(4);
+                                               END IF;
+
+                                       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_o  <= '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)(D)
+                                                               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;
+                                                               alu_Action_v    := A_ADD;
+                                                               IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                                                                       delayBit_v  := rA_v(4);
+                                                               END IF;
+
+                                                       WHEN "111" =>
+                                                               condition_raw_v := rD_v(2 downto 0);          -- Conditional branching
+                                                               branch_Action_v := BR;
+                                                               alu_Action_v := A_ADD;
+                                                               alu_Op1_v    := ALU_IN_PC;
+                                                               IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                                                                       delayBit_v := rD_v(4);
+                                                               END IF;
+                                                               wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
+
+                                                       WHEN OTHERS =>
+                                                               noLiteOpc_o  <= '1';
+                                               END CASE;
+                                       END IF;
+
+                               WHEN "11" =>
+                                       IF (opcIx_v (3 DOWNTO 0) = "1111") THEN             -- HALT
+                                               alu_Action_v := A_NOP;
+                                               wrb_Action_v := NO_WRB;
+                                               halt_v       := '1';
+                                       ELSE
+                                               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_o <= '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;
+                                       END IF;
+
+                               WHEN OTHERS =>
+                                       noLiteOpc_o  <= '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.it_Action        <= it_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.halt             <= halt_v;
+               --
+               CASE condition_raw_v IS
+                       WHEN "000"  =>
+                               ID2EX_o.condition    <= COND_EQ;
+                       WHEN "001"  =>
+                               ID2EX_o.condition    <= COND_NE;
+                       WHEN "010"  =>
+                               ID2EX_o.condition    <= COND_LT;
+                       WHEN "011"  =>
+                               ID2EX_o.condition    <= COND_LE;
+                       WHEN "100"  =>
+                               ID2EX_o.condition    <= COND_GT;
+                       WHEN "101"  =>
+                               ID2EX_o.condition    <= COND_GE;
+                       WHEN "111"  =>
+                               ID2EX_o.condition    <= COND_ALL;
+                       WHEN OTHERS =>
+                               ID2EX_o.condition    <= COND_ALL;
+                               noLiteOpc_o            <= '1';
+               END CASE;
+               --
+               IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                       ID2CTRL_o.delayBit   <= delayBit_v;
+               END IF;
+               ID2CTRL_o.int_busy     <= int_busy_v;
+
+       END PROCESS;
 
 END ARCHITECTURE rtl;