../src/lowrisc_ibex_ibex_core_0.1/rtl/ibex_decoder.sv Cov: 99.4%
1: // Copyright lowRISC contributors.
2: // Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
3: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
4: // SPDX-License-Identifier: Apache-2.0
5:
6: // Source/Destination register instruction index
7: `define REG_S1 19:15
8: `define REG_S2 24:20
9: `define REG_S3 31:27
10: `define REG_D 11:07
11:
12: /**
13: * Instruction decoder
14: *
15: * This module is fully combinatorial, clock and reset are used for
16: * assertions only.
17: */
18:
19: `include "prim_assert.sv"
20:
21: module ibex_decoder #(
22: parameter bit RV32E = 0,
23: parameter bit RV32M = 1,
24: parameter bit RV32B = 0,
25: parameter bit BranchTargetALU = 0
26: ) (
27: input logic clk_i,
28: input logic rst_ni,
29:
30: // to/from controller
31: output logic illegal_insn_o, // illegal instr encountered
32: output logic ebrk_insn_o, // trap instr encountered
33: output logic mret_insn_o, // return from exception instr
34: // encountered
35: output logic dret_insn_o, // return from debug instr encountered
36: output logic ecall_insn_o, // syscall instr encountered
37: output logic wfi_insn_o, // wait for interrupt instr encountered
38: output logic jump_set_o, // jump taken set signal
39: input logic branch_taken_i, // registered branch decision
40: output logic icache_inval_o,
41:
42: // from IF-ID pipeline register
43: input logic instr_first_cycle_i, // instruction read is in its first cycle
44: input logic [31:0] instr_rdata_i, // instruction read from memory/cache
45: input logic [31:0] instr_rdata_alu_i, // instruction read from memory/cache
46: // replicated to ease fan-out)
47:
48: input logic illegal_c_insn_i, // compressed instruction decode failed
49:
50: // immediates
51: output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a
52: output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b
53: output ibex_pkg::op_a_sel_e bt_a_mux_sel_o, // branch target selection operand a
54: output ibex_pkg::imm_b_sel_e bt_b_mux_sel_o, // branch target selection operand b
55: output logic [31:0] imm_i_type_o,
56: output logic [31:0] imm_s_type_o,
57: output logic [31:0] imm_b_type_o,
58: output logic [31:0] imm_u_type_o,
59: output logic [31:0] imm_j_type_o,
60: output logic [31:0] zimm_rs1_type_o,
61:
62: // register file
63: output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection
64: output logic rf_we_o, // write enable for regfile
65: output logic [4:0] rf_raddr_a_o,
66: output logic [4:0] rf_raddr_b_o,
67: output logic [4:0] rf_waddr_o,
68: output logic rf_ren_a_o, // Instruction reads from RF addr A
69: output logic rf_ren_b_o, // Instruction reads from RF addr B
70:
71: // ALU
72: output ibex_pkg::alu_op_e alu_operator_o, // ALU operation selection
73: output ibex_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC,
74: // immediate or zero
75: output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or
76: // immediate
77: output logic alu_multicycle_o, // ternary bitmanip instruction
78:
79: // MULT & DIV
80: output logic mult_en_o, // perform integer multiplication
81: output logic div_en_o, // perform integer division or remainder
82: output logic mult_sel_o, // as above but static, for data muxes
83: output logic div_sel_o, // as above but static, for data muxes
84:
85: output ibex_pkg::md_op_e multdiv_operator_o,
86: output logic [1:0] multdiv_signed_mode_o,
87:
88: // CSRs
89: output logic csr_access_o, // access to CSR
90: output ibex_pkg::csr_op_e csr_op_o, // operation to perform on CSR
91:
92: // LSU
93: output logic data_req_o, // start transaction to data memory
94: output logic data_we_o, // write enable
95: output logic [1:0] data_type_o, // size of transaction: byte, half
96: // word or word
97: output logic data_sign_extension_o, // sign extension for data read from
98: // memory
99:
100: // jump/branches
101: output logic jump_in_dec_o, // jump is being calculated in ALU
102: output logic branch_in_dec_o
103: );
104:
105: import ibex_pkg::*;
106:
107: logic illegal_insn;
108: logic illegal_reg_rv32e;
109: logic csr_illegal;
110: logic rf_we;
111:
112: logic [31:0] instr;
113: logic [31:0] instr_alu;
114:
115: logic use_rs3;
116:
117: csr_op_e csr_op;
118:
119: opcode_e opcode;
120: opcode_e opcode_alu;
121:
122: // To help timing the flops containing the current instruction are replicated to reduce fan-out.
123: // instr_alu is used to determine the ALU control logic and associated operand/imm select signals
124: // as the ALU is often on the more critical timing paths. instr is used for everything else.
125: assign instr = instr_rdata_i;
126: assign instr_alu = instr_rdata_alu_i;
127:
128: //////////////////////////////////////
129: // Register and immediate selection //
130: //////////////////////////////////////
131:
132: // immediate extraction and sign extension
133: assign imm_i_type_o = { {20{instr[31]}}, instr[31:20] };
134: assign imm_s_type_o = { {20{instr[31]}}, instr[31:25], instr[11:7] };
135: assign imm_b_type_o = { {19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0 };
136: assign imm_u_type_o = { instr[31:12], 12'b0 };
137: assign imm_j_type_o = { {12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };
138:
139: // immediate for CSR manipulation (zero extended)
140: assign zimm_rs1_type_o = { 27'b0, instr[`REG_S1] }; // rs1
141:
142: // source registers
143: assign rf_raddr_a_o = use_rs3 ? instr[`REG_S3] : instr[`REG_S1]; // rs3 / rs1
144: assign rf_raddr_b_o = instr[`REG_S2]; // rs2
145:
146: // destination register
147: assign rf_waddr_o = instr[`REG_D]; // rd
148:
149: ////////////////////
150: // Register check //
151: ////////////////////
152: if (RV32E) begin : gen_rv32e_reg_check_active
153: assign illegal_reg_rv32e = ((rf_raddr_a_o[4] & (alu_op_a_mux_sel_o == OP_A_REG_A)) |
154: (rf_raddr_b_o[4] & (alu_op_b_mux_sel_o == OP_B_REG_B)) |
155: (rf_waddr_o[4] & rf_we));
156: end else begin : gen_rv32e_reg_check_inactive
157: assign illegal_reg_rv32e = 1'b0;
158: end
159:
160: ///////////////////////
161: // CSR operand check //
162: ///////////////////////
163: always_comb begin : csr_operand_check
164: csr_op_o = csr_op;
165:
166: // CSRRSI/CSRRCI must not write 0 to CSRs (uimm[4:0]=='0)
167: // CSRRS/CSRRC must not write from x0 to CSRs (rs1=='0)
168: if ((csr_op == CSR_OP_SET || csr_op == CSR_OP_CLEAR) &&
169: instr[`REG_S1] == '0) begin
170: csr_op_o = CSR_OP_READ;
171: end
172: end
173:
174: /////////////
175: // Decoder //
176: /////////////
177:
178: always_comb begin
179: jump_in_dec_o = 1'b0;
180: jump_set_o = 1'b0;
181: branch_in_dec_o = 1'b0;
182: icache_inval_o = 1'b0;
183:
184: multdiv_operator_o = MD_OP_MULL;
185: multdiv_signed_mode_o = 2'b00;
186:
187: rf_wdata_sel_o = RF_WD_EX;
188: rf_we = 1'b0;
189: rf_ren_a_o = 1'b0;
190: rf_ren_b_o = 1'b0;
191:
192: csr_access_o = 1'b0;
193: csr_illegal = 1'b0;
194: csr_op = CSR_OP_READ;
195:
196: data_we_o = 1'b0;
197: data_type_o = 2'b00;
198: data_sign_extension_o = 1'b0;
199: data_req_o = 1'b0;
200:
201: illegal_insn = 1'b0;
202: ebrk_insn_o = 1'b0;
203: mret_insn_o = 1'b0;
204: dret_insn_o = 1'b0;
205: ecall_insn_o = 1'b0;
206: wfi_insn_o = 1'b0;
207:
208: opcode = opcode_e'(instr[6:0]);
209:
210: unique case (opcode)
211:
212: ///////////
213: // Jumps //
214: ///////////
215:
216: OPCODE_JAL: begin // Jump and Link
217: jump_in_dec_o = 1'b1;
218:
219: if (instr_first_cycle_i) begin
220: // Calculate jump target (and store PC + 4 if BranchTargetALU is configured)
221: rf_we = BranchTargetALU;
222: jump_set_o = 1'b1;
223: end else begin
224: // Calculate and store PC+4
225: rf_we = 1'b1;
226: end
227: end
228:
229: OPCODE_JALR: begin // Jump and Link Register
230: jump_in_dec_o = 1'b1;
231:
232: if (instr_first_cycle_i) begin
233: // Calculate jump target (and store PC + 4 if BranchTargetALU is configured)
234: rf_we = BranchTargetALU;
235: jump_set_o = 1'b1;
236: end else begin
237: // Calculate and store PC+4
238: rf_we = 1'b1;
239: end
240: if (instr[14:12] != 3'b0) begin
241: illegal_insn = 1'b1;
242: end
243:
244: rf_ren_a_o = 1'b1;
245: end
246:
247: OPCODE_BRANCH: begin // Branch
248: branch_in_dec_o = 1'b1;
249: // Check branch condition selection
250: unique case (instr[14:12])
251: 3'b000,
252: 3'b001,
253: 3'b100,
254: 3'b101,
255: 3'b110,
256: 3'b111: illegal_insn = 1'b0;
257: default: illegal_insn = 1'b1;
258: endcase
259:
260: rf_ren_a_o = 1'b1;
261: rf_ren_b_o = 1'b1;
262: end
263:
264: ////////////////
265: // Load/store //
266: ////////////////
267:
268: OPCODE_STORE: begin
269: rf_ren_a_o = 1'b1;
270: rf_ren_b_o = 1'b1;
271: data_req_o = 1'b1;
272: data_we_o = 1'b1;
273:
274: if (instr[14]) begin
275: illegal_insn = 1'b1;
276: end
277:
278: // store size
279: unique case (instr[13:12])
280: 2'b00: data_type_o = 2'b10; // sb
281: 2'b01: data_type_o = 2'b01; // sh
282: 2'b10: data_type_o = 2'b00; // sw
283: default: illegal_insn = 1'b1;
284: endcase
285: end
286:
287: OPCODE_LOAD: begin
288: rf_ren_a_o = 1'b1;
289: data_req_o = 1'b1;
290: data_type_o = 2'b00;
291:
292: // sign/zero extension
293: data_sign_extension_o = ~instr[14];
294:
295: // load size
296: unique case (instr[13:12])
297: 2'b00: data_type_o = 2'b10; // lb(u)
298: 2'b01: data_type_o = 2'b01; // lh(u)
299: 2'b10: begin
300: data_type_o = 2'b00; // lw
301: if (instr[14]) begin
302: illegal_insn = 1'b1; // lwu does not exist
303: end
304: end
305: default: begin
306: illegal_insn = 1'b1;
307: end
308: endcase
309: end
310:
311: /////////
312: // ALU //
313: /////////
314:
315: OPCODE_LUI: begin // Load Upper Immediate
316: rf_we = 1'b1;
317: end
318:
319: OPCODE_AUIPC: begin // Add Upper Immediate to PC
320: rf_we = 1'b1;
321: end
322:
323: OPCODE_OP_IMM: begin // Register-Immediate ALU Operations
324: rf_ren_a_o = 1'b1;
325: rf_we = 1'b1;
326:
327: unique case (instr[14:12])
328: 3'b000,
329: 3'b010,
330: 3'b011,
331: 3'b100,
332: 3'b110,
333: 3'b111: illegal_insn = 1'b0;
334:
335: 3'b001: begin
336: unique case (instr[31:27])
337: 5'b0_0000: illegal_insn = 1'b0; // slli
338: 5'b0_0100, // sloi
339: 5'b0_1001, // sbclri
340: 5'b0_0101, // sbseti
341: 5'b0_1101: illegal_insn = RV32B ? 1'b0 : 1'b1; // sbinvi
342: 5'b0_0001: if (instr[26] == 1'b0) begin
343: illegal_insn = RV32B ? 1'b0 : 1'b1; // shfl
344: end else begin
345: illegal_insn = 1'b1;
346: end
347: 5'b0_1100: begin
348: unique case(instr[26:20])
349: 7'b000_0000, // clz
350: 7'b000_0001, // ctz
351: 7'b000_0010, // pcnt
352: 7'b000_0100, // sext.b
353: 7'b000_0101, // sext.h
354: 7'b001_0000, // crc32.b
355: 7'b001_0001, // crc32.h
356: 7'b001_0010, // crc32.w
357: 7'b001_1000, // crc32c.b
358: 7'b001_1001, // crc32c.h
359: 7'b001_1010: illegal_insn = RV32B ? 1'b0 : 1'b1; // crc32c.w
360:
361: default: illegal_insn = 1'b1;
362: endcase
363: end
364: default : illegal_insn = 1'b1;
365: endcase
366: end
367:
368: 3'b101: begin
369: if (instr[26]) begin
370: illegal_insn = RV32B ? 1'b0 : 1'b1; // fsri
371: end else begin
372: unique case (instr[31:27])
373: 5'b0_0000, // srli
374: 5'b0_1000: illegal_insn = 1'b0; // srai
375:
376: 5'b0_0100, // sroi
377: 5'b0_1100, // rori
378: 5'b0_1001: illegal_insn = RV32B ? 1'b0 : 1'b1; // sbexti
379:
380: 5'b0_1101, // grevi
381: 5'b0_0101: illegal_insn = RV32B ? 1'b0 : 1'b1; // gorci
382: 5'b0_0001: if (instr[26] == 1'b0) begin
383: illegal_insn = RV32B ? 1'b0 : 1'b1; // unshfl
384: end else begin
385: illegal_insn = 1'b1;
386: end
387:
388: default: illegal_insn = 1'b1;
389: endcase
390: end
391: end
392:
393: default: illegal_insn = 1'b1;
394: endcase
395: end
396:
397: OPCODE_OP: begin // Register-Register ALU operation
398: rf_ren_a_o = 1'b1;
399: rf_ren_b_o = 1'b1;
400: rf_we = 1'b1;
401: if ({instr[26], instr[13:12]} == {1'b1, 2'b01}) begin
402: illegal_insn = RV32B ? 1'b0 : 1'b1; // cmix / cmov / fsl / fsr
403: end else begin
404: unique case ({instr[31:25], instr[14:12]})
405: // RV32I ALU operations
406: {7'b000_0000, 3'b000},
407: {7'b010_0000, 3'b000},
408: {7'b000_0000, 3'b010},
409: {7'b000_0000, 3'b011},
410: {7'b000_0000, 3'b100},
411: {7'b000_0000, 3'b110},
412: {7'b000_0000, 3'b111},
413: {7'b000_0000, 3'b001},
414: {7'b000_0000, 3'b101},
415: {7'b010_0000, 3'b101}: illegal_insn = 1'b0;
416:
417: // RV32B zbb
418: {7'b010_0000, 3'b111}, // andn
419: {7'b010_0000, 3'b110}, // orn
420: {7'b010_0000, 3'b100}, // xnor
421: {7'b001_0000, 3'b001}, // slo
422: {7'b001_0000, 3'b101}, // sro
423: {7'b011_0000, 3'b001}, // rol
424: {7'b011_0000, 3'b101}, // ror
425: {7'b000_0101, 3'b100}, // min
426: {7'b000_0101, 3'b101}, // max
427: {7'b000_0101, 3'b110}, // minu
428: {7'b000_0101, 3'b111}, // maxu
429: {7'b000_0100, 3'b100}, // pack
430: {7'b010_0100, 3'b100}, // packu
431: {7'b000_0100, 3'b111}, // packh
432: // RV32B zbs
433: {7'b010_0100, 3'b001}, // sbclr
434: {7'b001_0100, 3'b001}, // sbset
435: {7'b011_0100, 3'b001}, // sbinv
436: {7'b010_0100, 3'b101}, // sbext
437: // RV32B zbe
438: {7'b010_0100, 3'b110}, // bdep
439: {7'b000_0100, 3'b110}, // bext
440: // RV32B zbp
441: {7'b011_0100, 3'b101}, // grev
442: {7'b001_0100, 3'b101}, // gorc
443: {7'b000_0100, 3'b001}, // shfl
444: {7'b000_0100, 3'b101}, // unshfl
445: // RV32B zbf
446: {7'b010_0100, 3'b111}, // bfp
447: // RV32B zbc
448: {7'b000_0101, 3'b001}, // clmul
449: {7'b000_0101, 3'b010}, // clmulr
450: {7'b000_0101, 3'b011}: illegal_insn = RV32B ? 1'b0 : 1'b1; // clmulh
451:
452: // RV32M instructions
453: {7'b000_0001, 3'b000}: begin // mul
454: multdiv_operator_o = MD_OP_MULL;
455: multdiv_signed_mode_o = 2'b00;
456: illegal_insn = RV32M ? 1'b0 : 1'b1;
457: end
458: {7'b000_0001, 3'b001}: begin // mulh
459: multdiv_operator_o = MD_OP_MULH;
460: multdiv_signed_mode_o = 2'b11;
461: illegal_insn = RV32M ? 1'b0 : 1'b1;
462: end
463: {7'b000_0001, 3'b010}: begin // mulhsu
464: multdiv_operator_o = MD_OP_MULH;
465: multdiv_signed_mode_o = 2'b01;
466: illegal_insn = RV32M ? 1'b0 : 1'b1;
467: end
468: {7'b000_0001, 3'b011}: begin // mulhu
469: multdiv_operator_o = MD_OP_MULH;
470: multdiv_signed_mode_o = 2'b00;
471: illegal_insn = RV32M ? 1'b0 : 1'b1;
472: end
473: {7'b000_0001, 3'b100}: begin // div
474: multdiv_operator_o = MD_OP_DIV;
475: multdiv_signed_mode_o = 2'b11;
476: illegal_insn = RV32M ? 1'b0 : 1'b1;
477: end
478: {7'b000_0001, 3'b101}: begin // divu
479: multdiv_operator_o = MD_OP_DIV;
480: multdiv_signed_mode_o = 2'b00;
481: illegal_insn = RV32M ? 1'b0 : 1'b1;
482: end
483: {7'b000_0001, 3'b110}: begin // rem
484: multdiv_operator_o = MD_OP_REM;
485: multdiv_signed_mode_o = 2'b11;
486: illegal_insn = RV32M ? 1'b0 : 1'b1;
487: end
488: {7'b000_0001, 3'b111}: begin // remu
489: multdiv_operator_o = MD_OP_REM;
490: multdiv_signed_mode_o = 2'b00;
491: illegal_insn = RV32M ? 1'b0 : 1'b1;
492: end
493: default: begin
494: illegal_insn = 1'b1;
495: end
496: endcase
497: end
498: end
499:
500: /////////////
501: // Special //
502: /////////////
503:
504: OPCODE_MISC_MEM: begin
505: // For now, treat the FENCE (funct3 == 000) instruction as a NOP. This may not be correct
506: // in a system with caches and should be revisited.
507: // FENCE.I will flush the IF stage and prefetch buffer (or ICache) but nothing else.
508: unique case (instr[14:12])
509: 3'b000: begin
510: rf_we = 1'b0;
511: end
512: 3'b001: begin
513: // FENCE.I is implemented as a jump to the next PC, this gives the required flushing
514: // behaviour (iside prefetch buffer flushed and response to any outstanding iside
515: // requests will be ignored).
516: // If present, the ICache will also be flushed.
517: jump_in_dec_o = 1'b1;
518:
519: rf_we = 1'b0;
520:
521: if (instr_first_cycle_i) begin
522: jump_set_o = 1'b1;
523: icache_inval_o = 1'b1;
524: end
525: end
526: default: begin
527: illegal_insn = 1'b1;
528: end
529: endcase
530: end
531:
532: OPCODE_SYSTEM: begin
533: if (instr[14:12] == 3'b000) begin
534: // non CSR related SYSTEM instructions
535: unique case (instr[31:20])
536: 12'h000: // ECALL
537: // environment (system) call
538: ecall_insn_o = 1'b1;
539:
540: 12'h001: // ebreak
541: // debugger trap
542: ebrk_insn_o = 1'b1;
543:
544: 12'h302: // mret
545: mret_insn_o = 1'b1;
546:
547: 12'h7b2: // dret
548: dret_insn_o = 1'b1;
549:
550: 12'h105: // wfi
551: wfi_insn_o = 1'b1;
552:
553: default:
554: illegal_insn = 1'b1;
555: endcase
556:
557: // rs1 and rd must be 0
558: if (instr[`REG_S1] != 5'b0 || instr[`REG_D] != 5'b0) begin
559: illegal_insn = 1'b1;
560: end
561: end else begin
562: // instruction to read/modify CSR
563: csr_access_o = 1'b1;
564: rf_wdata_sel_o = RF_WD_CSR;
565: rf_we = 1'b1;
566:
567: if (~instr[14]) begin
568: rf_ren_a_o = 1'b1;
569: end
570:
571: unique case (instr[13:12])
572: 2'b01: csr_op = CSR_OP_WRITE;
573: 2'b10: csr_op = CSR_OP_SET;
574: 2'b11: csr_op = CSR_OP_CLEAR;
575: default: csr_illegal = 1'b1;
576: endcase
577:
578: illegal_insn = csr_illegal;
579: end
580:
581: end
582: default: begin
583: illegal_insn = 1'b1;
584: end
585: endcase
586:
587: // make sure illegal compressed instructions cause illegal instruction exceptions
588: if (illegal_c_insn_i) begin
589: illegal_insn = 1'b1;
590: end
591:
592: // make sure illegal instructions detected in the decoder do not propagate from decoder
593: // into register file, LSU, EX, WB, CSRs, PC
594: // NOTE: instructions can also be detected to be illegal inside the CSRs (upon accesses with
595: // insufficient privileges), or when accessing non-available registers in RV32E,
596: // these cases are not handled here
597: if (illegal_insn) begin
598: rf_we = 1'b0;
599: data_req_o = 1'b0;
600: data_we_o = 1'b0;
601: jump_in_dec_o = 1'b0;
602: jump_set_o = 1'b0;
603: branch_in_dec_o = 1'b0;
604: csr_access_o = 1'b0;
605: end
606: end
607:
608: /////////////////////////////
609: // Decoder for ALU control //
610: /////////////////////////////
611:
612: always_comb begin
613: alu_operator_o = ALU_SLTU;
614: alu_op_a_mux_sel_o = OP_A_IMM;
615: alu_op_b_mux_sel_o = OP_B_IMM;
616:
617: imm_a_mux_sel_o = IMM_A_ZERO;
618: imm_b_mux_sel_o = IMM_B_I;
619:
620: bt_a_mux_sel_o = OP_A_CURRPC;
621: bt_b_mux_sel_o = IMM_B_I;
622:
623:
624: opcode_alu = opcode_e'(instr_alu[6:0]);
625:
626: use_rs3 = 1'b0;
627: alu_multicycle_o = 1'b0;
628: mult_sel_o = 1'b0;
629: div_sel_o = 1'b0;
630:
631: unique case (opcode_alu)
632:
633: ///////////
634: // Jumps //
635: ///////////
636:
637: OPCODE_JAL: begin // Jump and Link
638: if (BranchTargetALU) begin
639: bt_a_mux_sel_o = OP_A_CURRPC;
640: bt_b_mux_sel_o = IMM_B_J;
641: end
642:
643: // Jumps take two cycles without the BTALU
644: if (instr_first_cycle_i && !BranchTargetALU) begin
645: // Calculate jump target
646: alu_op_a_mux_sel_o = OP_A_CURRPC;
647: alu_op_b_mux_sel_o = OP_B_IMM;
648: imm_b_mux_sel_o = IMM_B_J;
649: alu_operator_o = ALU_ADD;
650: end else begin
651: // Calculate and store PC+4
652: alu_op_a_mux_sel_o = OP_A_CURRPC;
653: alu_op_b_mux_sel_o = OP_B_IMM;
654: imm_b_mux_sel_o = IMM_B_INCR_PC;
655: alu_operator_o = ALU_ADD;
656: end
657: end
658:
659: OPCODE_JALR: begin // Jump and Link Register
660: if (BranchTargetALU) begin
661: bt_a_mux_sel_o = OP_A_REG_A;
662: bt_b_mux_sel_o = IMM_B_I;
663: end
664:
665: // Jumps take two cycles without the BTALU
666: if (instr_first_cycle_i && !BranchTargetALU) begin
667: // Calculate jump target
668: alu_op_a_mux_sel_o = OP_A_REG_A;
669: alu_op_b_mux_sel_o = OP_B_IMM;
670: imm_b_mux_sel_o = IMM_B_I;
671: alu_operator_o = ALU_ADD;
672: end else begin
673: // Calculate and store PC+4
674: alu_op_a_mux_sel_o = OP_A_CURRPC;
675: alu_op_b_mux_sel_o = OP_B_IMM;
676: imm_b_mux_sel_o = IMM_B_INCR_PC;
677: alu_operator_o = ALU_ADD;
678: end
679: end
680:
681: OPCODE_BRANCH: begin // Branch
682: // Check branch condition selection
683: unique case (instr_alu[14:12])
684: 3'b000: alu_operator_o = ALU_EQ;
685: 3'b001: alu_operator_o = ALU_NE;
686: 3'b100: alu_operator_o = ALU_LT;
687: 3'b101: alu_operator_o = ALU_GE;
688: 3'b110: alu_operator_o = ALU_LTU;
689: 3'b111: alu_operator_o = ALU_GEU;
690: default: ;
691: endcase
692:
693: if (BranchTargetALU) begin
694: bt_a_mux_sel_o = OP_A_CURRPC;
695: // Not-taken branch will jump to next instruction (used in secure mode)
696: bt_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC;
697: end
698:
699: // Without branch target ALU, a branch is a two-stage operation using the Main ALU in both
700: // stages
701: if (instr_first_cycle_i) begin
702: // First evaluate the branch condition
703: alu_op_a_mux_sel_o = OP_A_REG_A;
704: alu_op_b_mux_sel_o = OP_B_REG_B;
705: end else begin
706: // Then calculate jump target
707: alu_op_a_mux_sel_o = OP_A_CURRPC;
708: alu_op_b_mux_sel_o = OP_B_IMM;
709: // Not-taken branch will jump to next instruction (used in secure mode)
710: imm_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC;
711: alu_operator_o = ALU_ADD;
712: end
713: end
714:
715: ////////////////
716: // Load/store //
717: ////////////////
718:
719: OPCODE_STORE: begin
720: alu_op_a_mux_sel_o = OP_A_REG_A;
721: alu_op_b_mux_sel_o = OP_B_REG_B;
722: alu_operator_o = ALU_ADD;
723:
724: if (!instr_alu[14]) begin
725: // offset from immediate
726: imm_b_mux_sel_o = IMM_B_S;
727: alu_op_b_mux_sel_o = OP_B_IMM;
728: end
729: end
730:
731: OPCODE_LOAD: begin
732: alu_op_a_mux_sel_o = OP_A_REG_A;
733:
734: // offset from immediate
735: alu_operator_o = ALU_ADD;
736: alu_op_b_mux_sel_o = OP_B_IMM;
737: imm_b_mux_sel_o = IMM_B_I;
738: end
739:
740: /////////
741: // ALU //
742: /////////
743:
744: OPCODE_LUI: begin // Load Upper Immediate
745: alu_op_a_mux_sel_o = OP_A_IMM;
746: alu_op_b_mux_sel_o = OP_B_IMM;
747: imm_a_mux_sel_o = IMM_A_ZERO;
748: imm_b_mux_sel_o = IMM_B_U;
749: alu_operator_o = ALU_ADD;
750: end
751:
752: OPCODE_AUIPC: begin // Add Upper Immediate to PC
753: alu_op_a_mux_sel_o = OP_A_CURRPC;
754: alu_op_b_mux_sel_o = OP_B_IMM;
755: imm_b_mux_sel_o = IMM_B_U;
756: alu_operator_o = ALU_ADD;
757: end
758:
759: OPCODE_OP_IMM: begin // Register-Immediate ALU Operations
760: alu_op_a_mux_sel_o = OP_A_REG_A;
761: alu_op_b_mux_sel_o = OP_B_IMM;
762: imm_b_mux_sel_o = IMM_B_I;
763:
764: unique case (instr_alu[14:12])
765: 3'b000: alu_operator_o = ALU_ADD; // Add Immediate
766: 3'b010: alu_operator_o = ALU_SLT; // Set to one if Lower Than Immediate
767: 3'b011: alu_operator_o = ALU_SLTU; // Set to one if Lower Than Immediate Unsigned
768: 3'b100: alu_operator_o = ALU_XOR; // Exclusive Or with Immediate
769: 3'b110: alu_operator_o = ALU_OR; // Or with Immediate
770: 3'b111: alu_operator_o = ALU_AND; // And with Immediate
771:
772: 3'b001: begin
773: if (RV32B) begin
774: unique case (instr_alu[31:27])
775: 5'b0_0000: alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate
776: 5'b0_0100: alu_operator_o = ALU_SLO; // Shift Left Ones by Immediate
777: 5'b0_1001: alu_operator_o = ALU_SBCLR; // Clear bit specified by immediate
778: 5'b0_0101: alu_operator_o = ALU_SBSET; // Set bit specified by immediate
779: 5'b0_1101: alu_operator_o = ALU_SBINV; // Invert bit specified by immediate.
780: // Shuffle with Immediate Control Value
781: 5'b0_0001: if (instr_alu[26] == 0) alu_operator_o = ALU_SHFL;
782: 5'b0_1100: begin
783: unique case (instr_alu[26:20])
784: 7'b000_0000: alu_operator_o = ALU_CLZ; // clz
785: 7'b000_0001: alu_operator_o = ALU_CTZ; // ctz
786: 7'b000_0010: alu_operator_o = ALU_PCNT; // pcnt
787: 7'b000_0100: alu_operator_o = ALU_SEXTB; // sext.b
788: 7'b000_0101: alu_operator_o = ALU_SEXTH; // sext.h
789: 7'b001_0000: begin
790: alu_operator_o = ALU_CRC32_B; // crc32.b
791: alu_multicycle_o = 1'b1;
792: end
793: 7'b001_0001: begin
794: alu_operator_o = ALU_CRC32_H; // crc32.h
795: alu_multicycle_o = 1'b1;
796: end
797: 7'b001_0010: begin
798: alu_operator_o = ALU_CRC32_W; // crc32.w
799: alu_multicycle_o = 1'b1;
800: end
801: 7'b001_1000: begin
802: alu_operator_o = ALU_CRC32C_B; // crc32c.b
803: alu_multicycle_o = 1'b1;
804: end
805: 7'b001_1001: begin
806: alu_operator_o = ALU_CRC32C_H; // crc32c.h
807: alu_multicycle_o = 1'b1;
808: end
809: 7'b001_1010: begin
810: alu_operator_o = ALU_CRC32C_W; // crc32c.w
811: alu_multicycle_o = 1'b1;
812: end
813: default: ;
814: endcase
815: end
816:
817: default: ;
818: endcase
819: end else begin
820: alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate
821: end
822: end
823:
824: 3'b101: begin
825: if (RV32B) begin
826: if (instr_alu[26] == 1'b1) begin
827: alu_operator_o = ALU_FSR;
828: alu_multicycle_o = 1'b1;
829: if (instr_first_cycle_i) begin
830: use_rs3 = 1'b0;
831: end else begin
832: use_rs3 = 1'b1;
833: end
834: end else begin
835: unique case (instr_alu[31:27])
836: 5'b0_0000: alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate
837: 5'b0_1000: alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate
838: 5'b0_0100: alu_operator_o = ALU_SRO; // Shift Right Ones by Immediate
839: 5'b0_1001: alu_operator_o = ALU_SBEXT; // Extract bit specified by immediate.
840: 5'b0_1100: begin
841: alu_operator_o = ALU_ROR; // Rotate Right by Immediate
842: alu_multicycle_o = 1'b1;
843: end
844: 5'b0_1101: alu_operator_o = ALU_GREV; // General Reverse with Imm Control Val
845: 5'b0_0101: alu_operator_o = ALU_GORC; // General Or-combine with Imm Control Val
846: // Unshuffle with Immediate Control Value
847: 5'b0_0001: if (instr_alu[26] == 1'b0) alu_operator_o = ALU_UNSHFL;
848: default: ;
849: endcase
850: end
851:
852: end else begin
853: if (instr_alu[31:27] == 5'b0_0000) begin
854: alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate
855: end else if (instr_alu[31:27] == 5'b0_1000) begin
856: alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate
857: end
858: end
859: end
860:
861: default: ;
862: endcase
863: end
864:
865: OPCODE_OP: begin // Register-Register ALU operation
866: alu_op_a_mux_sel_o = OP_A_REG_A;
867: alu_op_b_mux_sel_o = OP_B_REG_B;
868:
869: if (instr_alu[26]) begin
870: if (RV32B) begin
871: unique case ({instr_alu[26:25], instr_alu[14:12]})
872: {2'b11, 3'b001}: begin
873: alu_operator_o = ALU_CMIX; // cmix
874: alu_multicycle_o = 1'b1;
875: if (instr_first_cycle_i) begin
876: use_rs3 = 1'b0;
877: end else begin
878: use_rs3 = 1'b1;
879: end
880: end
881: {2'b11, 3'b101}: begin
882: alu_operator_o = ALU_CMOV; // cmov
883: alu_multicycle_o = 1'b1;
884: if (instr_first_cycle_i) begin
885: use_rs3 = 1'b0;
886: end else begin
887: use_rs3 = 1'b1;
888: end
889: end
890: {2'b10, 3'b001}: begin
891: alu_operator_o = ALU_FSL; // fsl
892: alu_multicycle_o = 1'b1;
893: if (instr_first_cycle_i) begin
894: use_rs3 = 1'b0;
895: end else begin
896: use_rs3 = 1'b1;
897: end
898: end
899: {2'b10, 3'b101}: begin
900: alu_operator_o = ALU_FSR; // fsr
901: alu_multicycle_o = 1'b1;
902: if (instr_first_cycle_i) begin
903: use_rs3 = 1'b0;
904: end else begin
905: use_rs3 = 1'b1;
906: end
907: end
908: default: ;
909: endcase
910: end
911: end else begin
912: unique case ({instr_alu[31:25], instr_alu[14:12]})
913: // RV32I ALU operations
914: {7'b000_0000, 3'b000}: alu_operator_o = ALU_ADD; // Add
915: {7'b010_0000, 3'b000}: alu_operator_o = ALU_SUB; // Sub
916: {7'b000_0000, 3'b010}: alu_operator_o = ALU_SLT; // Set Lower Than
917: {7'b000_0000, 3'b011}: alu_operator_o = ALU_SLTU; // Set Lower Than Unsigned
918: {7'b000_0000, 3'b100}: alu_operator_o = ALU_XOR; // Xor
919: {7'b000_0000, 3'b110}: alu_operator_o = ALU_OR; // Or
920: {7'b000_0000, 3'b111}: alu_operator_o = ALU_AND; // And
921: {7'b000_0000, 3'b001}: alu_operator_o = ALU_SLL; // Shift Left Logical
922: {7'b000_0000, 3'b101}: alu_operator_o = ALU_SRL; // Shift Right Logical
923: {7'b010_0000, 3'b101}: alu_operator_o = ALU_SRA; // Shift Right Arithmetic
924:
925: // RV32B ALU Operations
926: {7'b001_0000, 3'b001}: if (RV32B) alu_operator_o = ALU_SLO; // slo
927: {7'b001_0000, 3'b101}: if (RV32B) alu_operator_o = ALU_SRO; // sro
928: {7'b011_0000, 3'b001}: begin
929: if (RV32B) begin
930: alu_operator_o = ALU_ROL; // rol
931: alu_multicycle_o = 1'b1;
932: end
933: end
934: {7'b011_0000, 3'b101}: begin
935: if (RV32B) begin
936: alu_operator_o = ALU_ROR; // ror
937: alu_multicycle_o = 1'b1;
938: end
939: end
940:
941: {7'b000_0101, 3'b100}: if (RV32B) alu_operator_o = ALU_MIN; // min
942: {7'b000_0101, 3'b101}: if (RV32B) alu_operator_o = ALU_MAX; // max
943: {7'b000_0101, 3'b110}: if (RV32B) alu_operator_o = ALU_MINU; // minu
944: {7'b000_0101, 3'b111}: if (RV32B) alu_operator_o = ALU_MAXU; // maxu
945:
946: {7'b000_0100, 3'b100}: if (RV32B) alu_operator_o = ALU_PACK; // pack
947: {7'b010_0100, 3'b100}: if (RV32B) alu_operator_o = ALU_PACKU; // packu
948: {7'b000_0100, 3'b111}: if (RV32B) alu_operator_o = ALU_PACKH; // packh
949:
950: {7'b010_0000, 3'b100}: if (RV32B) alu_operator_o = ALU_XNOR; // xnor
951: {7'b010_0000, 3'b110}: if (RV32B) alu_operator_o = ALU_ORN; // orn
952: {7'b010_0000, 3'b111}: if (RV32B) alu_operator_o = ALU_ANDN; // andn
953:
954: // RV32B zbp
955: {7'b011_0100, 3'b101}: if (RV32B) alu_operator_o = ALU_GREV; // grev
956: {7'b001_0100, 3'b101}: if (RV32B) alu_operator_o = ALU_GORC; // grev
957: {7'b000_0100, 3'b001}: if (RV32B) alu_operator_o = ALU_SHFL; // shfl
958: {7'b000_0100, 3'b101}: if (RV32B) alu_operator_o = ALU_UNSHFL; // unshfl
959:
960: // RV32B zbs
961: {7'b010_0100, 3'b001}: if (RV32B) alu_operator_o = ALU_SBCLR; // sbclr
962: {7'b001_0100, 3'b001}: if (RV32B) alu_operator_o = ALU_SBSET; // sbset
963: {7'b011_0100, 3'b001}: if (RV32B) alu_operator_o = ALU_SBINV; // sbinv
964: {7'b010_0100, 3'b101}: if (RV32B) alu_operator_o = ALU_SBEXT; // sbext
965:
966: // RV32B zbc
967: {7'b000_0101, 3'b001}: if (RV32B) alu_operator_o = ALU_CLMUL; // clmul
968: {7'b000_0101, 3'b010}: if (RV32B) alu_operator_o = ALU_CLMULR; // clmulr
969: {7'b000_0101, 3'b011}: if (RV32B) alu_operator_o = ALU_CLMULH; // clmulh
970:
971: // RV32B zbe
972: {7'b010_0100, 3'b110}: if (RV32B) alu_operator_o = ALU_BDEP; // bdep
973: {7'b000_0100, 3'b110}: if (RV32B) alu_operator_o = ALU_BEXT; // bext
974: // RV32B zbf
975: {7'b010_0100, 3'b111}: if (RV32B) alu_operator_o = ALU_BFP; // bfp
976:
977: // RV32M instructions, all use the same ALU operation
978: {7'b000_0001, 3'b000}: begin // mul
979: alu_operator_o = ALU_ADD;
980: mult_sel_o = RV32M ? 1'b1 : 1'b0;
981: end
982: {7'b000_0001, 3'b001}: begin // mulh
983: alu_operator_o = ALU_ADD;
984: mult_sel_o = RV32M ? 1'b1 : 1'b0;
985: end
986: {7'b000_0001, 3'b010}: begin // mulhsu
987: alu_operator_o = ALU_ADD;
988: mult_sel_o = RV32M ? 1'b1 : 1'b0;
989: end
990: {7'b000_0001, 3'b011}: begin // mulhu
991: alu_operator_o = ALU_ADD;
992: mult_sel_o = RV32M ? 1'b1 : 1'b0;
993: end
994: {7'b000_0001, 3'b100}: begin // div
995: alu_operator_o = ALU_ADD;
996: div_sel_o = RV32M ? 1'b1 : 1'b0;
997: end
998: {7'b000_0001, 3'b101}: begin // divu
999: alu_operator_o = ALU_ADD;
1000: div_sel_o = RV32M ? 1'b1 : 1'b0;
1001: end
1002: {7'b000_0001, 3'b110}: begin // rem
1003: alu_operator_o = ALU_ADD;
1004: div_sel_o = RV32M ? 1'b1 : 1'b0;
1005: end
1006: {7'b000_0001, 3'b111}: begin // remu
1007: alu_operator_o = ALU_ADD;
1008: div_sel_o = RV32M ? 1'b1 : 1'b0;
1009: end
1010:
1011: default: ;
1012: endcase
1013: end
1014: end
1015:
1016: /////////////
1017: // Special //
1018: /////////////
1019:
1020: OPCODE_MISC_MEM: begin
1021: // For now, treat the FENCE (funct3 == 000) instruction as a NOP. This may not be correct
1022: // in a system with caches and should be revisited.
1023: // FENCE.I will flush the IF stage and prefetch buffer but nothing else.
1024: unique case (instr_alu[14:12])
1025: 3'b000: begin
1026: alu_operator_o = ALU_ADD; // nop
1027: alu_op_a_mux_sel_o = OP_A_REG_A;
1028: alu_op_b_mux_sel_o = OP_B_IMM;
1029: end
1030: 3'b001: begin
1031: if (BranchTargetALU) begin
1032: bt_a_mux_sel_o = OP_A_CURRPC;
1033: bt_b_mux_sel_o = IMM_B_INCR_PC;
1034: end else begin
1035: alu_op_a_mux_sel_o = OP_A_CURRPC;
1036: alu_op_b_mux_sel_o = OP_B_IMM;
1037: imm_b_mux_sel_o = IMM_B_INCR_PC;
1038: alu_operator_o = ALU_ADD;
1039: end
1040: end
1041: default: ;
1042: endcase
1043: end
1044:
1045: OPCODE_SYSTEM: begin
1046: if (instr_alu[14:12] == 3'b000) begin
1047: // non CSR related SYSTEM instructions
1048: alu_op_a_mux_sel_o = OP_A_REG_A;
1049: alu_op_b_mux_sel_o = OP_B_IMM;
1050: end else begin
1051: // instruction to read/modify CSR
1052: alu_op_b_mux_sel_o = OP_B_IMM;
1053: imm_a_mux_sel_o = IMM_A_Z;
1054: imm_b_mux_sel_o = IMM_B_I; // CSR address is encoded in I imm
1055:
1056: if (instr_alu[14]) begin
1057: // rs1 field is used as immediate
1058: alu_op_a_mux_sel_o = OP_A_IMM;
1059: end else begin
1060: alu_op_a_mux_sel_o = OP_A_REG_A;
1061: end
1062: end
1063:
1064: end
1065: default: ;
1066: endcase
1067: end
1068:
1069: // do not enable multdiv in case of illegal instruction exceptions
1070: assign mult_en_o = illegal_insn ? 1'b0 : mult_sel_o;
1071: assign div_en_o = illegal_insn ? 1'b0 : div_sel_o;
1072:
1073: // make sure instructions accessing non-available registers in RV32E cause illegal
1074: // instruction exceptions
1075: assign illegal_insn_o = illegal_insn | illegal_reg_rv32e;
1076:
1077: // do not propgate regfile write enable if non-available registers are accessed in RV32E
1078: assign rf_we_o = rf_we & ~illegal_reg_rv32e;
1079:
1080: ////////////////
1081: // Assertions //
1082: ////////////////
1083:
1084: // Selectors must be known/valid.
1085: `ASSERT(IbexRegImmAluOpKnown, (opcode == OPCODE_OP_IMM) |->
1086: !$isunknown(instr[14:12]))
1087: endmodule // controller
1088: