]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/core_ctrl.vhd
Reformat code and restructure decoder to save LUTs and fit critical path
[fpga/lx-cpu1/tumbl.git] / hw / core_ctrl.vhd
1 ---------------------------------------------------------------------------------
2 --
3 --  Entity:       core_ctrl
4 --  Filename:     core_ctrl.vhd
5 --  Description:  the control unit for the TUD MB-Lite implementation
6 --
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).
16 --  Remarks:
17 --
18 --------------------------------------------------------------------------------
19
20 LIBRARY IEEE;
21
22 USE IEEE.std_logic_1164.all;
23 USE WORK.mbl_Pkg.all;
24
25 --------------------------------------------------------------------------------
26 ENTITY core_ctrl IS
27 --------------------------------------------------------------------------------
28         GENERIC
29         (
30                 COMPATIBILITY_MODE_g : BOOLEAN := FALSE
31         );
32         PORT
33         (
34                 clk_i           :  IN STD_LOGIC;
35                 rst_i           :  IN STD_LOGIC;
36                 halt_i          :  IN STD_LOGIC;
37                 bad_op_i        :  IN STD_LOGIC;
38                 int_i           :  IN STD_LOGIC;
39                 trace_i         :  IN STD_LOGIC;
40                 trace_kick_i    :  IN STD_LOGIC;
41                 core_clken_o    : OUT STD_LOGIC;
42                 -- specific fetch i/o
43                 imem_addr_o     : OUT STD_LOGIC_VECTOR (31 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                 -- GPRF control
53                 gprf_clken_o    : OUT STD_LOGIC;
54                 -- exeq to fetch feedback registers
55                 EX2IF_REG_i     :  IN EX2IF_Type;
56                 EX2IF_REG_o     : OUT EX2IF_Type;
57                 EX2CTRL_REG_i   :  IN EX2CTRL_Type;
58                 -- exeq to core (halting)
59                 exeq_halt_i     :  IN STD_LOGIC;
60                 -- exeq to mem pipeline registers
61                 EX2MEM_REG_i    :  IN EX2MEM_Type;
62                 EX2MEM_REG_o    : OUT EX2MEM_Type;
63                 -- mem pipeline register
64                 MEM_REG_i       :  IN MEM_REG_Type;
65                 MEM_REG_o       : OUT MEM_REG_Type;
66                 -- decode control i/o
67                 ID2CTRL_i       :  IN ID2CTRL_Type;
68                 INT_CTRL_o      : OUT INT_CTRL_Type;
69                 -- exeq control i/o
70                 EX_WRB_i        :  IN WRB_Type;
71                 EX_WRB_o        : OUT WRB_Type;
72                 -- data hazard i/o
73                 HAZARD_WRB_i    :  IN HAZARD_WRB_Type;
74                 HAZARD_WRB_o    : OUT HAZARD_WRB_Type;
75                 -- for handling the 'IMM' instruction
76                 IMM_LOCK_i      :  IN IMM_LOCK_Type;
77                 IMM_LOCK_o      : OUT IMM_LOCK_Type;
78                 -- for handling the Machine Status Register
79                 MSR_i           :  IN MSR_Type;
80                 MSR_o           : OUT MSR_Type;
81                 -- miscellaneous
82                 MEM2CTRL_i      :  IN MEM2CTRL_Type
83         );
84 END ENTITY core_ctrl;
85
86 --------------------------------------------------------------------------------
87 ARCHITECTURE rtl OF core_ctrl IS
88 --------------------------------------------------------------------------------
89
90         SIGNAL rst_r           : STD_LOGIC;
91         SIGNAL reset_s         : STD_LOGIC;
92         SIGNAL core_clken_s    : STD_LOGIC;
93
94         SIGNAL ID2EX_REG_r     : ID2EX_Type;
95         SIGNAL EX2IF_REG_r     : EX2IF_Type;
96         SIGNAL IMM_LOCK_r      : IMM_LOCK_Type;
97         SIGNAL HAZARD_WRB_r    : HAZARD_WRB_Type;
98         SIGNAL flush_first_r   : STD_LOGIC;
99         SIGNAL flush_second_r  : STD_LOGIC;
100         SIGNAL flush_second_2r : STD_LOGIC;
101         SIGNAL ignore_state_r  : STD_LOGIC; -- Please note: Flushing first is considered immediate!
102         SIGNAL delayBit_r      : STD_LOGIC;
103         SIGNAL clken_s         : STD_LOGIC;
104         SIGNAL clken_pipe_s    : STD_LOGIC;
105         SIGNAL flush_ID2EX_s   : STD_LOGIC;
106         SIGNAL flush_ID2EX_r   : STD_LOGIC;
107         SIGNAL flush_EX2MEM_s  : STD_LOGIC;
108
109         SIGNAL setup_int_r     : STD_LOGIC;
110         SIGNAL int_busy_r      : STD_LOGIC;
111
112 BEGIN
113
114         -- static connections
115         reset_s        <= rst_i OR rst_r;
116         pc_ctrl_o      <= NOT rst_r;
117         imem_addr_o    <= IF2ID_REG_i.program_counter;
118         -- Tracing
119         -- Reset_s is 1 when rst_i is one and then gets deactivated
120         core_clken_s  <= reset_s OR ((NOT bad_op_i) AND (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i));
121         core_clken_o  <= core_clken_s;
122         -- clock/wait control lines
123         clken_s        <= MEM2CTRL_i.clken OR rst_i;
124         clken_pipe_s   <= clken_s AND (NOT HAZARD_WRB_i.hazard);
125         imem_clken_o   <= clken_pipe_s;
126         gprf_clken_o   <= clken_s;
127         -- signals for clearing the ID2EX and EX2MEM registers during branches
128         flush_ID2EX_s  <= ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE
129                                                                                 ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR flush_first_r OR
130                                                                                                 ((NOT EX2CTRL_REG_i.ignore_state) AND (NOT ignore_state_r) AND flush_second_2r));
131         flush_EX2MEM_s <= HAZARD_WRB_i.hazard;
132         -- outputs that need to be readable too, so needing shadowing signals
133         ID2EX_REG_o    <= ID2EX_REG_r;
134         EX2IF_REG_o    <= EX2IF_REG_r;
135         IMM_LOCK_o     <= IMM_LOCK_r;
136         HAZARD_WRB_o   <= HAZARD_WRB_r;
137         --
138         INT_CTRL_o.setup_int   <= setup_int_r;
139         INT_CTRL_o.rti_target  <= ID2EX_REG_r.program_counter;
140         INT_CTRL_o.int_busy    <= int_busy_r;
141
142 regd_proc:
143         PROCESS ( clk_i, rst_i, halt_i, core_clken_s,
144                                                 -- complete sensitivity list for synthesizer
145                                                 reset_s, MEM2CTRL_i, clken_pipe_s, IF2ID_REG_i,
146                                                 flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i,
147                                                 MEM_REG_i, ID2CTRL_i, int_i, MSR_i,
148                                                 int_busy_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
149                                                 EX2IF_REG_i, EX2CTRL_REG_i, EX_WRB_i, EX2MEM_REG_i )
150
151         -- some local procedures
152         PROCEDURE lp_rst_IF2ID_REG IS
153         BEGIN
154                 IF2ID_REG_o.program_counter <= (OTHERS => '0');
155         END PROCEDURE;
156
157         PROCEDURE lp_rst_ID2EX_REG IS
158         BEGIN
159                 -- reset and handle ID2EX_REG_r.program_counter separately,
160                 -- since it will be needed during interrupt setup
161                 ID2EX_REG_r.rdix_rA          <= (OTHERS => '0');
162                 ID2EX_REG_r.rdix_rB          <= (OTHERS => '0');
163                 ID2EX_REG_r.curr_rD          <= (OTHERS => '0');
164                 ID2EX_REG_r.alu_Action       <= A_NOP;
165                 ID2EX_REG_r.alu_Op1          <= ALU_IN_ZERO;
166                 ID2EX_REG_r.alu_Op2          <= ALU_IN_IMM;
167                 ID2EX_REG_r.alu_Cin          <= CIN_ZERO;
168                 ID2EX_REG_r.IMM16            <= (OTHERS => '0');
169                 ID2EX_REG_r.IMM_Lock         <= '0';
170                 ID2EX_REG_r.msr_Action       <= KEEP_CARRY;
171                 ID2EX_REG_r.branch_Action    <= NO_BR;
172                 ID2EX_REG_r.mem_Action       <= NO_MEM;
173                 ID2EX_REG_r.transfer_Size    <= WORD;
174                 ID2EX_REG_r.wrb_Action       <= NO_WRB;
175                 ID2EX_REG_r.condition        <= COND_ALL;
176                 ID2EX_REG_r.halt             <= '0';
177                 IF (COMPATIBILITY_MODE_g = FALSE) THEN
178                         ID2EX_REG_r.it_Action      <= NO_IT;
179                 ELSE
180                 END IF;
181         END PROCEDURE;
182
183         PROCEDURE lp_rst_EX2IF_REG IS
184         BEGIN
185                 EX2IF_REG_r.take_branch   <= '0';
186                 EX2IF_REG_r.branch_target <= (OTHERS => '0');
187         END PROCEDURE;
188
189         PROCEDURE lp_rst_EX2MEM_REG IS
190         BEGIN
191                 EX2MEM_REG_o.mem_Action  <= NO_MEM;
192                 EX2MEM_REG_o.wrb_Action  <= NO_WRB;
193                 EX2MEM_REG_o.exeq_result <= (OTHERS => '0');
194                 EX2MEM_REG_o.data_rD     <= (OTHERS => '0');
195                 EX2MEM_REG_o.byte_Enable <= (OTHERS => '0');
196                 EX2MEM_REG_o.wrix_rD     <= (OTHERS => '0');
197         END PROCEDURE;
198
199         PROCEDURE lp_rst_IMM_LOCK IS
200         BEGIN
201                 IMM_LOCK_r.locked   <= '0';
202                 IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
203         END PROCEDURE;
204
205         PROCEDURE lp_rst_MSR IS
206         BEGIN
207                 MSR_o.IE  <= '0';
208                 MSR_o.C   <= '0';
209         END PROCEDURE;
210
211         PROCEDURE lp_rst_EX_WRB IS
212         BEGIN
213                 EX_WRB_o.wrb_Action <= NO_WRB;
214                 EX_WRB_o.wrix_rD    <= (OTHERS => '0');
215                 EX_WRB_o.data_rD    <= (OTHERS => '0');
216         END PROCEDURE;
217
218         PROCEDURE lp_rst_HAZARD_WRB IS
219         BEGIN
220                 HAZARD_WRB_r.hazard  <= '0';
221                 HAZARD_WRB_r.save_rX <= NO_SAVE;
222                 HAZARD_WRB_r.data_rX <= (OTHERS => '0');
223                 HAZARD_WRB_r.data_rD <= (OTHERS => '0');
224         END PROCEDURE;
225
226         PROCEDURE lp_rst_MEM_REG IS
227         BEGIN
228                 MEM_REG_o.wrb_Action  <= NO_WRB;
229                 MEM_REG_o.exeq_result <= (OTHERS => '0');
230                 MEM_REG_o.byte_Enable <= (OTHERS => '0');
231                 MEM_REG_o.wrix_rD     <= (OTHERS => '0');
232         END PROCEDURE;
233
234         BEGIN
235
236         IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' AND
237                                 core_clken_s = '1' THEN
238                         rst_r <= rst_i;
239
240                 IF (reset_s = '1') THEN     -- synchronous reset ...
241                         lp_rst_IF2ID_REG;       -- ... so lasts at least one clock_cycle
242                         lp_rst_MSR;
243                         lp_rst_HAZARD_WRB;
244                         lp_rst_MEM_REG;
245
246                         IF (COMPATIBILITY_MODE_g = TRUE) THEN
247                                 delayBit_r      <= '0';
248                         ELSE
249                                 flush_first_r   <= '0';
250                                 flush_second_r  <= '0';
251                                 flush_second_2r <= '0';
252                                 ignore_state_r  <= '0';
253                         END IF;
254
255                         flush_ID2EX_r <= '0';
256                         setup_int_r   <= '0';
257                         int_busy_r    <= '0';
258                         ID2EX_REG_r.program_counter <= (OTHERS => '0');
259                 ELSE
260                         IF (clken_pipe_s = '1') THEN
261                                 IF2ID_REG_o <= IF2ID_REG_i;
262                         END IF;
263                         flush_ID2EX_r <= flush_ID2EX_s;
264                         IF (COMPATIBILITY_MODE_g = FALSE) THEN
265                                 -- Flushing based on IT / ITE / ITT along with IMM locking
266                                 IF (ID2EX_REG_i.IMM_Lock = '1') THEN
267                                         IF (flush_second_2r = '0') THEN
268                                                 flush_second_2r <= flush_second_r;
269                                         END IF;
270                                         flush_first_r   <= EX2CTRL_REG_i.flush_first;
271                                         flush_second_r  <= EX2CTRL_REG_i.flush_second;
272                                         ignore_state_r  <= EX2CTRL_REG_i.ignore_state;
273                                 ELSE
274                                         flush_first_r   <= '0';
275                                         -- Directly to 2r (flushing the following instruction)
276                                         flush_second_2r <= flush_second_r OR EX2CTRL_REG_i.flush_second;
277                                         flush_second_r  <= '0';
278                                         ignore_state_r  <= '0';
279                                 END IF;
280                         END IF;
281                         HAZARD_WRB_r  <= HAZARD_WRB_i;
282                         MEM_REG_o     <= MEM_REG_i;
283                         int_busy_r    <= ID2CTRL_i.int_busy;
284                 END IF;
285                 -- decode-to-exeq unit registers
286                 IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
287                         setup_int_r <= '0';
288                         lp_rst_ID2EX_REG;
289                         IF (COMPATIBILITY_MODE_g = TRUE) THEN
290                                 delayBit_r <= '0';
291                         END IF;
292                 -- check for the need and possibility to handle active interrupt requests
293                 ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND
294                                         (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND
295                                         -- pending branch should be taken before interrupt can be executed
296                                         -- dectected by Matthis Meier, TU Dortmund (Sept 2012)
297                                         --
298                                         -- Same goes for pending flushing - should be taken before interrupt can be executed
299                                         (EX2IF_REG_i.take_branch = '0') AND (EX2IF_REG_r.take_branch = '0') AND ((COMPATIBILITY_MODE_g = TRUE)
300                                         OR ((flush_first_r = '0') AND (flush_second_r = '0') AND (flush_second_2r = '0'))) AND
301                                         (IMM_LOCK_i.locked = '0') AND (HAZARD_WRB_i.hazard = '0')) THEN
302                         setup_int_r <= '1';
303                         ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
304                         lp_rst_ID2EX_REG;
305                 ELSIF (clken_pipe_s = '1') THEN
306                         setup_int_r <= '0';
307                         ID2EX_REG_r <= ID2EX_REG_i;
308                         IF (COMPATIBILITY_MODE_g = TRUE) THEN
309                                 delayBit_r  <= ID2CTRL_i.delayBit;
310                         END IF;
311                 END IF;
312                 -- exeq-to-mem unit registers
313                 IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
314                         lp_rst_EX2IF_REG;
315                         lp_rst_EX2MEM_REG;
316                         lp_rst_EX_WRB;
317                         lp_rst_IMM_LOCK;
318                 ELSE
319                         IF (clken_pipe_s = '1') THEN
320                                 EX2IF_REG_r   <= EX2IF_REG_i;
321                                 EX_WRB_o      <= EX_WRB_i;
322                         END IF;
323                         IF (clken_s = '1') THEN
324                                 -- next test to prevent a flush from disrupting
325                                 -- the write-back pipeline
326                                 IF (flush_ID2EX_r = '0') THEN
327                                         EX2MEM_REG_o <= EX2MEM_REG_i;
328                                 END IF;
329                                 IMM_LOCK_r <= IMM_LOCK_i;
330                                 MSR_o      <= MSR_i;
331                         END IF;
332                 END IF;
333         END IF;     -- rising edge clk_i ...
334         END PROCESS regd_proc;
335
336 END ARCHITECTURE rtl;