hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv Cov: 98%

   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_D  11:07
  10: 
  11: /**
  12:  * Instruction decoder
  13:  *
  14:  * This module is fully combinatorial, clock and reset are used for
  15:  * assertions only.
  16:  */
  17: module ibex_decoder #(
  18:     parameter bit RV32E = 0,
  19:     parameter bit RV32M = 1
  20: ) (
  21:     input  logic                 clk_i,
  22:     input  logic                 rst_ni,
  23: 
  24:     // to/from controller
  25:     output logic                 illegal_insn_o,        // illegal instr encountered
  26:     output logic                 ebrk_insn_o,           // trap instr encountered
  27:     output logic                 mret_insn_o,           // return from exception instr
  28:                                                         // encountered
  29:     output logic                 dret_insn_o,           // return from debug instr encountered
  30:     output logic                 ecall_insn_o,          // syscall instr encountered
  31:     output logic                 wfi_insn_o,            // wait for interrupt instr encountered
  32:     output logic                 jump_set_o,            // jump taken set signal
  33: 
  34:     // from IF-ID pipeline register
  35:     input  logic                 instr_new_i,           // instruction read is new
  36:     input  logic [31:0]          instr_rdata_i,         // instruction read from memory/cache
  37:     input  logic                 illegal_c_insn_i,      // compressed instruction decode failed
  38: 
  39:     // immediates
  40:     output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o,       // immediate selection for operand a
  41:     output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o,       // immediate selection for operand b
  42:     output logic [31:0]          imm_i_type_o,
  43:     output logic [31:0]          imm_s_type_o,
  44:     output logic [31:0]          imm_b_type_o,
  45:     output logic [31:0]          imm_u_type_o,
  46:     output logic [31:0]          imm_j_type_o,
  47:     output logic [31:0]          zimm_rs1_type_o,
  48: 
  49:     // register file
  50:     output ibex_pkg::rf_wd_sel_e regfile_wdata_sel_o,   // RF write data selection
  51:     output logic                 regfile_we_o,          // write enable for regfile
  52:     output logic [4:0]           regfile_raddr_a_o,
  53:     output logic [4:0]           regfile_raddr_b_o,
  54:     output logic [4:0]           regfile_waddr_o,
  55: 
  56:     // ALU
  57:     output ibex_pkg::alu_op_e    alu_operator_o,        // ALU operation selection
  58:     output ibex_pkg::op_a_sel_e  alu_op_a_mux_sel_o,    // operand a selection: reg value, PC,
  59:                                                         // immediate or zero
  60:     output ibex_pkg::op_b_sel_e  alu_op_b_mux_sel_o,    // operand b selection: reg value or
  61:                                                         // immediate
  62: 
  63:     // MULT & DIV
  64:     output logic                 mult_en_o,             // perform integer multiplication
  65:     output logic                 div_en_o,              // perform integer division or
  66:                                                         // remainder
  67:     output ibex_pkg::md_op_e     multdiv_operator_o,
  68:     output logic [1:0]           multdiv_signed_mode_o,
  69: 
  70:     // CSRs
  71:     output logic                 csr_access_o,          // access to CSR
  72:     output ibex_pkg::csr_op_e    csr_op_o,              // operation to perform on CSR
  73:     output logic                 csr_pipe_flush_o,      // CSR-related pipeline flush
  74: 
  75:     // LSU
  76:     output logic                 data_req_o,            // start transaction to data memory
  77:     output logic                 data_we_o,             // write enable
  78:     output logic [1:0]           data_type_o,           // size of transaction: byte, half
  79:                                                         // word or word
  80:     output logic                 data_sign_extension_o, // sign extension for data read from
  81:                                                         // memory
  82: 
  83:     // jump/branches
  84:     output logic                 jump_in_dec_o,         // jump is being calculated in ALU
  85:     output logic                 branch_in_dec_o
  86: );
  87: 
  88:   import ibex_pkg::*;
  89: 
  90:   logic        illegal_insn;
  91:   logic        illegal_reg_rv32e;
  92:   logic        csr_illegal;
  93:   logic        regfile_we;
  94: 
  95:   logic [31:0] instr;
  96: 
  97:   csr_op_e     csr_op;
  98: 
  99:   opcode_e     opcode;
 100: 
 101:   assign instr = instr_rdata_i;
 102: 
 103:   //////////////////////////////////////
 104:   // Register and immediate selection //
 105:   //////////////////////////////////////
 106: 
 107:   // immediate extraction and sign extension
 108:   assign imm_i_type_o = { {20{instr[31]}}, instr[31:20] };
 109:   assign imm_s_type_o = { {20{instr[31]}}, instr[31:25], instr[11:7] };
 110:   assign imm_b_type_o = { {19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0 };
 111:   assign imm_u_type_o = { instr[31:12], 12'b0 };
 112:   assign imm_j_type_o = { {12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };
 113: 
 114:   // immediate for CSR manipulation (zero extended)
 115:   assign zimm_rs1_type_o = { 27'b0, instr[`REG_S1] }; // rs1
 116: 
 117:   // source registers
 118:   assign regfile_raddr_a_o = instr[`REG_S1]; // rs1
 119:   assign regfile_raddr_b_o = instr[`REG_S2]; // rs2
 120: 
 121:   // destination register
 122:   assign regfile_waddr_o   = instr[`REG_D]; // rd
 123: 
 124:   ////////////////////
 125:   // Register check //
 126:   ////////////////////
 127:   if (RV32E) begin : gen_rv32e_reg_check_active
 128:     assign illegal_reg_rv32e = ((regfile_raddr_a_o[4] & (alu_op_a_mux_sel_o == OP_A_REG_A)) |
 129:                                 (regfile_raddr_b_o[4] & (alu_op_b_mux_sel_o == OP_B_REG_B)) |
 130:                                 (regfile_waddr_o[4]   & regfile_we));
 131:   end else begin : gen_rv32e_reg_check_inactive
 132:     assign illegal_reg_rv32e = 1'b0;
 133:   end
 134: 
 135:   ///////////////////////
 136:   // CSR operand check //
 137:   ///////////////////////
 138:   always_comb begin : csr_operand_check
 139:     csr_op_o = csr_op;
 140: 
 141:     // CSRRSI/CSRRCI must not write 0 to CSRs (uimm[4:0]=='0)
 142:     // CSRRS/CSRRC must not write from x0 to CSRs (rs1=='0)
 143:     if ((csr_op == CSR_OP_SET || csr_op == CSR_OP_CLEAR) &&
 144:         instr[`REG_S1] == '0) begin
 145:       csr_op_o = CSR_OP_READ;
 146:     end
 147:   end
 148: 
 149:   /////////////////////////////////
 150:   // CSR-related pipline flushes //
 151:   /////////////////////////////////
 152:   always_comb begin : csr_pipeline_flushes
 153:     csr_pipe_flush_o = 1'b0;
 154: 
 155:     // A pipeline flush is needed to let the controller react after modifying certain CSRs:
 156:     // - When enabling interrupts, pending IRQs become visible to the controller only during
 157:     //   the next cycle. If during that cycle the core disables interrupts again, it does not
 158:     //   see any pending IRQs and consequently does not start to handle interrupts.
 159:     // - When modifying debug CSRs - TODO: Check if this is really needed
 160:     if (csr_access_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin
 161:       if (csr_num_e'(instr[31:20]) == CSR_MSTATUS   ||
 162:           csr_num_e'(instr[31:20]) == CSR_MIE) begin
 163:         csr_pipe_flush_o = 1'b1;
 164:       end
 165:     end else if (csr_access_o == 1'b1 && csr_op_o != CSR_OP_READ) begin
 166:       if (csr_num_e'(instr[31:20]) == CSR_DCSR      ||
 167:           csr_num_e'(instr[31:20]) == CSR_DPC       ||
 168:           csr_num_e'(instr[31:20]) == CSR_DSCRATCH0 ||
 169:           csr_num_e'(instr[31:20]) == CSR_DSCRATCH1) begin
 170:         csr_pipe_flush_o = 1'b1;
 171:       end
 172:     end
 173:   end
 174: 
 175:   /////////////
 176:   // Decoder //
 177:   /////////////
 178: 
 179:   always_comb begin
 180:     jump_in_dec_o               = 1'b0;
 181:     jump_set_o                  = 1'b0;
 182:     branch_in_dec_o             = 1'b0;
 183:     alu_operator_o              = ALU_SLTU;
 184:     alu_op_a_mux_sel_o          = OP_A_IMM;
 185:     alu_op_b_mux_sel_o          = OP_B_IMM;
 186: 
 187:     imm_a_mux_sel_o             = IMM_A_ZERO;
 188:     imm_b_mux_sel_o             = IMM_B_I;
 189: 
 190:     mult_en_o                   = 1'b0;
 191:     div_en_o                    = 1'b0;
 192:     multdiv_operator_o          = MD_OP_MULL;
 193:     multdiv_signed_mode_o       = 2'b00;
 194: 
 195:     regfile_wdata_sel_o         = RF_WD_EX;
 196:     regfile_we                  = 1'b0;
 197: 
 198:     csr_access_o                = 1'b0;
 199:     csr_illegal                 = 1'b0;
 200:     csr_op                      = CSR_OP_READ;
 201: 
 202:     data_we_o                   = 1'b0;
 203:     data_type_o                 = 2'b00;
 204:     data_sign_extension_o       = 1'b0;
 205:     data_req_o                  = 1'b0;
 206: 
 207:     illegal_insn                = 1'b0;
 208:     ebrk_insn_o                 = 1'b0;
 209:     mret_insn_o                 = 1'b0;
 210:     dret_insn_o                 = 1'b0;
 211:     ecall_insn_o                = 1'b0;
 212:     wfi_insn_o                  = 1'b0;
 213: 
 214:     opcode                      = opcode_e'(instr[6:0]);
 215: 
 216:     unique case (opcode)
 217: 
 218:       ///////////
 219:       // Jumps //
 220:       ///////////
 221: 
 222:       OPCODE_JAL: begin   // Jump and Link
 223:         jump_in_dec_o         = 1'b1;
 224:         if (instr_new_i) begin
 225:           // Calculate jump target
 226:           alu_op_a_mux_sel_o  = OP_A_CURRPC;
 227:           alu_op_b_mux_sel_o  = OP_B_IMM;
 228:           imm_b_mux_sel_o     = IMM_B_J;
 229:           alu_operator_o      = ALU_ADD;
 230:           regfile_we          = 1'b0;
 231:           jump_set_o          = 1'b1;
 232:         end else begin
 233:           // Calculate and store PC+4
 234:           alu_op_a_mux_sel_o  = OP_A_CURRPC;
 235:           alu_op_b_mux_sel_o  = OP_B_IMM;
 236:           imm_b_mux_sel_o     = IMM_B_INCR_PC;
 237:           alu_operator_o      = ALU_ADD;
 238:           regfile_we          = 1'b1;
 239:         end
 240:       end
 241: 
 242:       OPCODE_JALR: begin  // Jump and Link Register
 243:         jump_in_dec_o         = 1'b1;
 244:         if (instr_new_i) begin
 245:           // Calculate jump target
 246:           alu_op_a_mux_sel_o  = OP_A_REG_A;
 247:           alu_op_b_mux_sel_o  = OP_B_IMM;
 248:           imm_b_mux_sel_o     = IMM_B_I;
 249:           alu_operator_o      = ALU_ADD;
 250:           regfile_we          = 1'b0;
 251:           jump_set_o          = 1'b1;
 252:         end else begin
 253:           // Calculate and store PC+4
 254:           alu_op_a_mux_sel_o  = OP_A_CURRPC;
 255:           alu_op_b_mux_sel_o  = OP_B_IMM;
 256:           imm_b_mux_sel_o     = IMM_B_INCR_PC;
 257:           alu_operator_o      = ALU_ADD;
 258:           regfile_we          = 1'b1;
 259:         end
 260:         if (instr[14:12] != 3'b0) begin
 261:           illegal_insn = 1'b1;
 262:         end
 263:       end
 264: 
 265:       OPCODE_BRANCH: begin // Branch
 266:         branch_in_dec_o       = 1'b1;
 267:         // Check branch condition selection
 268:         unique case (instr[14:12])
 269:           3'b000:  alu_operator_o = ALU_EQ;
 270:           3'b001:  alu_operator_o = ALU_NE;
 271:           3'b100:  alu_operator_o = ALU_LT;
 272:           3'b101:  alu_operator_o = ALU_GE;
 273:           3'b110:  alu_operator_o = ALU_LTU;
 274:           3'b111:  alu_operator_o = ALU_GEU;
 275:           default: illegal_insn   = 1'b1;
 276:         endcase
 277:         if (instr_new_i) begin
 278:           // Evaluate branch condition
 279:           alu_op_a_mux_sel_o  = OP_A_REG_A;
 280:           alu_op_b_mux_sel_o  = OP_B_REG_B;
 281:         end else begin
 282:           // Calculate jump target in EX
 283:           alu_op_a_mux_sel_o  = OP_A_CURRPC;
 284:           alu_op_b_mux_sel_o  = OP_B_IMM;
 285:           imm_b_mux_sel_o     = IMM_B_B;
 286:           alu_operator_o      = ALU_ADD;
 287:           regfile_we          = 1'b0;
 288:         end
 289:       end
 290: 
 291:       ////////////////
 292:       // Load/store //
 293:       ////////////////
 294: 
 295:       OPCODE_STORE: begin
 296:         alu_op_a_mux_sel_o = OP_A_REG_A;
 297:         alu_op_b_mux_sel_o = OP_B_REG_B;
 298:         data_req_o         = 1'b1;
 299:         data_we_o          = 1'b1;
 300:         alu_operator_o     = ALU_ADD;
 301: 
 302:         if (!instr[14]) begin
 303:           // offset from immediate
 304:           imm_b_mux_sel_o     = IMM_B_S;
 305:           alu_op_b_mux_sel_o  = OP_B_IMM;
 306:         end else begin
 307:           // Register offset is illegal since no register c available
 308:           illegal_insn = 1'b1;
 309:         end
 310: 
 311:         // store size
 312:         unique case (instr[13:12])
 313:           2'b00:   data_type_o  = 2'b10; // SB
 314:           2'b01:   data_type_o  = 2'b01; // SH
 315:           2'b10:   data_type_o  = 2'b00; // SW
 316:           default: illegal_insn = 1'b1;
 317:         endcase
 318:       end
 319: 
 320:       OPCODE_LOAD: begin
 321:         alu_op_a_mux_sel_o  = OP_A_REG_A;
 322:         data_req_o          = 1'b1;
 323:         regfile_wdata_sel_o = RF_WD_LSU;
 324:         regfile_we          = 1'b1;
 325:         data_type_o         = 2'b00;
 326: 
 327:         // offset from immediate
 328:         alu_operator_o      = ALU_ADD;
 329:         alu_op_b_mux_sel_o  = OP_B_IMM;
 330:         imm_b_mux_sel_o     = IMM_B_I;
 331: 
 332:         // sign/zero extension
 333:         data_sign_extension_o = ~instr[14];
 334: 
 335:         // load size
 336:         unique case (instr[13:12])
 337:           2'b00: data_type_o = 2'b10; // LB(U)
 338:           2'b01: data_type_o = 2'b01; // LH(U)
 339:           2'b10: begin
 340:             data_type_o = 2'b00;      // LW
 341:             if (instr[14]) begin
 342:               illegal_insn = 1'b1;    // LWU does not exist
 343:             end
 344:           end
 345:           default: begin
 346:             illegal_insn = 1'b1;
 347:           end
 348:         endcase
 349:       end
 350: 
 351:       /////////
 352:       // ALU //
 353:       /////////
 354: 
 355:       OPCODE_LUI: begin  // Load Upper Immediate
 356:         alu_op_a_mux_sel_o  = OP_A_IMM;
 357:         alu_op_b_mux_sel_o  = OP_B_IMM;
 358:         imm_a_mux_sel_o     = IMM_A_ZERO;
 359:         imm_b_mux_sel_o     = IMM_B_U;
 360:         alu_operator_o      = ALU_ADD;
 361:         regfile_we          = 1'b1;
 362:       end
 363: 
 364:       OPCODE_AUIPC: begin  // Add Upper Immediate to PC
 365:         alu_op_a_mux_sel_o  = OP_A_CURRPC;
 366:         alu_op_b_mux_sel_o  = OP_B_IMM;
 367:         imm_b_mux_sel_o     = IMM_B_U;
 368:         alu_operator_o      = ALU_ADD;
 369:         regfile_we          = 1'b1;
 370:       end
 371: 
 372:       OPCODE_OP_IMM: begin // Register-Immediate ALU Operations
 373:         alu_op_a_mux_sel_o  = OP_A_REG_A;
 374:         alu_op_b_mux_sel_o  = OP_B_IMM;
 375:         imm_b_mux_sel_o     = IMM_B_I;
 376:         regfile_we          = 1'b1;
 377: 
 378:         unique case (instr[14:12])
 379:           3'b000: alu_operator_o = ALU_ADD;  // Add Immediate
 380:           3'b010: alu_operator_o = ALU_SLT;  // Set to one if Lower Than Immediate
 381:           3'b011: alu_operator_o = ALU_SLTU; // Set to one if Lower Than Immediate Unsigned
 382:           3'b100: alu_operator_o = ALU_XOR;  // Exclusive Or with Immediate
 383:           3'b110: alu_operator_o = ALU_OR;   // Or with Immediate
 384:           3'b111: alu_operator_o = ALU_AND;  // And with Immediate
 385: 
 386:           3'b001: begin
 387:             alu_operator_o = ALU_SLL;  // Shift Left Logical by Immediate
 388:             if (instr[31:25] != 7'b0) begin
 389:               illegal_insn = 1'b1;
 390:             end
 391:           end
 392: 
 393:           3'b101: begin
 394:             if (instr[31:25] == 7'b0) begin
 395:               alu_operator_o = ALU_SRL;  // Shift Right Logical by Immediate
 396:             end else if (instr[31:25] == 7'b010_0000) begin
 397:               alu_operator_o = ALU_SRA;  // Shift Right Arithmetically by Immediate
 398:             end else begin
 399:               illegal_insn   = 1'b1;
 400:             end
 401:           end
 402: 
 403:           default: begin
 404:             alu_operator_o = ALU_SLTU;
 405:           end
 406:         endcase
 407:       end
 408: 
 409:       OPCODE_OP: begin  // Register-Register ALU operation
 410:         alu_op_a_mux_sel_o = OP_A_REG_A;
 411:         alu_op_b_mux_sel_o = OP_B_REG_B;
 412:         regfile_we         = 1'b1;
 413: 
 414:         if (instr[31]) begin
 415:           illegal_insn = 1'b1;
 416:         end else begin
 417:           unique case ({instr[30:25], instr[14:12]})
 418:             // RV32I ALU operations
 419:             {6'b00_0000, 3'b000}: alu_operator_o = ALU_ADD;   // Add
 420:             {6'b10_0000, 3'b000}: alu_operator_o = ALU_SUB;   // Sub
 421:             {6'b00_0000, 3'b010}: alu_operator_o = ALU_SLT;   // Set Lower Than
 422:             {6'b00_0000, 3'b011}: alu_operator_o = ALU_SLTU;  // Set Lower Than Unsigned
 423:             {6'b00_0000, 3'b100}: alu_operator_o = ALU_XOR;   // Xor
 424:             {6'b00_0000, 3'b110}: alu_operator_o = ALU_OR;    // Or
 425:             {6'b00_0000, 3'b111}: alu_operator_o = ALU_AND;   // And
 426:             {6'b00_0000, 3'b001}: alu_operator_o = ALU_SLL;   // Shift Left Logical
 427:             {6'b00_0000, 3'b101}: alu_operator_o = ALU_SRL;   // Shift Right Logical
 428:             {6'b10_0000, 3'b101}: alu_operator_o = ALU_SRA;   // Shift Right Arithmetic
 429: 
 430:             // supported RV32M instructions
 431:             {6'b00_0001, 3'b000}: begin // mul
 432:               alu_operator_o        = ALU_ADD;
 433:               multdiv_operator_o    = MD_OP_MULL;
 434:               mult_en_o             = RV32M ? 1'b1 : 1'b0;
 435:               multdiv_signed_mode_o = 2'b00;
 436:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 437:             end
 438:             {6'b00_0001, 3'b001}: begin // mulh
 439:               alu_operator_o        = ALU_ADD;
 440:               multdiv_operator_o    = MD_OP_MULH;
 441:               mult_en_o             = RV32M ? 1'b1 : 1'b0;
 442:               multdiv_signed_mode_o = 2'b11;
 443:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 444:             end
 445:             {6'b00_0001, 3'b010}: begin // mulhsu
 446:               alu_operator_o        = ALU_ADD;
 447:               multdiv_operator_o    = MD_OP_MULH;
 448:               mult_en_o             = RV32M ? 1'b1 : 1'b0;
 449:               multdiv_signed_mode_o = 2'b01;
 450:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 451:             end
 452:             {6'b00_0001, 3'b011}: begin // mulhu
 453:               alu_operator_o        = ALU_ADD;
 454:               multdiv_operator_o    = MD_OP_MULH;
 455:               mult_en_o             = RV32M ? 1'b1 : 1'b0;
 456:               multdiv_signed_mode_o = 2'b00;
 457:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 458:             end
 459:             {6'b00_0001, 3'b100}: begin // div
 460:               alu_operator_o        = ALU_ADD;
 461:               multdiv_operator_o    = MD_OP_DIV;
 462:               div_en_o              = RV32M ? 1'b1 : 1'b0;
 463:               multdiv_signed_mode_o = 2'b11;
 464:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 465:             end
 466:             {6'b00_0001, 3'b101}: begin // divu
 467:               alu_operator_o        = ALU_ADD;
 468:               multdiv_operator_o    = MD_OP_DIV;
 469:               div_en_o              = RV32M ? 1'b1 : 1'b0;
 470:               multdiv_signed_mode_o = 2'b00;
 471:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 472:             end
 473:             {6'b00_0001, 3'b110}: begin // rem
 474:               alu_operator_o        = ALU_ADD;
 475:               multdiv_operator_o    = MD_OP_REM;
 476:               div_en_o              = RV32M ? 1'b1 : 1'b0;
 477:               multdiv_signed_mode_o = 2'b11;
 478:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 479:             end
 480:             {6'b00_0001, 3'b111}: begin // remu
 481:               alu_operator_o        = ALU_ADD;
 482:               multdiv_operator_o    = MD_OP_REM;
 483:               div_en_o              = RV32M ? 1'b1 : 1'b0;
 484:               multdiv_signed_mode_o = 2'b00;
 485:               illegal_insn          = RV32M ? 1'b0 : 1'b1;
 486:             end
 487:             default: begin
 488:               illegal_insn = 1'b1;
 489:             end
 490:           endcase
 491:         end
 492:       end
 493: 
 494:       /////////////
 495:       // Special //
 496:       /////////////
 497: 
 498:       OPCODE_MISC_MEM: begin
 499:         // For now, treat the FENCE (funct3 == 000) instruction as a NOP.  This may not be correct
 500:         // in a system with caches and should be revisited.
 501:         // FENCE.I will flush the IF stage and prefetch buffer but nothing else.
 502:         unique case (instr[14:12])
 503:           3'b000: begin
 504:             alu_operator_o     = ALU_ADD; // nop
 505:             alu_op_a_mux_sel_o = OP_A_REG_A;
 506:             alu_op_b_mux_sel_o = OP_B_IMM;
 507:             regfile_we         = 1'b0;
 508:           end
 509:           3'b001: begin
 510:             // FENCE.I is implemented as a jump to the next PC, this gives the required flushing
 511:             // behaviour (iside prefetch buffer flushed and response to any outstanding iside
 512:             // requests will be ignored).
 513:             jump_in_dec_o      = 1'b1;
 514: 
 515:             alu_op_a_mux_sel_o = OP_A_CURRPC;
 516:             alu_op_b_mux_sel_o = OP_B_IMM;
 517:             imm_b_mux_sel_o    = IMM_B_INCR_PC;
 518:             alu_operator_o     = ALU_ADD;
 519:             regfile_we         = 1'b0;
 520: 
 521:             if (instr_new_i) begin
 522:               jump_set_o       = 1'b1;
 523:             end
 524:           end
 525:           default: begin
 526:             illegal_insn       = 1'b1;
 527:           end
 528:         endcase
 529:       end
 530: 
 531:       OPCODE_SYSTEM: begin
 532:         if (instr[14:12] == 3'b000) begin
 533:           // non CSR related SYSTEM instructions
 534:           alu_op_a_mux_sel_o = OP_A_REG_A;
 535:           alu_op_b_mux_sel_o = OP_B_IMM;
 536:           unique case (instr[31:20])
 537:             12'h000:  // ECALL
 538:               // environment (system) call
 539:               ecall_insn_o = 1'b1;
 540: 
 541:             12'h001:  // ebreak
 542:               // debugger trap
 543:               ebrk_insn_o = 1'b1;
 544: 
 545:             12'h302:  // mret
 546:               mret_insn_o = 1'b1;
 547: 
 548:             12'h7b2:  // dret
 549:               dret_insn_o = 1'b1;
 550: 
 551:             12'h105:  // wfi
 552:               wfi_insn_o = 1'b1;
 553: 
 554:             default:
 555:               illegal_insn = 1'b1;
 556:           endcase
 557: 
 558:           // rs1 and rd must be 0
 559:           if (instr[`REG_S1] != 5'b0 || instr[`REG_D] != 5'b0) begin
 560:             illegal_insn = 1'b1;
 561:           end
 562:         end else begin
 563:           // instruction to read/modify CSR
 564:           csr_access_o        = 1'b1;
 565:           regfile_wdata_sel_o = RF_WD_CSR;
 566:           regfile_we          = 1'b1;
 567:           alu_op_b_mux_sel_o  = OP_B_IMM;
 568:           imm_a_mux_sel_o     = IMM_A_Z;
 569:           imm_b_mux_sel_o     = IMM_B_I;  // CSR address is encoded in I imm
 570: 
 571:           if (instr[14]) begin
 572:             // rs1 field is used as immediate
 573:             alu_op_a_mux_sel_o = OP_A_IMM;
 574:           end else begin
 575:             alu_op_a_mux_sel_o = OP_A_REG_A;
 576:           end
 577: 
 578:           unique case (instr[13:12])
 579:             2'b01:   csr_op = CSR_OP_WRITE;
 580:             2'b10:   csr_op = CSR_OP_SET;
 581:             2'b11:   csr_op = CSR_OP_CLEAR;
 582:             default: csr_illegal = 1'b1;
 583:           endcase
 584: 
 585:           illegal_insn = csr_illegal;
 586:         end
 587: 
 588:       end
 589:       default: begin
 590:         illegal_insn = 1'b1;
 591:       end
 592:     endcase
 593: 
 594:     // make sure illegal compressed instructions cause illegal instruction exceptions
 595:     if (illegal_c_insn_i) begin
 596:       illegal_insn = 1'b1;
 597:     end
 598: 
 599:     // make sure illegal instructions detected in the decoder do not propagate from decoder
 600:     // into register file, LSU, EX, WB, CSRs, PC
 601:     // NOTE: instructions can also be detected to be illegal inside the CSRs (upon accesses with
 602:     // insufficient privileges), or when accessing non-available registers in RV32E,
 603:     // these cases are not handled here
 604:     if (illegal_insn) begin
 605:       regfile_we      = 1'b0;
 606:       data_req_o      = 1'b0;
 607:       data_we_o       = 1'b0;
 608:       mult_en_o       = 1'b0;
 609:       div_en_o        = 1'b0;
 610:       jump_in_dec_o   = 1'b0;
 611:       jump_set_o      = 1'b0;
 612:       branch_in_dec_o = 1'b0;
 613:       csr_access_o    = 1'b0;
 614:     end
 615:   end
 616: 
 617:   // make sure instructions accessing non-available registers in RV32E cause illegal
 618:   // instruction exceptions
 619:   assign illegal_insn_o = illegal_insn | illegal_reg_rv32e;
 620: 
 621:   // do not propgate regfile write enable if non-available registers are accessed in RV32E
 622:   assign regfile_we_o = regfile_we & ~illegal_reg_rv32e;
 623: 
 624:   ////////////////
 625:   // Assertions //
 626:   ////////////////
 627: 
 628:   // Selectors must be known/valid.
 629:   `ASSERT(IbexRegImmAluOpKnown, (opcode == OPCODE_OP_IMM) |->
 630:       !$isunknown(instr[14:12]), clk_i, !rst_ni)
 631: 
 632: endmodule // controller
 633: