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, 2013: Core customization (Meloun)
12 -- September, 2012: interrupt handling corrected to let
13 -- a pending branch be taken first
14 -- (with thanks to Matthis Meier, TU Dortmund,
15 -- for detecting this errror).
18 --------------------------------------------------------------------------------
22 USE IEEE.std_logic_1164.all;
25 --------------------------------------------------------------------------------
27 --------------------------------------------------------------------------------
30 IMEM_ABITS_g : positive := 9;
31 COMPATIBILITY_MODE_g : BOOLEAN := FALSE
37 halt_i : IN STD_LOGIC;
39 trace_i : IN STD_LOGIC;
40 trace_kick_i : IN STD_LOGIC;
41 core_clken_o : OUT STD_LOGIC;
43 imem_addr_o : OUT STD_LOGIC_VECTOR ((IMEM_ABITS_g-1) DOWNTO 0);
44 imem_clken_o : OUT STD_LOGIC;
45 pc_ctrl_o : OUT STD_LOGIC;
46 -- fetch to decode pipeline registers
47 IF2ID_REG_i : IN IF2ID_Type;
48 IF2ID_REG_o : OUT IF2ID_Type;
49 -- decode to exeq pipeline registers
50 ID2EX_REG_i : IN ID2EX_Type;
51 ID2EX_REG_o : OUT ID2EX_Type;
52 delay_bit_o : OUT STD_LOGIC;
54 gprf_clken_o : OUT STD_LOGIC;
55 gprf_finish_wrb_mem_o : OUT STD_LOGIC;
56 -- exeq to fetch feedback registers
57 EX2IF_REG_i : IN EX2IF_Type;
58 EX2IF_REG_o : OUT EX2IF_Type;
59 EX2CTRL_REG_i : IN EX2CTRL_Type;
60 -- exeq to core (halting)
61 exeq_halt_i : IN STD_LOGIC;
62 -- exeq to mem pipeline registers
63 EX2MEM_REG_i : IN EX2MEM_Type;
64 EX2MEM_REG_o : OUT EX2MEM_Type;
65 -- mem pipeline register
66 MEM_REG_i : IN MEM_REG_Type;
67 MEM_REG_o : OUT MEM_REG_Type;
69 ID2CTRL_i : IN ID2CTRL_Type;
70 INT_CTRL_o : OUT INT_CTRL_Type;
72 EX_WRB_i : IN WRB_Type;
73 EX_WRB_o : OUT WRB_Type;
75 HAZARD_WRB_i : IN HAZARD_WRB_Type;
76 HAZARD_WRB_o : OUT HAZARD_WRB_Type;
77 -- for handling the 'IMM' instruction
78 IMM_LOCK_i : IN IMM_LOCK_Type;
79 IMM_LOCK_o : OUT IMM_LOCK_Type;
80 -- for handling the Machine Status Register
84 MEM2CTRL_i : IN MEM2CTRL_Type
88 --------------------------------------------------------------------------------
89 ARCHITECTURE rtl OF core_ctrl IS
90 --------------------------------------------------------------------------------
92 SIGNAL rst_r : STD_LOGIC;
93 SIGNAL reset_s : STD_LOGIC;
94 SIGNAL core_clken_s : STD_LOGIC;
96 SIGNAL EX2MEM_REG_r : EX2MEM_Type;
97 SIGNAL MEM_REG_r : MEM_REG_Type;
98 SIGNAL ID2EX_REG_r : ID2EX_Type;
99 SIGNAL EX2IF_REG_r : EX2IF_Type;
100 SIGNAL IMM_LOCK_r : IMM_LOCK_Type;
101 SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type;
102 SIGNAL flush_first_r : STD_LOGIC;
103 SIGNAL flush_second_r : STD_LOGIC;
104 SIGNAL flush_second_2r : STD_LOGIC;
105 SIGNAL ignore_state_r : STD_LOGIC; -- Please note: Flushing first is considered immediate!
106 SIGNAL delayBit_r : STD_LOGIC;
107 SIGNAL clken_s : STD_LOGIC;
108 SIGNAL clken_pipe_s : STD_LOGIC;
109 SIGNAL flush_ID2EX_s : STD_LOGIC;
110 SIGNAL flush_ID2EX_r : STD_LOGIC;
111 SIGNAL flush_EX2MEM_s : STD_LOGIC;
113 SIGNAL setup_int_r : STD_LOGIC;
114 SIGNAL int_busy_r : STD_LOGIC;
116 SIGNAL wait_for_mem_s : STD_LOGIC;
117 SIGNAL finish_wrb_mem_s: STD_LOGIC;
121 -- static connections
122 reset_s <= rst_i OR rst_r;
123 pc_ctrl_o <= NOT rst_r;
124 -- Addressing is 32-bit, so omit two lowest bytes from PC
125 imem_addr_o <= IF2ID_REG_i.program_counter((IMEM_ABITS_g+1) DOWNTO 2);
127 -- Reset_s is 1 when rst_i is one and then gets deactivated
128 core_clken_s <= reset_s OR (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i);
129 core_clken_o <= core_clken_s;
130 -- clock/wait control lines
131 finish_wrb_mem_s <= NOT MEM2CTRL_i.bus_wait WHEN (MEM_REG_r.wrb_Action = WRB_MEM AND MEM2CTRL_i.bus_taken = '1') ELSE '0';
132 wait_for_mem_s <= MEM2CTRL_i.bus_wait OR MEM2CTRL_i.bus_taken;
133 clken_s <= NOT wait_for_mem_s OR rst_i;
134 clken_pipe_s <= clken_s AND (NOT HAZARD_WRB_i.hazard);
135 imem_clken_o <= clken_pipe_s;
137 gprf_clken_o <= clken_s or finish_wrb_mem_s;
138 gprf_finish_wrb_mem_o <= finish_wrb_mem_s;
139 -- signals for clearing the ID2EX and EX2MEM registers during branches
140 flush_ID2EX_s <= ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE
141 ELSE ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR
142 flush_first_r OR ((NOT EX2CTRL_REG_i.ignore_state) AND (NOT ignore_state_r) AND flush_second_2r));
143 flush_EX2MEM_s <= HAZARD_WRB_i.hazard;
144 -- outputs that need to be readable too, so needing shadowing signals
145 EX2MEM_REG_o <= EX2MEM_REG_r;
146 MEM_REG_o <= MEM_REG_r;
147 ID2EX_REG_o <= ID2EX_REG_r;
148 delay_bit_o <= delayBit_r;
149 EX2IF_REG_o <= EX2IF_REG_r;
150 IMM_LOCK_o <= IMM_LOCK_r;
151 HAZARD_WRB_o <= HAZARD_WRB_r;
153 INT_CTRL_o.setup_int <= setup_int_r;
154 INT_CTRL_o.rti_target <= ID2EX_REG_r.program_counter;
155 INT_CTRL_o.int_busy <= int_busy_r;
160 -- some local procedures
161 PROCEDURE lp_rst_IF2ID_REG IS
163 IF2ID_REG_o.program_counter <= (OTHERS => '0');
166 PROCEDURE lp_rst_ID2EX_REG IS
168 -- reset and handle ID2EX_REG_r.program_counter separately,
169 -- since it will be needed during interrupt setup
170 ID2EX_REG_r.rdix_rA <= (OTHERS => '0');
171 ID2EX_REG_r.rdix_rB <= (OTHERS => '0');
172 ID2EX_REG_r.curr_rD <= (OTHERS => '0');
173 ID2EX_REG_r.alu_Action <= A_NOP;
174 ID2EX_REG_r.alu_Op1 <= ALU_IN_ZERO;
175 ID2EX_REG_r.alu_Op2 <= ALU_IN_IMM;
176 ID2EX_REG_r.alu_Cin <= CIN_ZERO;
177 ID2EX_REG_r.IMM16 <= (OTHERS => '0');
178 ID2EX_REG_r.IMM_Lock <= '0';
179 ID2EX_REG_r.msr_Action <= KEEP_CARRY;
180 ID2EX_REG_r.branch_Action <= NO_BR;
181 ID2EX_REG_r.mem_Action <= NO_MEM;
182 ID2EX_REG_r.transfer_Size <= WORD;
183 ID2EX_REG_r.wrb_Action <= NO_WRB;
184 ID2EX_REG_r.condition <= COND_ALL;
185 ID2EX_REG_r.halt <= '0';
186 IF (COMPATIBILITY_MODE_g = FALSE) THEN
187 ID2EX_REG_r.it_Action <= NO_IT;
192 PROCEDURE lp_rst_EX2IF_REG IS
194 EX2IF_REG_r.take_branch <= '0';
195 EX2IF_REG_r.branch_target <= (OTHERS => '0');
198 PROCEDURE lp_rst_EX2MEM_REG IS
200 EX2MEM_REG_r.mem_Action <= NO_MEM;
201 EX2MEM_REG_r.wrb_Action <= NO_WRB;
202 EX2MEM_REG_r.exeq_result <= (OTHERS => '0');
203 EX2MEM_REG_r.data_rD <= (OTHERS => '0');
204 EX2MEM_REG_r.byte_Enable <= (OTHERS => '0');
205 EX2MEM_REG_r.wrix_rD <= (OTHERS => '0');
208 PROCEDURE lp_rst_IMM_LOCK IS
210 IMM_LOCK_r.locked <= '0';
211 IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
214 PROCEDURE lp_rst_MSR IS
220 PROCEDURE lp_rst_EX_WRB IS
222 EX_WRB_o.wrb_Action <= NO_WRB;
223 EX_WRB_o.wrix_rD <= (OTHERS => '0');
224 EX_WRB_o.data_rD <= (OTHERS => '0');
227 PROCEDURE lp_rst_HAZARD_WRB IS
229 HAZARD_WRB_r.hazard <= '0';
230 HAZARD_WRB_r.save_rX <= NO_SAVE;
231 HAZARD_WRB_r.data_rX <= (OTHERS => '0');
232 HAZARD_WRB_r.data_rD <= (OTHERS => '0');
235 PROCEDURE lp_rst_MEM_REG IS
237 MEM_REG_r.wrb_Action <= NO_WRB;
238 MEM_REG_r.exeq_result <= (OTHERS => '0');
239 MEM_REG_r.byte_Enable <= (OTHERS => '0');
240 MEM_REG_r.wrix_rD <= (OTHERS => '0');
245 WAIT UNTIL clk_i'event AND clk_i = '1';
247 IF (wait_for_mem_s = '0' AND halt_i = '0' AND core_clken_s = '1') OR rst_i = '1' THEN
250 IF (reset_s = '1') THEN -- synchronous reset ...
251 lp_rst_IF2ID_REG; -- ... so lasts at least one clock_cycle
257 IF (COMPATIBILITY_MODE_g = FALSE) THEN
258 flush_first_r <= '0';
259 flush_second_r <= '0';
260 flush_second_2r <= '0';
261 ignore_state_r <= '0';
264 flush_ID2EX_r <= '0';
267 ID2EX_REG_r.program_counter <= (OTHERS => '0');
269 IF (clken_pipe_s = '1') THEN
270 IF2ID_REG_o <= IF2ID_REG_i;
272 flush_ID2EX_r <= flush_ID2EX_s;
273 IF (COMPATIBILITY_MODE_g = FALSE) THEN
274 -- Flushing based on IT / ITE / ITT along with IMM locking
275 IF (ID2EX_REG_i.IMM_Lock = '1') THEN
276 IF (flush_second_2r = '0') THEN
277 flush_second_2r <= flush_second_r;
279 flush_first_r <= EX2CTRL_REG_i.flush_first;
280 flush_second_r <= EX2CTRL_REG_i.flush_second;
281 ignore_state_r <= EX2CTRL_REG_i.ignore_state;
283 flush_first_r <= '0';
284 -- Directly to 2r (flushing the following instruction)
285 flush_second_2r <= flush_second_r OR EX2CTRL_REG_i.flush_second;
286 flush_second_r <= '0';
287 ignore_state_r <= '0';
290 HAZARD_WRB_r <= HAZARD_WRB_i;
291 MEM_REG_r <= MEM_REG_i;
292 int_busy_r <= ID2CTRL_i.int_busy;
294 -- decode-to-exeq unit registers
295 IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
299 -- check for the need and possibility to handle active interrupt requests
300 ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND
301 (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND
302 -- pending branch should be taken before interrupt can be executed
303 -- dectected by Matthis Meier, TU Dortmund (Sept 2012)
305 -- Same goes for pending flushing - should be taken before interrupt can be executed
306 (EX2IF_REG_i.take_branch = '0') AND (EX2IF_REG_r.take_branch = '0') AND ((COMPATIBILITY_MODE_g = TRUE)
307 OR ((flush_first_r = '0') AND (flush_second_r = '0') AND (flush_second_2r = '0'))) AND
308 (IMM_LOCK_i.locked = '0') AND (HAZARD_WRB_i.hazard = '0')) THEN
310 ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
312 ELSIF (clken_pipe_s = '1') THEN
314 ID2EX_REG_r <= ID2EX_REG_i;
315 delayBit_r <= ID2CTRL_i.delayBit;
317 -- exeq-to-mem unit registers
318 IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
324 IF (clken_pipe_s = '1') THEN
325 EX2IF_REG_r <= EX2IF_REG_i;
326 EX_WRB_o <= EX_WRB_i;
328 IF (clken_s = '1') THEN
329 -- next test to prevent a flush from disrupting
330 -- the write-back pipeline
331 IF (flush_ID2EX_r = '0') THEN
332 EX2MEM_REG_r <= EX2MEM_REG_i;
334 IMM_LOCK_r <= IMM_LOCK_i;
339 IF finish_wrb_mem_s = '1' THEN
340 MEM_REG_r.wrb_Action <= NO_WRB;
341 MEM_REG_r.wrix_rD <= (OTHERS => '0');
342 MEM_REG_r.byte_Enable <= (OTHERS => '0');
343 IF MEM2CTRL_i.need_keep = '1' THEN
344 EX2MEM_REG_r.data_rD <= MEM2CTRL_i.read_data;
347 END IF; -- rising edge clk_i ...
348 END PROCESS regd_proc;
350 END ARCHITECTURE rtl;