]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/core_ctrl.vhd
Connect internal finish_wrb_mem_s to GPRF - gprf_finish_wrb_mem.
[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                 IMEM_ABITS_g         : positive := 9;
31                 COMPATIBILITY_MODE_g : BOOLEAN := FALSE
32         );
33         PORT
34         (
35                 clk_i           :  IN STD_LOGIC;
36                 rst_i           :  IN STD_LOGIC;
37                 halt_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 ((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;
53                 -- GPRF control
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;
68                 -- decode control i/o
69                 ID2CTRL_i       :  IN ID2CTRL_Type;
70                 INT_CTRL_o      : OUT INT_CTRL_Type;
71                 -- exeq control i/o
72                 EX_WRB_i        :  IN WRB_Type;
73                 EX_WRB_o        : OUT WRB_Type;
74                 -- data hazard i/o
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
81                 MSR_i           :  IN MSR_Type;
82                 MSR_o           : OUT MSR_Type;
83                 -- miscellaneous
84                 MEM2CTRL_i      :  IN MEM2CTRL_Type
85         );
86 END ENTITY core_ctrl;
87
88 --------------------------------------------------------------------------------
89 ARCHITECTURE rtl OF core_ctrl IS
90 --------------------------------------------------------------------------------
91
92         SIGNAL rst_r           : STD_LOGIC;
93         SIGNAL reset_s         : STD_LOGIC;
94         SIGNAL core_clken_s    : STD_LOGIC;
95
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;
112
113         SIGNAL setup_int_r     : STD_LOGIC;
114         SIGNAL int_busy_r      : STD_LOGIC;
115
116         SIGNAL wait_for_mem_s  : STD_LOGIC;
117         SIGNAL finish_wrb_mem_s: STD_LOGIC;
118
119 BEGIN
120
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);
126         -- Tracing
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;
136
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;
152         --
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;
156
157 regd_proc:
158         PROCESS
159
160         -- some local procedures
161         PROCEDURE lp_rst_IF2ID_REG IS
162         BEGIN
163                 IF2ID_REG_o.program_counter <= (OTHERS => '0');
164         END PROCEDURE;
165
166         PROCEDURE lp_rst_ID2EX_REG IS
167         BEGIN
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;
188                 ELSE
189                 END IF;
190         END PROCEDURE;
191
192         PROCEDURE lp_rst_EX2IF_REG IS
193         BEGIN
194                 EX2IF_REG_r.take_branch   <= '0';
195                 EX2IF_REG_r.branch_target <= (OTHERS => '0');
196         END PROCEDURE;
197
198         PROCEDURE lp_rst_EX2MEM_REG IS
199         BEGIN
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');
206         END PROCEDURE;
207
208         PROCEDURE lp_rst_IMM_LOCK IS
209         BEGIN
210                 IMM_LOCK_r.locked   <= '0';
211                 IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
212         END PROCEDURE;
213
214         PROCEDURE lp_rst_MSR IS
215         BEGIN
216                 MSR_o.IE  <= '0';
217                 MSR_o.C   <= '0';
218         END PROCEDURE;
219
220         PROCEDURE lp_rst_EX_WRB IS
221         BEGIN
222                 EX_WRB_o.wrb_Action <= NO_WRB;
223                 EX_WRB_o.wrix_rD    <= (OTHERS => '0');
224                 EX_WRB_o.data_rD    <= (OTHERS => '0');
225         END PROCEDURE;
226
227         PROCEDURE lp_rst_HAZARD_WRB IS
228         BEGIN
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');
233         END PROCEDURE;
234
235         PROCEDURE lp_rst_MEM_REG IS
236         BEGIN
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');
241         END PROCEDURE;
242
243         BEGIN
244
245         WAIT UNTIL clk_i'event AND clk_i = '1';
246
247         IF (wait_for_mem_s = '0' AND  halt_i = '0' AND core_clken_s = '1') OR rst_i = '1' THEN
248                 rst_r <= rst_i;
249
250                 IF (reset_s = '1') THEN     -- synchronous reset ...
251                         lp_rst_IF2ID_REG;       -- ... so lasts at least one clock_cycle
252                         lp_rst_MSR;
253                         lp_rst_HAZARD_WRB;
254                         lp_rst_MEM_REG;
255                         delayBit_r        <= '0';
256
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';
262                         END IF;
263
264                         flush_ID2EX_r <= '0';
265                         setup_int_r   <= '0';
266                         int_busy_r    <= '0';
267                         ID2EX_REG_r.program_counter <= (OTHERS => '0');
268                 ELSE
269                         IF (clken_pipe_s = '1') THEN
270                                 IF2ID_REG_o <= IF2ID_REG_i;
271                         END IF;
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;
278                                         END IF;
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;
282                                 ELSE
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';
288                                 END IF;
289                         END IF;
290                         HAZARD_WRB_r  <= HAZARD_WRB_i;
291                         MEM_REG_r     <= MEM_REG_i;
292                         int_busy_r    <= ID2CTRL_i.int_busy;
293                 END IF;
294                 -- decode-to-exeq unit registers
295                 IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
296                         setup_int_r <= '0';
297                         lp_rst_ID2EX_REG;
298                         delayBit_r <= '0';
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)
304                                         --
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
309                         setup_int_r <= '1';
310                         ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
311                         lp_rst_ID2EX_REG;
312                 ELSIF (clken_pipe_s = '1') THEN
313                         setup_int_r <= '0';
314                         ID2EX_REG_r <= ID2EX_REG_i;
315                         delayBit_r  <= ID2CTRL_i.delayBit;
316                 END IF;
317                 -- exeq-to-mem unit registers
318                 IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
319                         lp_rst_EX2IF_REG;
320                         lp_rst_EX2MEM_REG;
321                         lp_rst_EX_WRB;
322                         lp_rst_IMM_LOCK;
323                 ELSE
324                         IF (clken_pipe_s = '1') THEN
325                                 EX2IF_REG_r   <= EX2IF_REG_i;
326                                 EX_WRB_o      <= EX_WRB_i;
327                         END IF;
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;
333                                 END IF;
334                                 IMM_LOCK_r <= IMM_LOCK_i;
335                                 MSR_o      <= MSR_i;
336                         END IF;
337                 END IF;
338         ELSE
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;
345                         END IF;
346                 END IF;
347         END IF;     -- rising edge clk_i ...
348         END PROCESS regd_proc;
349
350 END ARCHITECTURE rtl;