../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: