hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv Cov: 83.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: 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: