1 ---------------------------------------------------------------------------------
4 -- Filename: core_ctrl.vhd
5 -- Description: the control unit for the TUD MB-Lite implementation
7 -- Author: Huib Lincklaen Arriens
8 -- Delft University of Technology
9 -- Faculty EEMCS, Department ME&CE, Circuits and Systems
10 -- Date: December, 2010
11 -- Modified: September, 2012: interrupt handling corrected to let
12 -- a pending branch be taken first
13 -- (with thanks to Matthis Meier, TU Dortmund,
14 -- for detecting this errror).
17 --------------------------------------------------------------------------------
21 USE IEEE.std_logic_1164.all;
24 --------------------------------------------------------------------------------
26 --------------------------------------------------------------------------------
28 COMPATIBILITY_MODE_g : BOOLEAN := FALSE
33 halt_i : IN STD_LOGIC;
34 bad_op_i : IN STD_LOGIC;
36 trace_i : IN STD_LOGIC;
37 trace_kick_i : IN STD_LOGIC;
38 core_clken_o : OUT STD_LOGIC;
40 imem_addr_o : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
41 imem_clken_o : OUT STD_LOGIC;
42 pc_ctrl_o : OUT STD_LOGIC;
43 -- fetch to decode pipeline registers
44 IF2ID_REG_i : IN IF2ID_Type;
45 IF2ID_REG_o : OUT IF2ID_Type;
46 -- decode to exeq pipeline registers
47 ID2EX_REG_i : IN ID2EX_Type;
48 ID2EX_REG_o : OUT ID2EX_Type;
50 gprf_clken_o : OUT STD_LOGIC;
51 -- exeq to fetch feedback registers
52 EX2IF_REG_i : IN EX2IF_Type;
53 EX2IF_REG_o : OUT EX2IF_Type;
54 EX2CTRL_REG_i : IN EX2CTRL_Type;
55 -- exeq to core (halting)
56 exeq_halt_i : IN STD_LOGIC;
57 -- exeq to mem pipeline registers
58 EX2MEM_REG_i : IN EX2MEM_Type;
59 EX2MEM_REG_o : OUT EX2MEM_Type;
60 -- mem pipeline register
61 MEM_REG_i : IN MEM_REG_Type;
62 MEM_REG_o : OUT MEM_REG_Type;
64 ID2CTRL_i : IN ID2CTRL_Type;
65 INT_CTRL_o : OUT INT_CTRL_Type;
67 EX_WRB_i : IN WRB_Type;
68 EX_WRB_o : OUT WRB_Type;
70 HAZARD_WRB_i : IN HAZARD_WRB_Type;
71 HAZARD_WRB_o : OUT HAZARD_WRB_Type;
72 -- for handling the 'IMM' instruction
73 IMM_LOCK_i : IN IMM_LOCK_Type;
74 IMM_LOCK_o : OUT IMM_LOCK_Type;
75 -- for handling the Machine Status Register
79 MEM2CTRL_i : IN MEM2CTRL_Type
83 --------------------------------------------------------------------------------
84 ARCHITECTURE rtl OF core_ctrl IS
85 --------------------------------------------------------------------------------
87 SIGNAL rst_r : STD_LOGIC;
88 SIGNAL reset_s : STD_LOGIC;
89 SIGNAL core_clken_s : STD_LOGIC;
91 SIGNAL ID2EX_REG_r : ID2EX_Type;
92 SIGNAL EX2IF_REG_r : EX2IF_Type;
93 SIGNAL IMM_LOCK_r : IMM_LOCK_Type;
94 SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type;
95 SIGNAL flush_second_r : STD_LOGIC;
96 SIGNAL delayBit_r : STD_LOGIC;
97 SIGNAL clken_s : STD_LOGIC;
98 SIGNAL clken_pipe_s : STD_LOGIC;
99 SIGNAL flush_ID2EX_s : STD_LOGIC;
100 SIGNAL flush_ID2EX_r : STD_LOGIC;
101 SIGNAL flush_EX2MEM_s : STD_LOGIC;
103 SIGNAL setup_int_r : STD_LOGIC;
104 SIGNAL int_busy_r : STD_LOGIC;
108 -- static connections
109 reset_s <= rst_i OR rst_r;
110 pc_ctrl_o <= NOT rst_r;
111 imem_addr_o <= IF2ID_REG_i.program_counter;
113 -- Reset_s is 1 when rst_i is one and then gets deactivated
114 core_clken_s <= reset_s OR ((NOT bad_op_i) AND (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i));
115 core_clken_o <= core_clken_s;
116 -- clock/wait control lines
117 clken_s <= MEM2CTRL_i.clken OR rst_i;
118 clken_pipe_s <= clken_s AND (NOT HAZARD_WRB_i.hazard);
119 imem_clken_o <= clken_pipe_s;
120 gprf_clken_o <= clken_s;
121 -- signals for clearing the ID2EX and EX2MEM registers during branches
122 flush_ID2EX_s <= ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE
123 ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR flush_second_r);
124 flush_EX2MEM_s <= HAZARD_WRB_i.hazard;
125 -- outputs that need to be readable too, so needing shadowing signals
126 ID2EX_REG_o <= ID2EX_REG_r;
127 EX2IF_REG_o <= EX2IF_REG_r;
128 IMM_LOCK_o <= IMM_LOCK_r;
129 HAZARD_WRB_o <= HAZARD_WRB_r;
131 INT_CTRL_o.setup_int <= setup_int_r;
132 INT_CTRL_o.rti_target <= ID2EX_REG_r.program_counter;
133 INT_CTRL_o.int_busy <= int_busy_r;
136 PROCESS ( clk_i, rst_i, halt_i, core_clken_s,
137 -- complete sensitivity list for synthesizer
138 reset_s, MEM2CTRL_i, clken_pipe_s, IF2ID_REG_i,
139 flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i,
140 MEM_REG_i, ID2CTRL_i, int_i, MSR_i,
141 int_busy_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
142 EX2IF_REG_i, EX2CTRL_REG_i, EX_WRB_i, EX2MEM_REG_i )
144 -- some local procedures
145 PROCEDURE lp_rst_IF2ID_REG IS
147 IF2ID_REG_o.program_counter <= (OTHERS => '0');
150 PROCEDURE lp_rst_ID2EX_REG IS
152 -- reset and handle ID2EX_REG_r.program_counter separately,
153 -- since it will be needed during interrupt setup
154 ID2EX_REG_r.rdix_rA <= (OTHERS => '0');
155 ID2EX_REG_r.rdix_rB <= (OTHERS => '0');
156 ID2EX_REG_r.curr_rD <= (OTHERS => '0');
157 ID2EX_REG_r.alu_Action <= A_NOP;
158 ID2EX_REG_r.alu_Op1 <= ALU_IN_ZERO;
159 ID2EX_REG_r.alu_Op2 <= ALU_IN_IMM;
160 ID2EX_REG_r.alu_Cin <= CIN_ZERO;
161 ID2EX_REG_r.IMM16 <= (OTHERS => '0');
162 ID2EX_REG_r.IMM_Lock <= '0';
163 ID2EX_REG_r.msr_Action <= KEEP_CARRY;
164 ID2EX_REG_r.branch_Action <= NO_BR;
165 ID2EX_REG_r.mem_Action <= NO_MEM;
166 ID2EX_REG_r.transfer_Size <= WORD;
167 ID2EX_REG_r.wrb_Action <= NO_WRB;
170 PROCEDURE lp_rst_EX2IF_REG IS
172 EX2IF_REG_r.take_branch <= '0';
173 EX2IF_REG_r.branch_target <= (OTHERS => '0');
176 PROCEDURE lp_rst_EX2MEM_REG IS
178 EX2MEM_REG_o.mem_Action <= NO_MEM;
179 EX2MEM_REG_o.wrb_Action <= NO_WRB;
180 EX2MEM_REG_o.exeq_result <= (OTHERS => '0');
181 EX2MEM_REG_o.data_rD <= (OTHERS => '0');
182 EX2MEM_REG_o.byte_Enable <= (OTHERS => '0');
183 EX2MEM_REG_o.wrix_rD <= (OTHERS => '0');
186 PROCEDURE lp_rst_IMM_LOCK IS
188 IMM_LOCK_r.locked <= '0';
189 IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
192 PROCEDURE lp_rst_MSR IS
198 PROCEDURE lp_rst_EX_WRB IS
200 EX_WRB_o.wrb_Action <= NO_WRB;
201 EX_WRB_o.wrix_rD <= (OTHERS => '0');
202 EX_WRB_o.data_rD <= (OTHERS => '0');
205 PROCEDURE lp_rst_HAZARD_WRB IS
207 HAZARD_WRB_r.hazard <= '0';
208 HAZARD_WRB_r.save_rX <= NO_SAVE;
209 HAZARD_WRB_r.data_rX <= (OTHERS => '0');
210 HAZARD_WRB_r.data_rD <= (OTHERS => '0');
213 PROCEDURE lp_rst_MEM_REG IS
215 MEM_REG_o.wrb_Action <= NO_WRB;
216 MEM_REG_o.exeq_result <= (OTHERS => '0');
217 MEM_REG_o.byte_Enable <= (OTHERS => '0');
218 MEM_REG_o.wrix_rD <= (OTHERS => '0');
223 IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' AND
224 core_clken_s = '1' THEN
227 IF (reset_s = '1') THEN -- synchronous reset ...
228 lp_rst_IF2ID_REG; -- ... so lasts at least one clock_cycle
233 IF (COMPATIBILITY_MODE_g = TRUE) THEN
236 flush_second_r <= '0';
239 flush_ID2EX_r <= '0';
242 ID2EX_REG_r.program_counter <= (OTHERS => '0');
244 IF (clken_pipe_s = '1') THEN
245 IF2ID_REG_o <= IF2ID_REG_i;
247 flush_ID2EX_r <= flush_ID2EX_s;
248 IF (COMPATIBILITY_MODE_g = FALSE) THEN
249 flush_second_r <= EX2CTRL_REG_i.flush_second;
251 HAZARD_WRB_r <= HAZARD_WRB_i;
252 MEM_REG_o <= MEM_REG_i;
253 int_busy_r <= ID2CTRL_i.int_busy;
255 -- decode-to-exeq unit registers
256 IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
259 IF (COMPATIBILITY_MODE_g = TRUE) THEN
262 -- check for the need and possibility to handle active interrupt requests
263 ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND
264 (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND
265 -- pending branch should be taken before interrupt can be executed
266 -- dectected by Matthis Meier, TU Dortmund (Sept 2012)
267 (EX2IF_REG_i.take_branch = '0') AND
268 (EX2IF_REG_r.take_branch = '0') AND -- it is still pending a cycle after branching
269 (IMM_LOCK_i.locked = '0') AND
270 (HAZARD_WRB_i.hazard = '0')) THEN
272 ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
274 ELSIF (clken_pipe_s = '1') THEN
276 ID2EX_REG_r <= ID2EX_REG_i;
277 IF (COMPATIBILITY_MODE_g = TRUE) THEN
278 delayBit_r <= ID2CTRL_i.delayBit;
281 -- exeq-to-mem unit registers
282 IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
288 IF (clken_pipe_s = '1') THEN
289 EX2IF_REG_r <= EX2IF_REG_i;
290 EX_WRB_o <= EX_WRB_i;
292 IF (clken_s = '1') THEN
293 -- next test to prevent a flush from disrupting
294 -- the write-back pipeline
295 IF (flush_ID2EX_r = '0') THEN
296 EX2MEM_REG_o <= EX2MEM_REG_i;
298 IMM_LOCK_r <= IMM_LOCK_i;
302 END IF; -- rising edge clk_i ...
303 END PROCESS regd_proc;
305 END ARCHITECTURE rtl;