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