hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv Cov: 83%

   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:  * Control and Status Registers
   8:  *
   9:  * Control and Status Registers (CSRs) following the RISC-V Privileged
  10:  * Specification, draft version 1.11
  11:  */
  12: module ibex_cs_registers #(
  13:     parameter bit          DbgTriggerEn     = 0,
  14:     parameter int unsigned MHPMCounterNum   = 8,
  15:     parameter int unsigned MHPMCounterWidth = 40,
  16:     parameter bit          PMPEnable        = 0,
  17:     parameter int unsigned PMPGranularity   = 0,
  18:     parameter int unsigned PMPNumRegions    = 4,
  19:     parameter bit          RV32E            = 0,
  20:     parameter bit          RV32M            = 0
  21: ) (
  22:     // Clock and Reset
  23:     input  logic                 clk_i,
  24:     input  logic                 rst_ni,
  25: 
  26:     // Hart ID
  27:     input  logic [31:0]          hart_id_i,
  28: 
  29:     // Privilege mode
  30:     output ibex_pkg::priv_lvl_e  priv_mode_id_o,
  31:     output ibex_pkg::priv_lvl_e  priv_mode_if_o,
  32:     output ibex_pkg::priv_lvl_e  priv_mode_lsu_o,
  33:     output logic                 csr_mstatus_tw_o,
  34: 
  35:     // mtvec
  36:     output logic [31:0]          csr_mtvec_o,
  37:     input  logic                 csr_mtvec_init_i,
  38:     input  logic [31:0]          boot_addr_i,
  39: 
  40:     // Interface to registers (SRAM like)
  41:     input  logic                 csr_access_i,
  42:     input  ibex_pkg::csr_num_e   csr_addr_i,
  43:     input  logic [31:0]          csr_wdata_i,
  44:     input  ibex_pkg::csr_op_e    csr_op_i,
  45:     output logic [31:0]          csr_rdata_o,
  46: 
  47:     // interrupts
  48:     input  logic                 irq_software_i,
  49:     input  logic                 irq_timer_i,
  50:     input  logic                 irq_external_i,
  51:     input  logic [14:0]          irq_fast_i,
  52:     output logic                 irq_pending_o,          // interupt request pending
  53:     input  logic                 nmi_mode_i,
  54:     output logic                 csr_msip_o,             // software interrupt pending
  55:     output logic                 csr_mtip_o,             // timer interrupt pending
  56:     output logic                 csr_meip_o,             // external interrupt pending
  57:     output logic [14:0]          csr_mfip_o,             // fast interrupt pending
  58:     output logic                 csr_mstatus_mie_o,
  59:     output logic [31:0]          csr_mepc_o,
  60: 
  61:     // PMP
  62:     output ibex_pkg::pmp_cfg_t   csr_pmp_cfg_o  [PMPNumRegions],
  63:     output logic [33:0]          csr_pmp_addr_o [PMPNumRegions],
  64: 
  65:     // debug
  66:     input  logic                 debug_mode_i,
  67:     input  ibex_pkg::dbg_cause_e debug_cause_i,
  68:     input  logic                 debug_csr_save_i,
  69:     output logic [31:0]          csr_depc_o,
  70:     output logic                 debug_single_step_o,
  71:     output logic                 debug_ebreakm_o,
  72:     output logic                 debug_ebreaku_o,
  73:     output logic                 trigger_match_o,
  74: 
  75:     input  logic [31:0]          pc_if_i,
  76:     input  logic [31:0]          pc_id_i,
  77: 
  78:     input  logic                 csr_save_if_i,
  79:     input  logic                 csr_save_id_i,
  80:     input  logic                 csr_restore_mret_i,
  81:     input  logic                 csr_restore_dret_i,
  82:     input  logic                 csr_save_cause_i,
  83:     input  ibex_pkg::exc_cause_e csr_mcause_i,
  84:     input  logic [31:0]          csr_mtval_i,
  85:     output logic                 illegal_csr_insn_o,     // access to non-existent CSR,
  86:                                                          // with wrong priviledge level, or
  87:                                                          // missing write permissions
  88:     input  logic                 instr_new_id_i,         // ID stage sees a new instr
  89: 
  90:     // Performance Counters
  91:     input  logic                 instr_ret_i,            // instr retired in ID/EX stage
  92:     input  logic                 instr_ret_compressed_i, // compressed instr retired
  93:     input  logic                 imiss_i,                // instr fetch
  94:     input  logic                 pc_set_i,               // PC was set to a new value
  95:     input  logic                 jump_i,                 // jump instr seen (j, jr, jal, jalr)
  96:     input  logic                 branch_i,               // branch instr seen (bf, bnf)
  97:     input  logic                 branch_taken_i,         // branch was taken
  98:     input  logic                 mem_load_i,             // load from memory in this cycle
  99:     input  logic                 mem_store_i,            // store to memory in this cycle
 100:     input  logic                 lsu_busy_i
 101: );
 102: 
 103:   import ibex_pkg::*;
 104: 
 105:   // misa
 106:   localparam logic [1:0] MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32
 107:   localparam logic [31:0] MISA_VALUE =
 108:       (0          <<  0)  // A - Atomic Instructions extension
 109:     | (1          <<  2)  // C - Compressed extension
 110:     | (0          <<  3)  // D - Double precision floating-point extension
 111:     | (32'(RV32E) <<  4)  // E - RV32E base ISA
 112:     | (0          <<  5)  // F - Single precision floating-point extension
 113:     | (1          <<  8)  // I - RV32I/64I/128I base ISA
 114:     | (32'(RV32M) << 12)  // M - Integer Multiply/Divide extension
 115:     | (0          << 13)  // N - User level interrupts supported
 116:     | (0          << 18)  // S - Supervisor mode implemented
 117:     | (1          << 20)  // U - User mode implemented
 118:     | (0          << 23)  // X - Non-standard extensions present
 119:     | (32'(MXL)   << 30); // M-XLEN
 120: 
 121:   typedef struct packed {
 122:     logic      mie;
 123:     logic      mpie;
 124:     priv_lvl_e mpp;
 125:     logic      mprv;
 126:     logic      tw;
 127:   } Status_t;
 128: 
 129:   typedef struct packed {
 130:     logic      mpie;
 131:     priv_lvl_e mpp;
 132:   } StatusStk_t;
 133: 
 134:   // struct for mip/mie CSRs
 135:   typedef struct packed {
 136:     logic        irq_software;
 137:     logic        irq_timer;
 138:     logic        irq_external;
 139:     logic [14:0] irq_fast; // 15 fast interrupts,
 140:                            // one interrupt is reserved for NMI (not visible through mip/mie)
 141:   } Interrupts_t;
 142: 
 143:   typedef struct packed {
 144:       x_debug_ver_e xdebugver;
 145:       logic [11:0]  zero2;
 146:       logic         ebreakm;
 147:       logic         zero1;
 148:       logic         ebreaks;
 149:       logic         ebreaku;
 150:       logic         stepie;
 151:       logic         stopcount;
 152:       logic         stoptime;
 153:       dbg_cause_e   cause;
 154:       logic         zero0;
 155:       logic         mprven;
 156:       logic         nmip;
 157:       logic         step;
 158:       priv_lvl_e    prv;
 159:   } Dcsr_t;
 160: 
 161:   // Interrupt and exception control signals
 162:   logic [31:0] exception_pc;
 163: 
 164:   // CSRs
 165:   priv_lvl_e   priv_lvl_q, priv_lvl_d;
 166:   Status_t     mstatus_q, mstatus_d;
 167:   Interrupts_t mie_q, mie_d;
 168:   logic [31:0] mscratch_q, mscratch_d;
 169:   logic [31:0] mepc_q, mepc_d;
 170:   logic  [5:0] mcause_q, mcause_d;
 171:   logic [31:0] mtval_q, mtval_d;
 172:   logic [31:0] mtvec_q, mtvec_d;
 173:   Interrupts_t mip;
 174:   Dcsr_t       dcsr_q, dcsr_d;
 175:   logic [31:0] depc_q, depc_d;
 176:   logic [31:0] dscratch0_q, dscratch0_d;
 177:   logic [31:0] dscratch1_q, dscratch1_d;
 178: 
 179:   // CSRs for recoverable NMIs
 180:   // NOTE: these CSRS are nonstandard, see https://github.com/riscv/riscv-isa-manual/issues/261
 181:   StatusStk_t  mstack_q, mstack_d;
 182:   logic [31:0] mstack_epc_q, mstack_epc_d;
 183:   logic  [5:0] mstack_cause_q, mstack_cause_d;
 184: 
 185:   // PMP Signals
 186:   logic [31:0]                 pmp_addr_rdata  [PMP_MAX_REGIONS];
 187:   logic [PMP_CFG_W-1:0]        pmp_cfg_rdata   [PMP_MAX_REGIONS];
 188: 
 189:   // Hardware performance monitor signals
 190:   logic [31:0]                 mcountinhibit;
 191:   // Only have mcountinhibit flops for counters that actually exist
 192:   logic [MHPMCounterNum+3-1:0] mcountinhibit_d, mcountinhibit_q;
 193:   logic                        mcountinhibit_we;
 194: 
 195:   logic [63:0] mhpmcounter_d [32];
 196:   // mhpmcounter flops are elaborated below providing only the precise number that is required based
 197:   // on MHPMCounterNum/MHPMCounterWidth. This signal connects to the Q output of these flops
 198:   // where they exist and is otherwise 0.
 199:   logic [63:0] mhpmcounter [32];
 200:   logic [31:0] mhpmcounter_we;
 201:   logic [31:0] mhpmcounterh_we;
 202:   logic [31:0] mhpmcounter_incr;
 203:   logic [31:0] mhpmevent [32];
 204:   logic  [4:0] mhpmcounter_idx;
 205: 
 206:   // Debug / trigger registers
 207:   logic [31:0] tselect_rdata;
 208:   logic [31:0] tmatch_control_rdata;
 209:   logic [31:0] tmatch_value_rdata;
 210: 
 211:   // CSR update logic
 212:   logic [31:0] csr_wdata_int;
 213:   logic [31:0] csr_rdata_int;
 214:   logic        csr_we_int;
 215:   logic        csr_wreq;
 216: 
 217:   // Access violation signals
 218:   logic        illegal_csr;
 219:   logic        illegal_csr_priv;
 220:   logic        illegal_csr_write;
 221: 
 222:   logic [7:0]  unused_boot_addr;
 223:   logic [2:0]  unused_csr_addr;
 224: 
 225:   assign unused_boot_addr = boot_addr_i[7:0];
 226: 
 227:   /////////////
 228:   // CSR reg //
 229:   /////////////
 230: 
 231:   logic [$bits(csr_num_e)-1:0] csr_addr;
 232:   assign csr_addr           = {csr_addr_i};
 233:   assign unused_csr_addr    = csr_addr[7:5];
 234:   assign mhpmcounter_idx    = csr_addr[4:0];
 235: 
 236:   // See RISC-V Privileged Specification, version 1.11, Section 2.1
 237:   assign illegal_csr_priv   = (csr_addr[9:8] > {priv_lvl_q});
 238:   assign illegal_csr_write  = (csr_addr[11:10] == 2'b11) && csr_wreq;
 239:   assign illegal_csr_insn_o = csr_access_i & (illegal_csr | illegal_csr_write | illegal_csr_priv);
 240: 
 241:   // mip CSR is purely combinational - must be able to re-enable the clock upon WFI
 242:   assign mip.irq_software = irq_software_i & mie_q.irq_software;
 243:   assign mip.irq_timer    = irq_timer_i    & mie_q.irq_timer;
 244:   assign mip.irq_external = irq_external_i & mie_q.irq_external;
 245:   assign mip.irq_fast     = irq_fast_i     & mie_q.irq_fast;
 246: 
 247:   // read logic
 248:   always_comb begin
 249:     csr_rdata_int = '0;
 250:     illegal_csr   = 1'b0;
 251: 
 252:     unique case (csr_addr_i)
 253:       // mhartid: unique hardware thread id
 254:       CSR_MHARTID: csr_rdata_int = hart_id_i;
 255: 
 256:       // mstatus: always M-mode, contains IE bit
 257:       CSR_MSTATUS: begin
 258:         csr_rdata_int                                                   = '0;
 259:         csr_rdata_int[CSR_MSTATUS_MIE_BIT]                              = mstatus_q.mie;
 260:         csr_rdata_int[CSR_MSTATUS_MPIE_BIT]                             = mstatus_q.mpie;
 261:         csr_rdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW] = mstatus_q.mpp;
 262:         csr_rdata_int[CSR_MSTATUS_MPRV_BIT]                             = mstatus_q.mprv;
 263:         csr_rdata_int[CSR_MSTATUS_TW_BIT]                               = mstatus_q.tw;
 264:       end
 265: 
 266:       // misa
 267:       CSR_MISA: csr_rdata_int = MISA_VALUE;
 268: 
 269:       // interrupt enable
 270:       CSR_MIE: begin
 271:         csr_rdata_int                                     = '0;
 272:         csr_rdata_int[CSR_MSIX_BIT]                       = mie_q.irq_software;
 273:         csr_rdata_int[CSR_MTIX_BIT]                       = mie_q.irq_timer;
 274:         csr_rdata_int[CSR_MEIX_BIT]                       = mie_q.irq_external;
 275:         csr_rdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = mie_q.irq_fast;
 276:       end
 277: 
 278:       CSR_MSCRATCH: csr_rdata_int = mscratch_q;
 279: 
 280:       // mtvec: trap-vector base address
 281:       CSR_MTVEC: csr_rdata_int = mtvec_q;
 282: 
 283:       // mepc: exception program counter
 284:       CSR_MEPC: csr_rdata_int = mepc_q;
 285: 
 286:       // mcause: exception cause
 287:       CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]};
 288: 
 289:       // mtval: trap value
 290:       CSR_MTVAL: csr_rdata_int = mtval_q;
 291: 
 292:       // mip: interrupt pending
 293:       CSR_MIP: begin
 294:         csr_rdata_int                                     = '0;
 295:         csr_rdata_int[CSR_MSIX_BIT]                       = mip.irq_software;
 296:         csr_rdata_int[CSR_MTIX_BIT]                       = mip.irq_timer;
 297:         csr_rdata_int[CSR_MEIX_BIT]                       = mip.irq_external;
 298:         csr_rdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = mip.irq_fast;
 299:       end
 300: 
 301:       // PMP registers
 302:       CSR_PMPCFG0:   csr_rdata_int = {pmp_cfg_rdata[3],  pmp_cfg_rdata[2],
 303:                                       pmp_cfg_rdata[1],  pmp_cfg_rdata[0]};
 304:       CSR_PMPCFG1:   csr_rdata_int = {pmp_cfg_rdata[7],  pmp_cfg_rdata[6],
 305:                                       pmp_cfg_rdata[5],  pmp_cfg_rdata[4]};
 306:       CSR_PMPCFG2:   csr_rdata_int = {pmp_cfg_rdata[11], pmp_cfg_rdata[10],
 307:                                       pmp_cfg_rdata[9],  pmp_cfg_rdata[8]};
 308:       CSR_PMPCFG3:   csr_rdata_int = {pmp_cfg_rdata[15], pmp_cfg_rdata[14],
 309:                                       pmp_cfg_rdata[13], pmp_cfg_rdata[12]};
 310:       CSR_PMPADDR0:  csr_rdata_int = pmp_addr_rdata[0];
 311:       CSR_PMPADDR1:  csr_rdata_int = pmp_addr_rdata[1];
 312:       CSR_PMPADDR2:  csr_rdata_int = pmp_addr_rdata[2];
 313:       CSR_PMPADDR3:  csr_rdata_int = pmp_addr_rdata[3];
 314:       CSR_PMPADDR4:  csr_rdata_int = pmp_addr_rdata[4];
 315:       CSR_PMPADDR5:  csr_rdata_int = pmp_addr_rdata[5];
 316:       CSR_PMPADDR6:  csr_rdata_int = pmp_addr_rdata[6];
 317:       CSR_PMPADDR7:  csr_rdata_int = pmp_addr_rdata[7];
 318:       CSR_PMPADDR8:  csr_rdata_int = pmp_addr_rdata[8];
 319:       CSR_PMPADDR9:  csr_rdata_int = pmp_addr_rdata[9];
 320:       CSR_PMPADDR10: csr_rdata_int = pmp_addr_rdata[10];
 321:       CSR_PMPADDR11: csr_rdata_int = pmp_addr_rdata[11];
 322:       CSR_PMPADDR12: csr_rdata_int = pmp_addr_rdata[12];
 323:       CSR_PMPADDR13: csr_rdata_int = pmp_addr_rdata[13];
 324:       CSR_PMPADDR14: csr_rdata_int = pmp_addr_rdata[14];
 325:       CSR_PMPADDR15: csr_rdata_int = pmp_addr_rdata[15];
 326: 
 327:       CSR_DCSR: begin
 328:         csr_rdata_int = dcsr_q;
 329:         illegal_csr = ~debug_mode_i;
 330:       end
 331:       CSR_DPC: begin
 332:         csr_rdata_int = depc_q;
 333:         illegal_csr = ~debug_mode_i;
 334:       end
 335:       CSR_DSCRATCH0: begin
 336:         csr_rdata_int = dscratch0_q;
 337:         illegal_csr = ~debug_mode_i;
 338:       end
 339:       CSR_DSCRATCH1: begin
 340:         csr_rdata_int = dscratch1_q;
 341:         illegal_csr = ~debug_mode_i;
 342:       end
 343: 
 344:       // machine counter/timers
 345:       CSR_MCOUNTINHIBIT: csr_rdata_int = mcountinhibit;
 346:       CSR_MHPMEVENT3,
 347:       CSR_MHPMEVENT4,  CSR_MHPMEVENT5,  CSR_MHPMEVENT6,  CSR_MHPMEVENT7,
 348:       CSR_MHPMEVENT8,  CSR_MHPMEVENT9,  CSR_MHPMEVENT10, CSR_MHPMEVENT11,
 349:       CSR_MHPMEVENT12, CSR_MHPMEVENT13, CSR_MHPMEVENT14, CSR_MHPMEVENT15,
 350:       CSR_MHPMEVENT16, CSR_MHPMEVENT17, CSR_MHPMEVENT18, CSR_MHPMEVENT19,
 351:       CSR_MHPMEVENT20, CSR_MHPMEVENT21, CSR_MHPMEVENT22, CSR_MHPMEVENT23,
 352:       CSR_MHPMEVENT24, CSR_MHPMEVENT25, CSR_MHPMEVENT26, CSR_MHPMEVENT27,
 353:       CSR_MHPMEVENT28, CSR_MHPMEVENT29, CSR_MHPMEVENT30, CSR_MHPMEVENT31: begin
 354:         csr_rdata_int = mhpmevent[mhpmcounter_idx];
 355:       end
 356: 
 357:       CSR_MCYCLE,
 358:       CSR_MINSTRET,
 359:       CSR_MHPMCOUNTER3,
 360:       CSR_MHPMCOUNTER4,  CSR_MHPMCOUNTER5,  CSR_MHPMCOUNTER6,  CSR_MHPMCOUNTER7,
 361:       CSR_MHPMCOUNTER8,  CSR_MHPMCOUNTER9,  CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11,
 362:       CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15,
 363:       CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19,
 364:       CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23,
 365:       CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27,
 366:       CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31: begin
 367:         csr_rdata_int = mhpmcounter[mhpmcounter_idx][31:0];
 368:       end
 369: 
 370:       CSR_MCYCLEH,
 371:       CSR_MINSTRETH,
 372:       CSR_MHPMCOUNTER3H,
 373:       CSR_MHPMCOUNTER4H,  CSR_MHPMCOUNTER5H,  CSR_MHPMCOUNTER6H,  CSR_MHPMCOUNTER7H,
 374:       CSR_MHPMCOUNTER8H,  CSR_MHPMCOUNTER9H,  CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H,
 375:       CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H,
 376:       CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H,
 377:       CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H,
 378:       CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H,
 379:       CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H: begin
 380:         csr_rdata_int = mhpmcounter[mhpmcounter_idx][63:32];
 381:       end
 382: 
 383:       // Debug triggers
 384:       CSR_TSELECT: begin
 385:         csr_rdata_int = tselect_rdata;
 386:         illegal_csr   = ~DbgTriggerEn;
 387:       end
 388:       CSR_TDATA1: begin
 389:         csr_rdata_int = tmatch_control_rdata;
 390:         illegal_csr   = ~DbgTriggerEn;
 391:       end
 392:       CSR_TDATA2: begin
 393:         csr_rdata_int = tmatch_value_rdata;
 394:         illegal_csr   = ~DbgTriggerEn;
 395:       end
 396:       CSR_TDATA3: begin
 397:         csr_rdata_int = '0;
 398:         illegal_csr   = ~DbgTriggerEn;
 399:       end
 400:       CSR_MCONTEXT: begin
 401:         csr_rdata_int = '0;
 402:         illegal_csr   = ~DbgTriggerEn;
 403:       end
 404:       CSR_SCONTEXT: begin
 405:         csr_rdata_int = '0;
 406:         illegal_csr   = ~DbgTriggerEn;
 407:       end
 408: 
 409:       default: begin
 410:         illegal_csr = 1'b1;
 411:       end
 412:     endcase
 413:   end
 414: 
 415:   // write logic
 416:   always_comb begin
 417:     exception_pc = pc_id_i;
 418: 
 419:     priv_lvl_d   = priv_lvl_q;
 420:     mstatus_d    = mstatus_q;
 421:     mie_d        = mie_q;
 422:     mscratch_d   = mscratch_q;
 423:     mepc_d       = mepc_q;
 424:     mcause_d     = mcause_q;
 425:     mtval_d      = mtval_q;
 426:     mtvec_d      = csr_mtvec_init_i ? {boot_addr_i[31:8], 6'b0, 2'b01} : mtvec_q;
 427:     dcsr_d       = dcsr_q;
 428:     depc_d       = depc_q;
 429:     dscratch0_d  = dscratch0_q;
 430:     dscratch1_d  = dscratch1_q;
 431: 
 432:     mstack_d       = mstack_q;
 433:     mstack_epc_d   = mstack_epc_q;
 434:     mstack_cause_d = mstack_cause_q;
 435: 
 436:     mcountinhibit_we = 1'b0;
 437:     mhpmcounter_we   = '0;
 438:     mhpmcounterh_we  = '0;
 439: 
 440:     if (csr_we_int) begin
 441:       unique case (csr_addr_i)
 442:         // mstatus: IE bit
 443:         CSR_MSTATUS: begin
 444:           mstatus_d = '{
 445:               mie:  csr_wdata_int[CSR_MSTATUS_MIE_BIT],
 446:               mpie: csr_wdata_int[CSR_MSTATUS_MPIE_BIT],
 447:               mpp:  priv_lvl_e'(csr_wdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW]),
 448:               mprv: csr_wdata_int[CSR_MSTATUS_MPRV_BIT],
 449:               tw:   csr_wdata_int[CSR_MSTATUS_TW_BIT]
 450:           };
 451:           // Convert illegal values to M-mode
 452:           if ((mstatus_d.mpp != PRIV_LVL_M) && (mstatus_d.mpp != PRIV_LVL_U)) begin
 453:             mstatus_d.mpp = PRIV_LVL_M;
 454:           end
 455:         end
 456: 
 457:         // interrupt enable
 458:         CSR_MIE: begin
 459:           mie_d.irq_software = csr_wdata_int[CSR_MSIX_BIT];
 460:           mie_d.irq_timer    = csr_wdata_int[CSR_MTIX_BIT];
 461:           mie_d.irq_external = csr_wdata_int[CSR_MEIX_BIT];
 462:           mie_d.irq_fast     = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW];
 463:         end
 464: 
 465:         CSR_MSCRATCH: mscratch_d = csr_wdata_int;
 466: 
 467:         // mepc: exception program counter
 468:         CSR_MEPC: mepc_d = {csr_wdata_int[31:1], 1'b0};
 469: 
 470:         // mcause
 471:         CSR_MCAUSE: mcause_d = {csr_wdata_int[31], csr_wdata_int[4:0]};
 472: 
 473:         // mtval: trap value
 474:         CSR_MTVAL: mtval_d = csr_wdata_int;
 475: 
 476:         // mtvec
 477:         // mtvec.MODE set to vectored
 478:         // mtvec.BASE must be 256-byte aligned
 479:         CSR_MTVEC: mtvec_d = {csr_wdata_int[31:8], 6'b0, 2'b01};
 480: 
 481:         CSR_DCSR: begin
 482:           dcsr_d = csr_wdata_int;
 483:           dcsr_d.xdebugver = XDEBUGVER_STD;
 484:           // Change to PRIV_LVL_M if software writes an unsupported value
 485:           if ((dcsr_d.prv != PRIV_LVL_M) && (dcsr_d.prv != PRIV_LVL_U)) begin
 486:             dcsr_d.prv = PRIV_LVL_M;
 487:           end
 488: 
 489:           // currently not supported:
 490:           dcsr_d.nmip = 1'b0;
 491:           dcsr_d.mprven = 1'b0;
 492:           dcsr_d.stopcount = 1'b0;
 493:           dcsr_d.stoptime = 1'b0;
 494: 
 495:           // forced to be zero
 496:           dcsr_d.zero0 = 1'b0;
 497:           dcsr_d.zero1 = 1'b0;
 498:           dcsr_d.zero2 = 12'h0;
 499:         end
 500: 
 501:         // dpc: debug program counter
 502:         CSR_DPC: depc_d = {csr_wdata_int[31:1], 1'b0};
 503: 
 504:         CSR_DSCRATCH0: dscratch0_d = csr_wdata_int;
 505:         CSR_DSCRATCH1: dscratch1_d = csr_wdata_int;
 506: 
 507:         // machine counter/timers
 508:         CSR_MCOUNTINHIBIT: mcountinhibit_we = 1'b1;
 509: 
 510:         CSR_MCYCLE,
 511:         CSR_MINSTRET,
 512:         CSR_MHPMCOUNTER3,
 513:         CSR_MHPMCOUNTER4,  CSR_MHPMCOUNTER5,  CSR_MHPMCOUNTER6,  CSR_MHPMCOUNTER7,
 514:         CSR_MHPMCOUNTER8,  CSR_MHPMCOUNTER9,  CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11,
 515:         CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15,
 516:         CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19,
 517:         CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23,
 518:         CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27,
 519:         CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31: begin
 520:           mhpmcounter_we[mhpmcounter_idx] = 1'b1;
 521:         end
 522: 
 523:         CSR_MCYCLEH,
 524:         CSR_MINSTRETH,
 525:         CSR_MHPMCOUNTER3H,
 526:         CSR_MHPMCOUNTER4H,  CSR_MHPMCOUNTER5H,  CSR_MHPMCOUNTER6H,  CSR_MHPMCOUNTER7H,
 527:         CSR_MHPMCOUNTER8H,  CSR_MHPMCOUNTER9H,  CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H,
 528:         CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H,
 529:         CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H,
 530:         CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H,
 531:         CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H,
 532:         CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H: begin
 533:           mhpmcounterh_we[mhpmcounter_idx] = 1'b1;
 534:         end
 535: 
 536:         default:;
 537:       endcase
 538:     end
 539: 
 540:     // exception controller gets priority over other writes
 541:     unique case (1'b1)
 542: 
 543:       csr_save_cause_i: begin
 544:         unique case (1'b1)
 545:           csr_save_if_i: begin
 546:             exception_pc = pc_if_i;
 547:           end
 548:           csr_save_id_i: begin
 549:             exception_pc = pc_id_i;
 550:           end
 551:           default:;
 552:         endcase
 553: 
 554:         // Any exception, including debug mode, causes a switch to M-mode
 555:         priv_lvl_d = PRIV_LVL_M;
 556: 
 557:         if (debug_csr_save_i) begin
 558:           // all interrupts are masked
 559:           // do not update cause, epc, tval, epc and status
 560:           dcsr_d.prv   = priv_lvl_q;
 561:           dcsr_d.cause = debug_cause_i;
 562:           depc_d       = exception_pc;
 563:         end else if (!debug_mode_i) begin
 564:           // In debug mode, "exceptions do not update any registers. That
 565:           // includes cause, epc, tval, dpc and mstatus." [Debug Spec v0.13.2, p.39]
 566:           mtval_d        = csr_mtval_i;
 567:           mstatus_d.mie  = 1'b0; // disable interrupts
 568:           // save current status
 569:           mstatus_d.mpie = mstatus_q.mie;
 570:           mstatus_d.mpp  = priv_lvl_q;
 571:           mepc_d         = exception_pc;
 572:           mcause_d       = {csr_mcause_i};
 573:           // save previous status for recoverable NMI
 574:           mstack_d.mpie  = mstatus_q.mpie;
 575:           mstack_d.mpp   = mstatus_q.mpp;
 576:           mstack_epc_d   = mepc_q;
 577:           mstack_cause_d = mcause_q;
 578:         end
 579:       end // csr_save_cause_i
 580: 
 581:       csr_restore_dret_i: begin // DRET
 582:         priv_lvl_d = dcsr_q.prv;
 583:       end // csr_restore_dret_i
 584: 
 585:       csr_restore_mret_i: begin // MRET
 586:         priv_lvl_d     = mstatus_q.mpp;
 587:         mstatus_d.mie  = mstatus_q.mpie; // re-enable interrupts
 588: 
 589:         if (nmi_mode_i) begin
 590:           // when returning from an NMI restore state from mstack CSR
 591:           mstatus_d.mpie = mstack_q.mpie;
 592:           mstatus_d.mpp  = mstack_q.mpp;
 593:           mepc_d         = mstack_epc_q;
 594:           mcause_d       = mstack_cause_q;
 595:         end else begin
 596:           // otherwise just set mstatus.MPIE/MPP
 597:           // See RISC-V Privileged Specification, version 1.11, Section 3.1.6.1
 598:           mstatus_d.mpie = 1'b1;
 599:           mstatus_d.mpp  = PRIV_LVL_U;
 600:         end
 601:       end // csr_restore_mret_i
 602: 
 603:       default:;
 604:     endcase
 605:   end
 606: 
 607:   // CSR operation logic
 608:   always_comb begin
 609:     csr_wreq = 1'b1;
 610: 
 611:     unique case (csr_op_i)
 612:       CSR_OP_WRITE: csr_wdata_int =  csr_wdata_i;
 613:       CSR_OP_SET:   csr_wdata_int =  csr_wdata_i | csr_rdata_o;
 614:       CSR_OP_CLEAR: csr_wdata_int = ~csr_wdata_i & csr_rdata_o;
 615:       CSR_OP_READ: begin
 616:         csr_wdata_int = csr_wdata_i;
 617:         csr_wreq      = 1'b0;
 618:       end
 619:       default: begin
 620:         csr_wdata_int = csr_wdata_i;
 621:         csr_wreq      = 1'b0;
 622:       end
 623:     endcase
 624:   end
 625: 
 626:   // only write CSRs during one clock cycle
 627:   assign csr_we_int  = csr_wreq & ~illegal_csr_insn_o & instr_new_id_i;
 628: 
 629:   assign csr_rdata_o = csr_rdata_int;
 630: 
 631:   // directly output some registers
 632:   assign csr_msip_o  = mip.irq_software;
 633:   assign csr_mtip_o  = mip.irq_timer;
 634:   assign csr_meip_o  = mip.irq_external;
 635:   assign csr_mfip_o  = mip.irq_fast;
 636: 
 637:   assign csr_mepc_o  = mepc_q;
 638:   assign csr_depc_o  = depc_q;
 639:   assign csr_mtvec_o = mtvec_q;
 640: 
 641:   assign csr_mstatus_mie_o   = mstatus_q.mie;
 642:   assign csr_mstatus_tw_o    = mstatus_q.tw;
 643:   assign debug_single_step_o = dcsr_q.step;
 644:   assign debug_ebreakm_o     = dcsr_q.ebreakm;
 645:   assign debug_ebreaku_o     = dcsr_q.ebreaku;
 646: 
 647:   assign irq_pending_o = csr_msip_o | csr_mtip_o | csr_meip_o | (|csr_mfip_o);
 648: 
 649:   // actual registers
 650:   always_ff @(posedge clk_i or negedge rst_ni) begin
 651:     if (!rst_ni) begin
 652:       priv_lvl_q     <= PRIV_LVL_M;
 653:       mstatus_q      <= '{
 654:           mie:  1'b0,
 655:           mpie: 1'b1,
 656:           mpp:  PRIV_LVL_U,
 657:           mprv: 1'b0,
 658:           tw:   1'b0
 659:       };
 660:       mie_q          <= '0;
 661:       mscratch_q     <= '0;
 662:       mepc_q         <= '0;
 663:       mcause_q       <= '0;
 664:       mtval_q        <= '0;
 665:       mtvec_q        <= 32'b01;
 666:       dcsr_q         <= '{
 667:           xdebugver: XDEBUGVER_STD,
 668:           cause:     DBG_CAUSE_NONE, // 3'h0
 669:           prv:       PRIV_LVL_M,
 670:           default:   '0
 671:       };
 672:       depc_q         <= '0;
 673:       dscratch0_q    <= '0;
 674:       dscratch1_q    <= '0;
 675: 
 676:       mstack_q       <= '{
 677:           mpie: 1'b1,
 678:           mpp:  PRIV_LVL_U
 679:       };
 680:       mstack_epc_q   <= '0;
 681:       mstack_cause_q <= '0;
 682: 
 683:     end else begin
 684:       // update CSRs
 685:       priv_lvl_q     <= priv_lvl_d;
 686:       mstatus_q      <= mstatus_d;
 687:       mie_q          <= mie_d;
 688:       mscratch_q     <= mscratch_d;
 689:       mepc_q         <= mepc_d;
 690:       mcause_q       <= mcause_d;
 691:       mtval_q        <= mtval_d;
 692:       mtvec_q        <= mtvec_d;
 693:       dcsr_q         <= dcsr_d;
 694:       depc_q         <= depc_d;
 695:       dscratch0_q    <= dscratch0_d;
 696:       dscratch1_q    <= dscratch1_d;
 697: 
 698:       mstack_q       <= mstack_d;
 699:       mstack_epc_q   <= mstack_epc_d;
 700:       mstack_cause_q <= mstack_cause_d;
 701: 
 702:     end
 703:   end
 704: 
 705:   // Send current priv level to the decoder
 706:   assign priv_mode_id_o = priv_lvl_q;
 707:   // New instruction fetches need to account for updates to priv_lvl_q this cycle
 708:   assign priv_mode_if_o = priv_lvl_d;
 709:   // Load/store instructions must factor in MPRV for PMP checking
 710:   assign priv_mode_lsu_o = mstatus_q.mprv ? mstatus_q.mpp : priv_lvl_q;
 711: 
 712:   // -----------------
 713:   // PMP registers
 714:   // -----------------
 715: 
 716:   if (PMPEnable) begin : g_pmp_registers
 717:     pmp_cfg_t                    pmp_cfg         [PMPNumRegions];
 718:     pmp_cfg_t                    pmp_cfg_wdata   [PMPNumRegions];
 719:     logic [31:0]                 pmp_addr        [PMPNumRegions];
 720:     logic [PMPNumRegions-1:0]    pmp_cfg_we;
 721:     logic [PMPNumRegions-1:0]    pmp_addr_we;
 722: 
 723:     // Expanded / qualified register read data
 724:     for (genvar i = 0; i < PMP_MAX_REGIONS; i++) begin : g_exp_rd_data
 725:       if (i < PMPNumRegions) begin : g_implemented_regions
 726:         // Add in zero padding for reserved fields
 727:         assign pmp_cfg_rdata[i] = {pmp_cfg[i].lock, 2'b00, pmp_cfg[i].mode,
 728:                                    pmp_cfg[i].exec, pmp_cfg[i].write, pmp_cfg[i].read};
 729: 
 730:         // Address field read data depends on the current programmed mode and the granularity
 731:         // See RISC-V Privileged Specification, version 1.11, Section 3.6.1
 732:         if (PMPGranularity == 0) begin : g_pmp_g0
 733:           // If G == 0, read data is unmodified
 734:           assign pmp_addr_rdata[i] = pmp_addr[i];
 735: 
 736:         end else if (PMPGranularity == 1) begin : g_pmp_g1
 737:           // If G == 1, bit [G-1] reads as zero in TOR or OFF mode
 738:           always_comb begin
 739:             pmp_addr_rdata[i] = pmp_addr[i];
 740:             if ((pmp_cfg[i].mode == PMP_MODE_OFF) || (pmp_cfg[i].mode == PMP_MODE_TOR)) begin
 741:               pmp_addr_rdata[i][PMPGranularity-1:0] = '0;
 742:             end
 743:           end
 744: 
 745:         end else begin : g_pmp_g2
 746:           // For G >= 2, bits are masked to one or zero depending on the mode
 747:           always_comb begin
 748:             pmp_addr_rdata[i] = pmp_addr[i];
 749:             if ((pmp_cfg[i].mode == PMP_MODE_OFF) || (pmp_cfg[i].mode == PMP_MODE_TOR)) begin
 750:               // In TOR or OFF mode, bits [G-1:0] must read as zero
 751:               pmp_addr_rdata[i][PMPGranularity-1:0] = '0;
 752:             end else if (pmp_cfg[i].mode == PMP_MODE_NAPOT) begin
 753:               // In NAPOT mode, bits [G-2:0] must read as one
 754:               pmp_addr_rdata[i][PMPGranularity-2:0] = '1;
 755:             end
 756:           end
 757:         end
 758: 
 759:       end else begin : g_other_regions
 760:         // Non-implemented regions read as zero
 761:         assign pmp_cfg_rdata[i]  = '0;
 762:         assign pmp_addr_rdata[i] = '0;
 763:       end
 764:     end
 765: 
 766:     // Write data calculation
 767:     for (genvar i = 0; i < PMPNumRegions; i++) begin : g_pmp_csrs
 768:       // -------------------------
 769:       // Instantiate cfg registers
 770:       // -------------------------
 771:       assign pmp_cfg_we[i] = csr_we_int & ~pmp_cfg[i].lock &
 772:                              (csr_addr == (CSR_OFF_PMP_CFG + (i[11:0] >> 2)));
 773: 
 774:       // Select the correct WDATA (each CSR contains 4 CFG fields, each with 2 RES bits)
 775:       assign pmp_cfg_wdata[i].lock  = csr_wdata_int[(i%4)*PMP_CFG_W+7];
 776:       // NA4 mode is not selectable when G > 0, mode is treated as OFF
 777:       always_comb begin
 778:         unique case (csr_wdata_int[(i%4)*PMP_CFG_W+3+:2])
 779:           2'b00   : pmp_cfg_wdata[i].mode = PMP_MODE_OFF;
 780:           2'b01   : pmp_cfg_wdata[i].mode = PMP_MODE_TOR;
 781:           2'b10   : pmp_cfg_wdata[i].mode = (PMPGranularity == 0) ? PMP_MODE_NA4:
 782:                                                                     PMP_MODE_OFF;
 783:           2'b11   : pmp_cfg_wdata[i].mode = PMP_MODE_NAPOT;
 784:           default : pmp_cfg_wdata[i].mode = PMP_MODE_OFF;
 785:         endcase
 786:       end
 787:       assign pmp_cfg_wdata[i].exec  = csr_wdata_int[(i%4)*PMP_CFG_W+2];
 788:       // W = 1, R = 0 is a reserved combination. For now, we force W to 0 if R == 0
 789:       assign pmp_cfg_wdata[i].write = &csr_wdata_int[(i%4)*PMP_CFG_W+:2];
 790:       assign pmp_cfg_wdata[i].read  = csr_wdata_int[(i%4)*PMP_CFG_W];
 791: 
 792:       always_ff @(posedge clk_i or negedge rst_ni) begin
 793:         if (!rst_ni) begin
 794:           pmp_cfg[i] <= pmp_cfg_t'('b0);
 795:         end else if (pmp_cfg_we[i]) begin
 796:           pmp_cfg[i] <= pmp_cfg_wdata[i];
 797:         end
 798:       end
 799: 
 800:       // --------------------------
 801:       // Instantiate addr registers
 802:       // --------------------------
 803:       if (i < PMPNumRegions - 1) begin : g_lower
 804:         assign pmp_addr_we[i] = csr_we_int & ~pmp_cfg[i].lock &
 805:                                 (pmp_cfg[i+1].mode != PMP_MODE_TOR) &
 806:                                 (csr_addr == (CSR_OFF_PMP_ADDR + i[11:0]));
 807:       end else begin : g_upper
 808:         assign pmp_addr_we[i] = csr_we_int & ~pmp_cfg[i].lock &
 809:                                 (csr_addr == (CSR_OFF_PMP_ADDR + i[11:0]));
 810:       end
 811: 
 812:       always_ff @(posedge clk_i or negedge rst_ni) begin
 813:         if (!rst_ni) begin
 814:           pmp_addr[i] <= 'b0;
 815:         end else if (pmp_addr_we[i]) begin
 816:           pmp_addr[i] <= csr_wdata_int;
 817:         end
 818:       end
 819:       assign csr_pmp_cfg_o[i]  = pmp_cfg[i];
 820:       assign csr_pmp_addr_o[i] = {pmp_addr[i],2'b00};
 821:     end
 822: 
 823:   end else begin : g_no_pmp_tieoffs
 824:     // Generate tieoffs when PMP is not configured
 825:     for (genvar i = 0; i < PMP_MAX_REGIONS; i++) begin : g_rdata
 826:       assign pmp_addr_rdata[i] = '0;
 827:       assign pmp_cfg_rdata[i]  = '0;
 828:     end
 829:     for (genvar i = 0; i < PMPNumRegions; i++) begin : g_outputs
 830:       assign csr_pmp_cfg_o[i]  = pmp_cfg_t'(1'b0);
 831:       assign csr_pmp_addr_o[i] = '0;
 832:     end
 833:   end
 834: 
 835:   //////////////////////////
 836:   //  Performance monitor //
 837:   //////////////////////////
 838: 
 839:   // update enable signals
 840:   always_comb begin : mcountinhibit_update
 841:     if (mcountinhibit_we == 1'b1) begin
 842:       mcountinhibit_d = {csr_wdata_int[MHPMCounterNum+2:2], 1'b0, csr_wdata_int[0]}; // bit 1 must always be 0
 843:     end else begin
 844:       mcountinhibit_d = mcountinhibit_q;
 845:     end
 846:   end
 847: 
 848:   // event selection (hardwired) & control
 849:   always_comb begin : gen_mhpmcounter_incr
 850: 
 851:     // When adding or altering performance counter meanings and default
 852:     // mappings please update dv/verilator/pcount/cpp/ibex_pcounts.cc
 853:     // appropriately.
 854:     //
 855:     // active counters
 856:     mhpmcounter_incr[0]  = 1'b1;                   // mcycle
 857:     mhpmcounter_incr[1]  = 1'b0;                   // reserved
 858:     mhpmcounter_incr[2]  = instr_ret_i;            // minstret
 859:     mhpmcounter_incr[3]  = lsu_busy_i;             // cycles waiting for data memory
 860:     mhpmcounter_incr[4]  = imiss_i & ~pc_set_i;    // cycles waiting for instr fetches
 861:                                                    // excl. jump and branch set cycles
 862:     mhpmcounter_incr[5]  = mem_load_i;             // num of loads
 863:     mhpmcounter_incr[6]  = mem_store_i;            // num of stores
 864:     mhpmcounter_incr[7]  = jump_i;                 // num of jumps (unconditional)
 865:     mhpmcounter_incr[8]  = branch_i;               // num of branches (conditional)
 866:     mhpmcounter_incr[9]  = branch_taken_i;         // num of taken branches (conditional)
 867:     mhpmcounter_incr[10] = instr_ret_compressed_i; // num of compressed instr
 868: 
 869:     // inactive counters
 870:     for (int unsigned i=3+MHPMCounterNum; i<32; i++) begin : gen_mhpmcounter_incr_inactive
 871:       mhpmcounter_incr[i] = 1'b0;
 872:     end
 873:   end
 874: 
 875:   // event selector (hardwired, 0 means no event)
 876:   always_comb begin : gen_mhpmevent
 877: 
 878:     // activate all
 879:     for (int i=0; i<32; i++) begin : gen_mhpmevent_active
 880:       mhpmevent[i]    =   '0;
 881:       mhpmevent[i][i] = 1'b1;
 882:     end
 883: 
 884:     // deactivate
 885:     mhpmevent[1] = '0; // not existing, reserved
 886:     for (int unsigned i=3+MHPMCounterNum; i<32; i++) begin : gen_mhpmevent_inactive
 887:       mhpmevent[i] = '0;
 888:     end
 889:   end
 890: 
 891:   // update
 892:   always_comb begin : mhpmcounter_update
 893:     mhpmcounter_d = mhpmcounter;
 894: 
 895:     for (int i=0; i<32; i++) begin : gen_mhpmcounter_update
 896: 
 897:       // increment
 898:       if (mhpmcounter_incr[i] & ~mcountinhibit[i]) begin
 899:         mhpmcounter_d[i] = mhpmcounter[i] + 64'h1;
 900:       end
 901: 
 902:       // write
 903:       if (mhpmcounter_we[i]) begin
 904:         mhpmcounter_d[i][31: 0] = csr_wdata_int;
 905:       end else if (mhpmcounterh_we[i]) begin
 906:         mhpmcounter_d[i][63:32] = csr_wdata_int;
 907:       end
 908:     end
 909:   end
 910: 
 911:   // Performance monitor registers
 912:   // Only elaborate flops that are needed from the given MHPMCounterWidth and MHPMCounterNum
 913:   // parameters
 914:   for (genvar i = 0; i < 32; i++) begin : g_mhpmcounter
 915:     // First 3 counters (cycle, time, instret) must always be elaborated
 916:     if (i < 3 + MHPMCounterNum) begin : g_mhpmcounter_exists
 917:       // First 3 counters must be 64-bit the rest have parameterisable width
 918:       localparam int unsigned IMHPMCounterWidth = i < 3 ? 64 : MHPMCounterWidth;
 919: 
 920:       logic [IMHPMCounterWidth-1:0] mhpmcounter_q;
 921: 
 922:       always @(posedge clk_i or negedge rst_ni) begin
 923:         if(~rst_ni) begin
 924:           mhpmcounter_q <= '0;
 925:         end else begin
 926:           mhpmcounter_q <= mhpmcounter_d[i][IMHPMCounterWidth-1:0];
 927:         end
 928:       end
 929: 
 930:       if (IMHPMCounterWidth < 64) begin : g_mhpmcounter_narrow
 931:         assign mhpmcounter[i][IMHPMCounterWidth-1:0] = mhpmcounter_q;
 932:         assign mhpmcounter[i][63:IMHPMCounterWidth]  = '0;
 933:       end else begin : g_mhpmcounter_full
 934:         assign mhpmcounter[i] = mhpmcounter_q;
 935:       end
 936:     end else begin : g_no_mhpmcounter
 937:       assign mhpmcounter[i] = '0;
 938:     end
 939:   end
 940: 
 941:   if(MHPMCounterNum < 29) begin : g_mcountinhibit_reduced
 942:     assign mcountinhibit = {{29-MHPMCounterNum{1'b1}}, mcountinhibit_q};
 943:   end else begin : g_mcountinhibit_full
 944:     assign mcountinhibit = mcountinhibit_q;
 945:   end
 946: 
 947:   always_ff @(posedge clk_i or negedge rst_ni) begin
 948:     if (!rst_ni) begin
 949:       mcountinhibit_q <= '0;
 950:     end else begin
 951:       mcountinhibit_q <= mcountinhibit_d;
 952:     end
 953:   end
 954: 
 955:   /////////////////////////////
 956:   // Debug trigger registers //
 957:   /////////////////////////////
 958: 
 959:   if (DbgTriggerEn) begin : gen_trigger_regs
 960:     // Register values
 961:     logic        tmatch_control_d, tmatch_control_q;
 962:     logic [31:0] tmatch_value_d, tmatch_value_q;
 963:     // Write enables
 964:     logic tmatch_control_we;
 965:     logic tmatch_value_we;
 966: 
 967:     // Write select
 968:     assign tmatch_control_we = csr_we_int & debug_mode_i & (csr_addr_i == CSR_TDATA1);
 969:     assign tmatch_value_we   = csr_we_int & debug_mode_i & (csr_addr_i == CSR_TDATA2);
 970: 
 971:     // tmatch_control is enabled when the execute bit is set
 972:     assign tmatch_control_d = tmatch_control_we ? csr_wdata_int[2] :
 973:                                                   tmatch_control_q;
 974:     // tmatch_value has its own clock gate
 975:     assign tmatch_value_d   = csr_wdata_int[31:0];
 976: 
 977:     // Registers
 978:     always_ff @(posedge clk_i or negedge rst_ni) begin
 979:       if (!rst_ni) begin
 980:         tmatch_control_q <= 'b0;
 981:       end else begin
 982:         tmatch_control_q <= tmatch_control_d;
 983:       end
 984:     end
 985: 
 986:     always_ff @(posedge clk_i or negedge rst_ni) begin
 987:       if (!rst_ni) begin
 988:         tmatch_value_q <= 'b0;
 989:       end else if (tmatch_value_we) begin
 990:         tmatch_value_q <= tmatch_value_d;
 991:       end
 992:     end
 993: 
 994:     // Assign read data
 995:     // TSELECT - only one supported
 996:     assign tselect_rdata = 'b0;
 997:     // TDATA0 - only support simple address matching
 998:     assign tmatch_control_rdata = {4'h2,              // type    : address/data match
 999:                                    1'b1,              // dmode   : access from D mode only
1000:                                    6'h00,             // maskmax : exact match only
1001:                                    1'b0,              // hit     : not supported
1002:                                    1'b0,              // select  : address match only
1003:                                    1'b0,              // timing  : match before execution
1004:                                    2'b00,             // sizelo  : match any access
1005:                                    4'h1,              // action  : enter debug mode
1006:                                    1'b0,              // chain   : not supported
1007:                                    4'h0,              // match   : simple match
1008:                                    1'b1,              // m       : match in m-mode
1009:                                    1'b0,              // 0       : zero
1010:                                    1'b0,              // s       : not supported
1011:                                    1'b1,              // u       : match in u-mode
1012:                                    tmatch_control_q,  // execute : match instruction address
1013:                                    1'b0,              // store   : not supported
1014:                                    1'b0};             // load    : not supported
1015:     // TDATA1 - address match value only
1016:     assign tmatch_value_rdata = tmatch_value_q;
1017: 
1018:     // Breakpoint matching
1019:     // We match against the next address, as the breakpoint must be taken before execution
1020:     assign trigger_match_o = tmatch_control_q & (pc_if_i[31:0] == tmatch_value_q[31:0]);
1021: 
1022:   end else begin : gen_no_trigger_regs
1023:     assign tselect_rdata        = 'b0;
1024:     assign tmatch_control_rdata = 'b0;
1025:     assign tmatch_value_rdata   = 'b0;
1026:     assign trigger_match_o      = 'b0;
1027:   end
1028: 
1029:   ////////////////
1030:   // Assertions //
1031:   ////////////////
1032: 
1033:   // Selectors must be known/valid.
1034:   `ASSERT(IbexCsrOpValid, csr_op_i inside {
1035:       CSR_OP_READ,
1036:       CSR_OP_WRITE,
1037:       CSR_OP_SET,
1038:       CSR_OP_CLEAR
1039:       }, clk_i, !rst_ni)
1040:   `ASSERT_KNOWN(IbexCsrWdataIntKnown, csr_wdata_int, clk_i, !rst_ni)
1041: 
1042: endmodule
1043: