]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/exeq.vhd
Customized instruction set (with compatibility mode)
[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 (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         USE_HW_MUL_g : BOOLEAN := TRUE;
34         USE_BARREL_g : BOOLEAN := TRUE
35         );
36     PORT (
37         ID2EX_i      :  IN ID2EX_Type;
38         GPRF2EX_i    :  IN GPRF2EX_Type;
39         EX2IF_o      : OUT EX2IF_Type;
40         HALT_o       : OUT HALT_Type;
41         --
42         EX_WRB_i     :  IN WRB_Type;
43         EX_WRB_o     : OUT WRB_Type;
44         MEM_WRB_i    :  IN WRB_Type;
45         --
46         HAZARD_WRB_i :  IN HAZARD_WRB_Type;
47         HAZARD_WRB_o : OUT HAZARD_WRB_Type;
48         --
49         IMM_LOCK_i   :  IN IMM_LOCK_Type;
50         IMM_LOCK_o   : OUT IMM_LOCK_Type;
51         --
52         MSR_i        :  IN MSR_Type;
53         MSR_o        : OUT MSR_Type;
54         --
55         EX2MEM_o     : OUT EX2MEM_Type
56         );
57 END ENTITY exeq;
58
59
60 ----------------------------------------------------------
61 ARCHITECTURE rtl OF exeq IS
62 ----------------------------------------------------------
63
64 BEGIN
65
66 p_exeq:
67     PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i,
68                         IMM_LOCK_i, MSR_i, HAZARD_WRB_i)
69
70         -- function needed by BSLL (only if USE_BARREL_g = TRUE)
71         FUNCTION reverse_bits ( word32 : STD_LOGIC_VECTOR (31 DOWNTO 0) )
72                                                         RETURN STD_LOGIC_VECTOR IS
73             VARIABLE reversed_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
74         BEGIN
75         f_rev:
76             FOR i IN 0 TO 31 LOOP
77                 reversed_v(31-i) := word32(i);
78             END LOOP;
79             RETURN reversed_v;
80         END;
81
82         VARIABLE data_rA_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
83         VARIABLE data_rB_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
84         VARIABLE data_rD_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
85         VARIABLE in1_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
86         VARIABLE in2_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
87         VARIABLE hi16_v        : STD_LOGIC_VECTOR (15 DOWNTO 0);
88         VARIABLE IMM32_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
89         VARIABLE carry_i_v     : STD_LOGIC;
90         VARIABLE result_v      : STD_LOGIC_VECTOR (31 DOWNTO 0);
91         VARIABLE carry_o_v     : STD_LOGIC;
92         VARIABLE isZero_v      : STD_LOGIC;
93         VARIABLE signBit_in1_v : STD_LOGIC;
94         VARIABLE signBit_in2_v : STD_LOGIC;
95         VARIABLE signBit_rA_v  : STD_LOGIC;
96         VARIABLE rA_eq_ex_rD_v : STD_LOGIC;
97         VARIABLE rB_eq_ex_rD_v : STD_LOGIC;
98         VARIABLE hazard_v      : STD_LOGIC;
99         VARIABLE save_rX_v     : SAVE_REG_Type;
100         VARIABLE data_rX_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
101         VARIABLE do_branch_v   : STD_LOGIC;
102         VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
103         VARIABLE tmp64_v       : STD_LOGIC_VECTOR (63 DOWNTO 0);
104         VARIABLE padVec_v      : STD_LOGIC_VECTOR (15 DOWNTO 0);
105         VARIABLE halt_v        : STD_LOGIC;
106         VARIABLE halt_code_v   : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
107
108     BEGIN
109
110         rA_eq_ex_rD_v := '0';
111         rB_eq_ex_rD_v := '0';
112         hazard_v      := '0';
113         save_rX_v     := NO_SAVE;
114         data_rX_v     := data_rB_v;         -- default value for data_rX_v
115         result_v      := (OTHERS => '0');
116         carry_o_v     := '0';
117         do_branch_v   := '0';
118         byte_Enable_v := "0000";
119         halt_v        := '0';
120         halt_code_v   := "00000";
121
122         -- create some helper variables
123         IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN
124             rA_eq_ex_rD_v := '1';
125         END IF;
126         IF (ID2EX_i.rdix_rB = EX_WRB_i.wrix_rD) THEN
127             rB_eq_ex_rD_v := '1';
128         END IF;
129         -- test where to obtain data_rA from
130         IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rA_eq_ex_rD_v = '1')) THEN
131             data_rA_v := EX_WRB_i.data_rD;
132         ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rA = MEM_WRB_i.wrix_rD)) THEN
133             data_rA_v := MEM_WRB_i.data_rD;
134         ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RA)) THEN
135             data_rA_v := HAZARD_WRB_i.data_rX;
136         ELSE
137             data_rA_v := GPRF2EX_i.data_rA;
138         END IF;
139         -- test where to obtain data_rB from
140         IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rB_eq_ex_rD_v = '1')) THEN
141             data_rB_v := EX_WRB_i.data_rD;
142         ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rB = MEM_WRB_i.wrix_rD)) THEN
143             data_rB_v := MEM_WRB_i.data_rD;
144         ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RB)) THEN
145             data_rB_v := HAZARD_WRB_i.data_rX;
146         ELSE
147             data_rB_v := GPRF2EX_i.data_rB;
148         END IF;
149         -- .... or, isn't all necessary data available yet being still in the pipeline ?
150         data_rX_v := data_rB_v;                 -- default value for data_rX_v
151         IF (EX_WRB_i.wrb_Action = WRB_MEM) THEN
152             IF ((rA_eq_ex_rD_v = '1') OR (rB_eq_ex_rD_v = '1')) THEN
153                 hazard_v  := '1';
154 -- always??     IF (MEM_WRB_i.wrb_Action = WRB_MEM) THEN
155                     -- handle situations in which both rA and rB needed
156                     IF (rA_eq_ex_rD_v = '1') THEN
157                         save_rX_v := SAVE_RB;   -- already by default data_rX_v = data_rB_v
158                     ELSE
159                         save_rX_v := SAVE_RA;
160                         data_rX_v := data_rA_v;
161                     END IF;
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_rA_v  := data_rA_v(31);
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         CASE ID2EX_i.alu_Action IS
204             WHEN A_ADD | A_CMP | A_CMPU =>
205                 ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v);
206                 IF (id2ex_i.alu_Action = A_CMPU) THEN
207                     IF (signBit_in1_v = signBit_in2_v) THEN
208                         result_v(31) := NOT signBit_in1_v;
209                     END IF;
210                 ELSIF (id2ex_i.alu_Action = A_CMP) THEN
211                     IF (signBit_in1_v = signBit_in2_v) THEN
212                         result_v(31) := signBit_in1_v;
213                     END IF;
214                 END IF;
215             WHEN A_OR      =>
216                 result_v  := in1_v  OR in2_v;
217             WHEN A_AND    =>
218                 result_v  := in1_v AND in2_v;
219             WHEN A_XOR    =>
220                 result_v  := in1_v XOR in2_v;
221             WHEN A_SHIFT  =>
222                 result_v  := carry_i_v & in1_v(31 DOWNTO 1);
223                 carry_o_v := in1_v(0);
224             WHEN A_SEXT8   =>
225                 IF (in1_v(7) = '0') THEN
226                     result_v := C_24_ZEROS & in1_v( 7 DOWNTO 0);
227                 ELSE
228                     result_v :=  C_24_ONES & in1_v( 7 DOWNTO 0);
229                 END IF;
230             WHEN A_SEXT16  =>
231                 IF (in1_v(15) = '0') THEN
232                     result_v := C_16_ZEROS & in1_v(15 DOWNTO 0);
233                 ELSE
234                     result_v :=  C_16_ONES & in1_v(15 DOWNTO 0);
235                 END IF;
236             WHEN A_MFS     =>
237                 result_v := MSR_i.C & C_24_ZEROS & "0000" & MSR_i.C & MSR_i.IE & '0';
238             WHEN A_MTS     =>
239                 MSR_o.IE  <= data_Ra_v(1);
240                 MSR_o.C   <= data_Ra_v(2);
241             WHEN A_MUL     =>
242                 IF (USE_HW_MUL_g = TRUE) THEN
243                     tmp64_v  := STD_LOGIC_VECTOR( UNSIGNED(in1_v) * UNSIGNED(in2_v) );
244                     result_v := tmp64_v(31 DOWNTO 0);
245                 END IF;
246             WHEN A_BSLL | A_BSRL | A_BSRA  =>
247                 IF (USE_BARREL_g = TRUE) THEN
248                     IF (ID2EX_i.alu_Action = A_BSLL) THEN
249                         result_v := reverse_bits (in1_v);
250                     ELSE
251                         result_v := in1_v;
252                     END IF;
253                     IF (ID2EX_i.alu_Action = A_BSRA) THEN
254                         padVec_v := (OTHERS => in1_v(31));
255                     ELSE
256                         padVec_v := (OTHERS => '0');
257                     END IF;
258                     IF (in2_v(4) = '1') THEN
259                         result_v := padVec_v (15 DOWNTO 0) & result_v (31 DOWNTO 16);
260                     END IF;
261                     IF (in2_v(3) = '1') THEN
262                         result_v := padVec_v ( 7 DOWNTO 0) & result_v (31 DOWNTO  8);
263                     END IF;
264                     IF (in2_v(2) = '1') THEN
265                         result_v := padVec_v ( 3 DOWNTO 0) & result_v (31 DOWNTO  4);
266                     END IF;
267                     IF (in2_v(1) = '1') THEN
268                         result_v := padVec_v ( 1 DOWNTO 0) & result_v (31 DOWNTO  2);
269                     END IF;
270                     IF (in2_v(0) = '1') THEN
271                         result_v := padVec_v ( 0 DOWNTO 0) & result_v (31 DOWNTO  1);
272                     END IF;
273                     IF (ID2EX_i.alu_Action = A_BSLL) THEN
274                         result_v := reverse_bits (result_v);
275                     END IF;
276                 END IF;     -- (USE_BARREL_g = TRUE)
277             WHEN A_HALT    =>
278                 halt_v := '1';
279                 halt_code_v := ID2EX_i.IMM16(4 DOWNTO 0);
280             WHEN OTHERS    =>
281                 NULL;
282         END CASE;
283
284         IF (data_rA_v = C_32_ZEROS) THEN
285             isZero_v := '1';
286         ELSE
287             isZero_v := '0';
288         END IF;
289         CASE ID2EX_i.branch_Action IS
290             WHEN BR     => do_branch_v := '1';
291             WHEN BRL    => do_branch_v := '1';
292             WHEN BEQ    => do_branch_v := isZero_v;
293             WHEN BNE    => do_branch_v := NOT isZero_v;
294             WHEN BLT    => do_branch_v := signBit_rA_v;
295             WHEN BLE    => do_branch_v := signBit_rA_v OR isZero_v;
296             WHEN BGT    => do_branch_v := NOT (signBit_rA_v OR isZero_v);
297             WHEN BGE    => do_branch_v := NOT signBit_rA_v;
298             WHEN OTHERS => NULL;
299         END CASE;
300         IF (do_branch_v = '1') THEN
301             EX2IF_o.take_branch   <= '1';
302             EX2IF_o.branch_target <= result_v;
303         ELSE
304             EX2IF_o.take_branch   <= '0';
305             EX2IF_o.branch_target <= C_32_ZEROS;
306         END IF;
307
308         -- Halting
309         HALT_o.halt      <= halt_v;
310         HALT_o.halt_code <= halt_code_v;
311
312         -- WR_MEM/RD_MEM:      result_v --> exeq_result --> mem_address,
313         --        WR_MEM:                       data_rD --> data_out_to_mem
314         --           BRL:  prog_counter --> exeq_result
315         --          else       result_v --> exeq_result (data_rD not used)
316         EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD;
317         IF (ID2EX_i.branch_Action = BRL) THEN
318             EX2MEM_o.wrb_Action  <= WRB_EX;
319             EX2MEM_o.exeq_result <= ID2EX_i.program_counter;
320             EX2MEM_o.data_rD     <= ID2EX_i.program_counter;
321             -- set data_rD_v, although unused, to prevent an inferred latch
322             data_rD_v := GPRF2EX_i.data_rD;
323         ELSE
324             EX2MEM_o.wrb_Action  <= ID2EX_i.wrb_Action;
325             EX2MEM_o.exeq_result <= result_v;
326             -- test where to obtain data_rD from
327             IF (HAZARD_WRB_i.hazard = '1') THEN
328                 data_rD_v := HAZARD_WRB_i.data_rD;
329             ELSIF ((EX_WRB_i.wrb_Action = WRB_EX) AND (ID2EX_i.curr_rD = EX_WRB_i.wrix_rD)) THEN
330                 -- forward rD_data just calculated, to handle e.g. addi rD,rA,Imm; sw rD,mem[y]; ...
331                 data_rD_v := EX_WRB_i.data_rD;
332             ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.curr_rD = MEM_WRB_i.wrix_rD)) THEN
333                 data_rD_v := MEM_WRB_i.data_rD;
334             ELSE
335                 data_rD_v := GPRF2EX_i.data_rD;
336             END IF;
337         END IF;
338         IF (ID2EX_i.mem_Action /= NO_MEM) THEN
339             CASE ID2EX_i.transfer_Size IS
340                 WHEN BYTE     =>
341                     CASE result_v( 1 DOWNTO 0) IS
342                         WHEN "00"   => byte_Enable_v := "1000";
343                         WHEN "01"   => byte_Enable_v := "0100";
344                         WHEN "10"   => byte_Enable_v := "0010";
345                         WHEN "11"   => byte_Enable_v := "0001";
346                         WHEN OTHERS => NULL;
347                     END CASE;
348                 WHEN HALFWORD =>
349                     CASE result_v( 1 DOWNTO 0) IS
350                         WHEN "00"   => byte_Enable_v := "1100";
351                         WHEN "10"   => byte_Enable_v := "0011";
352                         WHEN OTHERS => NULL;
353                     END CASE;
354                 WHEN OTHERS   =>       byte_Enable_v := "1111";
355             END CASE;
356         END IF;
357
358         -- update MSR[IE] and/or MSR[C] if needed
359         IF (ID2EX_i.alu_Action /= A_MTS) THEN
360             MSR_o.IE  <= MSR_i.IE;
361             IF (ID2EX_i.msr_Action = UPDATE_CARRY) THEN
362                 MSR_o.C <= carry_o_v;
363             ELSE
364                 MSR_o.C <= MSR_i.C;
365             END IF;
366         END IF;
367
368         -- pass remaining data to mem
369         EX2MEM_o.mem_Action  <= ID2EX_i.mem_Action;
370         EX2MEM_o.data_rD     <= data_rD_v;
371         EX2MEM_o.byte_Enable <= byte_Enable_v;
372         EX2MEM_o.wrix_rD     <= ID2EX_i.curr_rD;
373         --
374         IMM_LOCK_o.locked    <= ID2EX_i.IMM_Lock;
375         IMM_LOCK_o.IMM_hi16  <= ID2EX_i.IMM16;
376         --
377         EX_WRB_o.wrb_Action  <= ID2EX_i.wrb_Action;
378         EX_WRB_o.wrix_rD     <= ID2EX_i.curr_rD;
379         EX_WRB_o.data_rD     <= result_v;
380         --
381         HAZARD_WRB_o.hazard  <= hazard_v;
382         HAZARD_WRB_o.save_rX <= save_rX_v;
383         HAZARD_WRB_o.data_rX <= data_rX_v;
384         HAZARD_WRB_o.data_rD <= data_rD_v;
385
386     END PROCESS;
387
388 END ARCHITECTURE rtl;
389