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