--- /dev/null
+---------------------------------------------------------------------------------
+--
+-- 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;
--- /dev/null
+---------------------------------------------------------------------------------
+--
+-- 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;
+
--- /dev/null
+---------------------------------------------------------------------------------
+--
+-- 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;
+
--- /dev/null
+---------------------------------------------------------------------------------
+--
+-- 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;
--- /dev/null
+---------------------------------------------------------------------------------
+--
+-- 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
--- /dev/null
+---------------------------------------------------------------------------------
+--
+-- 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;