]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/decode.vhd
Customized instruction set (with compatibility mode)
[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 --------------------------------------------------------------------------------
25 ENTITY decode IS
26 --------------------------------------------------------------------------------
27     GENERIC (
28         USE_HW_MUL_g : BOOLEAN := TRUE;
29         USE_BARREL_g : BOOLEAN := TRUE;
30         COMPATIBILITY_MODE_g : BOOLEAN := FALSE
31         );
32     PORT (
33         IF2ID_i     :  IN IF2ID_Type;
34         imem_data_i :  IN STD_LOGIC_VECTOR (31 DOWNTO 0);
35         --
36         ID2GPRF_o   : OUT ID2GPRF_Type;
37         ID2EX_o     : OUT ID2EX_Type;
38         --
39         INT_CTRL_i  :  IN INT_CTRL_Type;
40         ID2CTRL_o   : OUT ID2CTRL_Type;
41         --
42         noLiteOpc_o : OUT STD_LOGIC
43         );
44 END ENTITY decode;
45
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 delayBit_v      : STD_LOGIC;
72         VARIABLE mem_Action_v    : MEM_ACTION_Type;
73         VARIABLE transfer_Size_v : TRANSFER_SIZE_Type;
74         VARIABLE wrb_Action_v    : WRB_ACTION_Type;
75         VARIABLE int_busy_v      : STD_LOGIC;
76
77     BEGIN
78         prog_counter_v  := IF2ID_i.program_counter;
79         instruction_v   := imem_data_i;
80         opcIx_v         := instruction_v (31 DOWNTO 26);
81         rD_v            := instruction_v (25 DOWNTO 21);
82         rA_v            := instruction_v (20 DOWNTO 16);
83         rB_v            := instruction_v (15 DOWNTO 11);
84         IMM16_v         := instruction_v (15 DOWNTO  0);
85         IMM_Lock_v      := '0';
86         IF (COMPATIBILITY_MODE_g = TRUE) THEN
87             delayBit_v      := '0';
88         END IF;
89         alu_Cin_v       := CIN_ZERO;
90         alu_Action_v    := A_NOP;
91         msr_Action_v    := KEEP_CARRY;
92         branch_Action_v := NO_BR;
93         mem_Action_v    := NO_MEM;
94         transfer_Size_v := WORD;
95         wrb_Action_v    := WRB_EX;
96         -- for decoding SEXT16, SEXT8, SRC, SRC or SRL
97         code_x26_v      := instruction_v(6) & instruction_v(5) & instruction_v(0);
98         int_busy_v      := INT_CTRL_i.int_busy;
99         -- for debugging purposes
100         noLiteOpc_o     <= '0';
101
102         IF (INT_CTRL_i.setup_int = '1') THEN
103
104             alu_Op1_v       := ALU_IN_ZERO;
105             alu_Op2_v       := ALU_IN_IMM;
106             IMM16_v         := X"0010";                 -- address of _interrupt_handler vector
107             prog_counter_v  := INT_CTRL_i.rti_target;   -- delayed program counter
108             alu_Action_v    := A_ADD;
109             rD_v            := "01110";                 -- r14 reserved for storing program_counter
110             rA_v            := (OTHERS => '0');         -- also set rA and rB to avoid possible ...
111             rB_v            := (OTHERS => '0');         -- ... erronuous hazard detection in exeq module
112             int_busy_v      := '1';
113             branch_Action_v := BRL;
114
115         ELSE
116
117             alu_Op1_v := ALU_IN_REGA;
118             IF (opcIx_v(3) = '0') THEN
119                 alu_Op2_v := ALU_IN_REGB;
120             ELSE
121                 alu_Op2_v := ALU_IN_IMM;
122             END IF;
123
124             CASE opcIx_v (5 DOWNTO 4) IS
125
126                 WHEN "00" =>                                            -- ADD / RSUB
127                     IF (opcIx_v(0) = '1') THEN                          -- RSUB
128                         alu_Op1_v := ALU_IN_NOT_REGA;
129                     END IF;
130                     IF (opcIx_v(1) = '0') THEN                          -- xxx
131                         IF (opcIx_v(0) = '0') THEN
132                             alu_Cin_v := CIN_ZERO;
133                         ELSE
134                             alu_Cin_v := CIN_ONE;
135                         END IF;
136                     ELSE                                                -- xxxC
137                         alu_Cin_v := FROM_MSR;
138                     END IF;
139                     IF ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
140                     -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode
141                         IF (IMM16_v(1) = '1') THEN                        -- U-bit set, CMPU
142                             alu_Action_v := A_CMPU;
143                         ELSE
144                             alu_Action_v := A_CMP;
145                         END IF;
146                     ELSE
147                         alu_Action_v := A_ADD;
148                         IF (opcIx_v(2) = '0') THEN
149                             msr_Action_v := UPDATE_CARRY;
150                         END IF;
151                     END IF;
152
153                 WHEN "01" =>                                            -- MUL / BS
154                     CASE opcIx_v (2 DOWNTO 0) IS
155                         WHEN "000" =>                                   -- MUL
156                             IF (USE_HW_MUL_g = TRUE) THEN
157                                 alu_Action_v := A_MUL;
158                             ELSE
159                                 noLiteOpc_o <= '1';
160                             END IF;
161                         WHEN "001" =>                                   -- BS
162                             IF (USE_BARREL_g = TRUE) THEN
163                                 IF (instruction_v(10) = '1') THEN
164                                     alu_Action_v := A_BSLL;
165                                 ELSE
166                                     IF (instruction_v(9) = '1') THEN
167                                         alu_Action_v := A_BSRA;
168                                     ELSE
169                                         alu_Action_v := A_BSRL;
170                                     END IF;
171                                 END IF;
172                             ELSE
173                                 noLiteOpc_o <= '1';
174                             END IF;
175                         WHEN "010" =>                                             -- CMP / CMPU / CMPI (new format)
176                             IF (COMPATIBILITY_MODE_g = FALSE) THEN
177                                 IF (IMM16_v(5) = '1') THEN   -- U-bit set, CMPU
178                                     alu_Action_v := A_CMPU;
179                                 ELSE
180                                     alu_Action_v := A_CMP;
181                                 END IF;
182                             ELSE
183                                 noLiteOpc_o <= '1';
184                             END IF;
185                         WHEN OTHERS =>
186                             noLiteOpc_o <= '1';
187                     END CASE;
188
189                 WHEN "10" =>
190                     IF (opcIx_v (3 DOWNTO 0) = "0100") THEN
191                         CASE code_x26_v IS
192                             WHEN "001" | "011" | "101" =>
193                                 CASE code_x26_v(2 DOWNTO 1) IS
194                                     WHEN "00" =>                        -- SRA
195                                         alu_Cin_v := FROM_IN1;
196                                     WHEN "01" =>                        -- SRC
197                                         alu_Cin_v := FROM_MSR;
198                                     WHEN "10" =>                        -- SRL
199                                         alu_Cin_v := CIN_ZERO;
200                                     WHEN OTHERS =>
201                                         noLiteOpc_o <= '1';
202                                 END CASE;
203                                 alu_Action_v := A_SHIFT;
204                                 msr_Action_v := UPDATE_CARRY;
205                             WHEN "110" =>                               -- SEXT8
206                                 alu_Action_v := A_SEXT8;
207                             WHEN "111" =>                               -- SEXT16
208                                 alu_Action_v := A_SEXT16;
209                             WHEN OTHERS  =>
210                                 noLiteOpc_o  <= '1';
211                         END CASE;
212                     ELSIF (opcIx_v (3 DOWNTO 0) = "1100") THEN          -- IMM
213                         IMM_Lock_v   := '1';
214                         -- always: IMM_LOCK_o.IMM16 <= IMM16_v;
215                         alu_Action_v := A_NOP;
216                         wrb_Action_v := NO_WRB;
217                     ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN
218                         CASE rD_v (3 DOWNTO 0) IS
219                             WHEN "0001" =>                              -- RTI(D)
220                                 int_busy_v := '0';
221                             WHEN "0000" =>                              -- RTS(D)
222                             WHEN OTHERS  =>
223                                 noLiteOpc_o <= '1';
224                         END CASE;
225                         alu_Action_v    := A_ADD;
226                         branch_Action_v := BR;
227                         wrb_Action_v    := NO_WRB;
228                         IF (COMPATIBILITY_MODE_g = TRUE) THEN
229                             delayBit_v  := rD_v(4);
230                         END IF;
231                     ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN
232                         CASE IMM16_v IS
233                             WHEN X"8001" =>                             -- MFS (MSR only)
234                                 alu_Action_v := A_MFS;
235                             WHEN X"C001" =>                             -- MTS (MSR only)
236                                 alu_Action_v := A_MTS;
237                                 wrb_Action_v := NO_WRB;
238                             WHEN OTHERS  =>
239                                 noLiteOpc_o  <= '1';
240                         END CASE;
241                         rB_v := (OTHERS => '0');    -- in order to prevent occasional hazards (r16, r24)
242                     ELSE
243                         CASE opcIx_v (2 DOWNTO 0) IS
244                             WHEN "000" =>
245                                 alu_Action_v := A_OR;
246                             WHEN "001" =>
247                                 alu_Action_v := A_AND;
248                             WHEN "010" =>
249                                 alu_Action_v := A_XOR;
250                             WHEN "011" =>
251                                 alu_Action_v := A_AND;
252                                 IF (opcIx_v(3) = '0') THEN
253                                     alu_Op2_v := ALU_IN_NOT_REGB;
254                                 ELSE
255                                     alu_Op2_v := ALU_IN_NOT_IMM;
256                                 END IF;
257                             WHEN "110" =>                               -- BR(I)(D)
258                                 IF (rA_v(2) = '1') THEN
259                                     branch_Action_v := BRL;
260                                 ELSE
261                                     branch_Action_v := BR;
262                                     wrb_Action_v    := NO_WRB;
263                                 END IF;
264                                 IF (rA_v(3) = '1') THEN
265                                     alu_Op1_v := ALU_IN_ZERO;
266                                 ELSE
267                                     alu_Op1_v := ALU_IN_PC;
268                                 END IF;
269                                 alu_Action_v    := A_ADD;
270                                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
271                                     delayBit_v  := rA_v(4);
272                                 END IF;
273                             WHEN "111" =>
274                                 CASE rD_v(3 DOWNTO 0) IS
275                                     WHEN "0000" =>                      -- BEQ
276                                         branch_Action_v := BEQ;
277                                     WHEN "0001" =>                      -- BNE
278                                         branch_Action_v := BNE;
279                                     WHEN "0010" =>                      -- BLT
280                                         branch_Action_v := BLT;
281                                     WHEN "0011" =>                      -- BLE
282                                         branch_Action_v := BLE;
283                                     WHEN "0100" =>                      -- BGT
284                                         branch_Action_v := BGT;
285                                     WHEN "0101" =>                      -- BGE
286                                         branch_Action_v := BGE;
287                                     WHEN OTHERS =>
288                                         noLiteOpc_o <= '1';
289                                 END CASE;
290                                 alu_Action_v := A_ADD;
291                                 alu_Op1_v    := ALU_IN_PC;
292                                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
293                                     delayBit_v := rD_v(4);
294                                 END IF;
295                                 wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
296                             WHEN OTHERS =>
297                                 noLiteOpc_o  <= '1';
298                         END CASE;
299                     END IF;
300
301                 WHEN "11" =>
302                     IF (opcIx_v (3 DOWNTO 0) = "1111") THEN             -- HALT
303                         alu_Action_v :=  A_HALT;
304                         wrb_Action_v := NO_WRB;
305                     ELSE
306                         alu_Action_v :=  A_ADD;
307                         CASE opcIx_v (1 DOWNTO 0) IS
308                             WHEN "00"   => transfer_Size_v := BYTE;
309                             WHEN "01"   => transfer_Size_v := HALFWORD;
310                             WHEN "10"   => transfer_Size_v := WORD;
311                             WHEN OTHERS =>
312                                 noLiteOpc_o <= '1';
313                         END CASE;
314                         IF (opcIx_v(2) = '0') THEN
315                             mem_Action_v := RD_MEM;
316                             wrb_Action_v := WRB_MEM;
317                         ELSE
318                             mem_Action_v := WR_MEM;
319                             wrb_Action_v := NO_WRB;
320                         END IF;
321                     END IF;
322
323                 WHEN OTHERS =>
324                     noLiteOpc_o  <= '1';
325
326             END CASE;
327
328         END IF;         -- interrupt test
329
330         ID2GPRF_o.rdix_rA  <= rA_v;
331         ID2GPRF_o.rdix_rB  <= rB_v;
332         ID2GPRF_o.rdix_rD  <= rD_v;
333
334         ID2EX_o.program_counter  <= prog_counter_v;
335         ID2EX_o.rdix_rA          <= rA_v;
336         ID2EX_o.rdix_rB          <= rB_v;
337         ID2EX_o.curr_rD          <= rD_v;
338         ID2EX_o.alu_Action       <= alu_Action_v;
339         ID2EX_o.alu_Op1          <= alu_Op1_v;
340         ID2EX_o.alu_Op2          <= alu_Op2_v;
341         ID2EX_o.alu_Cin          <= alu_Cin_v;
342         ID2EX_o.IMM16            <= IMM16_v;
343         ID2EX_o.IMM_Lock         <= IMM_Lock_v;
344         ID2EX_o.msr_Action       <= msr_Action_v;
345         ID2EX_o.branch_Action    <= branch_Action_v;
346         ID2EX_o.mem_Action       <= mem_Action_v;
347         ID2EX_o.transfer_Size    <= transfer_Size_v;
348         ID2EX_o.wrb_Action       <= wrb_Action_v;
349         --
350         IF (COMPATIBILITY_MODE_g = TRUE) THEN
351             ID2CTRL_o.delayBit      <= delayBit_v;
352         END IF;
353         ID2CTRL_o.int_busy      <= int_busy_v;
354
355     END PROCESS;
356
357 END ARCHITECTURE rtl;
358