From b4ac16f8af94e83dcf1af5caf7b54a9335f41dd1 Mon Sep 17 00:00:00 2001 From: Martin Meloun Date: Mon, 30 Sep 2013 14:25:21 +0200 Subject: [PATCH] Reformat code and restructure decoder to save LUTs and fit critical path Instruction set is also modified, ITxxx are separate from CMP, do not store the result to a register and are in unsigned / immediate value variants as well. Added also CMPUI (CMPU has slightly changed encoding). Signed-off-by: Martin Meloun --- hw/core_ctrl.vhd | 535 ++++++++++++++++--------------- hw/decode.vhd | 739 +++++++++++++++++++++--------------------- hw/exeq.vhd | 815 ++++++++++++++++++++++++----------------------- hw/mbl_Pkg.vhd | 754 +++++++++++++++++++++---------------------- hw/mem.vhd | 190 +++++------ 5 files changed, 1526 insertions(+), 1507 deletions(-) diff --git a/hw/core_ctrl.vhd b/hw/core_ctrl.vhd index 55c5344..991a1c2 100644 --- a/hw/core_ctrl.vhd +++ b/hw/core_ctrl.vhd @@ -7,8 +7,9 @@ -- 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 +-- Date: December, 2010 +-- Modified: September, 2013: Core customization (Meloun) +-- September, 2012: interrupt handling corrected to let -- a pending branch be taken first -- (with thanks to Matthis Meier, TU Dortmund, -- for detecting this errror). @@ -24,282 +25,312 @@ USE WORK.mbl_Pkg.all; -------------------------------------------------------------------------------- ENTITY core_ctrl IS -------------------------------------------------------------------------------- - GENERIC ( - COMPATIBILITY_MODE_g : BOOLEAN := FALSE - ); - PORT ( - clk_i : IN STD_LOGIC; - rst_i : IN STD_LOGIC; - halt_i : IN STD_LOGIC; - bad_op_i : IN STD_LOGIC; - int_i : IN STD_LOGIC; - trace_i : IN STD_LOGIC; - trace_kick_i : IN STD_LOGIC; - core_clken_o : OUT 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; - EX2CTRL_REG_i : IN EX2CTRL_Type; - -- exeq to core (halting) - exeq_halt_i : IN STD_LOGIC; - -- 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; - -- 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 - ); + GENERIC + ( + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); + PORT + ( + clk_i : IN STD_LOGIC; + rst_i : IN STD_LOGIC; + halt_i : IN STD_LOGIC; + bad_op_i : IN STD_LOGIC; + int_i : IN STD_LOGIC; + trace_i : IN STD_LOGIC; + trace_kick_i : IN STD_LOGIC; + core_clken_o : OUT 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; + EX2CTRL_REG_i : IN EX2CTRL_Type; + -- exeq to core (halting) + exeq_halt_i : IN STD_LOGIC; + -- 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; + -- 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 + ); END ENTITY core_ctrl; -------------------------------------------------------------------------------- ARCHITECTURE rtl OF core_ctrl IS -------------------------------------------------------------------------------- - SIGNAL rst_r : STD_LOGIC; - SIGNAL reset_s : STD_LOGIC; - SIGNAL core_clken_s : STD_LOGIC; + SIGNAL rst_r : STD_LOGIC; + SIGNAL reset_s : STD_LOGIC; + SIGNAL core_clken_s : STD_LOGIC; - SIGNAL ID2EX_REG_r : ID2EX_Type; - SIGNAL EX2IF_REG_r : EX2IF_Type; - SIGNAL IMM_LOCK_r : IMM_LOCK_Type; - SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type; - SIGNAL flush_second_r : STD_LOGIC; - SIGNAL delayBit_r : STD_LOGIC; - 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 ID2EX_REG_r : ID2EX_Type; + SIGNAL EX2IF_REG_r : EX2IF_Type; + SIGNAL IMM_LOCK_r : IMM_LOCK_Type; + SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type; + SIGNAL flush_first_r : STD_LOGIC; + SIGNAL flush_second_r : STD_LOGIC; + SIGNAL flush_second_2r : STD_LOGIC; + SIGNAL ignore_state_r : STD_LOGIC; -- Please note: Flushing first is considered immediate! + SIGNAL delayBit_r : STD_LOGIC; + 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 setup_int_r : STD_LOGIC; + SIGNAL int_busy_r : STD_LOGIC; BEGIN - -- static connections - reset_s <= rst_i OR rst_r; - pc_ctrl_o <= NOT rst_r; - imem_addr_o <= IF2ID_REG_i.program_counter; - -- Tracing - -- Reset_s is 1 when rst_i is one and then gets deactivated - core_clken_s <= reset_s OR ((NOT bad_op_i) AND (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i)); - core_clken_o <= core_clken_s; - -- clock/wait control lines - clken_s <= MEM2CTRL_i.clken 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_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE - ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR flush_second_r); - flush_EX2MEM_s <= 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; + -- static connections + reset_s <= rst_i OR rst_r; + pc_ctrl_o <= NOT rst_r; + imem_addr_o <= IF2ID_REG_i.program_counter; + -- Tracing + -- Reset_s is 1 when rst_i is one and then gets deactivated + core_clken_s <= reset_s OR ((NOT bad_op_i) AND (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i)); + core_clken_o <= core_clken_s; + -- clock/wait control lines + clken_s <= MEM2CTRL_i.clken 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_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE + ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR flush_first_r OR + ((NOT EX2CTRL_REG_i.ignore_state) AND (NOT ignore_state_r) AND flush_second_2r)); + flush_EX2MEM_s <= 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; regd_proc: - PROCESS ( clk_i, rst_i, halt_i, core_clken_s, - -- 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, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r, - EX2IF_REG_i, EX2CTRL_REG_i, EX_WRB_i, EX2MEM_REG_i ) + PROCESS ( clk_i, rst_i, halt_i, core_clken_s, + -- 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, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r, + EX2IF_REG_i, EX2CTRL_REG_i, EX_WRB_i, EX2MEM_REG_i ) - -- some local procedures - PROCEDURE lp_rst_IF2ID_REG IS - BEGIN - IF2ID_REG_o.program_counter <= (OTHERS => '0'); - END PROCEDURE; + -- 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; - 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.condition <= COND_ALL; + ID2EX_REG_r.halt <= '0'; + IF (COMPATIBILITY_MODE_g = FALSE) THEN + ID2EX_REG_r.it_Action <= NO_IT; + ELSE + END IF; + 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_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_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_IMM_LOCK IS - BEGIN - IMM_LOCK_r.locked <= '0'; - IMM_LOCK_r.IMM_hi16 <= (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'; - END PROCEDURE; + PROCEDURE lp_rst_MSR IS + BEGIN + MSR_o.IE <= '0'; + MSR_o.C <= '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_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_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; + 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 + BEGIN - IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' AND - core_clken_s = '1' THEN - rst_r <= rst_i; + IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' AND + core_clken_s = '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; + 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; - IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_r <= '0'; - ELSE - flush_second_r <= '0'; - END IF; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_r <= '0'; + ELSE + flush_first_r <= '0'; + flush_second_r <= '0'; + flush_second_2r <= '0'; + ignore_state_r <= '0'; + END IF; - flush_ID2EX_r <= '0'; - setup_int_r <= '0'; - int_busy_r <= '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; - IF (COMPATIBILITY_MODE_g = FALSE) THEN - flush_second_r <= EX2CTRL_REG_i.flush_second; - END IF; - 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 - setup_int_r <= '0'; - lp_rst_ID2EX_REG; - IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_r <= '0'; - END IF; - -- 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 - (EX2IF_REG_r.take_branch = '0') AND -- it is still pending a cycle after branching - (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; - IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_r <= ID2CTRL_i.delayBit; - END IF; - 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; - ELSE - IF (clken_pipe_s = '1') THEN - EX2IF_REG_r <= EX2IF_REG_i; - EX_WRB_o <= EX_WRB_i; - 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; - END IF; -- rising edge clk_i ... - END PROCESS regd_proc; + flush_ID2EX_r <= '0'; + setup_int_r <= '0'; + int_busy_r <= '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; + IF (COMPATIBILITY_MODE_g = FALSE) THEN + -- Flushing based on IT / ITE / ITT along with IMM locking + IF (ID2EX_REG_i.IMM_Lock = '1') THEN + IF (flush_second_2r = '0') THEN + flush_second_2r <= flush_second_r; + END IF; + flush_first_r <= EX2CTRL_REG_i.flush_first; + flush_second_r <= EX2CTRL_REG_i.flush_second; + ignore_state_r <= EX2CTRL_REG_i.ignore_state; + ELSE + flush_first_r <= '0'; + -- Directly to 2r (flushing the following instruction) + flush_second_2r <= flush_second_r OR EX2CTRL_REG_i.flush_second; + flush_second_r <= '0'; + ignore_state_r <= '0'; + END IF; + END IF; + 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 + setup_int_r <= '0'; + lp_rst_ID2EX_REG; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_r <= '0'; + END IF; + -- 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) + -- + -- Same goes for pending flushing - should be taken before interrupt can be executed + (EX2IF_REG_i.take_branch = '0') AND (EX2IF_REG_r.take_branch = '0') AND ((COMPATIBILITY_MODE_g = TRUE) + OR ((flush_first_r = '0') AND (flush_second_r = '0') AND (flush_second_2r = '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; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_r <= ID2CTRL_i.delayBit; + END IF; + 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; + ELSE + IF (clken_pipe_s = '1') THEN + EX2IF_REG_r <= EX2IF_REG_i; + EX_WRB_o <= EX_WRB_i; + 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; + END IF; -- rising edge clk_i ... + END PROCESS regd_proc; END ARCHITECTURE rtl; diff --git a/hw/decode.vhd b/hw/decode.vhd index 17c6781..cf681e0 100644 --- a/hw/decode.vhd +++ b/hw/decode.vhd @@ -20,30 +20,30 @@ LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE WORK.mbl_Pkg.all; - -------------------------------------------------------------------------------- ENTITY decode IS -------------------------------------------------------------------------------- - GENERIC ( - USE_HW_MUL_g : BOOLEAN := TRUE; - USE_BARREL_g : BOOLEAN := TRUE; - COMPATIBILITY_MODE_g : BOOLEAN := FALSE - ); - PORT ( - IF2ID_i : IN IF2ID_Type; - imem_data_i : IN STD_LOGIC_VECTOR (31 DOWNTO 0); - -- - ID2GPRF_o : OUT ID2GPRF_Type; - ID2EX_o : OUT ID2EX_Type; - -- - INT_CTRL_i : IN INT_CTRL_Type; - ID2CTRL_o : OUT ID2CTRL_Type; - -- - noLiteOpc_o : OUT STD_LOGIC - ); + GENERIC + ( + USE_HW_MUL_g : BOOLEAN := TRUE; + USE_BARREL_g : BOOLEAN := TRUE; + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); + PORT + ( + IF2ID_i : IN IF2ID_Type; + imem_data_i : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + -- + ID2GPRF_o : OUT ID2GPRF_Type; + ID2EX_o : OUT ID2EX_Type; + -- + INT_CTRL_i : IN INT_CTRL_Type; + ID2CTRL_o : OUT ID2CTRL_Type; + -- + noLiteOpc_o : OUT STD_LOGIC + ); END ENTITY decode; - -------------------------------------------------------------------------------- ARCHITECTURE rtl OF decode IS -------------------------------------------------------------------------------- @@ -51,348 +51,365 @@ ARCHITECTURE rtl OF decode IS BEGIN p_decode: - PROCESS (IF2ID_i, imem_data_i, INT_CTRL_i) IS - - VARIABLE prog_counter_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE opcIx_v : STD_LOGIC_VECTOR ( 5 DOWNTO 0); - VARIABLE instruction_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE rD_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); - VARIABLE rA_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); - VARIABLE rB_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); - VARIABLE IMM16_v : STD_LOGIC_VECTOR (15 DOWNTO 0); - VARIABLE code_x26_v : STD_LOGIC_VECTOR ( 2 DOWNTO 0); - VARIABLE IMM_Lock_v : STD_LOGIC; - VARIABLE alu_Action_v : ALU_ACTION_Type; - VARIABLE alu_Op1_v : ALU_IN1_Type; - VARIABLE alu_Op2_v : ALU_IN2_Type; - VARIABLE alu_Cin_v : ALU_CIN_Type; - VARIABLE msr_Action_v : MSR_ACTION_Type; - VARIABLE branch_Action_v : BRANCH_ACTION_Type; - VARIABLE delayBit_v : STD_LOGIC; - VARIABLE mem_Action_v : MEM_ACTION_Type; - VARIABLE transfer_Size_v : TRANSFER_SIZE_Type; - VARIABLE wrb_Action_v : WRB_ACTION_Type; - VARIABLE int_busy_v : STD_LOGIC; - VARIABLE cmp_Cond_v : CMP_COND_Type; - VARIABLE cmp_Cond_Type_v : CMP_COND_TYPE_Type; - - BEGIN - prog_counter_v := IF2ID_i.program_counter; - instruction_v := imem_data_i; - opcIx_v := instruction_v (31 DOWNTO 26); - rD_v := instruction_v (25 DOWNTO 21); - rA_v := instruction_v (20 DOWNTO 16); - rB_v := instruction_v (15 DOWNTO 11); - IMM16_v := instruction_v (15 DOWNTO 0); - IMM_Lock_v := '0'; - IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_v := '0'; - ELSE - cmp_cond_v := COND_ALL; - cmp_cond_type_v := COND_TYPE_ALL; - END IF; - alu_Cin_v := CIN_ZERO; - alu_Action_v := A_NOP; - msr_Action_v := KEEP_CARRY; - branch_Action_v := NO_BR; - mem_Action_v := NO_MEM; - transfer_Size_v := WORD; - wrb_Action_v := WRB_EX; - -- for decoding SEXT16, SEXT8, SRC, SRC or SRL - code_x26_v := instruction_v(6) & instruction_v(5) & instruction_v(0); - int_busy_v := INT_CTRL_i.int_busy; - -- for debugging purposes - noLiteOpc_o <= '0'; - - IF (INT_CTRL_i.setup_int = '1') THEN - - alu_Op1_v := ALU_IN_ZERO; - alu_Op2_v := ALU_IN_IMM; - IMM16_v := X"0010"; -- address of _interrupt_handler vector - prog_counter_v := INT_CTRL_i.rti_target; -- delayed program counter - alu_Action_v := A_ADD; - rD_v := "01110"; -- r14 reserved for storing program_counter - rA_v := (OTHERS => '0'); -- also set rA and rB to avoid possible ... - rB_v := (OTHERS => '0'); -- ... erronuous hazard detection in exeq module - int_busy_v := '1'; - branch_Action_v := BRL; - - ELSE - - alu_Op1_v := ALU_IN_REGA; - IF (opcIx_v(3) = '0') THEN - alu_Op2_v := ALU_IN_REGB; - ELSE - alu_Op2_v := ALU_IN_IMM; - END IF; - - CASE opcIx_v (5 DOWNTO 4) IS - - WHEN "00" => -- ADD / RSUB - IF (opcIx_v(0) = '1') THEN -- RSUB - alu_Op1_v := ALU_IN_NOT_REGA; - END IF; - IF (opcIx_v(1) = '0') THEN -- xxx - IF (opcIx_v(0) = '0') THEN - alu_Cin_v := CIN_ZERO; - ELSE - alu_Cin_v := CIN_ONE; - END IF; - ELSE -- xxxC - alu_Cin_v := FROM_MSR; - END IF; - IF ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN - -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode - IF (IMM16_v(1) = '1') THEN -- U-bit set, CMPU - alu_Action_v := A_CMPU; - ELSE - alu_Action_v := A_CMP; - END IF; - ELSE - alu_Action_v := A_ADD; - IF (opcIx_v(2) = '0') THEN - msr_Action_v := UPDATE_CARRY; - END IF; - END IF; - - WHEN "01" => -- MUL / BS - CASE opcIx_v (2 DOWNTO 0) IS - WHEN "000" => -- MUL - IF (USE_HW_MUL_g = TRUE) THEN - alu_Action_v := A_MUL; - ELSE - noLiteOpc_o <= '1'; - END IF; - WHEN "001" => -- BS - IF (USE_BARREL_g = TRUE) THEN - IF (instruction_v(10) = '1') THEN - alu_Action_v := A_BSLL; - ELSE - IF (instruction_v(9) = '1') THEN - alu_Action_v := A_BSRA; - ELSE - alu_Action_v := A_BSRL; - END IF; - END IF; - ELSE - noLiteOpc_o <= '1'; - END IF; - WHEN "010" => -- CMP / CMPU / CMPI (new format) - IF (COMPATIBILITY_MODE_g = FALSE) THEN - IF (IMM16_v(5) = '1') THEN -- U-bit set, CMPU - alu_Action_v := A_CMPU; - ELSE - alu_Action_v := A_CMP; - END IF; - - IF (opcIx_v(3) = '0') THEN -- IT, ITT, ITE is not available to CMPI - CASE IMM16_v(4 downto 3) IS - WHEN "00" => - cmp_Cond_Type_v := COND_TYPE_ALL; - WHEN "01" => - cmp_Cond_Type_v := COND_TYPE_IF_THEN; - WHEN "10" => - cmp_Cond_Type_v := COND_TYPE_IF_THEN_THEN; - WHEN "11" => - cmp_Cond_Type_v := COND_TYPE_IF_THEN_ELSE; - WHEN OTHERS => - NULL; - END CASE; - - CASE IMM16_v(2 downto 0) IS - WHEN "001" => - cmp_Cond_v := COND_EQ; - WHEN "010" => - cmp_Cond_v := COND_NE; - WHEN "011" => - cmp_Cond_v := COND_LT; - WHEN "100" => - cmp_Cond_v := COND_LE; - WHEN "101" => - cmp_Cond_v := COND_GT; - WHEN "110" => - cmp_Cond_v := COND_GE; - WHEN OTHERS => - NULL; - END CASE; - END IF; - ELSE - noLiteOpc_o <= '1'; - END IF; - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - - WHEN "10" => - IF (opcIx_v (3 DOWNTO 0) = "0100") THEN - CASE code_x26_v IS - WHEN "001" | "011" | "101" => - CASE code_x26_v(2 DOWNTO 1) IS - WHEN "00" => -- SRA - alu_Cin_v := FROM_IN1; - WHEN "01" => -- SRC - alu_Cin_v := FROM_MSR; - WHEN "10" => -- SRL - alu_Cin_v := CIN_ZERO; - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - alu_Action_v := A_SHIFT; - msr_Action_v := UPDATE_CARRY; - WHEN "110" => -- SEXT8 - alu_Action_v := A_SEXT8; - WHEN "111" => -- SEXT16 - alu_Action_v := A_SEXT16; - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - ELSIF (opcIx_v (3 DOWNTO 0) = "1100") THEN -- IMM - IMM_Lock_v := '1'; - -- always: IMM_LOCK_o.IMM16 <= IMM16_v; - alu_Action_v := A_NOP; - wrb_Action_v := NO_WRB; - ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN - CASE rD_v (3 DOWNTO 0) IS - WHEN "0001" => -- RTI(D) - int_busy_v := '0'; - WHEN "0000" => -- RTS(D) - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - alu_Action_v := A_ADD; - branch_Action_v := BR; - wrb_Action_v := NO_WRB; - IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_v := rD_v(4); - END IF; - ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN - CASE IMM16_v IS - WHEN X"8001" => -- MFS (MSR only) - alu_Action_v := A_MFS; - WHEN X"C001" => -- MTS (MSR only) - alu_Action_v := A_MTS; - wrb_Action_v := NO_WRB; - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - rB_v := (OTHERS => '0'); -- in order to prevent occasional hazards (r16, r24) - ELSE - CASE opcIx_v (2 DOWNTO 0) IS - WHEN "000" => - alu_Action_v := A_OR; - WHEN "001" => - alu_Action_v := A_AND; - WHEN "010" => - alu_Action_v := A_XOR; - WHEN "011" => - alu_Action_v := A_AND; - IF (opcIx_v(3) = '0') THEN - alu_Op2_v := ALU_IN_NOT_REGB; - ELSE - alu_Op2_v := ALU_IN_NOT_IMM; - END IF; - WHEN "110" => -- BR(I)(D) - IF (rA_v(2) = '1') THEN - branch_Action_v := BRL; - ELSE - branch_Action_v := BR; - wrb_Action_v := NO_WRB; - END IF; - IF (rA_v(3) = '1') THEN - alu_Op1_v := ALU_IN_ZERO; - ELSE - alu_Op1_v := ALU_IN_PC; - END IF; - alu_Action_v := A_ADD; - IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_v := rA_v(4); - END IF; - WHEN "111" => - CASE rD_v(3 DOWNTO 0) IS - WHEN "0000" => -- BEQ - branch_Action_v := BEQ; - WHEN "0001" => -- BNE - branch_Action_v := BNE; - WHEN "0010" => -- BLT - branch_Action_v := BLT; - WHEN "0011" => -- BLE - branch_Action_v := BLE; - WHEN "0100" => -- BGT - branch_Action_v := BGT; - WHEN "0101" => -- BGE - branch_Action_v := BGE; - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - alu_Action_v := A_ADD; - alu_Op1_v := ALU_IN_PC; - IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_v := rD_v(4); - END IF; - wrb_Action_v := NO_WRB; -- evaluate and update/overwrite in exeq - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - END IF; - - WHEN "11" => - IF (opcIx_v (3 DOWNTO 0) = "1111") THEN -- HALT - alu_Action_v := A_HALT; - wrb_Action_v := NO_WRB; - ELSE - alu_Action_v := A_ADD; - CASE opcIx_v (1 DOWNTO 0) IS - WHEN "00" => transfer_Size_v := BYTE; - WHEN "01" => transfer_Size_v := HALFWORD; - WHEN "10" => transfer_Size_v := WORD; - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - IF (opcIx_v(2) = '0') THEN - mem_Action_v := RD_MEM; - wrb_Action_v := WRB_MEM; - ELSE - mem_Action_v := WR_MEM; - wrb_Action_v := NO_WRB; - END IF; - END IF; - - WHEN OTHERS => - noLiteOpc_o <= '1'; - - END CASE; - - END IF; -- interrupt test - - ID2GPRF_o.rdix_rA <= rA_v; - ID2GPRF_o.rdix_rB <= rB_v; - ID2GPRF_o.rdix_rD <= rD_v; - - ID2EX_o.program_counter <= prog_counter_v; - ID2EX_o.rdix_rA <= rA_v; - ID2EX_o.rdix_rB <= rB_v; - ID2EX_o.curr_rD <= rD_v; - ID2EX_o.alu_Action <= alu_Action_v; - ID2EX_o.alu_Op1 <= alu_Op1_v; - ID2EX_o.alu_Op2 <= alu_Op2_v; - ID2EX_o.alu_Cin <= alu_Cin_v; - ID2EX_o.IMM16 <= IMM16_v; - ID2EX_o.IMM_Lock <= IMM_Lock_v; - ID2EX_o.msr_Action <= msr_Action_v; - ID2EX_o.branch_Action <= branch_Action_v; - ID2EX_o.mem_Action <= mem_Action_v; - ID2EX_o.transfer_Size <= transfer_Size_v; - ID2EX_o.wrb_Action <= wrb_Action_v; - -- - IF (COMPATIBILITY_MODE_g = TRUE) THEN - ID2CTRL_o.delayBit <= delayBit_v; - ELSE - ID2EX_o.cmp_Cond <= cmp_Cond_v; - ID2EX_o.cmp_Cond_Type <= cmp_Cond_Type_v; - END IF; - ID2CTRL_o.int_busy <= int_busy_v; - - END PROCESS; + PROCESS (IF2ID_i, imem_data_i, INT_CTRL_i) IS + + VARIABLE prog_counter_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE opcIx_v : STD_LOGIC_VECTOR ( 5 DOWNTO 0); + VARIABLE instruction_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE rD_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); + VARIABLE rA_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); + VARIABLE rB_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); + VARIABLE IMM16_v : STD_LOGIC_VECTOR (15 DOWNTO 0); + VARIABLE code_x26_v : STD_LOGIC_VECTOR ( 2 DOWNTO 0); + VARIABLE IMM_Lock_v : STD_LOGIC; + VARIABLE alu_Action_v : ALU_ACTION_Type; + VARIABLE alu_Op1_v : ALU_IN1_Type; + VARIABLE alu_Op2_v : ALU_IN2_Type; + VARIABLE alu_Cin_v : ALU_CIN_Type; + VARIABLE msr_Action_v : MSR_ACTION_Type; + VARIABLE branch_Action_v : BRANCH_ACTION_Type; + VARIABLE it_Action_v : IT_ACTION_Type; + VARIABLE delayBit_v : STD_LOGIC; + VARIABLE mem_Action_v : MEM_ACTION_Type; + VARIABLE transfer_Size_v : TRANSFER_SIZE_Type; + VARIABLE wrb_Action_v : WRB_ACTION_Type; + VARIABLE int_busy_v : STD_LOGIC; + VARIABLE condition_raw_v : STD_LOGIC_VECTOR ( 2 DOWNTO 0); + VARIABLE halt_v : STD_LOGIC; + + BEGIN + + prog_counter_v := IF2ID_i.program_counter; + instruction_v := imem_data_i; + opcIx_v := instruction_v (31 DOWNTO 26); + rD_v := instruction_v (25 DOWNTO 21); + rA_v := instruction_v (20 DOWNTO 16); + rB_v := instruction_v (15 DOWNTO 11); + IMM16_v := instruction_v (15 DOWNTO 0); + IMM_Lock_v := '0'; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := '0'; + ELSE + it_Action_v := NO_IT; + END IF; + condition_raw_v := (others => '1'); + alu_Cin_v := CIN_ZERO; + alu_Action_v := A_NOP; + msr_Action_v := KEEP_CARRY; + branch_Action_v := NO_BR; + mem_Action_v := NO_MEM; + transfer_Size_v := WORD; + wrb_Action_v := WRB_EX; + halt_v := '0'; + -- for decoding SEXT16, SEXT8, SRC, SRC or SRL + code_x26_v := instruction_v(6) & instruction_v(5) & instruction_v(0); + int_busy_v := INT_CTRL_i.int_busy; + -- for debugging purposes + noLiteOpc_o <= '0'; + + IF (INT_CTRL_i.setup_int = '1') THEN + + alu_Op1_v := ALU_IN_ZERO; + alu_Op2_v := ALU_IN_IMM; + IMM16_v := X"0010"; -- address of _interrupt_handler vector + prog_counter_v := INT_CTRL_i.rti_target; -- delayed program counter + alu_Action_v := A_ADD; + rD_v := "01110"; -- r14 reserved for storing program_counter + rA_v := (OTHERS => '0'); -- also set rA and rB to avoid possible ... + rB_v := (OTHERS => '0'); -- ... erronuous hazard detection in exeq module + int_busy_v := '1'; + branch_Action_v := BRL; + + ELSE + + alu_Op1_v := ALU_IN_REGA; + IF (opcIx_v(3) = '0') THEN + alu_Op2_v := ALU_IN_REGB; + ELSE + alu_Op2_v := ALU_IN_IMM; + END IF; + + CASE opcIx_v (5 DOWNTO 4) IS + + WHEN "00" => -- ADD / RSUB + IF (opcIx_v(0) = '1') THEN -- RSUB + alu_Op1_v := ALU_IN_NOT_REGA; + END IF; + IF (opcIx_v(1) = '0') THEN -- xxx + IF (opcIx_v(0) = '0') THEN + alu_Cin_v := CIN_ZERO; + ELSE + alu_Cin_v := CIN_ONE; + END IF; + ELSE -- xxxC + alu_Cin_v := FROM_MSR; + END IF; + IF ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN + -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode + IF (IMM16_v(1) = '1') THEN -- U-bit set, CMPU + alu_Action_v := A_CMPU; + ELSE + alu_Action_v := A_CMP; + END IF; + ELSE + alu_Action_v := A_ADD; + IF (opcIx_v(2) = '0') THEN + msr_Action_v := UPDATE_CARRY; + END IF; + END IF; + + WHEN "01" => -- MUL / BS + + CASE opcIx_v (2 DOWNTO 0) IS + WHEN "000" => -- MUL + IF (USE_HW_MUL_g = TRUE) THEN + alu_Action_v := A_MUL; + ELSE + noLiteOpc_o <= '1'; + END IF; + + WHEN "001" => -- BS + IF (USE_BARREL_g = TRUE) THEN + IF (instruction_v(10) = '1') THEN + alu_Action_v := A_BSLL; + ELSIF (instruction_v(9) = '1') THEN + alu_Action_v := A_BSRA; + ELSE + alu_Action_v := A_BSRL; + END IF; + ELSE + noLiteOpc_o <= '1'; + END IF; + + WHEN "010" | "011" => -- CMP(U) + IF (COMPATIBILITY_MODE_g = FALSE) THEN + IF (opcIx_v(0) = '1') THEN + alu_Action_v := A_CMPU; + ELSE + alu_Action_v := A_CMP; + END IF; + ELSE + noLiteOpc_o <= '1'; + END IF; + + WHEN "100" | "101" => -- IT(U) / ITT(U) / ITE(U) + IF (COMPATIBILITY_MODE_g = FALSE) THEN + IF (opcIx_v(0) = '1') THEN + alu_Action_v := A_CMPU; + ELSE + alu_Action_v := A_CMP; + END IF; + + CASE rD_v(4 downto 3) IS + WHEN "00" => + it_Action_v := IT; + WHEN "01" => + it_Action_v := ITT; + WHEN "10" => + it_Action_v := ITE; + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + condition_raw_v := rD_v(2 downto 0); + -- IT instruction isn't writing to anything + wrb_Action_v := NO_WRB; + ELSE + noLiteOpc_o <= '1'; + END IF; + + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + + WHEN "10" => + IF (opcIx_v (3 DOWNTO 0) = "0100") THEN + CASE code_x26_v IS + + WHEN "001" | "011" | "101" => + CASE code_x26_v(2 DOWNTO 1) IS + WHEN "00" => -- SRA + alu_Cin_v := FROM_IN1; + WHEN "01" => -- SRC + alu_Cin_v := FROM_MSR; + WHEN "10" => -- SRL + alu_Cin_v := CIN_ZERO; + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + alu_Action_v := A_SHIFT; + msr_Action_v := UPDATE_CARRY; + + WHEN "110" => -- SEXT8 + alu_Action_v := A_SEXT8; + WHEN "111" => -- SEXT16 + alu_Action_v := A_SEXT16; + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + + ELSIF (opcIx_v (3 DOWNTO 0) = "1100") THEN -- IMM + IMM_Lock_v := '1'; + -- always: IMM_LOCK_o.IMM16 <= IMM16_v; + alu_Action_v := A_NOP; + wrb_Action_v := NO_WRB; + ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN + + CASE rD_v (3 DOWNTO 0) IS + WHEN "0001" => -- RTI(D) + int_busy_v := '0'; + WHEN "0000" => -- RTS(D) + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + + alu_Action_v := A_ADD; + branch_Action_v := BR; + wrb_Action_v := NO_WRB; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := rD_v(4); + END IF; + + ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN + + CASE IMM16_v IS + WHEN X"8001" => -- MFS (MSR only) + alu_Action_v := A_MFS; + WHEN X"C001" => -- MTS (MSR only) + alu_Action_v := A_MTS; + wrb_Action_v := NO_WRB; + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + rB_v := (OTHERS => '0'); -- in order to prevent occasional hazards (r16, r24) + + ELSE + + CASE opcIx_v (2 DOWNTO 0) IS + WHEN "000" => + alu_Action_v := A_OR; + WHEN "001" => + alu_Action_v := A_AND; + WHEN "010" => + alu_Action_v := A_XOR; + WHEN "011" => + alu_Action_v := A_AND; + IF (opcIx_v(3) = '0') THEN + alu_Op2_v := ALU_IN_NOT_REGB; + ELSE + alu_Op2_v := ALU_IN_NOT_IMM; + END IF; + + WHEN "110" => -- BR(I)(D) + IF (rA_v(2) = '1') THEN + branch_Action_v := BRL; + ELSE + branch_Action_v := BR; + wrb_Action_v := NO_WRB; + END IF; + + IF (rA_v(3) = '1') THEN + alu_Op1_v := ALU_IN_ZERO; + ELSE + alu_Op1_v := ALU_IN_PC; + END IF; + alu_Action_v := A_ADD; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := rA_v(4); + END IF; + + WHEN "111" => + condition_raw_v := rD_v(2 downto 0); -- Conditional branching + branch_Action_v := BR; + alu_Action_v := A_ADD; + alu_Op1_v := ALU_IN_PC; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := rD_v(4); + END IF; + wrb_Action_v := NO_WRB; -- evaluate and update/overwrite in exeq + + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + END IF; + + WHEN "11" => + IF (opcIx_v (3 DOWNTO 0) = "1111") THEN -- HALT + alu_Action_v := A_NOP; + wrb_Action_v := NO_WRB; + halt_v := '1'; + ELSE + alu_Action_v := A_ADD; + CASE opcIx_v (1 DOWNTO 0) IS + WHEN "00" => transfer_Size_v := BYTE; + WHEN "01" => transfer_Size_v := HALFWORD; + WHEN "10" => transfer_Size_v := WORD; + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + IF (opcIx_v(2) = '0') THEN + mem_Action_v := RD_MEM; + wrb_Action_v := WRB_MEM; + ELSE + mem_Action_v := WR_MEM; + wrb_Action_v := NO_WRB; + END IF; + END IF; + + WHEN OTHERS => + noLiteOpc_o <= '1'; + + END CASE; + + END IF; -- interrupt test + + ID2GPRF_o.rdix_rA <= rA_v; + ID2GPRF_o.rdix_rB <= rB_v; + ID2GPRF_o.rdix_rD <= rD_v; + + ID2EX_o.program_counter <= prog_counter_v; + ID2EX_o.rdix_rA <= rA_v; + ID2EX_o.rdix_rB <= rB_v; + ID2EX_o.curr_rD <= rD_v; + ID2EX_o.alu_Action <= alu_Action_v; + ID2EX_o.alu_Op1 <= alu_Op1_v; + ID2EX_o.alu_Op2 <= alu_Op2_v; + ID2EX_o.alu_Cin <= alu_Cin_v; + ID2EX_o.IMM16 <= IMM16_v; + ID2EX_o.IMM_Lock <= IMM_Lock_v; + ID2EX_o.msr_Action <= msr_Action_v; + ID2EX_o.branch_Action <= branch_Action_v; + ID2EX_o.it_Action <= it_Action_v; + ID2EX_o.mem_Action <= mem_Action_v; + ID2EX_o.transfer_Size <= transfer_Size_v; + ID2EX_o.wrb_Action <= wrb_Action_v; + ID2EX_o.halt <= halt_v; + -- + CASE condition_raw_v IS + WHEN "000" => + ID2EX_o.condition <= COND_EQ; + WHEN "001" => + ID2EX_o.condition <= COND_NE; + WHEN "010" => + ID2EX_o.condition <= COND_LT; + WHEN "011" => + ID2EX_o.condition <= COND_LE; + WHEN "100" => + ID2EX_o.condition <= COND_GT; + WHEN "101" => + ID2EX_o.condition <= COND_GE; + WHEN "111" => + ID2EX_o.condition <= COND_ALL; + WHEN OTHERS => + ID2EX_o.condition <= COND_ALL; + noLiteOpc_o <= '1'; + END CASE; + -- + IF (COMPATIBILITY_MODE_g = TRUE) THEN + ID2CTRL_o.delayBit <= delayBit_v; + END IF; + ID2CTRL_o.int_busy <= int_busy_v; + + END PROCESS; END ARCHITECTURE rtl; diff --git a/hw/exeq.vhd b/hw/exeq.vhd index 1235795..0347712 100644 --- a/hw/exeq.vhd +++ b/hw/exeq.vhd @@ -9,7 +9,7 @@ -- Faculty EEMCS, Department ME&CE, Circuits and Systems -- Date: September, 2010 -- --- Modified: Septemper, 2013: FSL scratched (Meloun) +-- Modified: Septemper, 2013: FSL scratched, core customized (Meloun) -- December, 2010: FSL added (Huib) -- June, 2011: added code for MUL and BARREL (Huib) -- Adapted to work with separate fsl_M- @@ -29,36 +29,37 @@ USE WORK.mbl_Pkg.all; ---------------------------------------------------------- ENTITY exeq IS ---------------------------------------------------------- - GENERIC ( - USE_HW_MUL_g : BOOLEAN := TRUE; - USE_BARREL_g : BOOLEAN := TRUE; - COMPATIBILITY_MODE_g : BOOLEAN := FALSE - ); - PORT ( - ID2EX_i : IN ID2EX_Type; - GPRF2EX_i : IN GPRF2EX_Type; - EX2IF_o : OUT EX2IF_Type; - EX2CTRL_o : OUT EX2CTRL_Type; - HALT_o : OUT HALT_Type; - -- - EX_WRB_i : IN WRB_Type; - EX_WRB_o : OUT WRB_Type; - MEM_WRB_i : IN WRB_Type; - -- - HAZARD_WRB_i : IN HAZARD_WRB_Type; - HAZARD_WRB_o : OUT HAZARD_WRB_Type; - -- - IMM_LOCK_i : IN IMM_LOCK_Type; - IMM_LOCK_o : OUT IMM_LOCK_Type; - -- - MSR_i : IN MSR_Type; - MSR_o : OUT MSR_Type; - -- - EX2MEM_o : OUT EX2MEM_Type - ); + GENERIC + ( + USE_HW_MUL_g : BOOLEAN := TRUE; + USE_BARREL_g : BOOLEAN := TRUE; + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); + PORT + ( + ID2EX_i : IN ID2EX_Type; + GPRF2EX_i : IN GPRF2EX_Type; + EX2IF_o : OUT EX2IF_Type; + EX2CTRL_o : OUT EX2CTRL_Type; + HALT_o : OUT HALT_Type; + -- + EX_WRB_i : IN WRB_Type; + EX_WRB_o : OUT WRB_Type; + MEM_WRB_i : IN WRB_Type; + -- + HAZARD_WRB_i : IN HAZARD_WRB_Type; + HAZARD_WRB_o : OUT HAZARD_WRB_Type; + -- + IMM_LOCK_i : IN IMM_LOCK_Type; + IMM_LOCK_o : OUT IMM_LOCK_Type; + -- + MSR_i : IN MSR_Type; + MSR_o : OUT MSR_Type; + -- + EX2MEM_o : OUT EX2MEM_Type + ); END ENTITY exeq; - ---------------------------------------------------------- ARCHITECTURE rtl OF exeq IS ---------------------------------------------------------- @@ -66,379 +67,389 @@ ARCHITECTURE rtl OF exeq IS BEGIN p_exeq: - PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i, - IMM_LOCK_i, MSR_i, HAZARD_WRB_i) - - -- function needed by BSLL (only if USE_BARREL_g = TRUE) - FUNCTION reverse_bits ( word32 : STD_LOGIC_VECTOR (31 DOWNTO 0) ) - RETURN STD_LOGIC_VECTOR IS - VARIABLE reversed_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - BEGIN - f_rev: - FOR i IN 0 TO 31 LOOP - reversed_v(31-i) := word32(i); - END LOOP; - RETURN reversed_v; - END; - - VARIABLE data_rA_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE data_rB_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE data_rD_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE in1_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE in2_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE hi16_v : STD_LOGIC_VECTOR (15 DOWNTO 0); - VARIABLE IMM32_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE carry_i_v : STD_LOGIC; - VARIABLE result_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE carry_o_v : STD_LOGIC; - VARIABLE isZero_v : STD_LOGIC; - VARIABLE cmpResZero_v : STD_LOGIC; - VARIABLE signBit_in1_v : STD_LOGIC; - VARIABLE signBit_in2_v : STD_LOGIC; - VARIABLE signBit_rA_v : STD_LOGIC; - VARIABLE signBit_rD_v : STD_LOGIC; - VARIABLE rA_eq_ex_rD_v : STD_LOGIC; - VARIABLE rB_eq_ex_rD_v : STD_LOGIC; - VARIABLE hazard_v : STD_LOGIC; - VARIABLE save_rX_v : SAVE_REG_Type; - VARIABLE data_rX_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE do_branch_v : STD_LOGIC; - VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0); - VARIABLE tmp64_v : STD_LOGIC_VECTOR (63 DOWNTO 0); - VARIABLE padVec_v : STD_LOGIC_VECTOR (15 DOWNTO 0); - VARIABLE halt_v : STD_LOGIC; - VARIABLE halt_code_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); - VARIABLE do_cmp_cond_v : STD_LOGIC; - VARIABLE cmp_cond_type_v : CMP_COND_TYPE_Type; - - BEGIN - - rA_eq_ex_rD_v := '0'; - rB_eq_ex_rD_v := '0'; - hazard_v := '0'; - save_rX_v := NO_SAVE; - data_rX_v := data_rB_v; -- default value for data_rX_v - result_v := (OTHERS => '0'); - carry_o_v := '0'; - do_branch_v := '0'; - byte_Enable_v := "0000"; - halt_v := '0'; - halt_code_v := "00000"; - do_cmp_cond_v := '0'; - cmp_cond_type_v := COND_TYPE_ALL; - signBit_rD_v := '0'; - - -- create some helper variables - IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN - rA_eq_ex_rD_v := '1'; - END IF; - IF (ID2EX_i.rdix_rB = EX_WRB_i.wrix_rD) THEN - rB_eq_ex_rD_v := '1'; - END IF; - -- test where to obtain data_rA from - IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rA_eq_ex_rD_v = '1')) THEN - data_rA_v := EX_WRB_i.data_rD; - ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rA = MEM_WRB_i.wrix_rD)) THEN - data_rA_v := MEM_WRB_i.data_rD; - ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RA)) THEN - data_rA_v := HAZARD_WRB_i.data_rX; - ELSE - data_rA_v := GPRF2EX_i.data_rA; - END IF; - -- test where to obtain data_rB from - IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rB_eq_ex_rD_v = '1')) THEN - data_rB_v := EX_WRB_i.data_rD; - ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rB = MEM_WRB_i.wrix_rD)) THEN - data_rB_v := MEM_WRB_i.data_rD; - ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RB)) THEN - data_rB_v := HAZARD_WRB_i.data_rX; - ELSE - data_rB_v := GPRF2EX_i.data_rB; - END IF; - -- .... or, isn't all necessary data available yet being still in the pipeline ? - data_rX_v := data_rB_v; -- default value for data_rX_v - IF (EX_WRB_i.wrb_Action = WRB_MEM) THEN - IF ((rA_eq_ex_rD_v = '1') OR (rB_eq_ex_rD_v = '1')) THEN - hazard_v := '1'; --- always?? IF (MEM_WRB_i.wrb_Action = WRB_MEM) THEN - -- handle situations in which both rA and rB needed - IF (rA_eq_ex_rD_v = '1') THEN - save_rX_v := SAVE_RB; -- already by default data_rX_v = data_rB_v - ELSE - save_rX_v := SAVE_RA; - data_rX_v := data_rA_v; - END IF; --- END IF; - END IF; - END IF; - - IF (IMM_LOCK_i.locked = '1') THEN - hi16_v := IMM_LOCK_i.IMM_hi16; - ELSIF (ID2EX_i.IMM16(15) = '0') THEN - hi16_v := C_16_ZEROS; - ELSE - hi16_v := C_16_ONES; - END IF; - IMM32_v := hi16_v & ID2EX_i.IMM16; - - CASE ID2EX_i.alu_Op1 IS - WHEN ALU_IN_REGA => in1_v := data_rA_v; - WHEN ALU_IN_NOT_REGA => in1_v := NOT data_rA_v; - WHEN ALU_IN_PC => in1_v := ID2EX_i.program_counter; - WHEN ALU_IN_ZERO => in1_v := C_32_ZEROS; - WHEN OTHERS => NULL; - END CASE; - - CASE ID2EX_i.alu_Op2 IS - WHEN ALU_IN_REGB => in2_v := data_rB_v; - WHEN ALU_IN_NOT_REGB => in2_v := NOT data_rB_v; - WHEN ALU_IN_IMM => in2_v := IMM32_v; - WHEN ALU_IN_NOT_IMM => in2_v := NOT IMM32_v; - WHEN OTHERS => NULL; - END CASE; - - signBit_in1_v := in1_v(31); - signBit_in2_v := in2_v(31); - signBit_rA_v := data_rA_v(31); - - CASE ID2EX_i.alu_Cin IS - WHEN CIN_ZERO => carry_i_v := '0'; - WHEN CIN_ONE => carry_i_v := '1'; - WHEN FROM_MSR => carry_i_v := MSR_i.C; - WHEN FROM_IN1 => carry_i_v := in1_v(31); - WHEN OTHERS => carry_i_v := '0'; - END CASE; - - IF (data_rA_v = C_32_ZEROS) THEN - isZero_v := '1'; - ELSE - isZero_v := '0'; - END IF; - - CASE ID2EX_i.alu_Action IS - WHEN A_ADD | A_CMP | A_CMPU => - ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v); - IF (id2ex_i.alu_Action = A_CMPU) THEN - IF (signBit_in1_v = signBit_in2_v) THEN - signBit_rD_v := NOT signBit_in1_v; - END IF; - ELSIF (id2ex_i.alu_Action = A_CMP) THEN - IF (signBit_in1_v = signBit_in2_v) THEN - signBit_rD_v := signBit_in1_v; - END IF; - END IF; - - result_v(31) := signBit_rD_v; - - IF (COMPATIBILITY_MODE_g = FALSE) THEN - IF (ID2EX_i.cmp_Cond /= COND_ALL) THEN - IF (result_v = C_32_ZEROS) THEN - cmpResZero_v := '1'; - ELSE - cmpResZero_v := '0'; - END IF; - - CASE ID2EX_i.cmp_Cond IS - WHEN COND_EQ => do_cmp_cond_v := cmpResZero_v; - WHEN COND_NE => do_cmp_cond_v := NOT cmpResZero_v; - WHEN COND_LT => do_cmp_cond_v := signBit_rD_v; - WHEN COND_LE => do_cmp_cond_v := signBit_rD_v OR cmpResZero_v; - WHEN COND_GT => do_cmp_cond_v := NOT (signBit_rD_v OR cmpResZero_v); - WHEN COND_GE => do_cmp_cond_v := NOT signBit_rD_v; - WHEN OTHERS => NULL; - END CASE; - - cmp_cond_type_v := ID2EX_i.cmp_Cond_Type; - END IF; - END IF; - - WHEN A_OR => - result_v := in1_v OR in2_v; - WHEN A_AND => - result_v := in1_v AND in2_v; - WHEN A_XOR => - result_v := in1_v XOR in2_v; - WHEN A_SHIFT => - result_v := carry_i_v & in1_v(31 DOWNTO 1); - carry_o_v := in1_v(0); - WHEN A_SEXT8 => - IF (in1_v(7) = '0') THEN - result_v := C_24_ZEROS & in1_v( 7 DOWNTO 0); - ELSE - result_v := C_24_ONES & in1_v( 7 DOWNTO 0); - END IF; - WHEN A_SEXT16 => - IF (in1_v(15) = '0') THEN - result_v := C_16_ZEROS & in1_v(15 DOWNTO 0); - ELSE - result_v := C_16_ONES & in1_v(15 DOWNTO 0); - END IF; - WHEN A_MFS => - result_v := MSR_i.C & C_24_ZEROS & "0000" & MSR_i.C & MSR_i.IE & '0'; - WHEN A_MTS => - MSR_o.IE <= data_Ra_v(1); - MSR_o.C <= data_Ra_v(2); - WHEN A_MUL => - IF (USE_HW_MUL_g = TRUE) THEN - tmp64_v := STD_LOGIC_VECTOR( UNSIGNED(in1_v) * UNSIGNED(in2_v) ); - result_v := tmp64_v(31 DOWNTO 0); - END IF; - WHEN A_BSLL | A_BSRL | A_BSRA => - IF (USE_BARREL_g = TRUE) THEN - IF (ID2EX_i.alu_Action = A_BSLL) THEN - result_v := reverse_bits (in1_v); - ELSE - result_v := in1_v; - END IF; - IF (ID2EX_i.alu_Action = A_BSRA) THEN - padVec_v := (OTHERS => in1_v(31)); - ELSE - padVec_v := (OTHERS => '0'); - END IF; - IF (in2_v(4) = '1') THEN - result_v := padVec_v (15 DOWNTO 0) & result_v (31 DOWNTO 16); - END IF; - IF (in2_v(3) = '1') THEN - result_v := padVec_v ( 7 DOWNTO 0) & result_v (31 DOWNTO 8); - END IF; - IF (in2_v(2) = '1') THEN - result_v := padVec_v ( 3 DOWNTO 0) & result_v (31 DOWNTO 4); - END IF; - IF (in2_v(1) = '1') THEN - result_v := padVec_v ( 1 DOWNTO 0) & result_v (31 DOWNTO 2); - END IF; - IF (in2_v(0) = '1') THEN - result_v := padVec_v ( 0 DOWNTO 0) & result_v (31 DOWNTO 1); - END IF; - IF (ID2EX_i.alu_Action = A_BSLL) THEN - result_v := reverse_bits (result_v); - END IF; - END IF; -- (USE_BARREL_g = TRUE) - WHEN A_HALT => - halt_v := '1'; - halt_code_v := ID2EX_i.IMM16(4 DOWNTO 0); - WHEN OTHERS => - NULL; - END CASE; - - CASE ID2EX_i.branch_Action IS - WHEN BR => do_branch_v := '1'; - WHEN BRL => do_branch_v := '1'; - WHEN BEQ => do_branch_v := isZero_v; - WHEN BNE => do_branch_v := NOT isZero_v; - WHEN BLT => do_branch_v := signBit_rA_v; - WHEN BLE => do_branch_v := signBit_rA_v OR isZero_v; - WHEN BGT => do_branch_v := NOT (signBit_rA_v OR isZero_v); - WHEN BGE => do_branch_v := NOT signBit_rA_v; - WHEN OTHERS => NULL; - END CASE; - IF (do_branch_v = '1') THEN - EX2IF_o.take_branch <= '1'; - EX2IF_o.branch_target <= result_v; - ELSE - EX2IF_o.take_branch <= '0'; - EX2IF_o.branch_target <= C_32_ZEROS; - END IF; - - -- CMP conditioning - IF (COMPATIBILITY_MODE_g = FALSE) THEN - CASE cmp_cond_type_v IS - WHEN COND_TYPE_ALL => - EX2CTRL_o.flush_first <= '0'; - EX2CTRL_o.flush_second <= '0'; - WHEN COND_TYPE_IF_THEN => - EX2CTRL_o.flush_first <= not do_cmp_cond_v; - EX2CTRL_o.flush_second <= '0'; - WHEN COND_TYPE_IF_THEN_THEN => - EX2CTRL_o.flush_first <= not do_cmp_cond_v; - EX2CTRL_o.flush_second <= not do_cmp_cond_v; - WHEN COND_TYPE_IF_THEN_ELSE => - EX2CTRL_o.flush_first <= not do_cmp_cond_v; - EX2CTRL_o.flush_second <= do_cmp_cond_v; - WHEN OTHERS => - NULL; - END CASE; - END IF; - - -- Halting - HALT_o.halt <= halt_v; - HALT_o.halt_code <= halt_code_v; - - -- WR_MEM/RD_MEM: result_v --> exeq_result --> mem_address, - -- WR_MEM: data_rD --> data_out_to_mem - -- BRL: prog_counter --> exeq_result - -- else result_v --> exeq_result (data_rD not used) - EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD; - IF (ID2EX_i.branch_Action = BRL) THEN - EX2MEM_o.wrb_Action <= WRB_EX; - EX2MEM_o.exeq_result <= ID2EX_i.program_counter; - EX2MEM_o.data_rD <= ID2EX_i.program_counter; - -- set data_rD_v, although unused, to prevent an inferred latch - data_rD_v := GPRF2EX_i.data_rD; - ELSE - EX2MEM_o.wrb_Action <= ID2EX_i.wrb_Action; - EX2MEM_o.exeq_result <= result_v; - -- test where to obtain data_rD from - IF (HAZARD_WRB_i.hazard = '1') THEN - data_rD_v := HAZARD_WRB_i.data_rD; - ELSIF ((EX_WRB_i.wrb_Action = WRB_EX) AND (ID2EX_i.curr_rD = EX_WRB_i.wrix_rD)) THEN - -- forward rD_data just calculated, to handle e.g. addi rD,rA,Imm; sw rD,mem[y]; ... - data_rD_v := EX_WRB_i.data_rD; - ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.curr_rD = MEM_WRB_i.wrix_rD)) THEN - data_rD_v := MEM_WRB_i.data_rD; - ELSE - data_rD_v := GPRF2EX_i.data_rD; - END IF; - END IF; - IF (ID2EX_i.mem_Action /= NO_MEM) THEN - CASE ID2EX_i.transfer_Size IS - WHEN BYTE => - CASE result_v( 1 DOWNTO 0) IS - WHEN "00" => byte_Enable_v := "1000"; - WHEN "01" => byte_Enable_v := "0100"; - WHEN "10" => byte_Enable_v := "0010"; - WHEN "11" => byte_Enable_v := "0001"; - WHEN OTHERS => NULL; - END CASE; - WHEN HALFWORD => - CASE result_v( 1 DOWNTO 0) IS - WHEN "00" => byte_Enable_v := "1100"; - WHEN "10" => byte_Enable_v := "0011"; - WHEN OTHERS => NULL; - END CASE; - WHEN OTHERS => byte_Enable_v := "1111"; - END CASE; - END IF; - - -- update MSR[IE] and/or MSR[C] if needed - IF (ID2EX_i.alu_Action /= A_MTS) THEN - MSR_o.IE <= MSR_i.IE; - IF (ID2EX_i.msr_Action = UPDATE_CARRY) THEN - MSR_o.C <= carry_o_v; - ELSE - MSR_o.C <= MSR_i.C; - END IF; - END IF; - - -- pass remaining data to mem - EX2MEM_o.mem_Action <= ID2EX_i.mem_Action; - EX2MEM_o.data_rD <= data_rD_v; - EX2MEM_o.byte_Enable <= byte_Enable_v; - EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD; - -- - IMM_LOCK_o.locked <= ID2EX_i.IMM_Lock; - IMM_LOCK_o.IMM_hi16 <= ID2EX_i.IMM16; - -- - EX_WRB_o.wrb_Action <= ID2EX_i.wrb_Action; - EX_WRB_o.wrix_rD <= ID2EX_i.curr_rD; - EX_WRB_o.data_rD <= result_v; - -- - HAZARD_WRB_o.hazard <= hazard_v; - HAZARD_WRB_o.save_rX <= save_rX_v; - HAZARD_WRB_o.data_rX <= data_rX_v; - HAZARD_WRB_o.data_rD <= data_rD_v; - - END PROCESS; + PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i, + IMM_LOCK_i, MSR_i, HAZARD_WRB_i) + + -- function needed by BSLL (only if USE_BARREL_g = TRUE) + FUNCTION reverse_bits ( word32 : STD_LOGIC_VECTOR (31 DOWNTO 0) ) + RETURN STD_LOGIC_VECTOR IS + VARIABLE reversed_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + BEGIN + f_rev: + FOR i IN 0 TO 31 LOOP + reversed_v(31-i) := word32(i); + END LOOP; + RETURN reversed_v; + END; + + VARIABLE data_rA_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE data_rB_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE data_rD_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE in1_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE in2_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE hi16_v : STD_LOGIC_VECTOR (15 DOWNTO 0); + VARIABLE IMM32_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE carry_i_v : STD_LOGIC; + VARIABLE result_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE carry_o_v : STD_LOGIC; + VARIABLE isZero_v : STD_LOGIC; + VARIABLE signBit_in1_v : STD_LOGIC; + VARIABLE signBit_in2_v : STD_LOGIC; + VARIABLE signBit_r_v : STD_LOGIC; + VARIABLE rA_eq_ex_rD_v : STD_LOGIC; + VARIABLE rB_eq_ex_rD_v : STD_LOGIC; + VARIABLE hazard_v : STD_LOGIC; + VARIABLE save_rX_v : SAVE_REG_Type; + VARIABLE data_rX_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + VARIABLE do_branch_v : STD_LOGIC; + VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0); + VARIABLE tmp64_v : STD_LOGIC_VECTOR (63 DOWNTO 0); + VARIABLE padVec_v : STD_LOGIC_VECTOR (15 DOWNTO 0); + VARIABLE do_cond_v : STD_LOGIC; + + BEGIN + + rA_eq_ex_rD_v := '0'; + rB_eq_ex_rD_v := '0'; + hazard_v := '0'; + save_rX_v := NO_SAVE; + data_rX_v := data_rB_v; -- default value for data_rX_v + result_v := (OTHERS => '0'); + carry_o_v := '0'; + do_branch_v := '0'; + byte_Enable_v := (OTHERS => '0'); + do_cond_v := '0'; + -- + MSR_o <= MSR_i; -- pass MSR by default + + -- create some helper variables + IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN + rA_eq_ex_rD_v := '1'; + END IF; + IF (ID2EX_i.rdix_rB = EX_WRB_i.wrix_rD) THEN + rB_eq_ex_rD_v := '1'; + END IF; + -- test where to obtain data_rA from + IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rA_eq_ex_rD_v = '1')) THEN + data_rA_v := EX_WRB_i.data_rD; + ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rA = MEM_WRB_i.wrix_rD)) THEN + data_rA_v := MEM_WRB_i.data_rD; + ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RA)) THEN + data_rA_v := HAZARD_WRB_i.data_rX; + ELSE + data_rA_v := GPRF2EX_i.data_rA; + END IF; + -- test where to obtain data_rB from + IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rB_eq_ex_rD_v = '1')) THEN + data_rB_v := EX_WRB_i.data_rD; + ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rB = MEM_WRB_i.wrix_rD)) THEN + data_rB_v := MEM_WRB_i.data_rD; + ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RB)) THEN + data_rB_v := HAZARD_WRB_i.data_rX; + ELSE + data_rB_v := GPRF2EX_i.data_rB; + END IF; + -- .... or, isn't all necessary data available yet being still in the pipeline ? + data_rX_v := data_rB_v; -- default value for data_rX_v + IF (EX_WRB_i.wrb_Action = WRB_MEM) THEN + IF ((rA_eq_ex_rD_v = '1') OR (rB_eq_ex_rD_v = '1')) THEN + hazard_v := '1'; + IF (rA_eq_ex_rD_v = '1') THEN + save_rX_v := SAVE_RB; -- already by default data_rX_v = data_rB_v + ELSE + save_rX_v := SAVE_RA; + data_rX_v := data_rA_v; + END IF; + END IF; + END IF; + + IF (IMM_LOCK_i.locked = '1') THEN + hi16_v := IMM_LOCK_i.IMM_hi16; + ELSIF (ID2EX_i.IMM16(15) = '0') THEN + hi16_v := C_16_ZEROS; + ELSE + hi16_v := C_16_ONES; + END IF; + IMM32_v := hi16_v & ID2EX_i.IMM16; + + CASE ID2EX_i.alu_Op1 IS + WHEN ALU_IN_REGA => in1_v := data_rA_v; + WHEN ALU_IN_NOT_REGA => in1_v := NOT data_rA_v; + WHEN ALU_IN_PC => in1_v := ID2EX_i.program_counter; + WHEN ALU_IN_ZERO => in1_v := C_32_ZEROS; + WHEN OTHERS => NULL; + END CASE; + + CASE ID2EX_i.alu_Op2 IS + WHEN ALU_IN_REGB => in2_v := data_rB_v; + WHEN ALU_IN_NOT_REGB => in2_v := NOT data_rB_v; + WHEN ALU_IN_IMM => in2_v := IMM32_v; + WHEN ALU_IN_NOT_IMM => in2_v := NOT IMM32_v; + WHEN OTHERS => NULL; + END CASE; + + signBit_in1_v := in1_v(31); + signBit_in2_v := in2_v(31); + signBit_r_v := data_rA_v(31); -- Init with Op1, then possibly override + + CASE ID2EX_i.alu_Cin IS + WHEN CIN_ZERO => carry_i_v := '0'; + WHEN CIN_ONE => carry_i_v := '1'; + WHEN FROM_MSR => carry_i_v := MSR_i.C; + WHEN FROM_IN1 => carry_i_v := in1_v(31); + WHEN OTHERS => carry_i_v := '0'; + END CASE; + + IF (data_rA_v = C_32_ZEROS) THEN + isZero_v := '1'; + ELSE + isZero_v := '0'; + END IF; + + CASE ID2EX_i.alu_Action IS + + WHEN A_ADD | A_CMP | A_CMPU => + ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v); + CASE ID2EX_i.alu_Action IS + + WHEN A_CMPU => + IF (signBit_in1_v = signBit_in2_v) THEN + signBit_r_v := NOT signBit_in1_v; + END IF; + IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN + -- have to update zero flag with current result + IF (result_v = C_32_ZEROS) THEN + isZero_v := '1'; + ELSE + isZero_v := '0'; + END IF; + END IF; + + WHEN A_CMP => + IF (signBit_in1_v = signBit_in2_v) THEN + signBit_r_v := signBit_in1_v; + END IF; + IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN + -- have to update zero flag with current result + IF (result_v = C_32_ZEROS) THEN + isZero_v := '1'; + ELSE + isZero_v := '0'; + END IF; + END IF; + + WHEN OTHERS => + NULL; + + END CASE; + + WHEN A_OR => + result_v := in1_v OR in2_v; + + WHEN A_AND => + result_v := in1_v AND in2_v; + + WHEN A_XOR => + result_v := in1_v XOR in2_v; + + WHEN A_SHIFT => + result_v := carry_i_v & in1_v(31 DOWNTO 1); + carry_o_v := in1_v(0); + + WHEN A_SEXT8 => + IF (in1_v(7) = '0') THEN + result_v := C_24_ZEROS & in1_v( 7 DOWNTO 0); + ELSE + result_v := C_24_ONES & in1_v( 7 DOWNTO 0); + END IF; + + WHEN A_SEXT16 => + IF (in1_v(15) = '0') THEN + result_v := C_16_ZEROS & in1_v(15 DOWNTO 0); + ELSE + result_v := C_16_ONES & in1_v(15 DOWNTO 0); + END IF; + + WHEN A_MFS => + result_v := MSR_i.C & C_24_ZEROS & "0000" & MSR_i.C & MSR_i.IE & '0'; + + WHEN A_MTS => + MSR_o.IE <= data_Ra_v(1); + MSR_o.C <= data_Ra_v(2); + + WHEN A_MUL => + IF (USE_HW_MUL_g = TRUE) THEN + tmp64_v := STD_LOGIC_VECTOR( UNSIGNED(in1_v) * UNSIGNED(in2_v) ); + result_v := tmp64_v(31 DOWNTO 0); + END IF; + + WHEN A_BSLL | A_BSRL | A_BSRA => + IF (USE_BARREL_g = TRUE) THEN + IF (ID2EX_i.alu_Action = A_BSLL) THEN + result_v := reverse_bits (in1_v); + ELSE + result_v := in1_v; + END IF; + IF (ID2EX_i.alu_Action = A_BSRA) THEN + padVec_v := (OTHERS => in1_v(31)); + ELSE + padVec_v := (OTHERS => '0'); + END IF; + IF (in2_v(4) = '1') THEN + result_v := padVec_v (15 DOWNTO 0) & result_v (31 DOWNTO 16); + END IF; + IF (in2_v(3) = '1') THEN + result_v := padVec_v ( 7 DOWNTO 0) & result_v (31 DOWNTO 8); + END IF; + IF (in2_v(2) = '1') THEN + result_v := padVec_v ( 3 DOWNTO 0) & result_v (31 DOWNTO 4); + END IF; + IF (in2_v(1) = '1') THEN + result_v := padVec_v ( 1 DOWNTO 0) & result_v (31 DOWNTO 2); + END IF; + IF (in2_v(0) = '1') THEN + result_v := padVec_v ( 0 DOWNTO 0) & result_v (31 DOWNTO 1); + END IF; + IF (ID2EX_i.alu_Action = A_BSLL) THEN + result_v := reverse_bits (result_v); + END IF; + END IF; -- (USE_BARREL_g = TRUE) + + WHEN OTHERS => + NULL; + + END CASE; + + CASE ID2EX_i.condition IS + WHEN COND_EQ => do_cond_v := isZero_v; + WHEN COND_NE => do_cond_v := NOT isZero_v; + WHEN COND_LT => do_cond_v := signBit_r_v; + WHEN COND_LE => do_cond_v := signBit_r_v OR isZero_v; + WHEN COND_GT => do_cond_v := NOT (signBit_r_v OR isZero_v); + WHEN COND_GE => do_cond_v := NOT signBit_r_v; + WHEN COND_ALL => do_cond_v := '1'; + WHEN OTHERS => NULL; + END CASE; + + CASE ID2EX_i.branch_Action IS + WHEN BR => do_branch_v := do_cond_v; + WHEN BRL => do_branch_v := '1'; + WHEN OTHERS => NULL; + END CASE; + + IF (do_branch_v = '1') THEN + EX2IF_o.take_branch <= '1'; + EX2IF_o.branch_target <= result_v; + ELSE + EX2IF_o.take_branch <= '0'; + EX2IF_o.branch_target <= C_32_ZEROS; + END IF; + + -- IT / ITE / ITT conditioning + IF (COMPATIBILITY_MODE_g = FALSE) THEN + CASE ID2EX_i.it_Action IS + WHEN IT => + EX2CTRL_o.flush_first <= not do_cond_v; + EX2CTRL_o.flush_second <= '0'; + EX2CTRL_o.ignore_state <= '1'; + WHEN ITT => + EX2CTRL_o.flush_first <= not do_cond_v; + EX2CTRL_o.flush_second <= not do_cond_v; + EX2CTRL_o.ignore_state <= '1'; + WHEN ITE => + EX2CTRL_o.flush_first <= not do_cond_v; + EX2CTRL_o.flush_second <= do_cond_v; + EX2CTRL_o.ignore_state <= '1'; + WHEN OTHERS => + EX2CTRL_o.flush_first <= '0'; + EX2CTRL_o.flush_second <= '0'; + EX2CTRL_o.ignore_state <= '0'; + END CASE; + END IF; + + -- Halting, the instruction parsing is separate + HALT_o.halt <= ID2EX_i.halt; + IF (ID2EX_i.halt = '1') THEN + HALT_o.halt_code <= ID2EX_i.IMM16(4 DOWNTO 0); + ELSE + HALT_o.halt_code <= (others => '0'); + END IF; + + -- WR_MEM/RD_MEM: result_v --> exeq_result --> mem_address, + -- WR_MEM: data_rD --> data_out_to_mem + -- BRL: prog_counter --> exeq_result + -- else result_v --> exeq_result (data_rD not used) + EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD; + IF (ID2EX_i.branch_Action = BRL) THEN + EX2MEM_o.wrb_Action <= WRB_EX; + EX2MEM_o.exeq_result <= ID2EX_i.program_counter; + EX2MEM_o.data_rD <= ID2EX_i.program_counter; + -- set data_rD_v, although unused, to prevent an inferred latch + data_rD_v := GPRF2EX_i.data_rD; + ELSE + EX2MEM_o.wrb_Action <= ID2EX_i.wrb_Action; + EX2MEM_o.exeq_result <= result_v; + -- test where to obtain data_rD from + IF (HAZARD_WRB_i.hazard = '1') THEN + data_rD_v := HAZARD_WRB_i.data_rD; + ELSIF ((EX_WRB_i.wrb_Action = WRB_EX) AND (ID2EX_i.curr_rD = EX_WRB_i.wrix_rD)) THEN + -- forward rD_data just calculated, to handle e.g. addi rD,rA,Imm; sw rD,mem[y]; ... + data_rD_v := EX_WRB_i.data_rD; + ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.curr_rD = MEM_WRB_i.wrix_rD)) THEN + data_rD_v := MEM_WRB_i.data_rD; + ELSE + data_rD_v := GPRF2EX_i.data_rD; + END IF; + END IF; + + IF (ID2EX_i.mem_Action /= NO_MEM) THEN + CASE ID2EX_i.transfer_Size IS + + WHEN BYTE => + CASE result_v( 1 DOWNTO 0) IS + WHEN "00" => byte_Enable_v := "1000"; + WHEN "01" => byte_Enable_v := "0100"; + WHEN "10" => byte_Enable_v := "0010"; + WHEN "11" => byte_Enable_v := "0001"; + WHEN OTHERS => NULL; + END CASE; + + WHEN HALFWORD => + CASE result_v( 1 DOWNTO 0) IS + WHEN "00" => byte_Enable_v := "1100"; + WHEN "10" => byte_Enable_v := "0011"; + WHEN OTHERS => NULL; + END CASE; + + WHEN OTHERS => byte_Enable_v := "1111"; + + END CASE; + END IF; + + -- update MSR[C] if needed + IF (ID2EX_i.msr_Action = UPDATE_CARRY) THEN + MSR_o.C <= carry_o_v; + END IF; + + -- pass remaining data to mem + EX2MEM_o.mem_Action <= ID2EX_i.mem_Action; + EX2MEM_o.data_rD <= data_rD_v; + EX2MEM_o.byte_Enable <= byte_Enable_v; + EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD; + -- + IMM_LOCK_o.locked <= ID2EX_i.IMM_Lock; + IMM_LOCK_o.IMM_hi16 <= ID2EX_i.IMM16; + -- + EX_WRB_o.wrb_Action <= ID2EX_i.wrb_Action; + EX_WRB_o.wrix_rD <= ID2EX_i.curr_rD; + EX_WRB_o.data_rD <= result_v; + -- + HAZARD_WRB_o.hazard <= hazard_v; + HAZARD_WRB_o.save_rX <= save_rX_v; + HAZARD_WRB_o.data_rX <= data_rX_v; + HAZARD_WRB_o.data_rD <= data_rD_v; + + END PROCESS; END ARCHITECTURE rtl; diff --git a/hw/mbl_Pkg.vhd b/hw/mbl_Pkg.vhd index c81f642..0f48b09 100644 --- a/hw/mbl_Pkg.vhd +++ b/hw/mbl_Pkg.vhd @@ -9,7 +9,7 @@ -- Faculty EEMCS, Department ME&CE, Circuits and Systems -- Date: September, 2010 -- --- Modified: September, 2013: Removed FSL +-- Modified: September, 2013: Removed FSL, core customization -- June, 2011: ALU_ACTION_Type extended to incorporate -- MUL and BS instructions (Huib) -- Adapted to work with separate fsl_M- @@ -25,429 +25,389 @@ 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_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"; + 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_HALT); - 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); - 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 CMP_COND_Type IS (COND_ALL, COND_EQ, COND_NE, COND_LT, COND_LE, COND_GT, COND_GE); - TYPE CMP_COND_TYPE_Type IS (COND_TYPE_ALL, COND_TYPE_IF_THEN, COND_TYPE_IF_THEN_THEN, COND_TYPE_IF_THEN_ELSE); - -- - 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; - cmp_Cond : CMP_COND_Type; - cmp_Cond_Type : CMP_COND_TYPE_Type; - 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] - END RECORD; - - TYPE EX2IF_Type IS RECORD - take_branch : STD_LOGIC; - branch_target : STD_LOGIC_VECTOR (31 DOWNTO 0); - END RECORD; - - TYPE EX2CTRL_Type IS RECORD - flush_first : STD_LOGIC; - flush_second : STD_LOGIC; - END RECORD; - - TYPE HALT_Type IS RECORD - halt : STD_LOGIC; - halt_code : STD_LOGIC_VECTOR ( 4 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 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 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); + 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); + TYPE IT_ACTION_Type IS (NO_IT, IT, ITT, ITE); + TYPE WRB_ACTION_Type IS (NO_WRB, WRB_EX, WRB_MEM); + 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 COND_Type IS (COND_ALL, COND_EQ, COND_NE, COND_LT, COND_LE, COND_GT, COND_GE); + -- + 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; + it_Action : IT_ACTION_Type; + mem_Action : MEM_ACTION_Type; -- rd_mem implies writeback + transfer_Size : TRANSFER_SIZE_Type; + wrb_Action : WRB_ACTION_Type; + condition : COND_Type; + halt : 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] + END RECORD; + + TYPE EX2IF_Type IS RECORD + take_branch : STD_LOGIC; + branch_target : STD_LOGIC_VECTOR (31 DOWNTO 0); + END RECORD; + + TYPE EX2CTRL_Type IS RECORD + flush_first : STD_LOGIC; + flush_second : STD_LOGIC; + ignore_state : STD_LOGIC; + END RECORD; + + TYPE HALT_Type IS RECORD + halt : STD_LOGIC; + halt_code : STD_LOGIC_VECTOR ( 4 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 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 !! ---------------------------------------------------------------------------------------------- -- 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 := TRUE; - USE_BARREL_g : BOOLEAN := TRUE; - COMPATIBILITY_MODE_g : BOOLEAN := FALSE - ); - PORT ( - IF2ID_i : IN IF2ID_Type; - imem_data_i : IN STD_LOGIC_VECTOR (31 DOWNTO 0); - -- - ID2GPRF_o : OUT ID2GPRF_Type; - ID2EX_o : OUT ID2EX_Type; - -- - INT_CTRL_i : IN INT_CTRL_Type; - ID2CTRL_o : OUT ID2CTRL_Type; - -- - noLiteOpc_o : OUT STD_LOGIC - ); - END 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; - COMPATIBILITY_MODE_g : BOOLEAN := FALSE - ); - PORT ( - ID2EX_i : IN ID2EX_Type; - GPRF2EX_i : IN GPRF2EX_Type; - EX2IF_o : OUT EX2IF_Type; - EX2CTRL_o : OUT EX2CTRL_Type; - HALT_o : OUT HALT_Type; - -- - EX_WRB_i : IN WRB_Type; - EX_WRB_o : OUT WRB_Type; - MEM_WRB_i : IN WRB_Type; - -- - HAZARD_WRB_i : IN HAZARD_WRB_Type; - HAZARD_WRB_o : OUT HAZARD_WRB_Type; - -- - IMM_LOCK_i : IN IMM_LOCK_Type; - IMM_LOCK_o : OUT IMM_LOCK_Type; - -- - MSR_i : IN MSR_Type; - MSR_o : OUT MSR_Type; - -- - EX2MEM_o : OUT EX2MEM_Type - ); - END COMPONENT; - - COMPONENT mem IS - PORT ( - EX2MEM_i : IN EX2MEM_Type; - -- - DMEMB_i : IN DMEMB2CORE_Type; - DMEMB_o : OUT CORE2DMEMB_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 - GENERIC ( - COMPATIBILITY_MODE_g : BOOLEAN := FALSE - ); - PORT ( - clk_i : IN STD_LOGIC; - rst_i : IN STD_LOGIC; - halt_i : IN STD_LOGIC; - bad_op_i : IN STD_LOGIC; - int_i : IN STD_LOGIC; - trace_i : IN STD_LOGIC; - trace_kick_i : IN STD_LOGIC; - core_clken_o : OUT 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; - EX2CTRL_REG_i : IN EX2CTRL_Type; - -- exeq to core (halting) - exeq_halt_i : IN STD_LOGIC; - -- 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; - -- 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 - ); - END COMPONENT; + 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 := TRUE; + USE_BARREL_g : BOOLEAN := TRUE; + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); + PORT + ( + IF2ID_i : IN IF2ID_Type; + imem_data_i : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + -- + ID2GPRF_o : OUT ID2GPRF_Type; + ID2EX_o : OUT ID2EX_Type; + -- + INT_CTRL_i : IN INT_CTRL_Type; + ID2CTRL_o : OUT ID2CTRL_Type; + -- + noLiteOpc_o : OUT STD_LOGIC + ); + END COMPONENT; + + COMPONENT exeq IS + GENERIC + ( + USE_HW_MUL_g : BOOLEAN := FALSE; + USE_BARREL_g : BOOLEAN := FALSE; + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); + PORT + ( + ID2EX_i : IN ID2EX_Type; + GPRF2EX_i : IN GPRF2EX_Type; + EX2IF_o : OUT EX2IF_Type; + EX2CTRL_o : OUT EX2CTRL_Type; + HALT_o : OUT HALT_Type; + -- + EX_WRB_i : IN WRB_Type; + EX_WRB_o : OUT WRB_Type; + MEM_WRB_i : IN WRB_Type; + -- + HAZARD_WRB_i : IN HAZARD_WRB_Type; + HAZARD_WRB_o : OUT HAZARD_WRB_Type; + -- + IMM_LOCK_i : IN IMM_LOCK_Type; + IMM_LOCK_o : OUT IMM_LOCK_Type; + -- + MSR_i : IN MSR_Type; + MSR_o : OUT MSR_Type; + -- + EX2MEM_o : OUT EX2MEM_Type + ); + END COMPONENT; + + COMPONENT mem IS + PORT + ( + EX2MEM_i : IN EX2MEM_Type; + -- + DMEMB_i : IN DMEMB2CORE_Type; + DMEMB_o : OUT CORE2DMEMB_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 + GENERIC + ( + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); + PORT + ( + clk_i : IN STD_LOGIC; + rst_i : IN STD_LOGIC; + halt_i : IN STD_LOGIC; + bad_op_i : IN STD_LOGIC; + int_i : IN STD_LOGIC; + trace_i : IN STD_LOGIC; + trace_kick_i : IN STD_LOGIC; + core_clken_o : OUT 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; + EX2CTRL_REG_i : IN EX2CTRL_Type; + -- exeq to core (halting) + exeq_halt_i : IN STD_LOGIC; + -- 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; + -- 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 + ); + 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_add32nc ( a, b : IN STD_LOGIC_VECTOR (31 DOWNTO 0); - ci : IN STD_LOGIC; - VARIABLE s : OUT STD_LOGIC_VECTOR (31 DOWNTO 0)); + 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 ); + PROCEDURE ep_add32nc ( a, b : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + ci : IN STD_LOGIC; + VARIABLE s : OUT STD_LOGIC_VECTOR (31 DOWNTO 0)); - FUNCTION ef_nbits ( value : NATURAL ) RETURN POSITIVE; + 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_add32nc ( a, b : IN STD_LOGIC_VECTOR (31 DOWNTO 0); - ci : IN STD_LOGIC; - VARIABLE s : OUT STD_LOGIC_VECTOR (31 DOWNTO 0) ) 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); - ELSE - s := tmp_hi1_v(NBITS_HI_c DOWNTO 1) & tmp_lo_v(NBITS_LO_c DOWNTO 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 + 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_add32nc ( a, b : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + ci : IN STD_LOGIC; + VARIABLE s : OUT STD_LOGIC_VECTOR (31 DOWNTO 0) ) 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); + ELSE + s := tmp_hi1_v(NBITS_HI_c DOWNTO 1) & tmp_lo_v(NBITS_LO_c DOWNTO 1); + END IF; + END PROCEDURE; + + + 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; diff --git a/hw/mem.vhd b/hw/mem.vhd index 6d54982..139451c 100644 --- a/hw/mem.vhd +++ b/hw/mem.vhd @@ -14,122 +14,122 @@ -- 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; - -- - 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 - ); + PORT + ( + EX2MEM_i : IN EX2MEM_Type; + -- + DMEMB_i : IN DMEMB2CORE_Type; + DMEMB_o : OUT CORE2DMEMB_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; + -- 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) - VARIABLE exeq_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0); - VARIABLE dmem_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0); + PROCESS (EX2MEM_i, DMEMB_i, MEM_REG_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 + CASE EX2MEM_i.mem_Action IS - BEGIN + 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 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; - -- 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; + 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'); - -- 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 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; + 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 OTHERS => MEM_WRB_o.data_rD <= MEM_REG_i.exeq_result; - END CASE; + -- additional wrb signals + CASE MEM_REG_i.wrb_Action IS + WHEN WRB_MEM => MEM_WRB_o.data_rD <= dmem_data_v; + WHEN OTHERS => MEM_WRB_o.data_rD <= MEM_REG_i.exeq_result; + END CASE; - END PROCESS; + END PROCESS; END ARCHITECTURE rtl; -- 2.39.2