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