]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/decode.vhd
Reformat code and restructure decoder to save LUTs and fit critical path
[fpga/lx-cpu1/tumbl.git] / hw / decode.vhd
1 ---------------------------------------------------------------------------------
2 --
3 --  Entity:       decode
4 --  Filename:     decode.vhd
5 --  Description:  the Instruction Decode (ID) unit for
6 --                the TUD MB-Lite implementation
7 --
8 --  Author:       Huib Lincklaen Arriens
9 --                Delft University of Technology
10 --                Faculty EEMCS, Department ME&CE, Circuits and Systems
11 --  Date:         September, 2010
12 --                     June, 2011: added code for MUL and BARREL (Huib)
13 --  Modified:
14 --  Remarks:
15 --
16 --------------------------------------------------------------------------------
17
18 LIBRARY IEEE;
19
20 USE IEEE.std_logic_1164.all;
21 USE WORK.mbl_Pkg.all;
22
23 --------------------------------------------------------------------------------
24 ENTITY decode IS
25 --------------------------------------------------------------------------------
26         GENERIC
27         (
28                 USE_HW_MUL_g : BOOLEAN := TRUE;
29                 USE_BARREL_g : BOOLEAN := TRUE;
30                 COMPATIBILITY_MODE_g : BOOLEAN := FALSE
31         );
32         PORT
33         (
34                 IF2ID_i     :  IN IF2ID_Type;
35                 imem_data_i :  IN STD_LOGIC_VECTOR (31 DOWNTO 0);
36                 --
37                 ID2GPRF_o   : OUT ID2GPRF_Type;
38                 ID2EX_o     : OUT ID2EX_Type;
39                 --
40                 INT_CTRL_i  :  IN INT_CTRL_Type;
41                 ID2CTRL_o   : OUT ID2CTRL_Type;
42                 --
43                 noLiteOpc_o : OUT STD_LOGIC
44         );
45 END ENTITY decode;
46
47 --------------------------------------------------------------------------------
48 ARCHITECTURE rtl OF decode IS
49 --------------------------------------------------------------------------------
50
51 BEGIN
52
53 p_decode:
54         PROCESS (IF2ID_i, imem_data_i, INT_CTRL_i) IS
55
56                 VARIABLE prog_counter_v  : STD_LOGIC_VECTOR (31 DOWNTO 0);
57                 VARIABLE opcIx_v         : STD_LOGIC_VECTOR ( 5 DOWNTO 0);
58                 VARIABLE instruction_v   : STD_LOGIC_VECTOR (31 DOWNTO 0);
59                 VARIABLE rD_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
60                 VARIABLE rA_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
61                 VARIABLE rB_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
62                 VARIABLE IMM16_v         : STD_LOGIC_VECTOR (15 DOWNTO 0);
63                 VARIABLE code_x26_v      : STD_LOGIC_VECTOR ( 2 DOWNTO 0);
64                 VARIABLE IMM_Lock_v      : STD_LOGIC;
65                 VARIABLE alu_Action_v    : ALU_ACTION_Type;
66                 VARIABLE alu_Op1_v       : ALU_IN1_Type;
67                 VARIABLE alu_Op2_v       : ALU_IN2_Type;
68                 VARIABLE alu_Cin_v       : ALU_CIN_Type;
69                 VARIABLE msr_Action_v    : MSR_ACTION_Type;
70                 VARIABLE branch_Action_v : BRANCH_ACTION_Type;
71                 VARIABLE it_Action_v     : IT_ACTION_Type;
72                 VARIABLE delayBit_v      : STD_LOGIC;
73                 VARIABLE mem_Action_v    : MEM_ACTION_Type;
74                 VARIABLE transfer_Size_v : TRANSFER_SIZE_Type;
75                 VARIABLE wrb_Action_v    : WRB_ACTION_Type;
76                 VARIABLE int_busy_v      : STD_LOGIC;
77                 VARIABLE condition_raw_v : STD_LOGIC_VECTOR ( 2 DOWNTO 0);
78                 VARIABLE halt_v          : STD_LOGIC;
79
80         BEGIN
81
82                 prog_counter_v  := IF2ID_i.program_counter;
83                 instruction_v   := imem_data_i;
84                 opcIx_v         := instruction_v (31 DOWNTO 26);
85                 rD_v            := instruction_v (25 DOWNTO 21);
86                 rA_v            := instruction_v (20 DOWNTO 16);
87                 rB_v            := instruction_v (15 DOWNTO 11);
88                 IMM16_v         := instruction_v (15 DOWNTO  0);
89                 IMM_Lock_v      := '0';
90                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
91                         delayBit_v    := '0';
92                 ELSE
93                         it_Action_v   :=  NO_IT;
94                 END IF;
95                 condition_raw_v := (others => '1');
96                 alu_Cin_v       := CIN_ZERO;
97                 alu_Action_v    := A_NOP;
98                 msr_Action_v    := KEEP_CARRY;
99                 branch_Action_v := NO_BR;
100                 mem_Action_v    := NO_MEM;
101                 transfer_Size_v := WORD;
102                 wrb_Action_v    := WRB_EX;
103                 halt_v          := '0';
104                 -- for decoding SEXT16, SEXT8, SRC, SRC or SRL
105                 code_x26_v      := instruction_v(6) & instruction_v(5) & instruction_v(0);
106                 int_busy_v      := INT_CTRL_i.int_busy;
107                 -- for debugging purposes
108                 noLiteOpc_o     <= '0';
109
110                 IF (INT_CTRL_i.setup_int = '1') THEN
111
112                         alu_Op1_v       := ALU_IN_ZERO;
113                         alu_Op2_v       := ALU_IN_IMM;
114                         IMM16_v         := X"0010";                 -- address of _interrupt_handler vector
115                         prog_counter_v  := INT_CTRL_i.rti_target;   -- delayed program counter
116                         alu_Action_v    := A_ADD;
117                         rD_v            := "01110";                 -- r14 reserved for storing program_counter
118                         rA_v            := (OTHERS => '0');         -- also set rA and rB to avoid possible ...
119                         rB_v            := (OTHERS => '0');         -- ... erronuous hazard detection in exeq module
120                         int_busy_v      := '1';
121                         branch_Action_v := BRL;
122
123                 ELSE
124
125                         alu_Op1_v := ALU_IN_REGA;
126                         IF (opcIx_v(3) = '0') THEN
127                                 alu_Op2_v := ALU_IN_REGB;
128                         ELSE
129                                 alu_Op2_v := ALU_IN_IMM;
130                         END IF;
131
132                         CASE opcIx_v (5 DOWNTO 4) IS
133
134                                 WHEN "00" =>                                          -- ADD / RSUB
135                                         IF (opcIx_v(0) = '1') THEN                          -- RSUB
136                                                 alu_Op1_v := ALU_IN_NOT_REGA;
137                                         END IF;
138                                         IF (opcIx_v(1) = '0') THEN                          -- xxx
139                                                 IF (opcIx_v(0) = '0') THEN
140                                                         alu_Cin_v := CIN_ZERO;
141                                                 ELSE
142                                                         alu_Cin_v := CIN_ONE;
143                                                 END IF;
144                                         ELSE                                                -- xxxC
145                                                 alu_Cin_v := FROM_MSR;
146                                         END IF;
147                                         IF ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
148                                                 -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode
149                                                 IF (IMM16_v(1) = '1') THEN                        -- U-bit set, CMPU
150                                                         alu_Action_v := A_CMPU;
151                                                 ELSE
152                                                         alu_Action_v := A_CMP;
153                                                 END IF;
154                                                 ELSE
155                                                         alu_Action_v := A_ADD;
156                                                 IF (opcIx_v(2) = '0') THEN
157                                                         msr_Action_v := UPDATE_CARRY;
158                                                 END IF;
159                                         END IF;
160
161                                 WHEN "01" =>                                          -- MUL / BS
162
163                                         CASE opcIx_v (2 DOWNTO 0) IS
164                                                 WHEN "000" =>                                     -- MUL
165                                                         IF (USE_HW_MUL_g = TRUE) THEN
166                                                                 alu_Action_v := A_MUL;
167                                                         ELSE
168                                                                 noLiteOpc_o <= '1';
169                                                         END IF;
170
171                                                 WHEN "001" =>                                     -- BS
172                                                         IF (USE_BARREL_g = TRUE) THEN
173                                                                 IF (instruction_v(10) = '1') THEN
174                                                                         alu_Action_v := A_BSLL;
175                                                                 ELSIF (instruction_v(9) = '1') THEN
176                                                                         alu_Action_v := A_BSRA;
177                                                                 ELSE
178                                                                         alu_Action_v := A_BSRL;
179                                                                 END IF;
180                                                         ELSE
181                                                                 noLiteOpc_o <= '1';
182                                                         END IF;
183
184                                                 WHEN "010" | "011" =>                             -- CMP(U)
185                                                         IF (COMPATIBILITY_MODE_g = FALSE) THEN
186                                                                 IF (opcIx_v(0) = '1') THEN
187                                                                         alu_Action_v := A_CMPU;
188                                                                 ELSE
189                                                                         alu_Action_v := A_CMP;
190                                                                 END IF;
191                                                         ELSE
192                                                                 noLiteOpc_o <= '1';
193                                                         END IF;
194
195                                                 WHEN "100" | "101" =>                             -- IT(U) / ITT(U) / ITE(U)
196                                                         IF (COMPATIBILITY_MODE_g = FALSE) THEN
197                                                                 IF (opcIx_v(0) = '1') THEN
198                                                                         alu_Action_v := A_CMPU;
199                                                                 ELSE
200                                                                         alu_Action_v := A_CMP;
201                                                                 END IF;
202
203                                                                 CASE rD_v(4 downto 3) IS
204                                                                         WHEN "00"   =>
205                                                                                 it_Action_v := IT;
206                                                                         WHEN "01"   =>
207                                                                                 it_Action_v := ITT;
208                                                                         WHEN "10"   =>
209                                                                                 it_Action_v := ITE;
210                                                                         WHEN OTHERS =>
211                                                                                 noLiteOpc_o <= '1';
212                                                                 END CASE;
213                                                                 condition_raw_v := rD_v(2 downto 0);
214                                                                 -- IT instruction isn't writing to anything
215                                                                 wrb_Action_v := NO_WRB;
216                                                         ELSE
217                                                                 noLiteOpc_o <= '1';
218                                                         END IF;
219
220                                                 WHEN OTHERS =>
221                                                                 noLiteOpc_o <= '1';
222                                         END CASE;
223
224                                 WHEN "10" =>
225                                         IF (opcIx_v (3 DOWNTO 0) = "0100") THEN
226                                                 CASE code_x26_v IS
227
228                                                         WHEN "001" | "011" | "101" =>
229                                                                 CASE code_x26_v(2 DOWNTO 1) IS
230                                                                         WHEN "00" =>                                -- SRA
231                                                                                 alu_Cin_v := FROM_IN1;
232                                                                         WHEN "01" =>                                -- SRC
233                                                                                 alu_Cin_v := FROM_MSR;
234                                                                         WHEN "10" =>                                -- SRL
235                                                                                 alu_Cin_v := CIN_ZERO;
236                                                                         WHEN OTHERS =>
237                                                                                 noLiteOpc_o <= '1';
238                                                                         END CASE;
239                                                                 alu_Action_v := A_SHIFT;
240                                                                 msr_Action_v := UPDATE_CARRY;
241
242                                                         WHEN "110" =>                                   -- SEXT8
243                                                                 alu_Action_v := A_SEXT8;
244                                                         WHEN "111" =>                                   -- SEXT16
245                                                                 alu_Action_v := A_SEXT16;
246                                                         WHEN OTHERS  =>
247                                                                 noLiteOpc_o  <= '1';
248                                                 END CASE;
249
250                                         ELSIF (opcIx_v (3 DOWNTO 0) = "1100") THEN          -- IMM
251                                                 IMM_Lock_v   := '1';
252                                                 -- always: IMM_LOCK_o.IMM16 <= IMM16_v;
253                                                 alu_Action_v := A_NOP;
254                                                 wrb_Action_v := NO_WRB;
255                                         ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN
256
257                                                 CASE rD_v (3 DOWNTO 0) IS
258                                                         WHEN "0001" =>                                  -- RTI(D)
259                                                                 int_busy_v := '0';
260                                                         WHEN "0000" =>                                  -- RTS(D)
261                                                                 WHEN OTHERS  =>
262                                                         noLiteOpc_o <= '1';
263                                                 END CASE;
264
265                                                 alu_Action_v    := A_ADD;
266                                                 branch_Action_v := BR;
267                                                 wrb_Action_v    := NO_WRB;
268                                                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
269                                                         delayBit_v  := rD_v(4);
270                                                 END IF;
271
272                                         ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN
273
274                                                 CASE IMM16_v IS
275                                                         WHEN X"8001" =>                                 -- MFS (MSR only)
276                                                                 alu_Action_v := A_MFS;
277                                                         WHEN X"C001" =>                                 -- MTS (MSR only)
278                                                                 alu_Action_v := A_MTS;
279                                                                 wrb_Action_v := NO_WRB;
280                                                         WHEN OTHERS  =>
281                                                                 noLiteOpc_o  <= '1';
282                                                 END CASE;
283                                                 rB_v := (OTHERS => '0');    -- in order to prevent occasional hazards (r16, r24)
284
285                                         ELSE
286
287                                                 CASE opcIx_v (2 DOWNTO 0) IS
288                                                         WHEN "000" =>
289                                                                 alu_Action_v := A_OR;
290                                                         WHEN "001" =>
291                                                                 alu_Action_v := A_AND;
292                                                         WHEN "010" =>
293                                                                 alu_Action_v := A_XOR;
294                                                         WHEN "011" =>
295                                                                 alu_Action_v := A_AND;
296                                                                 IF (opcIx_v(3) = '0') THEN
297                                                                         alu_Op2_v := ALU_IN_NOT_REGB;
298                                                                 ELSE
299                                                                         alu_Op2_v := ALU_IN_NOT_IMM;
300                                                                 END IF;
301
302                                                         WHEN "110" =>                                                                             -- BR(I)(D)
303                                                                 IF (rA_v(2) = '1') THEN
304                                                                         branch_Action_v := BRL;
305                                                                 ELSE
306                                                                         branch_Action_v := BR;
307                                                                         wrb_Action_v    := NO_WRB;
308                                                                 END IF;
309
310                                                                 IF (rA_v(3) = '1') THEN
311                                                                         alu_Op1_v := ALU_IN_ZERO;
312                                                                 ELSE
313                                                                         alu_Op1_v := ALU_IN_PC;
314                                                                 END IF;
315                                                                 alu_Action_v    := A_ADD;
316                                                                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
317                                                                         delayBit_v  := rA_v(4);
318                                                                 END IF;
319
320                                                         WHEN "111" =>
321                                                                 condition_raw_v := rD_v(2 downto 0);          -- Conditional branching
322                                                                 branch_Action_v := BR;
323                                                                 alu_Action_v := A_ADD;
324                                                                 alu_Op1_v    := ALU_IN_PC;
325                                                                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
326                                                                         delayBit_v := rD_v(4);
327                                                                 END IF;
328                                                                 wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
329
330                                                         WHEN OTHERS =>
331                                                                 noLiteOpc_o  <= '1';
332                                                 END CASE;
333                                         END IF;
334
335                                 WHEN "11" =>
336                                         IF (opcIx_v (3 DOWNTO 0) = "1111") THEN             -- HALT
337                                                 alu_Action_v := A_NOP;
338                                                 wrb_Action_v := NO_WRB;
339                                                 halt_v       := '1';
340                                         ELSE
341                                                 alu_Action_v :=  A_ADD;
342                                                 CASE opcIx_v (1 DOWNTO 0) IS
343                                                         WHEN "00"   => transfer_Size_v := BYTE;
344                                                         WHEN "01"   => transfer_Size_v := HALFWORD;
345                                                         WHEN "10"   => transfer_Size_v := WORD;
346                                                         WHEN OTHERS =>
347                                                                 noLiteOpc_o <= '1';
348                                                 END CASE;
349                                                 IF (opcIx_v(2) = '0') THEN
350                                                         mem_Action_v := RD_MEM;
351                                                         wrb_Action_v := WRB_MEM;
352                                                 ELSE
353                                                         mem_Action_v := WR_MEM;
354                                                         wrb_Action_v := NO_WRB;
355                                                 END IF;
356                                         END IF;
357
358                                 WHEN OTHERS =>
359                                         noLiteOpc_o  <= '1';
360
361                         END CASE;
362
363                 END IF;         -- interrupt test
364
365                 ID2GPRF_o.rdix_rA  <= rA_v;
366                 ID2GPRF_o.rdix_rB  <= rB_v;
367                 ID2GPRF_o.rdix_rD  <= rD_v;
368
369                 ID2EX_o.program_counter  <= prog_counter_v;
370                 ID2EX_o.rdix_rA          <= rA_v;
371                 ID2EX_o.rdix_rB          <= rB_v;
372                 ID2EX_o.curr_rD          <= rD_v;
373                 ID2EX_o.alu_Action       <= alu_Action_v;
374                 ID2EX_o.alu_Op1          <= alu_Op1_v;
375                 ID2EX_o.alu_Op2          <= alu_Op2_v;
376                 ID2EX_o.alu_Cin          <= alu_Cin_v;
377                 ID2EX_o.IMM16            <= IMM16_v;
378                 ID2EX_o.IMM_Lock         <= IMM_Lock_v;
379                 ID2EX_o.msr_Action       <= msr_Action_v;
380                 ID2EX_o.branch_Action    <= branch_Action_v;
381                 ID2EX_o.it_Action        <= it_Action_v;
382                 ID2EX_o.mem_Action       <= mem_Action_v;
383                 ID2EX_o.transfer_Size    <= transfer_Size_v;
384                 ID2EX_o.wrb_Action       <= wrb_Action_v;
385                 ID2EX_o.halt             <= halt_v;
386                 --
387                 CASE condition_raw_v IS
388                         WHEN "000"  =>
389                                 ID2EX_o.condition    <= COND_EQ;
390                         WHEN "001"  =>
391                                 ID2EX_o.condition    <= COND_NE;
392                         WHEN "010"  =>
393                                 ID2EX_o.condition    <= COND_LT;
394                         WHEN "011"  =>
395                                 ID2EX_o.condition    <= COND_LE;
396                         WHEN "100"  =>
397                                 ID2EX_o.condition    <= COND_GT;
398                         WHEN "101"  =>
399                                 ID2EX_o.condition    <= COND_GE;
400                         WHEN "111"  =>
401                                 ID2EX_o.condition    <= COND_ALL;
402                         WHEN OTHERS =>
403                                 ID2EX_o.condition    <= COND_ALL;
404                                 noLiteOpc_o            <= '1';
405                 END CASE;
406                 --
407                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
408                         ID2CTRL_o.delayBit   <= delayBit_v;
409                 END IF;
410                 ID2CTRL_o.int_busy     <= int_busy_v;
411
412         END PROCESS;
413
414 END ARCHITECTURE rtl;
415