USE IEEE.std_logic_1164.all;
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_clk_en_o : OUT 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;
-- exeq to fetch feedback registers
EX2IF_REG_i : IN EX2IF_Type;
EX2IF_REG_o : OUT EX2IF_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;
MSR_i : IN MSR_Type;
MSR_o : OUT MSR_Type;
-- miscellaneous
- MEM2CTRL_i : IN MEM2CTRL_Type;
- done_o : OUT STD_LOGIC
+ MEM2CTRL_i : IN MEM2CTRL_Type
);
END ENTITY core_ctrl;
SIGNAL rst_r : STD_LOGIC;
SIGNAL reset_s : STD_LOGIC;
- SIGNAL core_clk_en_s : STD_LOGIC;
+ SIGNAL core_clken_s : STD_LOGIC;
SIGNAL ID2EX_REG_r : ID2EX_Type;
SIGNAL EX2IF_REG_r : EX2IF_Type;
- SIGNAL delayBit_r : STD_LOGIC;
- SIGNAL delayBit_2r : STD_LOGIC;
SIGNAL IMM_LOCK_r : IMM_LOCK_Type;
SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type;
-
+ SIGNAL delayBit_r : STD_LOGIC;
SIGNAL clken_s : STD_LOGIC;
SIGNAL clken_pipe_s : STD_LOGIC;
SIGNAL flush_ID2EX_s : STD_LOGIC;
SIGNAL setup_int_r : STD_LOGIC;
SIGNAL int_busy_r : STD_LOGIC;
-
BEGIN
-- static connections
imem_addr_o <= IF2ID_REG_i.program_counter;
-- Tracing
-- Reset_s is 1 when rst_i is one and then gets deactivated
- core_clk_en_s <= reset_s OR (NOT trace_i) OR trace_kick_i;
- core_clk_en_o <= core_clk_en_s;
+ 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_r.take_branch;
- flush_EX2MEM_s <= (flush_ID2EX_s AND (NOT delayBit_2r)) OR HAZARD_WRB_i.hazard;
+ 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);
+ 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;
INT_CTRL_o.int_busy <= int_busy_r;
regd_proc:
- PROCESS ( clk_i, rst_i, halt_i, core_clk_en_s,
+ 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, delayBit_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
+ int_busy_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
EX2IF_REG_i, EX_WRB_i, EX2MEM_REG_i )
-- some local procedures
BEGIN
IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' AND
- core_clk_en_s = '1' THEN
+ 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;
- delayBit_r <= '0';
+
+ IF (COMPATIBILITY_MODE_g = TRUE) THEN
+ delayBit_r <= '0';
+ END IF;
+
flush_ID2EX_r <= '0';
setup_int_r <= '0';
int_busy_r <= '0';
- done_o <= '0';
ID2EX_REG_r.program_counter <= (OTHERS => '0');
ELSE
IF (clken_pipe_s = '1') THEN
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;
- delayBit_r <= '0';
+ 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
- (delayBit_r = '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';
lp_rst_ID2EX_REG;
ELSIF (clken_pipe_s = '1') THEN
setup_int_r <= '0';
- if (EX2IF_REG_i.take_branch = '1') THEN
- lp_rst_ID2EX_REG;
- ELSE
- ID2EX_REG_r <= ID2EX_REG_i;
+ ID2EX_REG_r <= ID2EX_REG_i;
+ IF (COMPATIBILITY_MODE_g = TRUE) THEN
+ delayBit_r <= ID2CTRL_i.delayBit;
END IF;
- delayBit_r <= ID2CTRL_i.delayBit;
END IF;
-- exeq-to-mem unit registers
IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
lp_rst_EX2MEM_REG;
lp_rst_EX_WRB;
lp_rst_IMM_LOCK;
- delayBit_2r <= '0';
ELSE
IF (clken_pipe_s = '1') THEN
EX2IF_REG_r <= EX2IF_REG_i;
- delayBit_2r <= delayBit_r;
EX_WRB_o <= EX_WRB_i;
END IF;
IF (clken_s = '1') THEN
MSR_o <= MSR_i;
END IF;
END IF;
- -- check on End-Of-Program viz. "bri 0x00"
- -- use delayBit to distinguish between "bri" and "rtsd/rtid"
- IF ((ID2EX_REG_r.branch_Action = BR) AND
- (ID2EX_REG_r.alu_Op2 = ALU_IN_IMM) AND
- (ID2EX_REG_r.IMM16 = C_16_ZEROS) AND
- (delayBit_r = '0') AND (flush_EX2MEM_s = '0')) THEN
- done_o <= '1';
- END IF;
END IF; -- rising edge clk_i ...
END PROCESS regd_proc;