../src/lowrisc_ibex_ibex_core_0.1/rtl/ibex_cs_registers.sv Cov: 90.9%

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