]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blobdiff - hw/decode.vhd
Core updates
[fpga/lx-cpu1/tumbl.git] / hw / decode.vhd
index c7d9c861adb7259c0ae18dc3a7df8e2aa9fa9fac..b0e66ca8b0eb165a6e5fe2001f56fd5164251b70 100644 (file)
@@ -9,6 +9,8 @@
 --                Delft University of Technology
 --                Faculty EEMCS, Department ME&CE, Circuits and Systems
 --  Date:         September, 2010
+--                     September, 2013: core customization,
+--                                      new instructions (Meloun)
 --                     June, 2011: added code for MUL and BARREL (Huib)
 --  Modified:
 --  Remarks:
 LIBRARY IEEE;
 
 USE IEEE.std_logic_1164.all;
-USE WORK.mbl_Pkg.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_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
+       );
 END ENTITY decode;
 
-
 --------------------------------------------------------------------------------
 ARCHITECTURE rtl OF decode IS
 --------------------------------------------------------------------------------
@@ -50,289 +51,341 @@ 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;
-
-    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;
-        -- 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 / 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
-                    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 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 IS
-                            WHEN "10001" =>                             -- RTID
-                                int_busy_v := '0';
-                            WHEN "10000" =>                             -- RTSD
---                          WHEN "10010" =>                             -- RTBD
---                          WHEN "10100" =>                             -- RTED
-                            WHEN OTHERS  =>
-                                noLiteOpc_o <= '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_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)
-                                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_o <= '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_o  <= '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_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;
-
-                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;
-        --
-        ID2CTRL_o.delayBit      <= delayBit_v;
-        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';
+               delayBit_v      := '0';
+               IF (COMPATIBILITY_MODE_g = FALSE) THEN
+                       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;
+
+               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;
+                                                       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;
+                                                       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;
+                                                       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 =>  NULL;
+                                                               END CASE;
+                                                               condition_raw_v := rD_v(2 downto 0);
+                                                               -- IT instruction isn't writing to anything
+                                                               wrb_Action_v := NO_WRB;
+                                                       END IF;
+
+                                               WHEN OTHERS =>
+                                                               NULL;
+                                       END CASE;
+
+                               WHEN "10" =>
+                                       IF (opcIx_v (3 DOWNTO 0) = "0100") THEN
+                                               CASE code_x26_v IS
+
+                                                       WHEN "000" =>                                     -- CLZ
+                                                               alu_Action_v := A_CLZ;
+                                                       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 =>
+                                                                               NULL;
+                                                                       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  =>
+                                                               NULL;
+                                               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 OTHERS =>                                  -- RTS(D)
+                                                               NULL;
+                                               END CASE;
+
+                                               alu_Action_v    := A_ADD;
+                                               branch_Action_v := BR;
+                                               wrb_Action_v    := NO_WRB;
+                                               delayBit_v      := rD_v(4);
+
+                                       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  =>
+                                                               NULL;
+                                               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(3) = '1') THEN
+                                                                       alu_Op1_v := ALU_IN_ZERO;
+                                                               ELSE
+                                                                       alu_Op1_v := ALU_IN_PC;
+                                                               END IF;
+
+                                                               IF (rA_v(2) = '1') THEN
+                                                                       branch_Action_v := BRL;
+                                                               ELSE
+                                                                       branch_Action_v := BR;
+                                                                       wrb_Action_v    := NO_WRB;
+                                                               END IF;
+                                                               alu_Action_v := A_ADD;
+                                                               delayBit_v   := rA_v(4);
+
+                                                       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;
+                                                               delayBit_v      := rD_v(4);
+                                                               wrb_Action_v    := NO_WRB;     -- evaluate and update/overwrite in exeq
+
+                                                       WHEN OTHERS =>
+                                                               NULL;
+                                               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 => NULL;
+                                               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 =>
+                                       NULL;
+
+                       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;
+               END CASE;
+               --
+               ID2CTRL_o.delayBit       <= delayBit_v;
+               ID2CTRL_o.int_busy       <= int_busy_v;
+
+       END PROCESS;
 
 END ARCHITECTURE rtl;