]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/commitdiff
Initial commit for MBLite+ Tumbl (used as coprocessor)
authorMartin Meloun <meloumar@cmp.felk.cvut.cz>
Thu, 5 Sep 2013 16:04:56 +0000 (18:04 +0200)
committerMartin Meloun <meloumar@cmp.felk.cvut.cz>
Thu, 5 Sep 2013 16:04:56 +0000 (18:04 +0200)
This does not include memory interconnections (registers, instruction
and data memory wiring is required).

Signed-off-by: Martin Meloun <meloumar@cmp.felk.cvut.cz>
hw/core_ctrl.vhd [new file with mode: 0644]
hw/decode.vhd [new file with mode: 0644]
hw/exeq.vhd [new file with mode: 0644]
hw/fetch.vhd [new file with mode: 0644]
hw/mbl_Pkg.vhd [new file with mode: 0644]
hw/mem.vhd [new file with mode: 0644]

diff --git a/hw/core_ctrl.vhd b/hw/core_ctrl.vhd
new file mode 100644 (file)
index 0000000..95289fb
--- /dev/null
@@ -0,0 +1,310 @@
+---------------------------------------------------------------------------------
+--
+--  Entity:       core_ctrl
+--  Filename:     core_ctrl.vhd
+--  Description:  the control unit for the TUD MB-Lite implementation
+--
+--  Author:       Huib Lincklaen Arriens
+--                Delft University of Technology
+--                Faculty EEMCS, Department ME&CE, Circuits and Systems
+--  Date:          December, 2010
+--  Modified:     September, 2012: interrupt handling corrected to let
+--                                 a pending branch be taken first
+--                                 (with thanks to Matthis Meier, TU Dortmund,
+--                                  for detecting this errror).
+--  Remarks:
+--
+--------------------------------------------------------------------------------
+
+LIBRARY IEEE;
+
+USE IEEE.std_logic_1164.all;
+USE WORK.mbl_Pkg.all;
+
+
+--------------------------------------------------------------------------------
+ENTITY core_ctrl IS
+--------------------------------------------------------------------------------
+    PORT (
+        clk_i           :  IN STD_LOGIC;
+        rst_i           :  IN STD_LOGIC;
+--      halt_i          :  IN STD_LOGIC;
+        int_i           :  IN STD_LOGIC;
+        -- specific fetch i/o
+        imem_addr_o     : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
+        imem_clken_o    : OUT STD_LOGIC;
+        pc_ctrl_o       : OUT STD_LOGIC;
+        -- fetch to decode pipeline registers
+        IF2ID_REG_i     :  IN IF2ID_Type;
+        IF2ID_REG_o     : OUT IF2ID_Type;
+        -- decode to exeq pipeline registers
+        ID2EX_REG_i     :  IN ID2EX_Type;
+        ID2EX_REG_o     : OUT ID2EX_Type;
+        -- GPRF control
+        gprf_clken_o    : OUT STD_LOGIC;
+        -- exeq to fetch feedback registers
+        EX2IF_REG_i     :  IN EX2IF_Type;
+        EX2IF_REG_o     : OUT EX2IF_Type;
+        -- exeq to mem pipeline registers
+        EX2MEM_REG_i    :  IN EX2MEM_Type;
+        EX2MEM_REG_o    : OUT EX2MEM_Type;
+        -- mem pipeline register
+        MEM_REG_i       :  IN MEM_REG_Type;
+        MEM_REG_o       : OUT MEM_REG_Type;
+        -- FSL to mem data delay register(s)
+        FSL_S2MEM_REG_i :  IN FSL_S2MEM_Type;
+        FSL_S2MEM_REG_o : OUT FSL_S2MEM_Type;
+        -- decode control i/o
+        ID2CTRL_i       :  IN ID2CTRL_Type;
+        INT_CTRL_o      : OUT INT_CTRL_Type;
+        -- exeq control i/o
+        EX_WRB_i        :  IN WRB_Type;
+        EX_WRB_o        : OUT WRB_Type;
+        -- data hazard i/o
+        HAZARD_WRB_i    :  IN HAZARD_WRB_Type;
+        HAZARD_WRB_o    : OUT HAZARD_WRB_Type;
+        -- for handling the 'IMM' instruction
+        IMM_LOCK_i      :  IN IMM_LOCK_Type;
+        IMM_LOCK_o      : OUT IMM_LOCK_Type;
+        -- for handling the Machine Status Register
+        MSR_i           :  IN MSR_Type;
+        MSR_o           : OUT MSR_Type;
+        -- miscellaneous
+        MEM2CTRL_i      :  IN MEM2CTRL_Type;
+        FSL_nStall_i    :  IN STD_LOGIC;
+        done_o          : OUT STD_LOGIC
+        );
+END ENTITY core_ctrl;
+
+--------------------------------------------------------------------------------
+ARCHITECTURE rtl OF core_ctrl IS
+--------------------------------------------------------------------------------
+
+    SIGNAL rst_r          : STD_LOGIC;
+    SIGNAL reset_s        : STD_LOGIC;
+
+    SIGNAL ID2EX_REG_r    : ID2EX_Type;
+    SIGNAL EX2IF_REG_r    : EX2IF_Type;
+    SIGNAL delayBit_r     : STD_LOGIC;
+    SIGNAL delayBit_2r    : STD_LOGIC;
+    SIGNAL IMM_LOCK_r     : IMM_LOCK_Type;
+    SIGNAL HAZARD_WRB_r   : HAZARD_WRB_Type;
+
+    SIGNAL clken_s        : STD_LOGIC;
+    SIGNAL clken_pipe_s   : STD_LOGIC;
+    SIGNAL flush_ID2EX_s  : STD_LOGIC;
+    SIGNAL flush_ID2EX_r  : STD_LOGIC;
+    SIGNAL flush_EX2MEM_s : STD_LOGIC;
+
+    SIGNAL setup_int_r    : STD_LOGIC;
+    SIGNAL int_busy_r     : STD_LOGIC;
+
+    SIGNAL S_Data_r       : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    SIGNAL S_Data_2r      : STD_LOGIC_VECTOR (31 DOWNTO 0);
+
+
+BEGIN
+
+    -- static connections
+    reset_s        <= rst_i OR rst_r;
+    pc_ctrl_o      <= NOT rst_r;
+    imem_addr_o    <= IF2ID_REG_i.program_counter;
+    -- clock/wait control lines
+    clken_s        <= (MEM2CTRL_i.clken AND FSL_nStall_i) OR rst_i;
+    clken_pipe_s   <= clken_s AND (NOT HAZARD_WRB_i.hazard);
+    imem_clken_o   <= clken_pipe_s;
+    gprf_clken_o   <= clken_s;
+    -- signals for clearing the ID2EX and EX2MEM registers during branches
+    flush_ID2EX_s  <= EX2IF_REG_r.take_branch;
+    flush_EX2MEM_s <= (flush_ID2EX_s AND (NOT delayBit_2r)) OR HAZARD_WRB_i.hazard;
+    -- outputs that need to be readable too, so needing shadowing signals
+    ID2EX_REG_o    <= ID2EX_REG_r;
+    EX2IF_REG_o    <= EX2IF_REG_r;
+    IMM_LOCK_o     <= IMM_LOCK_r;
+    HAZARD_WRB_o   <= HAZARD_WRB_r;
+    --
+    INT_CTRL_o.setup_int   <= setup_int_r;
+    INT_CTRL_o.rti_target  <= ID2EX_REG_r.program_counter;
+    INT_CTRL_o.int_busy    <= int_busy_r;
+    --
+    FSL_S2MEM_REG_o.S_Data <= S_Data_2r;
+
+regd_proc:
+    PROCESS ( clk_i, rst_i,
+              -- complete sensitivity list for synthesizer
+              reset_s, MEM2CTRL_i, clken_pipe_s, IF2ID_REG_i,
+              flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i,
+              MEM_REG_i, ID2CTRL_i, int_i, MSR_i,
+              int_busy_r, delayBit_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
+              EX2IF_REG_i, EX_WRB_i, S_Data_r, FSL_S2MEM_REG_i, EX2MEM_REG_i )
+
+        -- some local procedures
+        PROCEDURE lp_rst_IF2ID_REG IS
+        BEGIN
+            IF2ID_REG_o.program_counter <= (OTHERS => '0');
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_ID2EX_REG IS
+        BEGIN
+            -- reset and handle ID2EX_REG_r.program_counter separately,
+            -- since it will be needed during interrupt setup
+            ID2EX_REG_r.rdix_rA          <= (OTHERS => '0');
+            ID2EX_REG_r.rdix_rB          <= (OTHERS => '0');
+            ID2EX_REG_r.curr_rD          <= (OTHERS => '0');
+            ID2EX_REG_r.alu_Action       <= A_NOP;
+            ID2EX_REG_r.alu_Op1          <= ALU_IN_ZERO;
+            ID2EX_REG_r.alu_Op2          <= ALU_IN_IMM;
+            ID2EX_REG_r.alu_Cin          <= CIN_ZERO;
+            ID2EX_REG_r.IMM16            <= (OTHERS => '0');
+            ID2EX_REG_r.IMM_Lock         <= '0';
+            ID2EX_REG_r.msr_Action       <= KEEP_CARRY;
+            ID2EX_REG_r.branch_Action    <= NO_BR;
+            ID2EX_REG_r.mem_Action       <= NO_MEM;
+            ID2EX_REG_r.transfer_Size    <= WORD;
+            ID2EX_REG_r.wrb_Action       <= NO_WRB;
+            ID2EX_REG_r.FSL_Test         <= '1';
+            ID2EX_REG_r.FSL_Non_blocking <= '1';
+            ID2EX_REG_r.FSL_Control      <= '0';
+            ID2EX_REG_r.FSL_Atomic       <= '0';
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_EX2IF_REG IS
+        BEGIN
+            EX2IF_REG_r.take_branch   <= '0';
+            EX2IF_REG_r.branch_target <= (OTHERS => '0');
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_EX2MEM_REG IS
+        BEGIN
+            EX2MEM_REG_o.mem_Action  <= NO_MEM;
+            EX2MEM_REG_o.wrb_Action  <= NO_WRB;
+            EX2MEM_REG_o.exeq_result <= (OTHERS => '0');
+            EX2MEM_REG_o.data_rD     <= (OTHERS => '0');
+            EX2MEM_REG_o.byte_Enable <= (OTHERS => '0');
+            EX2MEM_REG_o.wrix_rD     <= (OTHERS => '0');
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_FSL2MEM_REG IS
+        BEGIN
+            S_Data_r  <= (OTHERS => '0');
+            S_Data_2r <= (OTHERS => '0');
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_IMM_LOCK IS
+        BEGIN
+            IMM_LOCK_r.locked   <= '0';
+            IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_MSR IS
+        BEGIN
+            MSR_o.IE  <= '0';
+            MSR_o.C   <= '0';
+            MSR_o.FSL <= '0';
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_EX_WRB IS
+        BEGIN
+            EX_WRB_o.wrb_Action <= NO_WRB;
+            EX_WRB_o.wrix_rD    <= (OTHERS => '0');
+            EX_WRB_o.data_rD    <= (OTHERS => '0');
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_HAZARD_WRB IS
+        BEGIN
+            HAZARD_WRB_r.hazard  <= '0';
+            HAZARD_WRB_r.save_rX <= NO_SAVE;
+            HAZARD_WRB_r.data_rX <= (OTHERS => '0');
+            HAZARD_WRB_r.data_rD <= (OTHERS => '0');
+        END PROCEDURE;
+
+        PROCEDURE lp_rst_MEM_REG IS
+        BEGIN
+            MEM_REG_o.wrb_Action  <= NO_WRB;
+            MEM_REG_o.exeq_result <= (OTHERS => '0');
+            MEM_REG_o.byte_Enable <= (OTHERS => '0');
+            MEM_REG_o.wrix_rD     <= (OTHERS => '0');
+        END PROCEDURE;
+
+    BEGIN
+        IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) THEN
+            rst_r <= rst_i;
+            IF (reset_s = '1') THEN     -- synchronous reset ...
+                lp_rst_IF2ID_REG;       -- ... so lasts at least one clock_cycle
+                lp_rst_MSR;
+                lp_rst_HAZARD_WRB;
+                lp_rst_MEM_REG;
+                lp_rst_FSL2MEM_REG;
+                delayBit_r    <= '0';
+                flush_ID2EX_r <= '0';
+                setup_int_r   <= '0';
+                int_busy_r    <= '0';
+                done_o        <= '0';
+                ID2EX_REG_r.program_counter <= (OTHERS => '0');
+            ELSE
+                IF (clken_pipe_s = '1') THEN
+                    IF2ID_REG_o <= IF2ID_REG_i;
+                END IF;
+                flush_ID2EX_r <= flush_ID2EX_s;
+                HAZARD_WRB_r  <= HAZARD_WRB_i;
+                MEM_REG_o     <= MEM_REG_i;
+                int_busy_r    <= ID2CTRL_i.int_busy;
+            END IF;
+            -- decode-to-exeq unit registers
+            IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
+                lp_rst_ID2EX_REG;
+                delayBit_r <= '0';
+            -- check for the need and possibility to handle active interrupt requests
+            ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND
+                        (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND
+                -- pending branch should be taken before interrupt can be executed
+                -- dectected by Matthis Meier, TU Dortmund (Sept 2012)
+                            (EX2IF_REG_i.take_branch = '0') AND
+                                (delayBit_r = '0') AND
+                                    (IMM_LOCK_i.locked = '0') AND
+                                        (HAZARD_WRB_i.hazard = '0')) THEN
+                setup_int_r <= '1';
+                ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
+                lp_rst_ID2EX_REG;
+            ELSIF (clken_pipe_s = '1') THEN
+                setup_int_r <= '0';
+                ID2EX_REG_r <= ID2EX_REG_i;
+                delayBit_r  <= ID2CTRL_i.delayBit;
+            END IF;
+            -- exeq-to-mem unit registers
+            IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
+                lp_rst_EX2IF_REG;
+                lp_rst_EX2MEM_REG;
+                lp_rst_EX_WRB;
+                lp_rst_IMM_LOCK;
+                delayBit_2r <= '0';
+            ELSE
+                IF (clken_pipe_s = '1') THEN
+                    EX2IF_REG_r <= EX2IF_REG_i;
+                    delayBit_2r <= delayBit_r;
+                    EX_WRB_o    <= EX_WRB_i;
+                    S_Data_2r   <= S_Data_r;
+                    S_Data_r    <= FSL_S2MEM_REG_i.S_Data;
+                END IF;
+                IF (clken_s = '1') THEN
+                    -- next test to prevent a flush from disrupting
+                    -- the write-back pipeline
+                    IF (flush_ID2EX_r = '0') THEN
+                        EX2MEM_REG_o <= EX2MEM_REG_i;
+                    END IF;
+                    IMM_LOCK_r <= IMM_LOCK_i;
+                    MSR_o      <= MSR_i;
+                END IF;
+            END IF;
+            -- check on End-Of-Program viz. "bri 0x00"
+            -- use delayBit to distinguish between "bri" and "rtsd/rtid"
+            IF ((ID2EX_REG_r.branch_Action = BR) AND
+                    (ID2EX_REG_r.alu_Op2 = ALU_IN_IMM) AND
+                        (ID2EX_REG_r.IMM16 = C_16_ZEROS) AND
+                            (delayBit_r = '0') AND (flush_EX2MEM_s = '0')) THEN
+                done_o <= '1';
+            END IF;
+        END IF;     -- rising edge clk_i ...
+    END PROCESS regd_proc;
+
+END ARCHITECTURE rtl;
diff --git a/hw/decode.vhd b/hw/decode.vhd
new file mode 100644 (file)
index 0000000..bee212b
--- /dev/null
@@ -0,0 +1,358 @@
+---------------------------------------------------------------------------------
+--
+--  Entity:       decode
+--  Filename:     decode.vhd
+--  Description:  the Instruction Decode (ID) unit for
+--                the TUD MB-Lite implementation
+--
+--  Author:       Huib Lincklaen Arriens
+--                Delft University of Technology
+--                Faculty EEMCS, Department ME&CE, Circuits and Systems
+--  Date:         September, 2010
+--                     June, 2011: added code for MUL and BARREL (Huib)
+--  Modified:
+--  Remarks:
+--
+--------------------------------------------------------------------------------
+
+LIBRARY IEEE;
+
+USE IEEE.std_logic_1164.all;
+USE WORK.mbl_Pkg.all;
+
+
+--------------------------------------------------------------------------------
+ENTITY decode IS
+--------------------------------------------------------------------------------
+    GENERIC (
+        USE_HW_MUL_g : BOOLEAN := FALSE;
+        USE_BARREL_g : BOOLEAN := FALSE
+        );
+    PORT (
+        IF2ID_i     :  IN IF2ID_Type;
+        imem_data_i :  IN STD_LOGIC_VECTOR (31 DOWNTO 0);
+        --
+        ID2GPRF_o   : OUT ID2GPRF_Type;
+        ID2EX_o     : OUT ID2EX_Type;
+        --
+        INT_CTRL_i  :  IN INT_CTRL_Type;
+        ID2CTRL_o   : OUT ID2CTRL_Type
+        );
+END ENTITY decode;
+
+
+--------------------------------------------------------------------------------
+ARCHITECTURE rtl OF decode IS
+--------------------------------------------------------------------------------
+
+    SIGNAL noLiteOpc_s : STD_LOGIC;
+
+BEGIN
+
+p_decode:
+    PROCESS (IF2ID_i, imem_data_i, INT_CTRL_i) IS
+
+        VARIABLE prog_counter_v  : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE opcIx_v         : STD_LOGIC_VECTOR ( 5 DOWNTO 0);
+        VARIABLE instruction_v   : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE rD_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        VARIABLE rA_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        VARIABLE rB_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        VARIABLE IMM16_v         : STD_LOGIC_VECTOR (15 DOWNTO 0);
+        VARIABLE FSL_Mode_v      : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        VARIABLE code_x26_v      : STD_LOGIC_VECTOR ( 2 DOWNTO 0);
+        VARIABLE IMM_Lock_v      : STD_LOGIC;
+        VARIABLE alu_Action_v    : ALU_ACTION_Type;
+        VARIABLE alu_Op1_v       : ALU_IN1_Type;
+        VARIABLE alu_Op2_v       : ALU_IN2_Type;
+        VARIABLE alu_Cin_v       : ALU_CIN_Type;
+        VARIABLE msr_Action_v    : MSR_ACTION_Type;
+        VARIABLE branch_Action_v : BRANCH_ACTION_Type;
+        VARIABLE delayBit_v      : STD_LOGIC;
+        VARIABLE mem_Action_v    : MEM_ACTION_Type;
+        VARIABLE transfer_Size_v : TRANSFER_SIZE_Type;
+        VARIABLE wrb_Action_v    : WRB_ACTION_Type;
+        VARIABLE int_busy_v      : STD_LOGIC;
+
+    BEGIN
+        prog_counter_v  := IF2ID_i.program_counter;
+        instruction_v   := imem_data_i;
+        opcIx_v         := instruction_v (31 DOWNTO 26);
+        rD_v            := instruction_v (25 DOWNTO 21);
+        rA_v            := instruction_v (20 DOWNTO 16);
+        rB_v            := instruction_v (15 DOWNTO 11);
+        IMM16_v         := instruction_v (15 DOWNTO  0);
+        IMM_Lock_v      := '0';
+        delayBit_v      := '0';
+        alu_Cin_v       := CIN_ZERO;
+        alu_Action_v    := A_NOP;
+        msr_Action_v    := KEEP_CARRY;
+        branch_Action_v := NO_BR;
+        mem_Action_v    := NO_MEM;
+        transfer_Size_v := WORD;
+        wrb_Action_v    := WRB_EX;
+        FSL_Mode_v      := "01010";
+        -- for decoding SEXT16, SEXT8, SRC, SRC or SRL
+        code_x26_v      := instruction_v(6) & instruction_v(5) & instruction_v(0);
+        int_busy_v      := INT_CTRL_i.int_busy;
+        -- for debugging purposes
+        noLiteOpc_s     <= '0';
+
+        IF (INT_CTRL_i.setup_int = '1') THEN
+
+            alu_Op1_v       := ALU_IN_ZERO;
+            alu_Op2_v       := ALU_IN_IMM;
+            IMM16_v         := X"0010";                 -- address of _interrupt_handler vector
+            prog_counter_v  := INT_CTRL_i.rti_target;   -- delayed program counter
+            alu_Action_v    := A_ADD;
+            rD_v            := "01110";                 -- r14 reserved for storing program_counter
+            rA_v            := (OTHERS => '0');         -- also set rA and rB to avoid possible ...
+            rB_v            := (OTHERS => '0');         -- ... erronuous hazard detection in exeq module
+            int_busy_v      := '1';
+            branch_Action_v := BRL;
+
+        ELSE
+
+            alu_Op1_v := ALU_IN_REGA;
+            IF (opcIx_v(3) = '0') THEN
+                alu_Op2_v := ALU_IN_REGB;
+            ELSE
+                alu_Op2_v := ALU_IN_IMM;
+            END IF;
+
+            CASE opcIx_v (5 DOWNTO 4) IS
+
+                WHEN "00" =>                                            -- ADD / RSUB / CMP
+                    IF (opcIx_v(0) = '1') THEN                          -- RSUB / CMP
+                        alu_Op1_v := ALU_IN_NOT_REGA;
+                    END IF;
+                    IF (opcIx_v(1) = '0') THEN                          -- xxx
+                        IF (opcIx_v(0) = '0') THEN
+                            alu_Cin_v := CIN_ZERO;
+                        ELSE
+                            alu_Cin_v := CIN_ONE;
+                        END IF;
+                    ELSE                                                -- xxxC
+                        alu_Cin_v := FROM_MSR;
+                    END IF;
+                    IF ((opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
+                    -- special CMP(U) and not RSUB(I)K
+                        IF (IMM16_v(1) = '1') THEN                        -- U-bit set, CMPU
+                            alu_Action_v := A_CMPU;
+                        ELSE
+                            alu_Action_v := A_CMP;
+                        END IF;
+                    ELSE
+                        alu_Action_v := A_ADD;
+                        IF (opcIx_v(2) = '0') THEN
+                            msr_Action_v := UPDATE_CARRY;
+                        END IF;
+                    END IF;
+
+                WHEN "01" =>                                            -- MUL / BS / FSL
+                    CASE opcIx_v (2 DOWNTO 0) IS
+                        WHEN "000" =>                                   -- MUL
+                            IF (USE_HW_MUL_g = TRUE) THEN
+                                alu_Action_v := A_MUL;
+                            ELSE
+                                noLiteOpc_s <= '1';
+                            END IF;
+                        WHEN "001" =>                                   -- BS
+                            IF (USE_BARREL_g = TRUE) THEN
+                                IF (instruction_v(10) = '1') THEN
+                                    alu_Action_v := A_BSLL;
+                                ELSE
+                                    IF (instruction_v(9) = '1') THEN
+                                        alu_Action_v := A_BSRA;
+                                    ELSE
+                                        alu_Action_v := A_BSRL;
+                                    END IF;
+                                END IF;
+                            ELSE
+                                noLiteOpc_s <= '1';
+                            END IF;
+                        WHEN "011" =>                                   -- FSL
+                            IF (opcIx_v(3) = '0') THEN
+                                FSL_Mode_v := instruction_v(10 DOWNTO  6);
+                            ELSE
+                                FSL_Mode_v := instruction_v(15 DOWNTO 11);
+                            END IF;
+                            IF (FSL_Mode_v(4) = '0') THEN
+                                alu_Action_v := A_FSL_GET;
+                                wrb_Action_v := WRB_FSL;
+                            ELSE
+                                alu_Action_v := A_FSL_PUT;
+                                wrb_Action_v := NO_WRB;
+                            END IF;
+                            msr_Action_v := UPDATE_CARRY;
+                        WHEN OTHERS =>
+                            noLiteOpc_s <= '1';
+                    END CASE;
+
+                WHEN "10" =>
+                    IF (opcIx_v (3 DOWNTO 0) = "0100") THEN
+                        CASE code_x26_v IS
+                            WHEN "001" | "011" | "101" =>
+                                CASE code_x26_v(2 DOWNTO 1) IS
+                                    WHEN "00" =>                        -- SRA
+                                        alu_Cin_v := FROM_IN1;
+                                    WHEN "01" =>                        -- SRC
+                                        alu_Cin_v := FROM_MSR;
+                                    WHEN "10" =>                        -- SRL
+                                        alu_Cin_v := CIN_ZERO;
+                                    WHEN OTHERS =>
+                                        noLiteOpc_s <= '1';
+                                END CASE;
+                                alu_Action_v := A_SHIFT;
+                                msr_Action_v := UPDATE_CARRY;
+                            WHEN "110" =>                               -- SEXT8
+                                alu_Action_v := A_SEXT8;
+                            WHEN "111" =>                               -- SEXT16
+                                alu_Action_v := A_SEXT16;
+                            WHEN OTHERS  =>
+                                noLiteOpc_s  <= '1';
+                        END CASE;
+                    ELSIF (opcIx_v (3 DOWNTO 0) = "1100") THEN          -- IMM
+                        IMM_Lock_v   := '1';
+                        -- always: IMM_LOCK_o.IMM16 <= IMM16_v;
+                        alu_Action_v := A_NOP;
+                        wrb_Action_v := NO_WRB;
+                    ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN
+                        CASE rD_v IS
+                            WHEN "10001" =>                             -- RTID
+                                int_busy_v := '0';
+                            WHEN "10000" =>                             -- RTSD
+--                          WHEN "10010" =>                             -- RTBD
+--                          WHEN "10100" =>                             -- RTED
+                            WHEN OTHERS  =>
+                                noLiteOpc_s <= '1';
+                        END CASE;
+                        alu_Action_v    := A_ADD;
+                        branch_Action_v := BR;
+                        wrb_Action_v    := NO_WRB;
+                        delayBit_v      := '1';
+                    ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN
+                        CASE IMM16_v IS
+                            WHEN X"8001" =>                             -- MFS (MSR only)
+                                alu_Action_v := A_MFS;
+                            WHEN X"C001" =>                             -- MTS (MSR only)
+                                alu_Action_v := A_MTS;
+                                wrb_Action_v := NO_WRB;
+                            WHEN OTHERS  =>
+                                noLiteOpc_s  <= '1';
+                        END CASE;
+                        rB_v := (OTHERS => '0');    -- in order to prevent occasional hazards (r16, r24)
+                    ELSE
+                        CASE opcIx_v (2 DOWNTO 0) IS
+                            WHEN "000" =>
+                                alu_Action_v := A_OR;
+                            WHEN "001" =>
+                                alu_Action_v := A_AND;
+                            WHEN "010" =>
+                                alu_Action_v := A_XOR;
+                            WHEN "011" =>
+                                alu_Action_v := A_AND;
+                                IF (opcIx_v(3) = '0') THEN
+                                    alu_Op2_v := ALU_IN_NOT_REGB;
+                                ELSE
+                                    alu_Op2_v := ALU_IN_NOT_IMM;
+                                END IF;
+                            WHEN "110" =>                               -- BR(I)
+                                IF (rA_v(2) = '1') THEN
+                                    branch_Action_v := BRL;
+                                ELSE
+                                    branch_Action_v := BR;
+                                    wrb_Action_v    := NO_WRB;
+                                END IF;
+                                IF (rA_v(3) = '1') THEN
+                                    alu_Op1_v := ALU_IN_ZERO;
+                                ELSE
+                                    alu_Op1_v := ALU_IN_PC;
+                                END IF;
+                                IF (rA_v(4) = '1') THEN
+                                    delayBit_v  := '1';
+                                END IF;
+                                alu_Action_v    := A_ADD;
+                            WHEN "111" =>
+                                CASE rD_v(3 DOWNTO 0) IS
+                                    WHEN "0000" =>                      -- BEQ
+                                        branch_Action_v := BEQ;
+                                    WHEN "0001" =>                      -- BNE
+                                        branch_Action_v := BNE;
+                                    WHEN "0010" =>                      -- BLT
+                                        branch_Action_v := BLT;
+                                    WHEN "0011" =>                      -- BLE
+                                        branch_Action_v := BLE;
+                                    WHEN "0100" =>                      -- BGT
+                                        branch_Action_v := BGT;
+                                    WHEN "0101" =>                      -- BGE
+                                        branch_Action_v := BGE;
+                                    WHEN OTHERS =>
+                                        noLiteOpc_s <= '1';
+                                END CASE;
+                                alu_Action_v := A_ADD;
+                                alu_Op1_v    := ALU_IN_PC;
+                                delayBit_v   := rD_v(4);
+                            wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
+                            WHEN OTHERS =>
+                                noLiteOpc_s  <= '1';
+                        END CASE;
+                    END IF;
+
+                WHEN "11" =>
+                    alu_Action_v :=  A_ADD;
+                    CASE opcIx_v (1 DOWNTO 0) IS
+                        WHEN "00"   => transfer_Size_v := BYTE;
+                        WHEN "01"   => transfer_Size_v := HALFWORD;
+                        WHEN "10"   => transfer_Size_v := WORD;
+                        WHEN OTHERS =>
+                            noLiteOpc_s <= '1';
+                    END CASE;
+                    IF (opcIx_v(2) = '0') THEN
+                        mem_Action_v := RD_MEM;
+                        wrb_Action_v := WRB_MEM;
+                    ELSE
+                        mem_Action_v := WR_MEM;
+                        wrb_Action_v := NO_WRB;
+                    END IF;
+
+                WHEN OTHERS =>
+                    noLiteOpc_s  <= '1';
+
+            END CASE;
+
+        END IF;         -- interrupt test
+
+        ID2GPRF_o.rdix_rA  <= rA_v;
+        ID2GPRF_o.rdix_rB  <= rB_v;
+        ID2GPRF_o.rdix_rD  <= rD_v;
+
+        ID2EX_o.program_counter  <= prog_counter_v;
+        ID2EX_o.rdix_rA          <= rA_v;
+        ID2EX_o.rdix_rB          <= rB_v;
+        ID2EX_o.curr_rD          <= rD_v;
+        ID2EX_o.alu_Action       <= alu_Action_v;
+        ID2EX_o.alu_Op1          <= alu_Op1_v;
+        ID2EX_o.alu_Op2          <= alu_Op2_v;
+        ID2EX_o.alu_Cin          <= alu_Cin_v;
+        ID2EX_o.IMM16            <= IMM16_v;
+        ID2EX_o.IMM_Lock         <= IMM_Lock_v;
+        ID2EX_o.msr_Action       <= msr_Action_v;
+        ID2EX_o.branch_Action    <= branch_Action_v;
+        ID2EX_o.mem_Action       <= mem_Action_v;
+        ID2EX_o.transfer_Size    <= transfer_Size_v;
+        ID2EX_o.wrb_Action       <= wrb_Action_v;
+        ID2EX_o.FSL_Non_blocking <= FSL_Mode_v(3);
+        ID2EX_o.FSL_Control      <= FSL_Mode_v(2);
+        ID2EX_o.FSL_Test         <= FSL_Mode_v(1);
+        ID2EX_o.FSL_Atomic       <= FSL_Mode_v(0);
+        --
+        ID2CTRL_o.delayBit      <= delayBit_v;
+        ID2CTRL_o.int_busy      <= int_busy_v;
+
+
+
+    END PROCESS;
+
+END ARCHITECTURE rtl;
+
diff --git a/hw/exeq.vhd b/hw/exeq.vhd
new file mode 100644 (file)
index 0000000..da14be3
--- /dev/null
@@ -0,0 +1,442 @@
+---------------------------------------------------------------------------------
+--
+--  Entity:       exeq
+--  Filename:     exeq.vhd
+--  Description:  the Execution (EX) unit for the TUD MB-Lite implementation
+--
+--  Author:       Huib Lincklaen Arriens
+--                Delft University of Technology
+--                Faculty EEMCS, Department ME&CE, Circuits and Systems
+--  Date:         September, 2010
+--
+--  Modified:      December, 2010: FSL added (Huib)
+--                     June, 2011: added code for MUL and BARREL (Huib)
+--                                 Adapted to work with separate fsl_M-
+--                                 and fsl_S selectors and automatic
+--                                 tumbl<_jtag><_fsl>.vhd generation (Huib)
+--  Remarks:
+--
+--------------------------------------------------------------------------------
+
+LIBRARY IEEE;
+
+USE IEEE.std_logic_1164.all;
+USE IEEE.numeric_std.all;
+USE WORK.mbl_Pkg.all;
+
+
+----------------------------------------------------------
+ENTITY exeq IS
+----------------------------------------------------------
+    GENERIC (
+        USE_HW_MUL_g : BOOLEAN := FALSE;
+        USE_BARREL_g : BOOLEAN := FALSE
+        );
+    PORT (
+        ID2EX_i      :  IN ID2EX_Type;
+        GPRF2EX_i    :  IN GPRF2EX_Type;
+        EX2IF_o      : OUT EX2IF_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;
+        --
+        exq_branch_i :  IN STD_LOGIC;
+        --
+        FSL_M2EX_i   :  IN FSL_M2EX_Type;
+        EX2FSL_M_o   : OUT EX2FSL_M_Type;
+        --
+        FSL_S2EX_i   :  IN FSL_S2EX_Type;
+        EX2FSL_S_o   : OUT EX2FSL_S_Type;
+        --
+        FSL_nStall_o : OUT STD_LOGIC
+        );
+END ENTITY exeq;
+
+
+----------------------------------------------------------
+ARCHITECTURE rtl OF exeq IS
+----------------------------------------------------------
+
+BEGIN
+
+p_exeq:
+    PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i,
+                        IMM_LOCK_i, MSR_i, exq_branch_i, FSL_M2EX_i, FSL_S2EX_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_rA_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 FSLx_M_v      : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        VARIABLE FSLx_S_v      : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        VARIABLE FSL_Read_v    : STD_LOGIC;
+        VARIABLE FSL_Write_v   : STD_LOGIC;
+        VARIABLE FSL_nStall_v  : STD_LOGIC;
+        VARIABLE FSL_Atomic_v  : STD_LOGIC;
+        VARIABLE FSL_Error_v   : STD_LOGIC;
+        VARIABLE tmp64_v       : STD_LOGIC_VECTOR (63 DOWNTO 0);
+        VARIABLE padVec_v      : STD_LOGIC_VECTOR (15 DOWNTO 0);
+
+    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";
+        FSLx_M_v      := (OTHERS => '0');
+        FSLx_S_v      := (OTHERS => '0');
+        FSL_Read_v    := '0';
+        FSL_Write_v   := '0';
+        FSL_nStall_v  := '1';
+        FSL_Atomic_v  := '0';
+        FSL_Error_v   := MSR_i.FSL;
+
+        -- 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;
+
+        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
+                        result_v(31) := NOT signBit_in1_v;
+                    END IF;
+                ELSIF (id2ex_i.alu_Action = A_CMP) THEN
+                    IF (signBit_in1_v = signBit_in2_v) THEN
+                        result_v(31) := signBit_in1_v;
+                    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 & "00" & MSR_i.FSL & '0' & MSR_i.C & MSR_i.IE & '0';
+            WHEN A_MTS     =>
+                MSR_o.IE  <= data_Ra_v(1);
+                MSR_o.C   <= data_Ra_v(2);
+                MSR_o.FSL <= data_Ra_v(4);
+            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_FSL_GET =>
+                -- to be examined here, since FSL instruction treated differently than
+                -- e.g. memory read/writes, i.e. MSR-C and -FSL_E bit have to be set
+                -- depending on input values (exq_branch_i equals EX2IF_r.take_branch, i.e.
+                -- a one clock cycle delayed EX2IF_o.take_branch).
+                IF (exq_branch_i = '0') THEN
+                    FSLx_S_v     := in2_v(3 DOWNTO 0);
+                    FSL_Read_v   := FSL_S2EX_i.S_Exists AND (NOT hazard_v);
+                    FSL_Atomic_v := ID2EX_i.FSL_Atomic;
+                    IF (ID2EX_i.FSL_Non_blocking = '0') THEN
+                        FSL_nStall_v := FSL_Read_v;
+                    ELSE
+                        carry_o_v := NOT FSL_Read_v;
+                        IF ((FSL_Read_v = '1') AND
+                                (ID2EX_i.FSL_Control /= FSL_S2EX_i.S_Control)) THEN
+                            FSL_Error_v := '1';
+                        ELSE
+                            FSL_Error_v := '0';
+                        END IF;
+                    END IF;
+                END IF;
+            WHEN A_FSL_PUT =>
+                FSLx_M_v     := in2_v(3 DOWNTO 0);
+                FSL_Write_v  := NOT (FSL_M2EX_i.M_Full OR hazard_v);
+                FSL_Atomic_v := ID2EX_i.FSL_Atomic;
+                IF (ID2EX_i.FSL_Non_blocking = '0') THEN
+                    FSL_nStall_v := FSL_Write_v;
+                ELSE
+                    carry_o_v := FSL_M2EX_i.M_Full;
+                END IF;
+            WHEN OTHERS    =>
+                NULL;
+        END CASE;
+
+        IF (data_rA_v = C_32_ZEROS) THEN
+            isZero_v := '1';
+        ELSE
+            isZero_v := '0';
+        END IF;
+        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;
+
+        -- 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], MSR[C] and/or MSR[FSL_Error] if needed
+        IF (ID2EX_i.alu_Action /= A_MTS) THEN
+            MSR_o.FSL <= FSL_Error_v;
+            MSR_o.IE  <= MSR_i.IE AND (NOT FSL_Atomic_v);
+            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;
+        --
+        EX2FSL_M_o.FSLx_M    <= FSLx_M_v;
+        EX2FSL_M_o.M_Write   <= FSL_Write_v;
+        EX2FSL_M_o.M_Data    <= data_rA_v;
+        EX2FSL_M_o.M_Control <= ID2EX_i.FSL_Control;
+        --
+        EX2FSL_S_o.FSLx_S    <= FSLx_S_v;
+        EX2FSL_S_o.S_Read    <= FSL_Read_v;
+        --
+        FSL_nStall_o         <= FSL_nStall_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;
+
diff --git a/hw/fetch.vhd b/hw/fetch.vhd
new file mode 100644 (file)
index 0000000..0872293
--- /dev/null
@@ -0,0 +1,54 @@
+---------------------------------------------------------------------------------
+--
+--  Entity:       fetch
+--  Filename:     fetch.vhd
+--  Description:  the Instruction Fetch (IF) unit for
+--                the TUD MB-Lite implementation
+--
+--  Author:       Huib Lincklaen Arriens
+--                Delft University of Technology
+--                Faculty EEMCS, Department ME&CE, Circuits and Systems
+--  Date:         September, 2010
+--  Modified:
+--  Remarks:
+--
+--------------------------------------------------------------------------------
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.all;
+USE WORK.mbl_Pkg.all;
+
+--------------------------------------------------------------------------------
+ENTITY fetch IS
+--------------------------------------------------------------------------------
+    PORT (
+        prog_cntr_i :  IN STD_LOGIC_VECTOR (31 DOWNTO 0);
+        inc_pc_i    :  IN STD_LOGIC;
+        EX2IF_i     :  IN EX2IF_Type;
+        IF2ID_o     : OUT IF2ID_Type
+     );
+END ENTITY fetch;
+
+
+--------------------------------------------------------------------------------
+ARCHITECTURE rtl OF fetch IS
+--------------------------------------------------------------------------------
+
+BEGIN
+
+p_fetch:
+    PROCESS ( prog_cntr_i, inc_pc_i, EX2IF_i )
+        VARIABLE next_pc_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE incVal_v  : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE dummy_v   : STD_LOGIC;
+    BEGIN
+        incVal_v := X"0000000" & '0' & inc_pc_i & "00";
+        ep_add32 ( prog_cntr_i, incVal_v, '0', next_pc_v, dummy_v);
+        IF (EX2IF_i.take_branch = '0') THEN
+            IF2ID_o.program_counter <= next_pc_v;
+        ELSE
+            IF2ID_o.program_counter <= EX2IF_i.branch_target;
+        END IF;
+    END PROCESS;
+
+END ARCHITECTURE rtl;
diff --git a/hw/mbl_Pkg.vhd b/hw/mbl_Pkg.vhd
new file mode 100644 (file)
index 0000000..48e1162
--- /dev/null
@@ -0,0 +1,498 @@
+---------------------------------------------------------------------------------
+--
+--  Package:      mbl_Pkg
+--  Filename:     mbl_Pkg.vhd
+--  Description:  Package for the TUD MB-Lite implementation
+--
+--  Author:       Huib Lincklaen Arriens
+--                Delft University of Technology
+--                Faculty EEMCS, Department ME&CE, Circuits and Systems
+--  Date:         September, 2010
+--
+--  Modified:          June, 2011: ALU_ACTION_Type extended to incorporate
+--                                 MUL and BS instructions (Huib)
+--                                 Adapted to work with separate fsl_M-
+--                                 and fsl_S selectors and automatic
+--                                 tumbl<_jtag><_fsl>.vhd generation (Huib)
+--                     July, 2011: function ef_nbits added (Huib)
+--  Remarks:
+--
+--------------------------------------------------------------------------------
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.all;
+USE IEEE.std_logic_unsigned.all;
+USE IEEE.numeric_std.all;
+
+
+--------------------------------------------------------------------------------
+PACKAGE mbl_Pkg IS
+--------------------------------------------------------------------------------
+
+    CONSTANT  C_8_ZEROS : STD_LOGIC_VECTOR ( 7 DOWNTO 0) :=       X"00";
+    CONSTANT C_16_ZEROS : STD_LOGIC_VECTOR (15 DOWNTO 0) :=     X"0000";
+    CONSTANT C_24_ZEROS : STD_LOGIC_VECTOR (23 DOWNTO 0) :=   X"000000";
+    CONSTANT C_32_ZEROS : STD_LOGIC_VECTOR (31 DOWNTO 0) := X"00000000";
+
+    CONSTANT C_16_ONES  : STD_LOGIC_VECTOR (15 DOWNTO 0) :=     X"FFFF";
+    CONSTANT C_24_ONES  : STD_LOGIC_VECTOR (23 DOWNTO 0) :=   X"FFFFFF";
+
+
+----------------------------------------------------------------------------------------------
+-- TYPE DEFINITIONS
+----------------------------------------------------------------------------------------------
+
+    TYPE ALU_ACTION_Type    IS (A_NOP, A_ADD, A_CMP, A_CMPU, A_OR, A_AND, A_XOR,
+                                        A_SHIFT, A_SEXT8, A_SEXT16, A_MFS, A_MTS,
+                                                    A_MUL, A_BSLL, A_BSRL, A_BSRA,
+                                                             A_FSL_GET, A_FSL_PUT);
+    TYPE ALU_IN1_Type       IS (ALU_IN_REGA, ALU_IN_NOT_REGA, ALU_IN_PC, ALU_IN_ZERO);
+    TYPE ALU_IN2_Type       IS (ALU_IN_REGB, ALU_IN_NOT_REGB, ALU_IN_IMM, ALU_IN_NOT_IMM);
+    TYPE ALU_CIN_Type       IS (CIN_ZERO, CIN_ONE, FROM_MSR, FROM_IN1);
+    TYPE MSR_ACTION_Type    IS (UPDATE_CARRY, KEEP_CARRY);
+    TYPE BRANCH_ACTION_Type IS (NO_BR, BR, BRL, BEQ, BNE, BLT, BLE, BGT, BGE);
+    TYPE WRB_ACTION_Type    IS (NO_WRB, WRB_EX, WRB_MEM, WRB_FSL);
+    TYPE MEM_ACTION_Type    IS (NO_MEM, WR_MEM, RD_MEM);
+    TYPE TRANSFER_SIZE_Type IS (WORD, HALFWORD, BYTE);
+    TYPE SAVE_REG_Type      IS (NO_SAVE, SAVE_RA, SAVE_RB);
+    --
+    TYPE IF2ID_Type IS RECORD
+        program_counter : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    END RECORD;
+
+    TYPE ID2EX_Type IS RECORD
+        program_counter  : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        rdix_rA          : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        rdix_rB          : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        curr_rD          : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        alu_Action       : ALU_ACTION_Type;
+        alu_Op1          : ALU_IN1_Type;
+        alu_Op2          : ALU_IN2_Type;
+        alu_Cin          : ALU_CIN_Type;
+        IMM16            : STD_LOGIC_VECTOR (15 DOWNTO 0);
+        IMM_Lock         : STD_LOGIC;
+        msr_Action       : MSR_ACTION_Type;
+        branch_Action    : BRANCH_ACTION_Type;
+        mem_Action       : MEM_ACTION_Type;         -- rd_mem implies writeback
+        transfer_Size    : TRANSFER_SIZE_Type;
+        wrb_Action       : WRB_ACTION_Type;
+        FSL_Non_blocking : STD_LOGIC;               -- ncta
+        FSL_Control      : STD_LOGIC;
+        FSL_Test         : STD_LOGIC;
+        FSL_Atomic       : STD_LOGIC;
+    END RECORD;
+
+    TYPE ID2GPRF_Type IS RECORD
+        rdix_rA : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        rdix_rB : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        rdix_rD : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+    END RECORD;
+
+    TYPE INT_CTRL_Type IS RECORD
+        setup_int  : STD_LOGIC;
+        rti_target : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        int_busy   : STD_LOGIC;
+    END RECORD;
+
+    TYPE ID2CTRL_Type IS RECORD
+        delayBit : STD_LOGIC;
+        int_busy : STD_LOGIC;
+    END RECORD;
+
+    TYPE GPRF2EX_Type IS RECORD
+        data_rA : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        data_rB : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        data_rD : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    END RECORD;
+
+    TYPE IMM_LOCK_Type IS RECORD
+        locked   : STD_LOGIC;
+        IMM_hi16 : STD_LOGIC_VECTOR (15 DOWNTO 0);
+    END RECORD;
+
+    TYPE MSR_Type IS RECORD
+        IE  : STD_LOGIC;        -- MSR[VHDL b1] = [MicroBlaze b30]
+        C   : STD_LOGIC;        -- MSR[VHDL b2 and b31] = [MicroBlaze b29 and b0]
+        FSL : STD_LOGIC;        -- MSR[VHDL b4] = [MicroBlaze b27]
+    END RECORD;
+
+    TYPE EX2IF_Type IS RECORD
+        take_branch   : STD_LOGIC;
+        branch_target : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    END RECORD;
+
+    TYPE EX2MEM_Type IS RECORD
+        mem_Action      : MEM_ACTION_Type;                  -- RD_MEM implies writeback
+        wrb_Action      : WRB_ACTION_Type;
+        exeq_result     : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        data_rD         : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        byte_Enable     : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        wrix_rD         : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+    END RECORD;
+
+    TYPE WRB_Type IS RECORD
+        wrb_Action : WRB_ACTION_Type;
+        wrix_rD    : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        data_rD    : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    END RECORD;
+
+    TYPE HAZARD_WRB_Type IS RECORD
+        hazard  : STD_LOGIC;
+        save_rX : SAVE_REG_Type;
+        data_rX : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        data_rD : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    END RECORD;
+
+    TYPE EX2FSL_M_Type IS RECORD
+        FSLx_M    : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        M_Write   : STD_LOGIC;
+        M_Data    : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        M_Control : STD_LOGIC;
+    END RECORD;
+
+    TYPE FSL_M2EX_Type IS RECORD
+        M_Full    : STD_LOGIC;
+    END RECORD;
+
+    TYPE EX2FSL_S_Type IS RECORD
+        FSLx_S    : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        S_Read    : STD_LOGIC;
+    END RECORD;
+
+    TYPE FSL_S2EX_Type IS RECORD
+        S_Control : STD_LOGIC;
+        S_Exists  : STD_LOGIC;
+    END RECORD;
+
+    TYPE FSL_S2MEM_Type IS RECORD
+        S_Data    : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    END RECORD;
+
+    TYPE MEM_REG_Type IS RECORD
+        wrb_Action  : WRB_ACTION_Type;
+        exeq_result : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        byte_Enable : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        wrix_rD     : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+    END RECORD;
+
+    TYPE MEM2CTRL_Type IS RECORD
+        clken : STD_LOGIC;
+        int   : STD_LOGIC;
+    END RECORD;
+
+    TYPE CORE2DMEMB_Type IS RECORD
+        ena   : STD_LOGIC;
+        addr  : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        bSel  : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        wre   : STD_LOGIC;
+        data  : STD_LOGIC_VECTOR (31 DOWNTO 0);
+    END RECORD;
+
+    TYPE DMEMB2CORE_Type IS RECORD
+        clken : STD_LOGIC;
+        data  : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        int   : STD_LOGIC;
+    END RECORD;
+
+    TYPE MEMORY_MAP_Type IS ARRAY(NATURAL RANGE <>) OF STD_LOGIC_VECTOR (31 DOWNTO 0);
+    -- NOTE: Use the named association format  xxxx := ( 0 => X"A0010000" );
+    --       in case the array has to contain only one element !!
+
+    TYPE CORE2FSL_M_Type IS RECORD
+        -- connect M_Clk directly to highest level clock
+        M_Write   : STD_LOGIC;
+        M_Data    : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        M_Control : STD_LOGIC;
+    END RECORD;
+
+    TYPE FSL_M2CORE_Type IS RECORD
+        M_Full    : STD_LOGIC;
+    END RECORD;
+
+    TYPE CORE2FSL_S_Type IS RECORD
+        -- connect S_Clk directly to highest level clock
+        S_Read    : STD_LOGIC;
+    END RECORD;
+
+    TYPE FSL_S2CORE_Type IS RECORD
+        S_Exists  : STD_LOGIC;
+        S_Data    : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        S_Control : STD_LOGIC;
+    END RECORD;
+
+    TYPE CORE2FSL_M_ARRAY_Type IS ARRAY(NATURAL RANGE <>) OF CORE2FSL_M_Type;
+    TYPE FSL_M2CORE_ARRAY_Type IS ARRAY(NATURAL RANGE <>) OF FSL_M2CORE_Type;
+    TYPE CORE2FSL_S_ARRAY_Type IS ARRAY(NATURAL RANGE <>) OF CORE2FSL_S_Type;
+    TYPE FSL_S2CORE_ARRAY_Type IS ARRAY(NATURAL RANGE <>) OF FSL_S2CORE_Type;
+
+
+----------------------------------------------------------------------------------------------
+-- COMPONENTS
+----------------------------------------------------------------------------------------------
+
+    COMPONENT fetch IS
+        PORT (
+            prog_cntr_i :  IN STD_LOGIC_VECTOR (31 DOWNTO 0);
+            inc_pc_i    :  IN STD_LOGIC;
+            EX2IF_i     :  IN EX2IF_Type;
+            IF2ID_o     : OUT IF2ID_Type
+            );
+    END COMPONENT;
+
+    COMPONENT 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
+            );
+    END COMPONENT;
+
+    COMPONENT adder IS
+        GENERIC (
+            DW_g : POSITIVE := 32;
+            LW_g : POSITIVE := 15
+        );
+        PORT (
+            in1  :  IN STD_LOGIC_VECTOR (DW_g-1 DOWNTO 0);
+            in2  :  IN STD_LOGIC_VECTOR (DW_g-1 DOWNTO 0);
+            cin  :  IN STD_LOGIC;
+            sum  : OUT STD_LOGIC_VECTOR (DW_g-1 DOWNTO 0);
+            cout : OUT STD_LOGIC
+            );
+    END COMPONENT;
+
+    COMPONENT exeq IS
+        GENERIC (
+            USE_HW_MUL_g : BOOLEAN := FALSE;
+            USE_BARREL_g : BOOLEAN := FALSE
+            );
+        PORT (
+            ID2EX_i      :  IN ID2EX_Type;
+            GPRF2EX_i    :  IN GPRF2EX_Type;
+            EX2IF_o      : OUT EX2IF_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;
+            --
+            exq_branch_i :  IN STD_LOGIC;
+            --
+            FSL_M2EX_i   :  IN FSL_M2EX_Type;
+            EX2FSL_M_o   : OUT EX2FSL_M_Type;
+            --
+            FSL_S2EX_i   :  IN FSL_S2EX_Type;
+            EX2FSL_S_o   : OUT EX2FSL_S_Type;
+            --
+            FSL_nStall_o : OUT STD_LOGIC
+            );
+    END COMPONENT;
+
+    COMPONENT mem IS
+        PORT (
+            EX2MEM_i    :  IN EX2MEM_Type;
+            --
+            DMEMB_i     :  IN DMEMB2CORE_Type;
+            DMEMB_o     : OUT CORE2DMEMB_Type;
+            --
+            FSL_S2MEM_i :  IN FSL_S2MEM_Type;
+            --
+            MEM_REG_i   :  IN MEM_REG_Type;
+            MEM_REG_o   : OUT MEM_REG_Type;
+            --
+            MEM_WRB_o   : OUT WRB_Type;
+            MEM2CTRL_o  : OUT MEM2CTRL_Type
+            );
+    END COMPONENT;
+
+    COMPONENT core_ctrl IS
+        PORT (
+            clk_i           :  IN STD_LOGIC;
+            rst_i           :  IN STD_LOGIC;
+    --      halt_i          :  IN STD_LOGIC;
+            int_i           :  IN STD_LOGIC;
+            -- specific fetch i/o
+            imem_addr_o     : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
+            imem_clken_o    : OUT STD_LOGIC;
+            pc_ctrl_o       : OUT STD_LOGIC;
+            -- fetch to decode pipeline registers
+            IF2ID_REG_i     :  IN IF2ID_Type;
+            IF2ID_REG_o     : OUT IF2ID_Type;
+            -- decode to exeq pipeline registers
+            ID2EX_REG_i     :  IN ID2EX_Type;
+            ID2EX_REG_o     : OUT ID2EX_Type;
+            -- GPRF control
+            gprf_clken_o    : OUT STD_LOGIC;
+            -- exeq to fetch feedback registers
+            EX2IF_REG_i     :  IN EX2IF_Type;
+            EX2IF_REG_o     : OUT EX2IF_Type;
+            -- exeq to mem pipeline registers
+            EX2MEM_REG_i    :  IN EX2MEM_Type;
+            EX2MEM_REG_o    : OUT EX2MEM_Type;
+            -- mem pipeline register
+            MEM_REG_i       :  IN MEM_REG_Type;
+            MEM_REG_o       : OUT MEM_REG_Type;
+            -- decode control i/o
+            ID2CTRL_i       :  IN ID2CTRL_Type;
+            INT_CTRL_o      : OUT INT_CTRL_Type;
+            -- FSL to mem data delay register(s)
+            FSL_S2MEM_REG_i :  IN FSL_S2MEM_Type;
+            FSL_S2MEM_REG_o : OUT FSL_S2MEM_Type;
+            -- exeq control i/o
+            EX_WRB_i        :  IN WRB_Type;
+            EX_WRB_o        : OUT WRB_Type;
+            -- data hazard i/o
+            HAZARD_WRB_i    :  IN HAZARD_WRB_Type;
+            HAZARD_WRB_o    : OUT HAZARD_WRB_Type;
+            -- for handling the 'IMM' instruction
+            IMM_LOCK_i      :  IN IMM_LOCK_Type;
+            IMM_LOCK_o      : OUT IMM_LOCK_Type;
+            -- for handling the Machine Status Register
+            MSR_i           :  IN MSR_Type;
+            MSR_o           : OUT MSR_Type;
+            -- miscellaneous
+            MEM2CTRL_i      :  IN MEM2CTRL_Type;
+            FSL_nStall_i    :  IN STD_LOGIC;
+            done_o          : OUT STD_LOGIC
+            );
+    END COMPONENT;
+
+    COMPONENT fsl_M_selector IS
+        GENERIC (
+            N_FSL_M_g : POSITIVE RANGE 1 TO 16 :=  1    -- 1 upto 16
+            );
+        PORT (
+            EX2FSL_M_i    :  IN EX2FSL_M_Type;
+            FSL_M2EX_o    : OUT FSL_M2EX_Type;
+            --
+            FSL_M_ARRAY_i :  IN FSL_M2CORE_ARRAY_Type (0 TO N_FSL_M_g -1);
+            FSL_M_ARRAY_o : OUT CORE2FSL_M_ARRAY_Type (0 TO N_FSL_M_g -1)
+            );
+    END COMPONENT;
+
+    COMPONENT fsl_S_selector IS
+        GENERIC (
+            N_FSL_S_g : POSITIVE RANGE 1 TO 16 :=  1    -- 1 upto 16
+            );
+        PORT (
+            EX2FSL_S_i    :  IN EX2FSL_S_Type;
+            FSL_S2EX_o    : OUT FSL_S2EX_Type;
+            FSL_S2MEM_o   : OUT FSL_S2MEM_Type;
+            --
+            FSL_S_ARRAY_i :  IN FSL_S2CORE_ARRAY_Type (0 TO N_FSL_S_g -1);
+            FSL_S_ARRAY_o : OUT CORE2FSL_S_ARRAY_Type (0 TO N_FSL_S_g -1)
+            );
+    END COMPONENT;
+
+----------------------------------------------------------------------------------------------
+-- FUNCTION, PROCEDURE DECLARATIONS
+----------------------------------------------------------------------------------------------
+
+    PROCEDURE ep_add32 ( a, b :  IN STD_LOGIC_VECTOR (31 DOWNTO 0);
+                         ci   :  IN STD_LOGIC;
+                         VARIABLE s  : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
+                         VARIABLE co : OUT STD_LOGIC );
+
+--  PROCEDURE ep_add32 ( a, b : IN STD_LOGIC_VECTOR; ci : IN STD_LOGIC;
+--                       VARIABLE s  : OUT STD_LOGIC_VECTOR;
+--                       VARIABLE co : OUT STD_LOGIC );
+
+    FUNCTION ef_nbits ( value : NATURAL ) RETURN POSITIVE;
+
+END PACKAGE mbl_Pkg;
+
+
+----------------------------------------------------------
+PACKAGE BODY mbl_Pkg IS
+----------------------------------------------------------
+
+    PROCEDURE ep_add32 (        a, b :  IN STD_LOGIC_VECTOR (31 DOWNTO 0);
+                                ci   :  IN STD_LOGIC;
+                         VARIABLE s  : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
+                         VARIABLE co : OUT STD_LOGIC ) IS
+
+        CONSTANT NBITS_LO_c : POSITIVE := 17;
+        CONSTANT NBITS_HI_c : POSITIVE := 32 -NBITS_LO_c;
+        VARIABLE tmp_lo_v   : STD_LOGIC_VECTOR (NBITS_LO_c +1 DOWNTO 0);
+        VARIABLE tmp_hi0_v  : STD_LOGIC_VECTOR (NBITS_HI_c +1 DOWNTO 0);
+        VARIABLE tmp_hi1_v  : STD_LOGIC_VECTOR (NBITS_HI_c +1 DOWNTO 0);
+    BEGIN
+        tmp_lo_v  := STD_LOGIC_VECTOR( UNSIGNED( '0' & a(NBITS_LO_c -1 DOWNTO  0) & '1' ) +
+                                       UNSIGNED( '0' & b(NBITS_LO_c -1 DOWNTO  0) & ci  ));
+        tmp_hi0_v := STD_LOGIC_VECTOR( UNSIGNED( '0' & a(31 DOWNTO (32 - NBITS_HI_c)) & '1') +
+                                       UNSIGNED( '0' & b(31 DOWNTO (32 - NBITS_HI_c)) & '0'));
+        tmp_hi1_v := STD_LOGIC_VECTOR( UNSIGNED( '0' & a(31 DOWNTO (32 - NBITS_HI_c)) & '1') +
+                                       UNSIGNED( '0' & b(31 DOWNTO (32 - NBITS_HI_c)) & '1'));
+        IF (tmp_lo_v(NBITS_LO_c +1) = '0') THEN
+            s  := tmp_hi0_v(NBITS_HI_c DOWNTO 1) & tmp_lo_v(NBITS_LO_c DOWNTO 1);
+            co := tmp_hi0_v(NBITS_HI_c +1);
+        ELSE
+            s  := tmp_hi1_v(NBITS_HI_c DOWNTO 1) & tmp_lo_v(NBITS_LO_c DOWNTO 1);
+            co := tmp_hi1_v(NBITS_HI_c +1);
+        END IF;
+    END PROCEDURE;
+
+--  PROCEDURE ep_add32 ( a, b : IN STD_LOGIC_VECTOR; ci : IN STD_LOGIC;
+--                       VARIABLE s  : OUT STD_LOGIC_VECTOR;
+--                       VARIABLE co : OUT STD_LOGIC ) IS
+--        VARIABLE tmp_lo_v  : STD_LOGIC_VECTOR (a'LENGTH/2 +1 DOWNTO 0);
+--        VARIABLE tmp_hi0_v : STD_LOGIC_VECTOR (a'LENGTH/2 +1 DOWNTO 0);
+--        VARIABLE tmp_hi1_v : STD_LOGIC_VECTOR (a'LENGTH/2 +1 DOWNTO 0);
+--    BEGIN
+--      tmp_lo_v  := STD_LOGIC_VECTOR( UNSIGNED( '0' & a(a'LENGTH/2 -1 DOWNTO  0) & '1' ) +
+--                                     UNSIGNED( '0' & b(a'LENGTH/2 -1 DOWNTO  0) & ci  ));
+--      tmp_hi0_v := STD_LOGIC_VECTOR( UNSIGNED( '0' & a(a'LENGTH -1 DOWNTO a'LENGTH/2) & '1') +
+--                                     UNSIGNED( '0' & b(a'LENGTH -1 DOWNTO a'LENGTH/2) & '0'));
+--      tmp_hi1_v := STD_LOGIC_VECTOR( UNSIGNED( '0' & a(a'LENGTH -1 DOWNTO a'LENGTH/2) & '1') +
+--                                     UNSIGNED( '0' & b(a'LENGTH -1 DOWNTO a'LENGTH/2) & '1'));
+--      IF (tmp_lo_v(a'LENGTH/2 +1) = '0') THEN
+--          s  := tmp_hi0_v(a'LENGTH/2 DOWNTO 1) & tmp_lo_v(a'LENGTH/2 DOWNTO 1);
+--          co := tmp_hi0_v(a'LENGTH/2 +1);
+--      ELSE
+--          s  := tmp_hi1_v(a'LENGTH/2 DOWNTO 1) & tmp_lo_v(a'LENGTH/2 DOWNTO 1);
+--          co := tmp_hi1_v(a'LENGTH/2 +1);
+--      END IF;
+--  END PROCEDURE;
+
+--  Function ef_nbits returns the minimum number of binary bits to represent
+--  a value N with:
+--  so N =  0,1       NBITS = 1
+--     N =  2,3       NBITS = 2
+--     N =  4,5,6,7   NBITS = 3
+--     N =  8..15     NBITS = 4
+--     N = 16..31     NBITS = 5
+--       etc.
+
+    FUNCTION ef_nbits( value : NATURAL ) RETURN POSITIVE IS
+        VARIABLE temp_v : POSITIVE;
+    BEGIN
+        temp_v := 1;
+        FOR i IN 1 TO INTEGER'HIGH LOOP
+            temp_v := 2*temp_v;
+            IF (temp_v > value) THEN
+                RETURN i;
+            END IF;
+        END LOOP;
+                               RETURN 32;
+    END FUNCTION;
+
+END PACKAGE BODY mbl_Pkg;
\ No newline at end of file
diff --git a/hw/mem.vhd b/hw/mem.vhd
new file mode 100644 (file)
index 0000000..6ea137e
--- /dev/null
@@ -0,0 +1,141 @@
+---------------------------------------------------------------------------------
+--
+--  Entity:       mem
+--  Filename:     mem.vhd
+--  Description:  the Memory (MEM) control unit for
+--                the TUD MB-Lite implementation
+--
+--  Author:       Huib Lincklaen Arriens
+--                Delft University of Technology
+--                Faculty EEMCS, Department ME&CE, Circuits and Systems
+--  Date:         October, 2010
+--
+--  Modified:     December, 2010: handle S_FSL Data Input (Huib)
+--  Remarks:
+--------------------------------------------------------------------------------
+
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.all;
+USE work.mbl_Pkg.all;
+
+
+--------------------------------------------------------------------------------
+ENTITY mem IS
+--------------------------------------------------------------------------------
+    PORT (
+        EX2MEM_i    :  IN EX2MEM_Type;
+        --
+        DMEMB_i     :  IN DMEMB2CORE_Type;
+        DMEMB_o     : OUT CORE2DMEMB_Type;
+        --
+        FSL_S2MEM_i :  IN FSL_S2MEM_Type;
+        --
+        MEM_REG_i   :  IN MEM_REG_Type;
+        MEM_REG_o   : OUT MEM_REG_Type;
+        --
+        MEM_WRB_o   : OUT WRB_Type;
+        MEM2CTRL_o  : OUT MEM2CTRL_Type
+        );
+END ENTITY mem;
+
+
+--------------------------------------------------------------------------------
+ARCHITECTURE rtl OF mem IS
+--------------------------------------------------------------------------------
+
+BEGIN
+
+    -- writeback in case of reads from the data memory bus:
+    -- delay wrb-ctrl signals (see core_ctrl) to stay in sync
+    -- with synchronous dmem data output
+    -- Following are only the unconditional pass-through signals. More are in the p_mem process.
+    MEM_REG_o.wrb_Action  <= EX2MEM_i.wrb_Action;
+    MEM_REG_o.exeq_result <= EX2MEM_i.exeq_result;
+    MEM_REG_o.byte_Enable <= EX2MEM_i.byte_Enable;
+    MEM_REG_o.wrix_rD     <= EX2MEM_i.wrix_rD;
+    --
+    MEM_WRB_o.wrb_Action <= MEM_REG_i.wrb_Action;
+    MEM_WRB_o.wrix_rD    <= MEM_REG_i.wrix_rD;
+    -- also signal 'slow memory decices' and interrupts from devices
+    MEM2CTRL_o.clken <= DMEMB_i.clken;
+    MEM2CTRL_o.int   <= DMEMB_i.int;
+    -- pass byte_select signal (NOTE: BIG ENDIAN)
+    DMEMB_o.bSel     <= EX2MEM_i.byte_Enable;
+
+p_mem:
+    PROCESS (EX2MEM_i, DMEMB_i, MEM_REG_i, FSL_S2MEM_i)
+        VARIABLE exeq_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE dmem_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
+
+    BEGIN
+
+        -- always align Big Endian input data from memory(-bus)
+        CASE MEM_REG_i.byte_Enable IS
+            WHEN "1000" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(31 DOWNTO 24);
+            WHEN "0100" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(23 DOWNTO 16);
+            WHEN "0010" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(15 DOWNTO  8);
+            WHEN "0001" => dmem_data_v := C_24_ZEROS & DMEMB_i.data( 7 DOWNTO  0);
+            WHEN "1100" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(31 DOWNTO 16);
+            WHEN "0011" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(15 DOWNTO  0);
+            WHEN OTHERS => dmem_data_v :=              DMEMB_i.data;
+        END CASE;
+
+        -- output to dmem-bus
+--      DMEMB_o.addr <= EX2MEM_i.exeq_result;
+        CASE EX2MEM_i.mem_Action IS
+            WHEN WR_MEM =>
+                -- write (or forward) to data memory bus
+                DMEMB_o.addr <= EX2MEM_i.exeq_result;
+                DMEMB_o.ena  <= '1';
+                DMEMB_o.wre  <= '1';
+                -- Note: use MEM_REG_i here, since MEM_WRB_o (output) cannot be read
+                IF ((MEM_REG_i.wrb_Action /= NO_WRB) AND
+                        (EX2MEM_i.wrix_rD = MEM_REG_i.wrix_rD)) THEN
+                    CASE MEM_REG_i.wrb_Action IS
+                        WHEN WRB_EX  =>
+                            -- forward exeq output, to handle e.g. add rD,rA,xx; sw rD,mem[y]; ...
+                            exeq_data_v := MEM_REG_i.exeq_result;
+                        WHEN WRB_FSL =>
+                            -- forward FSL_S input, to handle e.g. nget rD,rFSLx; swi rD,mem[x],xx; ...
+                            exeq_data_v := FSL_S2MEM_i.S_Data;
+                        WHEN OTHERS  =>
+                            -- forward mem_data just read, to handle e.g. lhu rD,mem[x]; sh rD,mem[y]; ...
+                            exeq_data_v := dmem_data_v;
+                    END CASE;
+                ELSE
+                    exeq_data_v := EX2MEM_i.data_rD;
+                END IF;
+                -- output data will be in Big Endian format
+                CASE EX2MEM_i.byte_Enable IS
+                    WHEN "1000" => DMEMB_o.data <=              exeq_data_v( 7 DOWNTO 0) & C_24_ZEROS;
+                    WHEN "0100" => DMEMB_o.data <=  C_8_ZEROS & exeq_data_v( 7 DOWNTO 0) & C_16_ZEROS;
+                    WHEN "0010" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v( 7 DOWNTO 0) &  C_8_ZEROS;
+                    WHEN "0001" => DMEMB_o.data <= C_24_ZEROS & exeq_data_v( 7 DOWNTO 0);
+                    WHEN "1100" => DMEMB_o.data <=              exeq_data_v(15 DOWNTO 0) & C_16_ZEROS;
+                    WHEN "0011" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v(15 DOWNTO 0);
+                    WHEN OTHERS => DMEMB_o.data <=              exeq_data_v;
+                END CASE;
+            WHEN RD_MEM =>
+                -- read from data memory bus
+                DMEMB_o.addr <= EX2MEM_i.exeq_result;
+                DMEMB_o.ena  <= '1';
+                DMEMB_o.wre  <= '0';
+                DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
+            WHEN OTHERS =>      -- NO_MEM
+                DMEMB_o.addr <= C_32_ZEROS;
+                DMEMB_o.ena  <= '0';
+                DMEMB_o.wre  <= '0';
+                DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
+        END CASE;
+
+        -- additional wrb signals
+        CASE MEM_REG_i.wrb_Action IS
+            WHEN WRB_MEM => MEM_WRB_o.data_rD <= dmem_data_v;
+            WHEN WRB_FSL => MEM_WRB_o.data_rD <= FSL_S2MEM_i.S_Data;
+            WHEN OTHERS  => MEM_WRB_o.data_rD <= MEM_REG_i.exeq_result;
+        END CASE;
+
+    END PROCESS;
+
+END ARCHITECTURE rtl;