../src/lowrisc_ibex_ibex_core_0.1/rtl/ibex_controller.sv Cov: 95%

   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: /**
   7:  * Main controller of the processor
   8:  */
   9: 
  10: `include "prim_assert.sv"
  11: 
  12: module ibex_controller #(
  13:     parameter bit WritebackStage = 0
  14:  ) (
  15:     input  logic                  clk_i,
  16:     input  logic                  rst_ni,
  17: 
  18:     input  logic                  fetch_enable_i,        // start decoding
  19:     output logic                  ctrl_busy_o,           // core is busy processing instrs
  20: 
  21:     // decoder related signals
  22:     input  logic                  illegal_insn_i,          // decoder has an invalid instr
  23:     input  logic                  ecall_insn_i,            // decoder has ECALL instr
  24:     input  logic                  mret_insn_i,             // decoder has MRET instr
  25:     input  logic                  dret_insn_i,             // decoder has DRET instr
  26:     input  logic                  wfi_insn_i,              // decoder has WFI instr
  27:     input  logic                  ebrk_insn_i,             // decoder has EBREAK instr
  28:     input  logic                  csr_pipe_flush_i,        // do CSR-related pipeline flush
  29: 
  30:     // from IF-ID pipeline stage
  31:     input  logic                  instr_valid_i,           // instr from IF-ID reg is valid
  32:     input  logic [31:0]           instr_i,                 // instr from IF-ID reg, for mtval
  33:     input  logic [15:0]           instr_compressed_i,      // instr from IF-ID reg, for mtval
  34:     input  logic                  instr_is_compressed_i,   // instr from IF-ID reg is compressed
  35:     input  logic                  instr_fetch_err_i,       // instr from IF-ID reg has error
  36:     input  logic                  instr_fetch_err_plus2_i, // instr from IF-ID reg error is x32
  37:     input  logic [31:0]           pc_id_i,                 // instr from IF-ID reg address
  38: 
  39:     // to IF-ID pipeline stage
  40:     output logic                  instr_valid_clear_o,     // kill instr in IF-ID reg
  41:     output logic                  id_in_ready_o,           // ID stage is ready for new instr
  42:     output logic                  controller_run_o,        // Controller is in standard instruction
  43:                                                            // run mode
  44: 
  45:     // to prefetcher
  46:     output logic                  instr_req_o,             // start fetching instructions
  47:     output logic                  pc_set_o,                // jump to address set by pc_mux
  48:     output logic                  pc_set_spec_o,           // speculative branch
  49:     output ibex_pkg::pc_sel_e     pc_mux_o,                // IF stage fetch address selector
  50:                                                            // (boot, normal, exception...)
  51:     output ibex_pkg::exc_pc_sel_e exc_pc_mux_o,            // IF stage selector for exception PC
  52:     output ibex_pkg::exc_cause_e  exc_cause_o,             // for IF stage, CSRs
  53: 
  54:     // LSU
  55:     input  logic [31:0]           lsu_addr_last_i,         // for mtval
  56:     input  logic                  load_err_i,
  57:     input  logic                  store_err_i,
  58:     output logic                  wb_exception_o,          // Instruction in WB taking an exception
  59: 
  60:     // jump/branch signals
  61:     input  logic                  branch_set_i,            // branch taken set signal
  62:     input  logic                  branch_set_spec_i,       // speculative branch signal
  63:     input  logic                  jump_set_i,              // jump taken set signal
  64: 
  65:     // interrupt signals
  66:     input  logic                  csr_mstatus_mie_i,       // M-mode interrupt enable bit
  67:     input  logic                  irq_pending_i,           // interrupt request pending
  68:     input  ibex_pkg::irqs_t       irqs_i,                  // interrupt requests qualified with
  69:                                                            // mie CSR
  70:     input  logic                  irq_nm_i,                // non-maskeable interrupt
  71:     output logic                  nmi_mode_o,              // core executing NMI handler
  72: 
  73:     // debug signals
  74:     input  logic                  debug_req_i,
  75:     output ibex_pkg::dbg_cause_e  debug_cause_o,
  76:     output logic                  debug_csr_save_o,
  77:     output logic                  debug_mode_o,
  78:     input  logic                  debug_single_step_i,
  79:     input  logic                  debug_ebreakm_i,
  80:     input  logic                  debug_ebreaku_i,
  81:     input  logic                  trigger_match_i,
  82: 
  83:     output logic                  csr_save_if_o,
  84:     output logic                  csr_save_id_o,
  85:     output logic                  csr_save_wb_o,
  86:     output logic                  csr_restore_mret_id_o,
  87:     output logic                  csr_restore_dret_id_o,
  88:     output logic                  csr_save_cause_o,
  89:     output logic [31:0]           csr_mtval_o,
  90:     input  ibex_pkg::priv_lvl_e   priv_mode_i,
  91:     input  logic                  csr_mstatus_tw_i,
  92: 
  93:     // stall & flush signals
  94:     input  logic                  lsu_req_in_id_i,
  95:     input  logic                  stall_id_i,
  96:     input  logic                  stall_wb_i,
  97:     output logic                  flush_id_o,
  98:     input  logic                  ready_wb_i,
  99: 
 100:     // performance monitors
 101:     output logic                  perf_jump_o,             // we are executing a jump
 102:                                                            // instruction (j, jr, jal, jalr)
 103:     output logic                  perf_tbranch_o           // we are executing a taken branch
 104:                                                            // instruction
 105: );
 106:   import ibex_pkg::*;
 107: 
 108:   // FSM state encoding
 109:   typedef enum logic [3:0] {
 110:     RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH,
 111:     IRQ_TAKEN, DBG_TAKEN_IF, DBG_TAKEN_ID
 112:   } ctrl_fsm_e;
 113: 
 114:   ctrl_fsm_e ctrl_fsm_cs, ctrl_fsm_ns;
 115: 
 116:   logic nmi_mode_q, nmi_mode_d;
 117:   logic debug_mode_q, debug_mode_d;
 118:   logic load_err_q, load_err_d;
 119:   logic store_err_q, store_err_d;
 120:   logic exc_req_q, exc_req_d;
 121:   logic illegal_insn_q, illegal_insn_d;
 122: 
 123:   // Of the various exception/fault signals, which one takes priority in FLUSH and hence controls
 124:   // what happens next (setting exc_cause, csr_mtval etc)
 125:   logic instr_fetch_err_prio;
 126:   logic illegal_insn_prio;
 127:   logic ecall_insn_prio;
 128:   logic ebrk_insn_prio;
 129:   logic store_err_prio;
 130:   logic load_err_prio;
 131: 
 132:   logic stall;
 133:   logic halt_if;
 134:   logic retain_id;
 135:   logic flush_id;
 136:   logic illegal_dret;
 137:   logic illegal_umode;
 138:   logic exc_req_lsu;
 139:   logic special_req_all;
 140:   logic special_req_branch;
 141:   logic enter_debug_mode;
 142:   logic ebreak_into_debug;
 143:   logic handle_irq;
 144: 
 145:   logic [3:0] mfip_id;
 146:   logic       unused_irq_timer;
 147: 
 148:   logic ecall_insn;
 149:   logic mret_insn;
 150:   logic dret_insn;
 151:   logic wfi_insn;
 152:   logic ebrk_insn;
 153:   logic csr_pipe_flush;
 154:   logic instr_fetch_err;
 155: 
 156: `ifndef SYNTHESIS
 157:   // synopsys translate_off
 158:   // make sure we are called later so that we do not generate messages for
 159:   // glitches
 160:   always_ff @(negedge clk_i) begin
 161:     // print warning in case of decoding errors
 162:     if ((ctrl_fsm_cs == DECODE) && instr_valid_i && !instr_fetch_err_i && illegal_insn_d) begin
 163:       $display("%t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, ibex_core.hart_id_i,
 164:                ibex_id_stage.pc_id_i, ibex_id_stage.instr_rdata_i);
 165:     end
 166:   end
 167:   // synopsys translate_on
 168: `endif
 169: 
 170:   ////////////////
 171:   // Exceptions //
 172:   ////////////////
 173: 
 174:   assign load_err_d  = load_err_i;
 175:   assign store_err_d = store_err_i;
 176: 
 177:   // Decoder doesn't take instr_valid into account, factor it in here.
 178:   assign ecall_insn      = ecall_insn_i      & instr_valid_i;
 179:   assign mret_insn       = mret_insn_i       & instr_valid_i;
 180:   assign dret_insn       = dret_insn_i       & instr_valid_i;
 181:   assign wfi_insn        = wfi_insn_i        & instr_valid_i;
 182:   assign ebrk_insn       = ebrk_insn_i       & instr_valid_i;
 183:   assign csr_pipe_flush  = csr_pipe_flush_i  & instr_valid_i;
 184:   assign instr_fetch_err = instr_fetch_err_i & instr_valid_i;
 185: 
 186:   // "Executing DRET outside of Debug Mode causes an illegal instruction exception."
 187:   // [Debug Spec v0.13.2, p.41]
 188:   assign illegal_dret = dret_insn & ~debug_mode_q;
 189: 
 190:   // Some instructions can only be executed in M-Mode
 191:   assign illegal_umode = (priv_mode_i != PRIV_LVL_M) &
 192:                          // MRET must be in M-Mode. TW means trap WFI to M-Mode.
 193:                          (mret_insn | (csr_mstatus_tw_i & wfi_insn));
 194: 
 195:   // This is recorded in the illegal_insn_q flop to help timing.  Specifically
 196:   // it is needed to break the path from ibex_cs_registers/illegal_csr_insn_o
 197:   // to pc_set_o.  Clear when controller is in FLUSH so it won't remain set
 198:   // once illegal instruction is handled.
 199:   // All terms in this expression are qualified by instr_valid_i
 200:   assign illegal_insn_d = (illegal_insn_i | illegal_dret | illegal_umode) & (ctrl_fsm_cs != FLUSH);
 201: 
 202:   // exception requests
 203:   // requests are flopped in exc_req_q.  This is cleared when controller is in
 204:   // the FLUSH state so the cycle following exc_req_q won't remain set for an
 205:   // exception request that has just been handled.
 206:   // All terms in this expression are qualified by instr_valid_i
 207:   assign exc_req_d = (ecall_insn | ebrk_insn | illegal_insn_d | instr_fetch_err) &
 208:                      (ctrl_fsm_cs != FLUSH);
 209: 
 210:   // LSU exception requests
 211:   assign exc_req_lsu = store_err_i | load_err_i;
 212: 
 213: 
 214:   // special requests: special instructions, pipeline flushes, exceptions...
 215: 
 216:   // To avoid creating a path from data_err_i -> instr_req_o and to help timing the below
 217:   // special_req_all has a version that only applies to branches. For a branch the controller needs
 218:   // to set pc_set_o but only if there is no special request. If the generic special_req_all signal
 219:   // is used then a variety of signals that will never cause a special request during a branch
 220:   // instruction end up factored into pc_set_o. The special_req_branch only considers the special
 221:   // request reasons that are relevant to a branch.
 222: 
 223:   // generic special request signal, applies to all instructions
 224:   // All terms in this expression are qualified by instr_valid_i except exc_req_lsu which can come
 225:   // from the Writeback stage with no instr_valid_i from the ID stage
 226:   assign special_req_all = mret_insn | dret_insn | wfi_insn | csr_pipe_flush |
 227:       exc_req_d | exc_req_lsu;
 228: 
 229:   // special request that can specifically occur during branch instructions
 230:   // All terms in this expression are qualified by instr_valid_i
 231:   assign special_req_branch = instr_fetch_err & (ctrl_fsm_cs != FLUSH);
 232: 
 233:   `ASSERT(SpecialReqBranchGivesSpecialReqAll,
 234:     special_req_branch |-> special_req_all)
 235: 
 236:   `ASSERT(SpecialReqAllGivesSpecialReqBranchIfBranchInst,
 237:     special_req_all && (branch_set_i || jump_set_i) |-> special_req_branch)
 238: 
 239:   // Exception/fault prioritisation is taken from Table 3.7 of Priviledged Spec v1.11
 240:   if (WritebackStage) begin : g_wb_exceptions
 241:     always_comb begin
 242:       instr_fetch_err_prio = 0;
 243:       illegal_insn_prio    = 0;
 244:       ecall_insn_prio      = 0;
 245:       ebrk_insn_prio       = 0;
 246:       store_err_prio       = 0;
 247:       load_err_prio        = 0;
 248: 
 249:       // Note that with the writeback stage store/load errors occur on the instruction in writeback,
 250:       // all other exception/faults occur on the instruction in ID/EX. The faults from writeback
 251:       // must take priority as that instruction is architecurally ordered before the one in ID/EX.
 252:       if (store_err_q) begin
 253:         store_err_prio = 1'b1;
 254:       end else if (load_err_q) begin
 255:         load_err_prio  = 1'b1;
 256:       end else if (instr_fetch_err) begin
 257:         instr_fetch_err_prio = 1'b1;
 258:       end else if (illegal_insn_q) begin
 259:         illegal_insn_prio = 1'b1;
 260:       end else if (ecall_insn) begin
 261:         ecall_insn_prio = 1'b1;
 262:       end else if (ebrk_insn) begin
 263:         ebrk_insn_prio = 1'b1;
 264:       end
 265:     end
 266: 
 267:     // Instruction in writeback is generating an exception so instruction in ID must not execute
 268:     assign wb_exception_o = load_err_q | store_err_q | load_err_i | store_err_i;
 269:   end else begin : g_no_wb_exceptions
 270:     always_comb begin
 271:       instr_fetch_err_prio = 0;
 272:       illegal_insn_prio    = 0;
 273:       ecall_insn_prio      = 0;
 274:       ebrk_insn_prio       = 0;
 275:       store_err_prio       = 0;
 276:       load_err_prio        = 0;
 277: 
 278:       if (instr_fetch_err) begin
 279:         instr_fetch_err_prio = 1'b1;
 280:       end else if (illegal_insn_q) begin
 281:         illegal_insn_prio = 1'b1;
 282:       end else if (ecall_insn) begin
 283:         ecall_insn_prio = 1'b1;
 284:       end else if (ebrk_insn) begin
 285:         ebrk_insn_prio = 1'b1;
 286:       end else if (store_err_q) begin
 287:         store_err_prio = 1'b1;
 288:       end else if (load_err_q) begin
 289:         load_err_prio  = 1'b1;
 290:       end
 291:     end
 292:     assign wb_exception_o = 1'b0;
 293:   end
 294: 
 295:   `ASSERT_IF(IbexExceptionPrioOnehot,
 296:              $onehot({instr_fetch_err_prio,
 297:                       illegal_insn_prio,
 298:                       ecall_insn_prio,
 299:                       ebrk_insn_prio,
 300:                       store_err_prio,
 301:                       load_err_prio}),
 302:              (ctrl_fsm_cs == FLUSH) & exc_req_q);
 303: 
 304:   ////////////////
 305:   // Interrupts //
 306:   ////////////////
 307: 
 308:   // Enter debug mode due to an external debug_req_i or because the core is in
 309:   // single step mode (dcsr.step == 1). Single step must be qualified with
 310:   // instruction valid otherwise the core will immediately enter debug mode
 311:   // due to a recently flushed IF (or a delay in an instruction returning from
 312:   // memory) before it has had anything to single step.
 313:   // Also enter debug mode on a trigger match (hardware breakpoint)
 314:   assign enter_debug_mode = (debug_req_i | (debug_single_step_i & instr_valid_i) |
 315:                              trigger_match_i) & ~debug_mode_q;
 316: 
 317:   // Set when an ebreak should enter debug mode rather than jump to exception
 318:   // handler
 319:   assign ebreak_into_debug = priv_mode_i == PRIV_LVL_M ? debug_ebreakm_i :
 320:                              priv_mode_i == PRIV_LVL_U ? debug_ebreaku_i :
 321:                                                          1'b0;
 322: 
 323:   // Interrupts including NMI are ignored,
 324:   // - while in debug mode [Debug Spec v0.13.2, p.39],
 325:   // - while in NMI mode (nested NMIs are not supported, NMI has highest priority and
 326:   //   cannot be interrupted by regular interrupts).
 327:   assign handle_irq = ~debug_mode_q & ~nmi_mode_q &
 328:       (irq_nm_i | (irq_pending_i & csr_mstatus_mie_i));
 329: 
 330:   // generate ID of fast interrupts, highest priority to highest ID
 331:   always_comb begin : gen_mfip_id
 332:     if      (irqs_i.irq_fast[14]) mfip_id = 4'd14;
 333:     else if (irqs_i.irq_fast[13]) mfip_id = 4'd13;
 334:     else if (irqs_i.irq_fast[12]) mfip_id = 4'd12;
 335:     else if (irqs_i.irq_fast[11]) mfip_id = 4'd11;
 336:     else if (irqs_i.irq_fast[10]) mfip_id = 4'd10;
 337:     else if (irqs_i.irq_fast[ 9]) mfip_id = 4'd9;
 338:     else if (irqs_i.irq_fast[ 8]) mfip_id = 4'd8;
 339:     else if (irqs_i.irq_fast[ 7]) mfip_id = 4'd7;
 340:     else if (irqs_i.irq_fast[ 6]) mfip_id = 4'd6;
 341:     else if (irqs_i.irq_fast[ 5]) mfip_id = 4'd5;
 342:     else if (irqs_i.irq_fast[ 5]) mfip_id = 4'd5;
 343:     else if (irqs_i.irq_fast[ 4]) mfip_id = 4'd4;
 344:     else if (irqs_i.irq_fast[ 3]) mfip_id = 4'd3;
 345:     else if (irqs_i.irq_fast[ 2]) mfip_id = 4'd2;
 346:     else if (irqs_i.irq_fast[ 1]) mfip_id = 4'd1;
 347:     else                          mfip_id = 4'd0;
 348:   end
 349: 
 350:   assign unused_irq_timer = irqs_i.irq_timer;
 351: 
 352:   /////////////////////
 353:   // Core controller //
 354:   /////////////////////
 355: 
 356:   always_comb begin
 357:     // Default values
 358:     instr_req_o           = 1'b1;
 359: 
 360:     csr_save_if_o         = 1'b0;
 361:     csr_save_id_o         = 1'b0;
 362:     csr_save_wb_o         = 1'b0;
 363:     csr_restore_mret_id_o = 1'b0;
 364:     csr_restore_dret_id_o = 1'b0;
 365:     csr_save_cause_o      = 1'b0;
 366:     csr_mtval_o           = '0;
 367: 
 368:     // The values of pc_mux and exc_pc_mux are only relevant if pc_set is set. Some of the states
 369:     // below always set pc_mux and exc_pc_mux but only set pc_set if certain conditions are met.
 370:     // This avoid having to factor those conditions into the pc_mux and exc_pc_mux select signals
 371:     // helping timing.
 372:     pc_mux_o              = PC_BOOT;
 373:     pc_set_o              = 1'b0;
 374:     pc_set_spec_o         = 1'b0;
 375: 
 376:     exc_pc_mux_o          = EXC_PC_IRQ;
 377:     exc_cause_o           = EXC_CAUSE_INSN_ADDR_MISA; // = 6'h00
 378: 
 379:     ctrl_fsm_ns           = ctrl_fsm_cs;
 380: 
 381:     ctrl_busy_o           = 1'b1;
 382: 
 383:     halt_if               = 1'b0;
 384:     retain_id             = 1'b0;
 385:     flush_id              = 1'b0;
 386: 
 387:     debug_csr_save_o      = 1'b0;
 388:     debug_cause_o         = DBG_CAUSE_EBREAK;
 389:     debug_mode_d          = debug_mode_q;
 390:     nmi_mode_d            = nmi_mode_q;
 391: 
 392:     perf_tbranch_o        = 1'b0;
 393:     perf_jump_o           = 1'b0;
 394: 
 395:     controller_run_o      = 1'b0;
 396: 
 397:     unique case (ctrl_fsm_cs)
 398:       RESET: begin
 399:         // just wait for fetch_enable
 400:         instr_req_o   = 1'b0;
 401:         pc_mux_o      = PC_BOOT;
 402:         pc_set_o      = 1'b1;
 403:         pc_set_spec_o = 1'b1;
 404:         if (fetch_enable_i) begin
 405:           ctrl_fsm_ns = BOOT_SET;
 406:         end
 407:       end
 408: 
 409:       BOOT_SET: begin
 410:         // copy boot address to instr fetch address
 411:         instr_req_o   = 1'b1;
 412:         pc_mux_o      = PC_BOOT;
 413:         pc_set_o      = 1'b1;
 414:         pc_set_spec_o = 1'b1;
 415: 
 416:         ctrl_fsm_ns = FIRST_FETCH;
 417:       end
 418: 
 419:       WAIT_SLEEP: begin
 420:         ctrl_busy_o   = 1'b0;
 421:         instr_req_o   = 1'b0;
 422:         halt_if       = 1'b1;
 423:         flush_id      = 1'b1;
 424:         ctrl_fsm_ns   = SLEEP;
 425:       end
 426: 
 427:       SLEEP: begin
 428:         // instruction in IF stage is already valid
 429:         // we begin execution when an interrupt has arrived
 430:         instr_req_o   = 1'b0;
 431:         halt_if       = 1'b1;
 432:         flush_id      = 1'b1;
 433: 
 434:         // normal execution flow
 435:         // in debug mode or single step mode we leave immediately (wfi=nop)
 436:         if (irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i) begin
 437:           ctrl_fsm_ns = FIRST_FETCH;
 438:         end else begin
 439:           // Make sure clock remains disabled.
 440:           ctrl_busy_o = 1'b0;
 441:         end
 442:       end
 443: 
 444:       FIRST_FETCH: begin
 445:         // Stall because of IF miss
 446:         if (id_in_ready_o) begin
 447:           ctrl_fsm_ns = DECODE;
 448:         end
 449: 
 450:         // handle interrupts
 451:         if (handle_irq) begin
 452:           // We are handling an interrupt. Set halt_if to tell IF not to give
 453:           // us any more instructions before it redirects to the handler, but
 454:           // don't set flush_id: we must allow this instruction to complete
 455:           // (since it might have outstanding loads or stores).
 456:           ctrl_fsm_ns = IRQ_TAKEN;
 457:           halt_if     = 1'b1;
 458:         end
 459: 
 460:         // enter debug mode
 461:         if (enter_debug_mode) begin
 462:           ctrl_fsm_ns = DBG_TAKEN_IF;
 463:           // Halt IF only for now, ID will be flushed in DBG_TAKEN_IF as the
 464:           // ID state is needed for correct debug mode entry
 465:           halt_if     = 1'b1;
 466:         end
 467:       end
 468: 
 469:       DECODE: begin
 470:         // normal operating mode of the ID stage, in case of debug and interrupt requests,
 471:         // priorities are as follows (lower number == higher priority)
 472:         // 1. currently running (multicycle) instructions and exceptions caused by these
 473:         // 2. debug requests
 474:         // 3. interrupt requests
 475: 
 476:         controller_run_o = 1'b1;
 477: 
 478:         // Set PC mux for branch and jump here to ease timing. Value is only relevant if pc_set_o is
 479:         // also set. Setting the mux value here avoids factoring in special_req and instr_valid_i
 480:         // which helps timing.
 481:         pc_mux_o = PC_JUMP;
 482: 
 483: 
 484:         // Get ready for special instructions, exceptions, pipeline flushes
 485:         if (special_req_all) begin
 486:           // Halt IF but don't flush ID. This leaves a valid instruction in
 487:           // ID so controller can determine appropriate action in the
 488:           // FLUSH state.
 489:           retain_id = 1'b1;
 490: 
 491:           // Wait for the writeback stage to either be ready for a new instruction or raise its own
 492:           // exception before going to FLUSH. If the instruction in writeback raises an exception it
 493:           // must take priority over any exception from an instruction in ID/EX. Only once the
 494:           // writeback stage is ready can we be certain that won't happen. Without a writeback
 495:           // stage ready_wb_i == 1 so the FSM will always go directly to FLUSH.
 496: 
 497:           if (ready_wb_i | wb_exception_o) begin
 498:             ctrl_fsm_ns = FLUSH;
 499:           end
 500:         end
 501: 
 502:         if ((branch_set_i || jump_set_i) && !special_req_branch) begin
 503:           pc_set_o       = 1'b1;
 504: 
 505:           perf_tbranch_o = branch_set_i;
 506:           perf_jump_o    = jump_set_i;
 507:         end
 508: 
 509:         // pc_set signal excluding branch taken condition
 510:         if ((branch_set_spec_i || jump_set_i) && !special_req_branch) begin
 511:           pc_set_spec_o = 1'b1;
 512:         end
 513: 
 514:         // If entering debug mode or handling an IRQ the core needs to wait
 515:         // until the current instruction has finished executing. Stall IF
 516:         // during that time.
 517:         if ((enter_debug_mode || handle_irq) && (stall || lsu_req_in_id_i)) begin
 518:           halt_if = 1'b1;
 519:         end
 520: 
 521:         if (!stall && !lsu_req_in_id_i && !special_req_all) begin
 522:           if (enter_debug_mode) begin
 523:             // enter debug mode
 524:             ctrl_fsm_ns = DBG_TAKEN_IF;
 525:             // Halt IF only for now, ID will be flushed in DBG_TAKEN_IF as the
 526:             // ID state is needed for correct debug mode entry
 527:             halt_if     = 1'b1;
 528:           end else if (handle_irq) begin
 529:             // handle interrupt (not in debug mode)
 530:             ctrl_fsm_ns = IRQ_TAKEN;
 531:             // We are handling an interrupt (not in debug mode). Set halt_if to
 532:             // tell IF not to give us any more instructions before it redirects
 533:             // to the handler, but don't set flush_id: we must allow this
 534:             // instruction to complete (since it might have outstanding loads
 535:             // or stores).
 536:             halt_if     = 1'b1;
 537:           end
 538:         end
 539: 
 540:       end // DECODE
 541: 
 542:       IRQ_TAKEN: begin
 543:         pc_mux_o     = PC_EXC;
 544:         exc_pc_mux_o = EXC_PC_IRQ;
 545: 
 546:         if (handle_irq) begin
 547:           pc_set_o         = 1'b1;
 548:           pc_set_spec_o    = 1'b1;
 549: 
 550:           csr_save_if_o    = 1'b1;
 551:           csr_save_cause_o = 1'b1;
 552: 
 553:           // interrupt priorities according to Privileged Spec v1.11 p.31
 554:           if (irq_nm_i && !nmi_mode_q) begin
 555:             exc_cause_o = EXC_CAUSE_IRQ_NM;
 556:             nmi_mode_d  = 1'b1; // enter NMI mode
 557:           end else if (irqs_i.irq_fast != 15'b0) begin
 558:             // generate exception cause ID from fast interrupt ID:
 559:             // - first bit distinguishes interrupts from exceptions,
 560:             // - second bit adds 16 to fast interrupt ID
 561:             // for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16}
 562:             exc_cause_o = exc_cause_e'({2'b11, mfip_id});
 563:           end else if (irqs_i.irq_external) begin
 564:             exc_cause_o = EXC_CAUSE_IRQ_EXTERNAL_M;
 565:           end else if (irqs_i.irq_software) begin
 566:             exc_cause_o = EXC_CAUSE_IRQ_SOFTWARE_M;
 567:           end else begin // irqs_i.irq_timer
 568:             exc_cause_o = EXC_CAUSE_IRQ_TIMER_M;
 569:           end
 570:         end
 571: 
 572:         ctrl_fsm_ns = DECODE;
 573:       end
 574: 
 575:       DBG_TAKEN_IF: begin
 576:         pc_mux_o     = PC_EXC;
 577:         exc_pc_mux_o = EXC_PC_DBD;
 578: 
 579:         // enter debug mode and save PC in IF to dpc
 580:         // jump to debug exception handler in debug memory
 581:         if (debug_single_step_i || debug_req_i || trigger_match_i) begin
 582:           flush_id         = 1'b1;
 583:           pc_set_o         = 1'b1;
 584:           pc_set_spec_o    = 1'b1;
 585: 
 586:           csr_save_if_o    = 1'b1;
 587:           debug_csr_save_o = 1'b1;
 588: 
 589:           csr_save_cause_o = 1'b1;
 590:           if (trigger_match_i) begin
 591:             debug_cause_o = DBG_CAUSE_TRIGGER;
 592:           end else if (debug_single_step_i) begin
 593:             debug_cause_o = DBG_CAUSE_STEP;
 594:           end else begin
 595:             debug_cause_o = DBG_CAUSE_HALTREQ;
 596:           end
 597: 
 598:           // enter debug mode
 599:           debug_mode_d = 1'b1;
 600:         end
 601: 
 602:         ctrl_fsm_ns  = DECODE;
 603:       end
 604: 
 605:       DBG_TAKEN_ID: begin
 606:         // enter debug mode and save PC in ID to dpc, used when encountering
 607:         // 1. EBREAK during debug mode
 608:         // 2. EBREAK with forced entry into debug mode (ebreakm or ebreaku set).
 609:         // regular ebreak's go through FLUSH.
 610:         //
 611:         // for 1. do not update dcsr and dpc, for 2. do so [Debug Spec v0.13.2, p.39]
 612:         // jump to debug exception handler in debug memory
 613:         flush_id      = 1'b1;
 614:         pc_mux_o      = PC_EXC;
 615:         pc_set_o      = 1'b1;
 616:         pc_set_spec_o = 1'b1;
 617:         exc_pc_mux_o  = EXC_PC_DBD;
 618: 
 619:         // update dcsr and dpc
 620:         if (ebreak_into_debug && !debug_mode_q) begin // ebreak with forced entry
 621: 
 622:           // dpc (set to the address of the EBREAK, i.e. set to PC in ID stage)
 623:           csr_save_cause_o = 1'b1;
 624:           csr_save_id_o    = 1'b1;
 625: 
 626:           // dcsr
 627:           debug_csr_save_o = 1'b1;
 628:           debug_cause_o    = DBG_CAUSE_EBREAK;
 629:         end
 630: 
 631:         // enter debug mode
 632:         debug_mode_d = 1'b1;
 633: 
 634:         ctrl_fsm_ns  = DECODE;
 635:       end
 636: 
 637:       FLUSH: begin
 638:         // flush the pipeline
 639:         halt_if     = 1'b1;
 640:         flush_id    = 1'b1;
 641:         ctrl_fsm_ns = DECODE;
 642: 
 643:         // As pc_mux and exc_pc_mux can take various values in this state they aren't set early
 644:         // here.
 645: 
 646:         // exceptions: set exception PC, save PC and exception cause
 647:         // exc_req_lsu is high for one clock cycle only (in DECODE)
 648:         if (exc_req_q || store_err_q || load_err_q) begin
 649:           pc_set_o         = 1'b1;
 650:           pc_set_spec_o    = 1'b1;
 651:           pc_mux_o         = PC_EXC;
 652:           exc_pc_mux_o     = debug_mode_q ? EXC_PC_DBG_EXC : EXC_PC_EXC;
 653: 
 654:           if (WritebackStage) begin : g_writeback_mepc_save
 655:             // With the writeback stage present whether an instruction accessing memory will cause
 656:             // an exception is only known when it is in writeback. So when taking such an exception
 657:             // epc must come from writeback.
 658:             csr_save_id_o  = ~(store_err_q | load_err_q);
 659:             csr_save_wb_o  = store_err_q | load_err_q;
 660:           end else begin : g_no_writeback_mepc_save
 661:             csr_save_id_o  = 1'b0;
 662:           end
 663: 
 664:           csr_save_cause_o = 1'b1;
 665: 
 666:           // Exception/fault prioritisation logic will have set exactly 1 X_prio signal
 667:           unique case (1'b1)
 668:             instr_fetch_err_prio: begin
 669:                 exc_cause_o = EXC_CAUSE_INSTR_ACCESS_FAULT;
 670:                 csr_mtval_o = instr_fetch_err_plus2_i ? (pc_id_i + 32'd2) : pc_id_i;
 671:             end
 672:             illegal_insn_prio: begin
 673:               exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
 674:               csr_mtval_o = instr_is_compressed_i ? {16'b0, instr_compressed_i} : instr_i;
 675:             end
 676:             ecall_insn_prio: begin
 677:               exc_cause_o = (priv_mode_i == PRIV_LVL_M) ? EXC_CAUSE_ECALL_MMODE :
 678:                                                           EXC_CAUSE_ECALL_UMODE;
 679:             end
 680:             ebrk_insn_prio: begin
 681:               if (debug_mode_q | ebreak_into_debug) begin
 682:                 /*
 683:                  * EBREAK in debug mode re-enters debug mode
 684:                  *
 685:                  * "The only exception is EBREAK. When that is executed in Debug
 686:                  * Mode, it halts the hart again but without updating dpc or
 687:                  * dcsr." [Debug Spec v0.13.2, p.39]
 688:                  */
 689: 
 690:                 /*
 691:                  * dcsr.ebreakm == 1:
 692:                  * "EBREAK instructions in M-mode enter Debug Mode."
 693:                  * [Debug Spec v0.13.2, p.42]
 694:                  */
 695:                 pc_set_o         = 1'b0;
 696:                 pc_set_spec_o    = 1'b0;
 697:                 csr_save_id_o    = 1'b0;
 698:                 csr_save_cause_o = 1'b0;
 699:                 ctrl_fsm_ns      = DBG_TAKEN_ID;
 700:                 flush_id         = 1'b0;
 701:               end else begin
 702:                 /*
 703:                  * "The EBREAK instruction is used by debuggers to cause control
 704:                  * to be transferred back to a debugging environment. It
 705:                  * generates a breakpoint exception and performs no other
 706:                  * operation. [...] ECALL and EBREAK cause the receiving
 707:                  * privilege mode's epc register to be set to the address of the
 708:                  * ECALL or EBREAK instruction itself, not the address of the
 709:                  * following instruction." [Privileged Spec v1.11, p.40]
 710:                  */
 711:                 exc_cause_o      = EXC_CAUSE_BREAKPOINT;
 712:               end
 713:             end
 714:             store_err_prio: begin
 715:               exc_cause_o = EXC_CAUSE_STORE_ACCESS_FAULT;
 716:               csr_mtval_o = lsu_addr_last_i;
 717:             end
 718:             load_err_prio: begin
 719:               exc_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT;
 720:               csr_mtval_o = lsu_addr_last_i;
 721:             end
 722:           endcase
 723:         end else begin
 724:           // special instructions and pipeline flushes
 725:           if (mret_insn) begin
 726:             pc_mux_o              = PC_ERET;
 727:             pc_set_o              = 1'b1;
 728:             pc_set_spec_o         = 1'b1;
 729:             csr_restore_mret_id_o = 1'b1;
 730:             if (nmi_mode_q) begin
 731:               nmi_mode_d          = 1'b0; // exit NMI mode
 732:             end
 733:           end else if (dret_insn) begin
 734:             pc_mux_o              = PC_DRET;
 735:             pc_set_o              = 1'b1;
 736:             pc_set_spec_o         = 1'b1;
 737:             debug_mode_d          = 1'b0;
 738:             csr_restore_dret_id_o = 1'b1;
 739:           end else if (wfi_insn) begin
 740:             ctrl_fsm_ns           = WAIT_SLEEP;
 741:           end else if (csr_pipe_flush && handle_irq) begin
 742:             // start handling IRQs when doing CSR-related pipeline flushes
 743:             ctrl_fsm_ns           = IRQ_TAKEN;
 744:           end
 745:         end // exc_req_q
 746: 
 747:         // Entering debug mode due to either single step or debug_req. Ensure
 748:         // registers are set for exception but then enter debug handler rather
 749:         // than exception handler [Debug Spec v0.13.2, p.44]
 750:         // Leave all other signals as is to ensure CSRs and PC get set as if
 751:         // core was entering exception handler, entry to debug mode will then
 752:         // see the appropriate state and setup dpc correctly.
 753:         if (enter_debug_mode) begin
 754:           ctrl_fsm_ns = DBG_TAKEN_IF;
 755:         end
 756:       end // FLUSH
 757: 
 758:       default: begin
 759:         instr_req_o = 1'b0;
 760:         ctrl_fsm_ns = RESET;
 761:       end
 762:     endcase
 763:   end
 764: 
 765:   assign flush_id_o = flush_id;
 766: 
 767:   // signal to CSR when in debug mode
 768:   assign debug_mode_o = debug_mode_q;
 769: 
 770:   // signal to CSR when in an NMI handler (for nested exception handling)
 771:   assign nmi_mode_o = nmi_mode_q;
 772: 
 773:   ///////////////////
 774:   // Stall control //
 775:   ///////////////////
 776: 
 777:   // If high current instruction cannot complete this cycle. Either because it needs more cycles to
 778:   // finish (stall_id_i) or because the writeback stage cannot accept it yet (stall_wb_i). If there
 779:   // is no writeback stage stall_wb_i is a constant 0.
 780:   assign stall = stall_id_i | stall_wb_i;
 781: 
 782:   // signal to IF stage that ID stage is ready for next instr
 783:   assign id_in_ready_o = ~stall & ~halt_if & ~retain_id;
 784: 
 785:   // kill instr in IF-ID pipeline reg that are done, or if a
 786:   // multicycle instr causes an exception for example
 787:   // retain_id is another kind of stall, where the instr_valid bit must remain
 788:   // set (unless flush_id is set also). It cannot be factored directly into
 789:   // stall as this causes a combinational loop.
 790:   assign instr_valid_clear_o = ~(stall | retain_id) | flush_id;
 791: 
 792:   // update registers
 793:   always_ff @(posedge clk_i or negedge rst_ni) begin : update_regs
 794:     if (!rst_ni) begin
 795:       ctrl_fsm_cs    <= RESET;
 796:       nmi_mode_q     <= 1'b0;
 797:       debug_mode_q   <= 1'b0;
 798:       load_err_q     <= 1'b0;
 799:       store_err_q    <= 1'b0;
 800:       exc_req_q      <= 1'b0;
 801:       illegal_insn_q <= 1'b0;
 802:     end else begin
 803:       ctrl_fsm_cs    <= ctrl_fsm_ns;
 804:       nmi_mode_q     <= nmi_mode_d;
 805:       debug_mode_q   <= debug_mode_d;
 806:       load_err_q     <= load_err_d;
 807:       store_err_q    <= store_err_d;
 808:       exc_req_q      <= exc_req_d;
 809:       illegal_insn_q <= illegal_insn_d;
 810:     end
 811:   end
 812: 
 813:   ////////////////
 814:   // Assertions //
 815:   ////////////////
 816: 
 817:   // Selectors must be known/valid.
 818:   `ASSERT(IbexCtrlStateValid, ctrl_fsm_cs inside {
 819:       RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH,
 820:       IRQ_TAKEN, DBG_TAKEN_IF, DBG_TAKEN_ID})
 821: 
 822:   // The speculative branch signal should be set whenever the actual branch signal is set
 823:   `ASSERT(IbexSpecImpliesSetPC, pc_set_o |-> pc_set_spec_o)
 824: 
 825: endmodule
 826: