]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blobdiff - hw/exeq.vhd
Reformat code and restructure decoder to save LUTs and fit critical path
[fpga/lx-cpu1/tumbl.git] / hw / exeq.vhd
index 12357951fb2ec7f59e17c6c60773a3311c136830..03477128f2c0390bfa9720906e908b417c462468 100644 (file)
@@ -9,7 +9,7 @@
 --                Faculty EEMCS, Department ME&CE, Circuits and Systems
 --  Date:         September, 2010
 --
---  Modified:     Septemper, 2013: FSL scratched (Meloun)
+--  Modified:     Septemper, 2013: FSL scratched, core customized (Meloun)
 --                 December, 2010: FSL added (Huib)
 --                     June, 2011: added code for MUL and BARREL (Huib)
 --                                 Adapted to work with separate fsl_M-
@@ -29,36 +29,37 @@ USE WORK.mbl_Pkg.all;
 ----------------------------------------------------------
 ENTITY exeq IS
 ----------------------------------------------------------
-    GENERIC (
-        USE_HW_MUL_g : BOOLEAN := TRUE;
-        USE_BARREL_g : BOOLEAN := TRUE;
-        COMPATIBILITY_MODE_g : BOOLEAN := FALSE
-        );
-    PORT (
-        ID2EX_i      :  IN ID2EX_Type;
-        GPRF2EX_i    :  IN GPRF2EX_Type;
-        EX2IF_o      : OUT EX2IF_Type;
-        EX2CTRL_o    : OUT EX2CTRL_Type;
-        HALT_o       : OUT HALT_Type;
-        --
-        EX_WRB_i     :  IN WRB_Type;
-        EX_WRB_o     : OUT WRB_Type;
-        MEM_WRB_i    :  IN WRB_Type;
-        --
-        HAZARD_WRB_i :  IN HAZARD_WRB_Type;
-        HAZARD_WRB_o : OUT HAZARD_WRB_Type;
-        --
-        IMM_LOCK_i   :  IN IMM_LOCK_Type;
-        IMM_LOCK_o   : OUT IMM_LOCK_Type;
-        --
-        MSR_i        :  IN MSR_Type;
-        MSR_o        : OUT MSR_Type;
-        --
-        EX2MEM_o     : OUT EX2MEM_Type
-        );
+       GENERIC
+       (
+               USE_HW_MUL_g : BOOLEAN := TRUE;
+               USE_BARREL_g : BOOLEAN := TRUE;
+               COMPATIBILITY_MODE_g : BOOLEAN := FALSE
+       );
+       PORT
+       (
+               ID2EX_i      :  IN ID2EX_Type;
+               GPRF2EX_i    :  IN GPRF2EX_Type;
+               EX2IF_o      : OUT EX2IF_Type;
+               EX2CTRL_o    : OUT EX2CTRL_Type;
+               HALT_o       : OUT HALT_Type;
+               --
+               EX_WRB_i     :  IN WRB_Type;
+               EX_WRB_o     : OUT WRB_Type;
+               MEM_WRB_i    :  IN WRB_Type;
+               --
+               HAZARD_WRB_i :  IN HAZARD_WRB_Type;
+               HAZARD_WRB_o : OUT HAZARD_WRB_Type;
+               --
+               IMM_LOCK_i   :  IN IMM_LOCK_Type;
+               IMM_LOCK_o   : OUT IMM_LOCK_Type;
+               --
+               MSR_i        :  IN MSR_Type;
+               MSR_o        : OUT MSR_Type;
+               --
+               EX2MEM_o     : OUT EX2MEM_Type
+       );
 END ENTITY exeq;
 
-
 ----------------------------------------------------------
 ARCHITECTURE rtl OF exeq IS
 ----------------------------------------------------------
@@ -66,379 +67,389 @@ ARCHITECTURE rtl OF exeq IS
 BEGIN
 
 p_exeq:
-    PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i,
-                        IMM_LOCK_i, MSR_i, HAZARD_WRB_i)
-
-        -- function needed by BSLL (only if USE_BARREL_g = TRUE)
-        FUNCTION reverse_bits ( word32 : STD_LOGIC_VECTOR (31 DOWNTO 0) )
-                                                        RETURN STD_LOGIC_VECTOR IS
-            VARIABLE reversed_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        BEGIN
-        f_rev:
-            FOR i IN 0 TO 31 LOOP
-                reversed_v(31-i) := word32(i);
-            END LOOP;
-            RETURN reversed_v;
-        END;
-
-        VARIABLE data_rA_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE data_rB_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE data_rD_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE in1_v           : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE in2_v           : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE hi16_v          : STD_LOGIC_VECTOR (15 DOWNTO 0);
-        VARIABLE IMM32_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE carry_i_v       : STD_LOGIC;
-        VARIABLE result_v        : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE carry_o_v       : STD_LOGIC;
-        VARIABLE isZero_v        : STD_LOGIC;
-        VARIABLE cmpResZero_v    : STD_LOGIC;
-        VARIABLE signBit_in1_v   : STD_LOGIC;
-        VARIABLE signBit_in2_v   : STD_LOGIC;
-        VARIABLE signBit_rA_v    : STD_LOGIC;
-        VARIABLE signBit_rD_v    : STD_LOGIC;
-        VARIABLE rA_eq_ex_rD_v   : STD_LOGIC;
-        VARIABLE rB_eq_ex_rD_v   : STD_LOGIC;
-        VARIABLE hazard_v        : STD_LOGIC;
-        VARIABLE save_rX_v       : SAVE_REG_Type;
-        VARIABLE data_rX_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE do_branch_v     : STD_LOGIC;
-        VARIABLE byte_Enable_v   : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
-        VARIABLE tmp64_v         : STD_LOGIC_VECTOR (63 DOWNTO 0);
-        VARIABLE padVec_v        : STD_LOGIC_VECTOR (15 DOWNTO 0);
-        VARIABLE halt_v          : STD_LOGIC;
-        VARIABLE halt_code_v     : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
-        VARIABLE do_cmp_cond_v   : STD_LOGIC;
-        VARIABLE cmp_cond_type_v : CMP_COND_TYPE_Type;
-
-    BEGIN
-
-        rA_eq_ex_rD_v   := '0';
-        rB_eq_ex_rD_v   := '0';
-        hazard_v        := '0';
-        save_rX_v       := NO_SAVE;
-        data_rX_v       := data_rB_v;         -- default value for data_rX_v
-        result_v        := (OTHERS => '0');
-        carry_o_v       := '0';
-        do_branch_v     := '0';
-        byte_Enable_v   := "0000";
-        halt_v          := '0';
-        halt_code_v     := "00000";
-        do_cmp_cond_v   := '0';
-        cmp_cond_type_v := COND_TYPE_ALL;
-        signBit_rD_v    := '0';
-
-        -- create some helper variables
-        IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN
-            rA_eq_ex_rD_v := '1';
-        END IF;
-        IF (ID2EX_i.rdix_rB = EX_WRB_i.wrix_rD) THEN
-            rB_eq_ex_rD_v := '1';
-        END IF;
-        -- test where to obtain data_rA from
-        IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rA_eq_ex_rD_v = '1')) THEN
-            data_rA_v := EX_WRB_i.data_rD;
-        ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rA = MEM_WRB_i.wrix_rD)) THEN
-            data_rA_v := MEM_WRB_i.data_rD;
-        ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RA)) THEN
-            data_rA_v := HAZARD_WRB_i.data_rX;
-        ELSE
-            data_rA_v := GPRF2EX_i.data_rA;
-        END IF;
-        -- test where to obtain data_rB from
-        IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rB_eq_ex_rD_v = '1')) THEN
-            data_rB_v := EX_WRB_i.data_rD;
-        ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rB = MEM_WRB_i.wrix_rD)) THEN
-            data_rB_v := MEM_WRB_i.data_rD;
-        ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RB)) THEN
-            data_rB_v := HAZARD_WRB_i.data_rX;
-        ELSE
-            data_rB_v := GPRF2EX_i.data_rB;
-        END IF;
-        -- .... or, isn't all necessary data available yet being still in the pipeline ?
-        data_rX_v := data_rB_v;                 -- default value for data_rX_v
-        IF (EX_WRB_i.wrb_Action = WRB_MEM) THEN
-            IF ((rA_eq_ex_rD_v = '1') OR (rB_eq_ex_rD_v = '1')) THEN
-                hazard_v  := '1';
--- always??     IF (MEM_WRB_i.wrb_Action = WRB_MEM) THEN
-                    -- handle situations in which both rA and rB needed
-                    IF (rA_eq_ex_rD_v = '1') THEN
-                        save_rX_v := SAVE_RB;   -- already by default data_rX_v = data_rB_v
-                    ELSE
-                        save_rX_v := SAVE_RA;
-                        data_rX_v := data_rA_v;
-                    END IF;
---              END IF;
-            END IF;
-        END IF;
-
-        IF (IMM_LOCK_i.locked = '1') THEN
-            hi16_v := IMM_LOCK_i.IMM_hi16;
-        ELSIF (ID2EX_i.IMM16(15) = '0') THEN
-            hi16_v := C_16_ZEROS;
-        ELSE
-            hi16_v :=  C_16_ONES;
-        END IF;
-        IMM32_v := hi16_v & ID2EX_i.IMM16;
-
-        CASE ID2EX_i.alu_Op1 IS
-            WHEN ALU_IN_REGA     =>  in1_v := data_rA_v;
-            WHEN ALU_IN_NOT_REGA =>  in1_v := NOT data_rA_v;
-            WHEN ALU_IN_PC       =>  in1_v := ID2EX_i.program_counter;
-            WHEN ALU_IN_ZERO     =>  in1_v := C_32_ZEROS;
-            WHEN OTHERS          =>  NULL;
-        END CASE;
-
-        CASE ID2EX_i.alu_Op2 IS
-            WHEN ALU_IN_REGB     =>  in2_v := data_rB_v;
-            WHEN ALU_IN_NOT_REGB =>  in2_v := NOT data_rB_v;
-            WHEN ALU_IN_IMM      =>  in2_v := IMM32_v;
-            WHEN ALU_IN_NOT_IMM  =>  in2_v := NOT IMM32_v;
-            WHEN OTHERS          =>  NULL;
-        END CASE;
-
-        signBit_in1_v := in1_v(31);
-        signBit_in2_v := in2_v(31);
-        signBit_rA_v  := data_rA_v(31);
-
-        CASE ID2EX_i.alu_Cin IS
-            WHEN CIN_ZERO  =>   carry_i_v := '0';
-            WHEN CIN_ONE   =>   carry_i_v := '1';
-            WHEN FROM_MSR  =>   carry_i_v := MSR_i.C;
-            WHEN FROM_IN1  =>   carry_i_v := in1_v(31);
-            WHEN OTHERS    =>   carry_i_v := '0';
-        END CASE;
-
-        IF (data_rA_v = C_32_ZEROS) THEN
-            isZero_v := '1';
-        ELSE
-            isZero_v := '0';
-        END IF;
-
-        CASE ID2EX_i.alu_Action IS
-            WHEN A_ADD | A_CMP | A_CMPU =>
-                ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v);
-                IF (id2ex_i.alu_Action = A_CMPU) THEN
-                    IF (signBit_in1_v = signBit_in2_v) THEN
-                        signBit_rD_v := NOT signBit_in1_v;
-                    END IF;
-                ELSIF (id2ex_i.alu_Action = A_CMP) THEN
-                    IF (signBit_in1_v = signBit_in2_v) THEN
-                        signBit_rD_v := signBit_in1_v;
-                    END IF;
-                END IF;
-
-                result_v(31) := signBit_rD_v;
-
-                IF (COMPATIBILITY_MODE_g = FALSE) THEN
-                    IF (ID2EX_i.cmp_Cond /= COND_ALL) THEN
-                        IF (result_v = C_32_ZEROS) THEN
-                            cmpResZero_v := '1';
-                        ELSE
-                            cmpResZero_v := '0';
-                        END IF;
-
-                        CASE ID2EX_i.cmp_Cond IS
-                            WHEN COND_EQ => do_cmp_cond_v := cmpResZero_v;
-                            WHEN COND_NE => do_cmp_cond_v := NOT cmpResZero_v;
-                            WHEN COND_LT => do_cmp_cond_v := signBit_rD_v;
-                            WHEN COND_LE => do_cmp_cond_v := signBit_rD_v OR cmpResZero_v;
-                            WHEN COND_GT => do_cmp_cond_v := NOT (signBit_rD_v OR cmpResZero_v);
-                            WHEN COND_GE => do_cmp_cond_v := NOT signBit_rD_v;
-                            WHEN OTHERS  => NULL;
-                        END CASE;
-
-                        cmp_cond_type_v := ID2EX_i.cmp_Cond_Type;
-                    END IF;
-                END IF;
-
-            WHEN A_OR      =>
-                result_v  := in1_v  OR in2_v;
-            WHEN A_AND    =>
-                result_v  := in1_v AND in2_v;
-            WHEN A_XOR    =>
-                result_v  := in1_v XOR in2_v;
-            WHEN A_SHIFT  =>
-                result_v  := carry_i_v & in1_v(31 DOWNTO 1);
-                carry_o_v := in1_v(0);
-            WHEN A_SEXT8   =>
-                IF (in1_v(7) = '0') THEN
-                    result_v := C_24_ZEROS & in1_v( 7 DOWNTO 0);
-                ELSE
-                    result_v :=  C_24_ONES & in1_v( 7 DOWNTO 0);
-                END IF;
-            WHEN A_SEXT16  =>
-                IF (in1_v(15) = '0') THEN
-                    result_v := C_16_ZEROS & in1_v(15 DOWNTO 0);
-                ELSE
-                    result_v :=  C_16_ONES & in1_v(15 DOWNTO 0);
-                END IF;
-            WHEN A_MFS     =>
-                result_v := MSR_i.C & C_24_ZEROS & "0000" & MSR_i.C & MSR_i.IE & '0';
-            WHEN A_MTS     =>
-                MSR_o.IE  <= data_Ra_v(1);
-                MSR_o.C   <= data_Ra_v(2);
-            WHEN A_MUL     =>
-                IF (USE_HW_MUL_g = TRUE) THEN
-                    tmp64_v  := STD_LOGIC_VECTOR( UNSIGNED(in1_v) * UNSIGNED(in2_v) );
-                    result_v := tmp64_v(31 DOWNTO 0);
-                END IF;
-            WHEN A_BSLL | A_BSRL | A_BSRA  =>
-                IF (USE_BARREL_g = TRUE) THEN
-                    IF (ID2EX_i.alu_Action = A_BSLL) THEN
-                        result_v := reverse_bits (in1_v);
-                    ELSE
-                        result_v := in1_v;
-                    END IF;
-                    IF (ID2EX_i.alu_Action = A_BSRA) THEN
-                        padVec_v := (OTHERS => in1_v(31));
-                    ELSE
-                        padVec_v := (OTHERS => '0');
-                    END IF;
-                    IF (in2_v(4) = '1') THEN
-                        result_v := padVec_v (15 DOWNTO 0) & result_v (31 DOWNTO 16);
-                    END IF;
-                    IF (in2_v(3) = '1') THEN
-                        result_v := padVec_v ( 7 DOWNTO 0) & result_v (31 DOWNTO  8);
-                    END IF;
-                    IF (in2_v(2) = '1') THEN
-                        result_v := padVec_v ( 3 DOWNTO 0) & result_v (31 DOWNTO  4);
-                    END IF;
-                    IF (in2_v(1) = '1') THEN
-                        result_v := padVec_v ( 1 DOWNTO 0) & result_v (31 DOWNTO  2);
-                    END IF;
-                    IF (in2_v(0) = '1') THEN
-                        result_v := padVec_v ( 0 DOWNTO 0) & result_v (31 DOWNTO  1);
-                    END IF;
-                    IF (ID2EX_i.alu_Action = A_BSLL) THEN
-                        result_v := reverse_bits (result_v);
-                    END IF;
-                END IF;     -- (USE_BARREL_g = TRUE)
-            WHEN A_HALT    =>
-                halt_v := '1';
-                halt_code_v := ID2EX_i.IMM16(4 DOWNTO 0);
-            WHEN OTHERS    =>
-                NULL;
-        END CASE;
-
-        CASE ID2EX_i.branch_Action IS
-            WHEN BR     => do_branch_v := '1';
-            WHEN BRL    => do_branch_v := '1';
-            WHEN BEQ    => do_branch_v := isZero_v;
-            WHEN BNE    => do_branch_v := NOT isZero_v;
-            WHEN BLT    => do_branch_v := signBit_rA_v;
-            WHEN BLE    => do_branch_v := signBit_rA_v OR isZero_v;
-            WHEN BGT    => do_branch_v := NOT (signBit_rA_v OR isZero_v);
-            WHEN BGE    => do_branch_v := NOT signBit_rA_v;
-            WHEN OTHERS => NULL;
-        END CASE;
-        IF (do_branch_v = '1') THEN
-            EX2IF_o.take_branch   <= '1';
-            EX2IF_o.branch_target <= result_v;
-        ELSE
-            EX2IF_o.take_branch   <= '0';
-            EX2IF_o.branch_target <= C_32_ZEROS;
-        END IF;
-
-        -- CMP conditioning
-        IF (COMPATIBILITY_MODE_g = FALSE) THEN
-            CASE cmp_cond_type_v IS
-                WHEN COND_TYPE_ALL          =>
-                    EX2CTRL_o.flush_first  <= '0';
-                    EX2CTRL_o.flush_second <= '0';
-                WHEN COND_TYPE_IF_THEN      =>
-                    EX2CTRL_o.flush_first  <= not do_cmp_cond_v;
-                    EX2CTRL_o.flush_second <= '0';
-                WHEN COND_TYPE_IF_THEN_THEN =>
-                    EX2CTRL_o.flush_first  <= not do_cmp_cond_v;
-                    EX2CTRL_o.flush_second <= not do_cmp_cond_v;
-                WHEN COND_TYPE_IF_THEN_ELSE =>
-                    EX2CTRL_o.flush_first  <= not do_cmp_cond_v;
-                    EX2CTRL_o.flush_second <= do_cmp_cond_v;
-                WHEN OTHERS                 =>
-                    NULL;
-            END CASE;
-        END IF;
-
-        -- Halting
-        HALT_o.halt      <= halt_v;
-        HALT_o.halt_code <= halt_code_v;
-
-        -- WR_MEM/RD_MEM:      result_v --> exeq_result --> mem_address,
-        --        WR_MEM:                       data_rD --> data_out_to_mem
-        --           BRL:  prog_counter --> exeq_result
-        --          else       result_v --> exeq_result (data_rD not used)
-        EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD;
-        IF (ID2EX_i.branch_Action = BRL) THEN
-            EX2MEM_o.wrb_Action  <= WRB_EX;
-            EX2MEM_o.exeq_result <= ID2EX_i.program_counter;
-            EX2MEM_o.data_rD     <= ID2EX_i.program_counter;
-            -- set data_rD_v, although unused, to prevent an inferred latch
-            data_rD_v := GPRF2EX_i.data_rD;
-        ELSE
-            EX2MEM_o.wrb_Action  <= ID2EX_i.wrb_Action;
-            EX2MEM_o.exeq_result <= result_v;
-            -- test where to obtain data_rD from
-            IF (HAZARD_WRB_i.hazard = '1') THEN
-                data_rD_v := HAZARD_WRB_i.data_rD;
-            ELSIF ((EX_WRB_i.wrb_Action = WRB_EX) AND (ID2EX_i.curr_rD = EX_WRB_i.wrix_rD)) THEN
-                -- forward rD_data just calculated, to handle e.g. addi rD,rA,Imm; sw rD,mem[y]; ...
-                data_rD_v := EX_WRB_i.data_rD;
-            ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.curr_rD = MEM_WRB_i.wrix_rD)) THEN
-                data_rD_v := MEM_WRB_i.data_rD;
-            ELSE
-                data_rD_v := GPRF2EX_i.data_rD;
-            END IF;
-        END IF;
-        IF (ID2EX_i.mem_Action /= NO_MEM) THEN
-            CASE ID2EX_i.transfer_Size IS
-                WHEN BYTE     =>
-                    CASE result_v( 1 DOWNTO 0) IS
-                        WHEN "00"   => byte_Enable_v := "1000";
-                        WHEN "01"   => byte_Enable_v := "0100";
-                        WHEN "10"   => byte_Enable_v := "0010";
-                        WHEN "11"   => byte_Enable_v := "0001";
-                        WHEN OTHERS => NULL;
-                    END CASE;
-                WHEN HALFWORD =>
-                    CASE result_v( 1 DOWNTO 0) IS
-                        WHEN "00"   => byte_Enable_v := "1100";
-                        WHEN "10"   => byte_Enable_v := "0011";
-                        WHEN OTHERS => NULL;
-                    END CASE;
-                WHEN OTHERS   =>       byte_Enable_v := "1111";
-            END CASE;
-        END IF;
-
-        -- update MSR[IE] and/or MSR[C] if needed
-        IF (ID2EX_i.alu_Action /= A_MTS) THEN
-            MSR_o.IE  <= MSR_i.IE;
-            IF (ID2EX_i.msr_Action = UPDATE_CARRY) THEN
-                MSR_o.C <= carry_o_v;
-            ELSE
-                MSR_o.C <= MSR_i.C;
-            END IF;
-        END IF;
-
-        -- pass remaining data to mem
-        EX2MEM_o.mem_Action  <= ID2EX_i.mem_Action;
-        EX2MEM_o.data_rD     <= data_rD_v;
-        EX2MEM_o.byte_Enable <= byte_Enable_v;
-        EX2MEM_o.wrix_rD     <= ID2EX_i.curr_rD;
-        --
-        IMM_LOCK_o.locked    <= ID2EX_i.IMM_Lock;
-        IMM_LOCK_o.IMM_hi16  <= ID2EX_i.IMM16;
-        --
-        EX_WRB_o.wrb_Action  <= ID2EX_i.wrb_Action;
-        EX_WRB_o.wrix_rD     <= ID2EX_i.curr_rD;
-        EX_WRB_o.data_rD     <= result_v;
-        --
-        HAZARD_WRB_o.hazard  <= hazard_v;
-        HAZARD_WRB_o.save_rX <= save_rX_v;
-        HAZARD_WRB_o.data_rX <= data_rX_v;
-        HAZARD_WRB_o.data_rD <= data_rD_v;
-
-    END PROCESS;
+       PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i,
+                                               IMM_LOCK_i, MSR_i, HAZARD_WRB_i)
+
+               -- function needed by BSLL (only if USE_BARREL_g = TRUE)
+               FUNCTION reverse_bits ( word32 : STD_LOGIC_VECTOR (31 DOWNTO 0) )
+                       RETURN STD_LOGIC_VECTOR IS
+                               VARIABLE reversed_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               BEGIN
+               f_rev:
+                       FOR i IN 0 TO 31 LOOP
+                               reversed_v(31-i) := word32(i);
+                       END LOOP;
+                       RETURN reversed_v;
+               END;
+
+               VARIABLE data_rA_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE data_rB_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE data_rD_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE in1_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE in2_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE hi16_v        : STD_LOGIC_VECTOR (15 DOWNTO 0);
+               VARIABLE IMM32_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE carry_i_v     : STD_LOGIC;
+               VARIABLE result_v      : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE carry_o_v     : STD_LOGIC;
+               VARIABLE isZero_v      : STD_LOGIC;
+               VARIABLE signBit_in1_v : STD_LOGIC;
+               VARIABLE signBit_in2_v : STD_LOGIC;
+               VARIABLE signBit_r_v   : STD_LOGIC;
+               VARIABLE rA_eq_ex_rD_v : STD_LOGIC;
+               VARIABLE rB_eq_ex_rD_v : STD_LOGIC;
+               VARIABLE hazard_v      : STD_LOGIC;
+               VARIABLE save_rX_v     : SAVE_REG_Type;
+               VARIABLE data_rX_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE do_branch_v   : STD_LOGIC;
+               VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+               VARIABLE tmp64_v       : STD_LOGIC_VECTOR (63 DOWNTO 0);
+               VARIABLE padVec_v      : STD_LOGIC_VECTOR (15 DOWNTO 0);
+               VARIABLE do_cond_v     : STD_LOGIC;
+
+       BEGIN
+
+               rA_eq_ex_rD_v := '0';
+               rB_eq_ex_rD_v := '0';
+               hazard_v      := '0';
+               save_rX_v     := NO_SAVE;
+               data_rX_v     := data_rB_v;         -- default value for data_rX_v
+               result_v      := (OTHERS => '0');
+               carry_o_v     := '0';
+               do_branch_v   := '0';
+               byte_Enable_v := (OTHERS => '0');
+               do_cond_v     := '0';
+               --
+    MSR_o         <= MSR_i;             -- pass MSR by default
+
+               -- create some helper variables
+               IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN
+                       rA_eq_ex_rD_v := '1';
+               END IF;
+               IF (ID2EX_i.rdix_rB = EX_WRB_i.wrix_rD) THEN
+                       rB_eq_ex_rD_v := '1';
+               END IF;
+               -- test where to obtain data_rA from
+               IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rA_eq_ex_rD_v = '1')) THEN
+                       data_rA_v := EX_WRB_i.data_rD;
+               ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rA = MEM_WRB_i.wrix_rD)) THEN
+                       data_rA_v := MEM_WRB_i.data_rD;
+               ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RA)) THEN
+                       data_rA_v := HAZARD_WRB_i.data_rX;
+               ELSE
+                       data_rA_v := GPRF2EX_i.data_rA;
+               END IF;
+               -- test where to obtain data_rB from
+               IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rB_eq_ex_rD_v = '1')) THEN
+                       data_rB_v := EX_WRB_i.data_rD;
+               ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rB = MEM_WRB_i.wrix_rD)) THEN
+                       data_rB_v := MEM_WRB_i.data_rD;
+               ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RB)) THEN
+                       data_rB_v := HAZARD_WRB_i.data_rX;
+               ELSE
+                       data_rB_v := GPRF2EX_i.data_rB;
+               END IF;
+               -- .... or, isn't all necessary data available yet being still in the pipeline ?
+               data_rX_v := data_rB_v;                 -- default value for data_rX_v
+               IF (EX_WRB_i.wrb_Action = WRB_MEM) THEN
+                       IF ((rA_eq_ex_rD_v = '1') OR (rB_eq_ex_rD_v = '1')) THEN
+                               hazard_v  := '1';
+                               IF (rA_eq_ex_rD_v = '1') THEN
+                                       save_rX_v := SAVE_RB;   -- already by default data_rX_v = data_rB_v
+                               ELSE
+                                       save_rX_v := SAVE_RA;
+                                       data_rX_v := data_rA_v;
+                               END IF;
+                       END IF;
+               END IF;
+
+               IF (IMM_LOCK_i.locked = '1') THEN
+                       hi16_v := IMM_LOCK_i.IMM_hi16;
+               ELSIF (ID2EX_i.IMM16(15) = '0') THEN
+                       hi16_v := C_16_ZEROS;
+               ELSE
+                       hi16_v :=  C_16_ONES;
+               END IF;
+               IMM32_v := hi16_v & ID2EX_i.IMM16;
+
+               CASE ID2EX_i.alu_Op1 IS
+                       WHEN ALU_IN_REGA     =>  in1_v := data_rA_v;
+                       WHEN ALU_IN_NOT_REGA =>  in1_v := NOT data_rA_v;
+                       WHEN ALU_IN_PC       =>  in1_v := ID2EX_i.program_counter;
+                       WHEN ALU_IN_ZERO     =>  in1_v := C_32_ZEROS;
+                       WHEN OTHERS          =>  NULL;
+               END CASE;
+
+               CASE ID2EX_i.alu_Op2 IS
+                       WHEN ALU_IN_REGB     =>  in2_v := data_rB_v;
+                       WHEN ALU_IN_NOT_REGB =>  in2_v := NOT data_rB_v;
+                       WHEN ALU_IN_IMM      =>  in2_v := IMM32_v;
+                       WHEN ALU_IN_NOT_IMM  =>  in2_v := NOT IMM32_v;
+                       WHEN OTHERS          =>  NULL;
+               END CASE;
+
+               signBit_in1_v := in1_v(31);
+               signBit_in2_v := in2_v(31);
+               signBit_r_v   := data_rA_v(31); -- Init with Op1, then possibly override
+
+               CASE ID2EX_i.alu_Cin IS
+                       WHEN CIN_ZERO  =>   carry_i_v := '0';
+                       WHEN CIN_ONE   =>   carry_i_v := '1';
+                       WHEN FROM_MSR  =>   carry_i_v := MSR_i.C;
+                       WHEN FROM_IN1  =>   carry_i_v := in1_v(31);
+                       WHEN OTHERS    =>   carry_i_v := '0';
+               END CASE;
+
+               IF (data_rA_v = C_32_ZEROS) THEN
+                       isZero_v := '1';
+               ELSE
+                       isZero_v := '0';
+               END IF;
+
+               CASE ID2EX_i.alu_Action IS
+
+                       WHEN A_ADD | A_CMP | A_CMPU =>
+                               ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v);
+                               CASE ID2EX_i.alu_Action IS
+
+                                       WHEN A_CMPU  =>
+                                               IF (signBit_in1_v = signBit_in2_v) THEN
+                                                       signBit_r_v := NOT signBit_in1_v;
+                                               END IF;
+                                               IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN
+                                                       -- have to update zero flag with current result
+                                                       IF (result_v = C_32_ZEROS) THEN
+                                                               isZero_v := '1';
+                                                       ELSE
+                                                               isZero_v := '0';
+                                                       END IF;
+                                               END IF;
+
+                                       WHEN A_CMP  =>
+                                               IF (signBit_in1_v = signBit_in2_v) THEN
+                                                       signBit_r_v := signBit_in1_v;
+                                               END IF;
+                                               IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN
+                                                       -- have to update zero flag with current result
+                                                       IF (result_v = C_32_ZEROS) THEN
+                                                               isZero_v := '1';
+                                                       ELSE
+                                                               isZero_v := '0';
+                                                       END IF;
+                                               END IF;
+
+                                       WHEN OTHERS =>
+                                               NULL;
+
+                               END CASE;
+
+                       WHEN A_OR     =>
+                               result_v  := in1_v  OR in2_v;
+
+                       WHEN A_AND    =>
+                               result_v  := in1_v AND in2_v;
+
+                       WHEN A_XOR    =>
+                               result_v  := in1_v XOR in2_v;
+
+                       WHEN A_SHIFT  =>
+                               result_v  := carry_i_v & in1_v(31 DOWNTO 1);
+                               carry_o_v := in1_v(0);
+
+                       WHEN A_SEXT8  =>
+                               IF (in1_v(7) = '0') THEN
+                                       result_v := C_24_ZEROS & in1_v( 7 DOWNTO 0);
+                               ELSE
+                                       result_v :=  C_24_ONES & in1_v( 7 DOWNTO 0);
+                               END IF;
+
+                       WHEN A_SEXT16 =>
+                               IF (in1_v(15) = '0') THEN
+                                       result_v := C_16_ZEROS & in1_v(15 DOWNTO 0);
+                               ELSE
+                                       result_v :=  C_16_ONES & in1_v(15 DOWNTO 0);
+                               END IF;
+
+                       WHEN A_MFS    =>
+                               result_v := MSR_i.C & C_24_ZEROS & "0000" & MSR_i.C & MSR_i.IE & '0';
+
+                       WHEN A_MTS    =>
+                               MSR_o.IE  <= data_Ra_v(1);
+                               MSR_o.C   <= data_Ra_v(2);
+
+                       WHEN A_MUL    =>
+                               IF (USE_HW_MUL_g = TRUE) THEN
+                                       tmp64_v  := STD_LOGIC_VECTOR( UNSIGNED(in1_v) * UNSIGNED(in2_v) );
+                                       result_v := tmp64_v(31 DOWNTO 0);
+                               END IF;
+
+                       WHEN A_BSLL | A_BSRL | A_BSRA  =>
+                               IF (USE_BARREL_g = TRUE) THEN
+                                       IF (ID2EX_i.alu_Action = A_BSLL) THEN
+                                               result_v := reverse_bits (in1_v);
+                                       ELSE
+                                               result_v := in1_v;
+                                       END IF;
+                                       IF (ID2EX_i.alu_Action = A_BSRA) THEN
+                                               padVec_v := (OTHERS => in1_v(31));
+                                       ELSE
+                                               padVec_v := (OTHERS => '0');
+                                       END IF;
+                                       IF (in2_v(4) = '1') THEN
+                                               result_v := padVec_v (15 DOWNTO 0) & result_v (31 DOWNTO 16);
+                                       END IF;
+                                       IF (in2_v(3) = '1') THEN
+                                               result_v := padVec_v ( 7 DOWNTO 0) & result_v (31 DOWNTO  8);
+                                       END IF;
+                                       IF (in2_v(2) = '1') THEN
+                                               result_v := padVec_v ( 3 DOWNTO 0) & result_v (31 DOWNTO  4);
+                                       END IF;
+                                       IF (in2_v(1) = '1') THEN
+                                               result_v := padVec_v ( 1 DOWNTO 0) & result_v (31 DOWNTO  2);
+                                       END IF;
+                                       IF (in2_v(0) = '1') THEN
+                                               result_v := padVec_v ( 0 DOWNTO 0) & result_v (31 DOWNTO  1);
+                                       END IF;
+                                       IF (ID2EX_i.alu_Action = A_BSLL) THEN
+                                               result_v := reverse_bits (result_v);
+                                       END IF;
+                               END IF;     -- (USE_BARREL_g = TRUE)
+
+                       WHEN OTHERS    =>
+                               NULL;
+
+    END CASE;
+
+               CASE ID2EX_i.condition IS
+                       WHEN COND_EQ  => do_cond_v := isZero_v;
+                       WHEN COND_NE  => do_cond_v := NOT isZero_v;
+                       WHEN COND_LT  => do_cond_v := signBit_r_v;
+                       WHEN COND_LE  => do_cond_v := signBit_r_v OR isZero_v;
+                       WHEN COND_GT  => do_cond_v := NOT (signBit_r_v OR isZero_v);
+                       WHEN COND_GE  => do_cond_v := NOT signBit_r_v;
+                       WHEN COND_ALL => do_cond_v := '1';
+                       WHEN OTHERS   => NULL;
+               END CASE;
+
+               CASE ID2EX_i.branch_Action IS
+                       WHEN BR     => do_branch_v := do_cond_v;
+                       WHEN BRL    => do_branch_v := '1';
+                       WHEN OTHERS => NULL;
+               END CASE;
+
+               IF (do_branch_v = '1') THEN
+                       EX2IF_o.take_branch   <= '1';
+                       EX2IF_o.branch_target <= result_v;
+               ELSE
+                       EX2IF_o.take_branch   <= '0';
+                       EX2IF_o.branch_target <= C_32_ZEROS;
+               END IF;
+
+               -- IT / ITE / ITT conditioning
+               IF (COMPATIBILITY_MODE_g = FALSE) THEN
+                       CASE ID2EX_i.it_Action IS
+                               WHEN IT     =>
+                                       EX2CTRL_o.flush_first  <= not do_cond_v;
+                                       EX2CTRL_o.flush_second <= '0';
+                                       EX2CTRL_o.ignore_state <= '1';
+                               WHEN ITT    =>
+                                       EX2CTRL_o.flush_first  <= not do_cond_v;
+                                       EX2CTRL_o.flush_second <= not do_cond_v;
+                                       EX2CTRL_o.ignore_state <= '1';
+                               WHEN ITE    =>
+                                       EX2CTRL_o.flush_first  <= not do_cond_v;
+                                       EX2CTRL_o.flush_second <= do_cond_v;
+                                       EX2CTRL_o.ignore_state <= '1';
+                               WHEN OTHERS =>
+                                       EX2CTRL_o.flush_first  <= '0';
+                                       EX2CTRL_o.flush_second <= '0';
+                                       EX2CTRL_o.ignore_state <= '0';
+                       END CASE;
+               END IF;
+
+               -- Halting, the instruction parsing is separate
+               HALT_o.halt        <= ID2EX_i.halt;
+               IF (ID2EX_i.halt = '1') THEN
+                       HALT_o.halt_code <= ID2EX_i.IMM16(4 DOWNTO 0);
+               ELSE
+                       HALT_o.halt_code <= (others => '0');
+               END IF;
+
+               -- WR_MEM/RD_MEM:      result_v --> exeq_result --> mem_address,
+               --        WR_MEM:                       data_rD --> data_out_to_mem
+               --           BRL:  prog_counter --> exeq_result
+               --          else       result_v --> exeq_result (data_rD not used)
+               EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD;
+               IF (ID2EX_i.branch_Action = BRL) THEN
+                       EX2MEM_o.wrb_Action  <= WRB_EX;
+                       EX2MEM_o.exeq_result <= ID2EX_i.program_counter;
+                       EX2MEM_o.data_rD     <= ID2EX_i.program_counter;
+                       -- set data_rD_v, although unused, to prevent an inferred latch
+                       data_rD_v := GPRF2EX_i.data_rD;
+               ELSE
+                       EX2MEM_o.wrb_Action  <= ID2EX_i.wrb_Action;
+                       EX2MEM_o.exeq_result <= result_v;
+                       -- test where to obtain data_rD from
+                       IF (HAZARD_WRB_i.hazard = '1') THEN
+                               data_rD_v := HAZARD_WRB_i.data_rD;
+                       ELSIF ((EX_WRB_i.wrb_Action = WRB_EX) AND (ID2EX_i.curr_rD = EX_WRB_i.wrix_rD)) THEN
+                       -- forward rD_data just calculated, to handle e.g. addi rD,rA,Imm; sw rD,mem[y]; ...
+                               data_rD_v := EX_WRB_i.data_rD;
+                       ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.curr_rD = MEM_WRB_i.wrix_rD)) THEN
+                               data_rD_v := MEM_WRB_i.data_rD;
+                       ELSE
+                               data_rD_v := GPRF2EX_i.data_rD;
+                       END IF;
+               END IF;
+
+               IF (ID2EX_i.mem_Action /= NO_MEM) THEN
+                       CASE ID2EX_i.transfer_Size IS
+
+                               WHEN BYTE     =>
+                                       CASE result_v( 1 DOWNTO 0) IS
+                                               WHEN "00"   => byte_Enable_v := "1000";
+                                               WHEN "01"   => byte_Enable_v := "0100";
+                                               WHEN "10"   => byte_Enable_v := "0010";
+                                               WHEN "11"   => byte_Enable_v := "0001";
+                                               WHEN OTHERS => NULL;
+                                       END CASE;
+
+                               WHEN HALFWORD =>
+                                       CASE result_v( 1 DOWNTO 0) IS
+                                               WHEN "00"   => byte_Enable_v := "1100";
+                                               WHEN "10"   => byte_Enable_v := "0011";
+                                               WHEN OTHERS => NULL;
+                                       END CASE;
+
+                               WHEN OTHERS     => byte_Enable_v := "1111";
+
+                       END CASE;
+               END IF;
+
+               -- update MSR[C] if needed
+               IF (ID2EX_i.msr_Action = UPDATE_CARRY) THEN
+                       MSR_o.C <= carry_o_v;
+               END IF;
+
+               -- pass remaining data to mem
+               EX2MEM_o.mem_Action  <= ID2EX_i.mem_Action;
+               EX2MEM_o.data_rD     <= data_rD_v;
+               EX2MEM_o.byte_Enable <= byte_Enable_v;
+               EX2MEM_o.wrix_rD     <= ID2EX_i.curr_rD;
+               --
+               IMM_LOCK_o.locked    <= ID2EX_i.IMM_Lock;
+               IMM_LOCK_o.IMM_hi16  <= ID2EX_i.IMM16;
+               --
+               EX_WRB_o.wrb_Action  <= ID2EX_i.wrb_Action;
+               EX_WRB_o.wrix_rD     <= ID2EX_i.curr_rD;
+               EX_WRB_o.data_rD     <= result_v;
+               --
+               HAZARD_WRB_o.hazard  <= hazard_v;
+               HAZARD_WRB_o.save_rX <= save_rX_v;
+               HAZARD_WRB_o.data_rX <= data_rX_v;
+               HAZARD_WRB_o.data_rD <= data_rD_v;
+
+       END PROCESS;
 
 END ARCHITECTURE rtl;