]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/exeq.vhd
Core updates
[fpga/lx-cpu1/tumbl.git] / hw / exeq.vhd
1 ---------------------------------------------------------------------------------
2 --
3 --  Entity:       exeq
4 --  Filename:     exeq.vhd
5 --  Description:  the Execution (EX) 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:         September, 2010
11 --
12 --  Modified:     Septemper, 2013: FSL scratched, core customized (Meloun)
13 --                 December, 2010: FSL added (Huib)
14 --                     June, 2011: added code for MUL and BARREL (Huib)
15 --                                 Adapted to work with separate fsl_M-
16 --                                 and fsl_S selectors and automatic
17 --                                 tumbl<_jtag><_fsl>.vhd generation (Huib)
18 --  Remarks:
19 --
20 --------------------------------------------------------------------------------
21
22 LIBRARY IEEE;
23
24 USE IEEE.std_logic_1164.all;
25 USE IEEE.numeric_std.all;
26 USE WORK.mbl_pkg.all;
27
28 ----------------------------------------------------------
29 ENTITY exeq IS
30 ----------------------------------------------------------
31         GENERIC
32         (
33                 USE_HW_MUL_g : BOOLEAN := TRUE;
34                 USE_BARREL_g : BOOLEAN := TRUE;
35                 COMPATIBILITY_MODE_g : BOOLEAN := FALSE
36         );
37         PORT
38         (
39                 IF2ID_i      :  IN IF2ID_Type;
40                 --
41                 ID2EX_i      :  IN ID2EX_Type;
42                 delayBit_i   :  IN STD_LOGIC;
43                 GPRF2EX_i    :  IN GPRF2EX_Type;
44                 EX2IF_o      : OUT EX2IF_Type;
45                 EX2CTRL_o    : OUT EX2CTRL_Type;
46                 HALT_o       : OUT HALT_Type;
47                 --
48                 EX_WRB_i     :  IN WRB_Type;
49                 EX_WRB_o     : OUT WRB_Type;
50                 MEM_WRB_i    :  IN WRB_Type;
51                 --
52                 HAZARD_WRB_i :  IN HAZARD_WRB_Type;
53                 HAZARD_WRB_o : OUT HAZARD_WRB_Type;
54                 --
55                 IMM_LOCK_i   :  IN IMM_LOCK_Type;
56                 IMM_LOCK_o   : OUT IMM_LOCK_Type;
57                 --
58                 MSR_i        :  IN MSR_Type;
59                 MSR_o        : OUT MSR_Type;
60                 --
61                 EX2MEM_o     : OUT EX2MEM_Type
62         );
63 END ENTITY exeq;
64
65 ----------------------------------------------------------
66 ARCHITECTURE rtl OF exeq IS
67 ----------------------------------------------------------
68
69 BEGIN
70
71 p_exeq:
72         PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i,
73                                                 IF2ID_i, delayBit_i, IMM_LOCK_i, MSR_i, HAZARD_WRB_i)
74
75                 -- function needed by BSLL (only if USE_BARREL_g = TRUE)
76                 FUNCTION reverse_bits ( word32 : STD_LOGIC_VECTOR (31 DOWNTO 0) )
77                         RETURN STD_LOGIC_VECTOR IS
78                                 VARIABLE reversed_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
79                 BEGIN
80                 f_rev:
81                         FOR i IN 0 TO 31 LOOP
82                                 reversed_v(31-i) := word32(i);
83                         END LOOP;
84                         RETURN reversed_v;
85                 END;
86
87                 VARIABLE data_rA_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
88                 VARIABLE data_rB_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
89                 VARIABLE data_rD_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
90                 VARIABLE in1_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
91                 VARIABLE in2_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
92                 VARIABLE hi16_v        : STD_LOGIC_VECTOR (15 DOWNTO 0);
93                 VARIABLE IMM32_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
94                 VARIABLE carry_i_v     : STD_LOGIC;
95                 VARIABLE result_v      : STD_LOGIC_VECTOR (31 DOWNTO 0);
96                 VARIABLE carry_o_v     : STD_LOGIC;
97                 VARIABLE isZero_v      : STD_LOGIC;
98                 VARIABLE signBit_in1_v : STD_LOGIC;
99                 VARIABLE signBit_in2_v : STD_LOGIC;
100                 VARIABLE signBit_r_v   : STD_LOGIC;
101                 VARIABLE rA_eq_ex_rD_v : STD_LOGIC;
102                 VARIABLE rB_eq_ex_rD_v : STD_LOGIC;
103                 VARIABLE hazard_v      : STD_LOGIC;
104                 VARIABLE save_rX_v     : SAVE_REG_Type;
105                 VARIABLE data_rX_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
106                 VARIABLE do_branch_v   : STD_LOGIC;
107                 VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
108                 VARIABLE tmp64_v       : STD_LOGIC_VECTOR (63 DOWNTO 0);
109                 VARIABLE padVec_v      : STD_LOGIC_VECTOR (15 DOWNTO 0);
110                 VARIABLE do_cond_v     : STD_LOGIC;
111
112         BEGIN
113
114                 rA_eq_ex_rD_v := '0';
115                 rB_eq_ex_rD_v := '0';
116                 hazard_v      := '0';
117                 save_rX_v     := NO_SAVE;
118                 data_rX_v     := data_rB_v;         -- default value for data_rX_v
119                 result_v      := (OTHERS => '0');
120                 carry_o_v     := '0';
121                 do_branch_v   := '0';
122                 byte_Enable_v := (OTHERS => '0');
123                 do_cond_v     := '0';
124                 --
125     MSR_o         <= MSR_i;             -- pass MSR by default
126
127                 -- create some helper variables
128                 IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN
129                         rA_eq_ex_rD_v := '1';
130                 END IF;
131                 IF (ID2EX_i.rdix_rB = EX_WRB_i.wrix_rD) THEN
132                         rB_eq_ex_rD_v := '1';
133                 END IF;
134                 -- test where to obtain data_rA from
135                 IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rA_eq_ex_rD_v = '1')) THEN
136                         data_rA_v := EX_WRB_i.data_rD;
137                 ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rA = MEM_WRB_i.wrix_rD)) THEN
138                         data_rA_v := MEM_WRB_i.data_rD;
139                 ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RA)) THEN
140                         data_rA_v := HAZARD_WRB_i.data_rX;
141                 ELSE
142                         data_rA_v := GPRF2EX_i.data_rA;
143                 END IF;
144                 -- test where to obtain data_rB from
145                 IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rB_eq_ex_rD_v = '1')) THEN
146                         data_rB_v := EX_WRB_i.data_rD;
147                 ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rB = MEM_WRB_i.wrix_rD)) THEN
148                         data_rB_v := MEM_WRB_i.data_rD;
149                 ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RB)) THEN
150                         data_rB_v := HAZARD_WRB_i.data_rX;
151                 ELSE
152                         data_rB_v := GPRF2EX_i.data_rB;
153                 END IF;
154                 -- .... or, isn't all necessary data available yet being still in the pipeline ?
155                 data_rX_v := data_rB_v;                 -- default value for data_rX_v
156                 IF (EX_WRB_i.wrb_Action = WRB_MEM) THEN
157                         IF ((rA_eq_ex_rD_v = '1') OR (rB_eq_ex_rD_v = '1')) THEN
158                                 hazard_v  := '1';
159                                 IF (rA_eq_ex_rD_v = '1') THEN
160                                         save_rX_v := SAVE_RB;   -- already by default data_rX_v = data_rB_v
161                                 ELSE
162                                         save_rX_v := SAVE_RA;
163                                         data_rX_v := data_rA_v;
164                                 END IF;
165                         END IF;
166                 END IF;
167
168                 IF (IMM_LOCK_i.locked = '1') THEN
169                         hi16_v := IMM_LOCK_i.IMM_hi16;
170                 ELSIF (ID2EX_i.IMM16(15) = '0') THEN
171                         hi16_v := C_16_ZEROS;
172                 ELSE
173                         hi16_v :=  C_16_ONES;
174                 END IF;
175                 IMM32_v := hi16_v & ID2EX_i.IMM16;
176
177                 CASE ID2EX_i.alu_Op1 IS
178                         WHEN ALU_IN_REGA      =>  in1_v := data_rA_v;
179                         WHEN ALU_IN_NOT_REGA  =>  in1_v := NOT data_rA_v;
180                         WHEN ALU_IN_PC        =>  in1_v := ID2EX_i.program_counter;
181                         WHEN ALU_IN_ZERO      =>  in1_v := C_32_ZEROS;
182                         WHEN OTHERS           =>  NULL;
183                 END CASE;
184
185                 CASE ID2EX_i.alu_Op2 IS
186                         WHEN ALU_IN_REGB     =>  in2_v := data_rB_v;
187                         WHEN ALU_IN_NOT_REGB =>  in2_v := NOT data_rB_v;
188                         WHEN ALU_IN_IMM      =>  in2_v := IMM32_v;
189                         WHEN ALU_IN_NOT_IMM  =>  in2_v := NOT IMM32_v;
190                         WHEN OTHERS          =>  NULL;
191                 END CASE;
192
193                 signBit_in1_v := in1_v(31);
194                 signBit_in2_v := in2_v(31);
195                 signBit_r_v   := data_rA_v(31); -- Init with Op1, then possibly override
196
197                 CASE ID2EX_i.alu_Cin IS
198                         WHEN CIN_ZERO  =>   carry_i_v := '0';
199                         WHEN CIN_ONE   =>   carry_i_v := '1';
200                         WHEN FROM_MSR  =>   carry_i_v := MSR_i.C;
201                         WHEN FROM_IN1  =>   carry_i_v := in1_v(31);
202                         WHEN OTHERS    =>   carry_i_v := '0';
203                 END CASE;
204
205                 IF (data_rA_v = C_32_ZEROS) THEN
206                         isZero_v := '1';
207                 ELSE
208                         isZero_v := '0';
209                 END IF;
210
211                 CASE ID2EX_i.alu_Action IS
212
213                         WHEN A_ADD | A_CMP | A_CMPU =>
214                                 ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v);
215                                 CASE ID2EX_i.alu_Action IS
216
217                                         WHEN A_CMPU  =>
218                                                 IF (signBit_in1_v = signBit_in2_v) THEN
219                                                         signBit_r_v := NOT signBit_in1_v;
220                                                 END IF;
221                                                 IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN
222                                                         -- have to update zero flag with current result
223                                                         IF (result_v = C_32_ZEROS) THEN
224                                                                 isZero_v := '1';
225                                                         ELSE
226                                                                 isZero_v := '0';
227                                                         END IF;
228                                                 END IF;
229
230                                         WHEN A_CMP  =>
231                                                 IF (signBit_in1_v = signBit_in2_v) THEN
232                                                         signBit_r_v := signBit_in1_v;
233                                                 END IF;
234                                                 IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN
235                                                         -- have to update zero flag with current result
236                                                         IF (result_v = C_32_ZEROS) THEN
237                                                                 isZero_v := '1';
238                                                         ELSE
239                                                                 isZero_v := '0';
240                                                         END IF;
241                                                 END IF;
242
243                                         WHEN OTHERS =>
244                                                 NULL;
245
246                                 END CASE;
247
248                         WHEN A_OR     =>
249                                 result_v  := in1_v  OR in2_v;
250
251                         WHEN A_AND    =>
252                                 result_v  := in1_v AND in2_v;
253
254                         WHEN A_XOR    =>
255                                 result_v  := in1_v XOR in2_v;
256
257                         WHEN A_SHIFT  =>
258                                 result_v  := carry_i_v & in1_v(31 DOWNTO 1);
259                                 carry_o_v := in1_v(0);
260
261                         WHEN A_SEXT8  =>
262                                 IF (in1_v(7) = '0') THEN
263                                         result_v := C_24_ZEROS & in1_v( 7 DOWNTO 0);
264                                 ELSE
265                                         result_v :=  C_24_ONES & in1_v( 7 DOWNTO 0);
266                                 END IF;
267
268                         WHEN A_SEXT16 =>
269                                 IF (in1_v(15) = '0') THEN
270                                         result_v := C_16_ZEROS & in1_v(15 DOWNTO 0);
271                                 ELSE
272                                         result_v :=  C_16_ONES & in1_v(15 DOWNTO 0);
273                                 END IF;
274
275                         WHEN A_MFS    =>
276                                 if (COMPATIBILITY_MODE_g = FALSE) THEN
277                                         result_v := C_24_ZEROS & "00000" & MSR_i.C & MSR_i.IE & '0';
278                                 ELSE
279                                         result_v := MSR_i.C & C_24_ZEROS & "0000" & MSR_i.C & MSR_i.IE & '0';
280                                 END IF;
281
282                         WHEN A_MTS    =>
283                                 MSR_o.IE  <= data_Ra_v(1);
284                                 MSR_o.C   <= data_Ra_v(2);
285
286                         WHEN A_MUL    =>
287                                 IF (USE_HW_MUL_g = TRUE) THEN
288                                         tmp64_v  := STD_LOGIC_VECTOR( UNSIGNED(in1_v) * UNSIGNED(in2_v) );
289                                         result_v := tmp64_v(31 DOWNTO 0);
290                                 END IF;
291
292                         WHEN A_BSLL | A_BSRL | A_BSRA  =>
293                                 IF (USE_BARREL_g = TRUE) THEN
294                                         IF (ID2EX_i.alu_Action = A_BSLL) THEN
295                                                 result_v := reverse_bits (in1_v);
296                                         ELSE
297                                                 result_v := in1_v;
298                                         END IF;
299                                         IF (ID2EX_i.alu_Action = A_BSRA) THEN
300                                                 padVec_v := (OTHERS => in1_v(31));
301                                         ELSE
302                                                 padVec_v := (OTHERS => '0');
303                                         END IF;
304                                         IF (in2_v(4) = '1') THEN
305                                                 result_v := padVec_v (15 DOWNTO 0) & result_v (31 DOWNTO 16);
306                                         END IF;
307                                         IF (in2_v(3) = '1') THEN
308                                                 result_v := padVec_v ( 7 DOWNTO 0) & result_v (31 DOWNTO  8);
309                                         END IF;
310                                         IF (in2_v(2) = '1') THEN
311                                                 result_v := padVec_v ( 3 DOWNTO 0) & result_v (31 DOWNTO  4);
312                                         END IF;
313                                         IF (in2_v(1) = '1') THEN
314                                                 result_v := padVec_v ( 1 DOWNTO 0) & result_v (31 DOWNTO  2);
315                                         END IF;
316                                         IF (in2_v(0) = '1') THEN
317                                                 result_v := padVec_v ( 0 DOWNTO 0) & result_v (31 DOWNTO  1);
318                                         END IF;
319                                         IF (ID2EX_i.alu_Action = A_BSLL) THEN
320                                                 result_v := reverse_bits (result_v);
321                                         END IF;
322                                 END IF;     -- (USE_BARREL_g = TRUE)
323
324                         WHEN A_CLZ     =>
325                            tmp64_v := (OTHERS => '0');
326                                 leading_zeroes32 ( in1_v, UNSIGNED(tmp64_v(31 DOWNTO 0)), result_v );
327
328                         WHEN OTHERS    =>
329                                 NULL;
330
331     END CASE;
332
333                 CASE ID2EX_i.condition IS
334                         WHEN COND_EQ  => do_cond_v := isZero_v;
335                         WHEN COND_NE  => do_cond_v := NOT isZero_v;
336                         WHEN COND_LT  => do_cond_v := signBit_r_v;
337                         WHEN COND_LE  => do_cond_v := signBit_r_v OR isZero_v;
338                         WHEN COND_GT  => do_cond_v := NOT (signBit_r_v OR isZero_v);
339                         WHEN COND_GE  => do_cond_v := NOT signBit_r_v;
340                         WHEN COND_ALL => do_cond_v := '1';
341                         WHEN OTHERS   => NULL;
342                 END CASE;
343
344                 CASE ID2EX_i.branch_Action IS
345                         WHEN BR     => do_branch_v := do_cond_v;
346                         WHEN BRL    => do_branch_v := '1';
347                         WHEN OTHERS => NULL;
348                 END CASE;
349
350                 IF (do_branch_v = '1') THEN
351                         EX2IF_o.take_branch   <= '1';
352                         EX2IF_o.branch_target <= result_v;
353                 ELSE
354                         EX2IF_o.take_branch   <= '0';
355                         EX2IF_o.branch_target <= C_32_ZEROS;
356                 END IF;
357
358                 -- IT / ITE / ITT conditioning
359                 IF (COMPATIBILITY_MODE_g = FALSE) THEN
360                         CASE ID2EX_i.it_Action IS
361                                 WHEN IT     =>
362                                         EX2CTRL_o.flush_first  <= not do_cond_v;
363                                         EX2CTRL_o.flush_second <= '0';
364                                         EX2CTRL_o.ignore_state <= '1';
365                                 WHEN ITT    =>
366                                         EX2CTRL_o.flush_first  <= not do_cond_v;
367                                         EX2CTRL_o.flush_second <= not do_cond_v;
368                                         EX2CTRL_o.ignore_state <= '1';
369                                 WHEN ITE    =>
370                                         EX2CTRL_o.flush_first  <= not do_cond_v;
371                                         EX2CTRL_o.flush_second <= do_cond_v;
372                                         EX2CTRL_o.ignore_state <= '1';
373                                 WHEN OTHERS =>
374                                         EX2CTRL_o.flush_first  <= '0';
375                                         EX2CTRL_o.flush_second <= '0';
376                                         EX2CTRL_o.ignore_state <= '0';
377                         END CASE;
378                 END IF;
379
380                 -- Halting, the instruction parsing is separate
381                 HALT_o.halt        <= ID2EX_i.halt;
382                 IF (ID2EX_i.halt = '1') THEN
383                         HALT_o.halt_code <= ID2EX_i.IMM16(4 DOWNTO 0);
384                 ELSE
385                         HALT_o.halt_code <= (others => '0');
386                 END IF;
387
388                 -- WR_MEM/RD_MEM:      result_v --> exeq_result --> mem_address,
389                 --        WR_MEM:                       data_rD --> data_out_to_mem
390                 --           BRL:  prog_counter --> exeq_result
391                 --          else       result_v --> exeq_result (data_rD not used)
392                 EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD;
393                 IF (ID2EX_i.branch_Action = BRL) THEN
394                         EX2MEM_o.wrb_Action  <= WRB_EX;
395                         IF (COMPATIBILITY_MODE_g = TRUE) OR (delayBit_i = '0') THEN
396                                 EX2MEM_o.exeq_result <= ID2EX_i.program_counter;
397                                 EX2MEM_o.data_rD     <= ID2EX_i.program_counter;
398                         ELSE
399                                 EX2MEM_o.exeq_result <= IF2ID_i.program_counter;
400                                 EX2MEM_o.data_rD     <= IF2ID_i.program_counter;
401                         END IF;
402                         -- set data_rD_v, although unused, to prevent an inferred latch
403                         data_rD_v := GPRF2EX_i.data_rD;
404                 ELSE
405                         EX2MEM_o.wrb_Action  <= ID2EX_i.wrb_Action;
406                         EX2MEM_o.exeq_result <= result_v;
407                         -- test where to obtain data_rD from
408                         IF (HAZARD_WRB_i.hazard = '1') THEN
409                                 data_rD_v := HAZARD_WRB_i.data_rD;
410                         ELSIF ((EX_WRB_i.wrb_Action = WRB_EX) AND (ID2EX_i.curr_rD = EX_WRB_i.wrix_rD)) THEN
411                         -- forward rD_data just calculated, to handle e.g. addi rD,rA,Imm; sw rD,mem[y]; ...
412                                 data_rD_v := EX_WRB_i.data_rD;
413                         ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.curr_rD = MEM_WRB_i.wrix_rD)) THEN
414                                 data_rD_v := MEM_WRB_i.data_rD;
415                         ELSE
416                                 data_rD_v := GPRF2EX_i.data_rD;
417                         END IF;
418                 END IF;
419
420                 IF (ID2EX_i.mem_Action /= NO_MEM) THEN
421                         CASE ID2EX_i.transfer_Size IS
422
423                                 WHEN BYTE     =>
424                                         CASE result_v( 1 DOWNTO 0) IS
425                                                 WHEN "00"   => byte_Enable_v := "1000";
426                                                 WHEN "01"   => byte_Enable_v := "0100";
427                                                 WHEN "10"   => byte_Enable_v := "0010";
428                                                 WHEN "11"   => byte_Enable_v := "0001";
429                                                 WHEN OTHERS => NULL;
430                                         END CASE;
431
432                                 WHEN HALFWORD =>
433                                         CASE result_v( 1 DOWNTO 0) IS
434                                                 WHEN "00"   => byte_Enable_v := "1100";
435                                                 WHEN "10"   => byte_Enable_v := "0011";
436                                                 WHEN OTHERS => NULL;
437                                         END CASE;
438
439                                 WHEN OTHERS     => byte_Enable_v := "1111";
440
441                         END CASE;
442                 END IF;
443
444                 -- update MSR[C] if needed
445                 IF (ID2EX_i.msr_Action = UPDATE_CARRY) THEN
446                         MSR_o.C <= carry_o_v;
447                 END IF;
448
449                 -- pass remaining data to mem
450                 EX2MEM_o.mem_Action  <= ID2EX_i.mem_Action;
451                 EX2MEM_o.data_rD     <= data_rD_v;
452                 EX2MEM_o.byte_Enable <= byte_Enable_v;
453                 EX2MEM_o.wrix_rD     <= ID2EX_i.curr_rD;
454                 --
455                 IMM_LOCK_o.locked    <= ID2EX_i.IMM_Lock;
456                 IMM_LOCK_o.IMM_hi16  <= ID2EX_i.IMM16;
457                 --
458                 EX_WRB_o.wrb_Action  <= ID2EX_i.wrb_Action;
459                 EX_WRB_o.wrix_rD     <= ID2EX_i.curr_rD;
460                 EX_WRB_o.data_rD     <= result_v;
461                 --
462                 HAZARD_WRB_o.hazard  <= hazard_v;
463                 HAZARD_WRB_o.save_rX <= save_rX_v;
464                 HAZARD_WRB_o.data_rX <= data_rX_v;
465                 HAZARD_WRB_o.data_rD <= data_rD_v;
466
467         END PROCESS;
468
469 END ARCHITECTURE rtl;
470