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