-
Notifications
You must be signed in to change notification settings - Fork 0
/
cv32e40x_b_decoder.sv
354 lines (328 loc) · 13.6 KB
/
cv32e40x_b_decoder.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
// Copyright 2021 Silicon Labs, Inc.
//
// This file, and derivatives thereof are licensed under the
// Solderpad License, Version 2.0 (the "License");
// Use of this file means you agree to the terms and conditions
// of the license and are in full compliance with the License.
// You may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.0/
//
// Unless required by applicable law or agreed to in writing, software
// and hardware implementations thereof
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// Engineers Oivind Ekelund - oivind.ekelund@silabs.com //
// Halfdan Bechmann - halfdan.bechmann@silabs.com //
// //
// Design Name: B Decoder //
// Project Name: CV32E40X //
// Language: SystemVerilog //
// //
// Description: Decoder for the RV32B extension //
// //
////////////////////////////////////////////////////////////////////////////////
module cv32e40x_b_decoder import cv32e40x_pkg::*;
#(
parameter b_ext_e B_EXT = B_NONE
)
(
// from IF/ID pipeline
input logic [31:0] instr_rdata_i,
output decoder_ctrl_t decoder_ctrl_o
);
localparam RV32B_ZBA = (B_EXT == ZBA_ZBB) || (B_EXT == ZBA_ZBB_ZBS) || (B_EXT == ZBA_ZBB_ZBC_ZBS);
localparam RV32B_ZBB = (B_EXT == ZBA_ZBB) || (B_EXT == ZBA_ZBB_ZBS) || (B_EXT == ZBA_ZBB_ZBC_ZBS);
localparam RV32B_ZBS = (B_EXT == ZBA_ZBB_ZBS) || (B_EXT == ZBA_ZBB_ZBC_ZBS);
localparam RV32B_ZBC = (B_EXT == ZBA_ZBB_ZBC_ZBS);
always_comb
begin
// Default assignments
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
decoder_ctrl_o.illegal_insn = 1'b0;
unique case (instr_rdata_i[6:0])
OPCODE_OP: begin
decoder_ctrl_o.alu_en = 1'b1;
decoder_ctrl_o.alu_op_a_mux_sel = OP_A_REGA_OR_FWD;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_REGB_OR_FWD;
decoder_ctrl_o.rf_re[0] = 1'b1;
decoder_ctrl_o.rf_re[1] = 1'b1;
decoder_ctrl_o.rf_we = 1'b1;
unique case ({instr_rdata_i[31:25], instr_rdata_i[14:12]})
// Supported RV32B Zca instructions
{7'b001_0000, 3'b010}: begin // Shift left by 1 and add (sh1add)
if (RV32B_ZBA) begin
decoder_ctrl_o.alu_operator = ALU_B_SH1ADD;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b001_0000, 3'b100}: begin // Shift left by 2 and add (sh2add)
if (RV32B_ZBA) begin
decoder_ctrl_o.alu_operator = ALU_B_SH2ADD;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b001_0000, 3'b110}: begin // Shift left by 3 and add (sh3add)
if (RV32B_ZBA) begin
decoder_ctrl_o.alu_operator = ALU_B_SH3ADD;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
// RVB Zbb
{7'b0000101, 3'b100}: begin // Return minimum number, signed (min)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_MIN;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0000101, 3'b101}: begin // Return minimum number, unsigned (minu)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_MINU;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0000101, 3'b110}: begin // Return maximum number, signed (max)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_MAX;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0000101, 3'b111}: begin // Return maximum number, signed (maxu)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_MAXU;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0100000, 3'b111}: begin // Return minimum number, signed (andn)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_ANDN;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0100000, 3'b110}: begin // Return minimum number, signed (orn)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_ORN;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0100000, 3'b100}: begin // Return minimum number, signed (xnor)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_XNOR;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0110000, 3'b001}: begin // Rotate Left (rol)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_ROL;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0110000, 3'b101}: begin // Rotate Right (ror)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_ROR;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0000100, 3'b100}: begin // Zero extend halfword (zext.h)
// zext.h is a subset of the proposed pack instruction in Zbkb
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_ZEXT_H;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
decoder_ctrl_o.rf_re[1] = 1'b0; // rs2 is not read, but field is hardcoded to x0
if (instr_rdata_i[24:20] != 5'b00000) begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
// RVB Zbc
{7'b0000101, 3'b001}: begin // Carry-less Multiply (clmul)
if (RV32B_ZBC) begin
decoder_ctrl_o.alu_operator = ALU_B_CLMUL;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0000101, 3'b011}: begin // Carry-less Multiply upper bits (clmulh)
if (RV32B_ZBC) begin
decoder_ctrl_o.alu_operator = ALU_B_CLMULH;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0000101, 3'b010}: begin // Carry-less Multiply reversed (clmulr)
if (RV32B_ZBC) begin
decoder_ctrl_o.alu_operator = ALU_B_CLMULR;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
// RVB Zbs
{7'b0010100, 3'b001}: begin // Set bit in rs1 at index specified by rs2 (bset)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BSET;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0100100, 3'b001}: begin // Clear bit in rs1 at index specified by rs2 (bclr)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BCLR;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0110100, 3'b001}: begin // Invert bit in rs1 at index specified by rs2 (binv)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BINV;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0100100, 3'b101}: begin // Extract bit from rs1 at index specified by rs2 (bext)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BEXT;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
default: begin
// No match
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
endcase
end // case: OPCODE_OP
OPCODE_OPIMM: begin
decoder_ctrl_o.alu_en = 1'b1;
decoder_ctrl_o.alu_op_a_mux_sel = OP_A_REGA_OR_FWD;
decoder_ctrl_o.rf_re[0] = 1'b1;
decoder_ctrl_o.rf_re[1] = 1'b0;
decoder_ctrl_o.rf_we = 1'b1;
unique casez ({instr_rdata_i[31:25], instr_rdata_i[24:20], instr_rdata_i[14:12]})
// RVB Zbb
{7'b011_0000, 5'b0_0000, 3'b001} : begin
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_CLZ;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b011_0000, 5'b0_0001, 3'b001} : begin
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_CTZ;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b011_0000, 5'b0_0010, 3'b001} : begin
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_CPOP;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b001_0100, 5'b0_0111, 3'b101}: begin
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_ORC_B;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b011_0100, 5'b1_1000, 3'b101}: begin
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_REV8;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b011_0000, 5'b0_0100, 3'b001}: begin
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_SEXT_B;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b011_0000, 5'b0_0101, 3'b001}: begin
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_SEXT_H;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0110000, 5'b?_????, 3'b101}: begin // Rotate Right immediate (rori)
if (RV32B_ZBB) begin
decoder_ctrl_o.alu_operator = ALU_B_ROR;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_IMM;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
// RVB Zbs immediate
{7'b0010100, 5'b?_????, 3'b001}: begin // Set bit in rs1 at index specified by immediate (bseti)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BSET;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_IMM;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0100100, 5'b?_????, 3'b001}: begin // Clear bit in rs1 at index specified by immediate (bclri)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BCLR;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_IMM;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0110100, 5'b?_????, 3'b001}: begin // Invert bit in rs1 at index specified by immediate (binvi)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BINV;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_IMM;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
{7'b0100100, 5'b?_????, 3'b101}: begin // Extract bit from rs1 at index specified by immediate (bexti)
if (RV32B_ZBS) begin
decoder_ctrl_o.alu_operator = ALU_B_BEXT;
decoder_ctrl_o.alu_op_b_mux_sel = OP_B_IMM;
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
end
default: begin
// No match
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
endcase
end // case: OPCODE_OPIMM
default: begin
// No match
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end
endcase // unique case (instr_rdata_i[6:0])
end // always_comb
endmodule