hw/ip/nmi_gen/rtl/nmi_gen_reg_top.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // Register Top module auto-generated by `reggen`
6:
7: module nmi_gen_reg_top (
8: input clk_i,
9: input rst_ni,
10:
11: // Below Regster interface can be changed
12: input tlul_pkg::tl_h2d_t tl_i,
13: output tlul_pkg::tl_d2h_t tl_o,
14: // To HW
15: output nmi_gen_reg_pkg::nmi_gen_reg2hw_t reg2hw, // Write
16: input nmi_gen_reg_pkg::nmi_gen_hw2reg_t hw2reg, // Read
17:
18: // Config
19: input devmode_i // If 1, explicit error return for unmapped register access
20: );
21:
22: import nmi_gen_reg_pkg::* ;
23:
24: localparam int AW = 4;
25: localparam int DW = 32;
26: localparam int DBW = DW/8; // Byte Width
27:
28: // register signals
29: logic reg_we;
30: logic reg_re;
31: logic [AW-1:0] reg_addr;
32: logic [DW-1:0] reg_wdata;
33: logic [DBW-1:0] reg_be;
34: logic [DW-1:0] reg_rdata;
35: logic reg_error;
36:
37: logic addrmiss, wr_err;
38:
39: logic [DW-1:0] reg_rdata_next;
40:
41: tlul_pkg::tl_h2d_t tl_reg_h2d;
42: tlul_pkg::tl_d2h_t tl_reg_d2h;
43:
44: assign tl_reg_h2d = tl_i;
45: assign tl_o = tl_reg_d2h;
46:
47: tlul_adapter_reg #(
48: .RegAw(AW),
49: .RegDw(DW)
50: ) u_reg_if (
51: .clk_i,
52: .rst_ni,
53:
54: .tl_i (tl_reg_h2d),
55: .tl_o (tl_reg_d2h),
56:
57: .we_o (reg_we),
58: .re_o (reg_re),
59: .addr_o (reg_addr),
60: .wdata_o (reg_wdata),
61: .be_o (reg_be),
62: .rdata_i (reg_rdata),
63: .error_i (reg_error)
64: );
65:
66: assign reg_rdata = reg_rdata_next ;
67: assign reg_error = (devmode_i & addrmiss) | wr_err ;
68:
69: // Define SW related signals
70: // Format: __{wd|we|qs}
71: // or _{wd|we|qs} if field == 1 or 0
72: logic intr_state_esc0_qs;
73: logic intr_state_esc0_wd;
74: logic intr_state_esc0_we;
75: logic intr_state_esc1_qs;
76: logic intr_state_esc1_wd;
77: logic intr_state_esc1_we;
78: logic intr_state_esc2_qs;
79: logic intr_state_esc2_wd;
80: logic intr_state_esc2_we;
81: logic intr_state_esc3_qs;
82: logic intr_state_esc3_wd;
83: logic intr_state_esc3_we;
84: logic intr_enable_esc0_qs;
85: logic intr_enable_esc0_wd;
86: logic intr_enable_esc0_we;
87: logic intr_enable_esc1_qs;
88: logic intr_enable_esc1_wd;
89: logic intr_enable_esc1_we;
90: logic intr_enable_esc2_qs;
91: logic intr_enable_esc2_wd;
92: logic intr_enable_esc2_we;
93: logic intr_enable_esc3_qs;
94: logic intr_enable_esc3_wd;
95: logic intr_enable_esc3_we;
96: logic intr_test_esc0_wd;
97: logic intr_test_esc0_we;
98: logic intr_test_esc1_wd;
99: logic intr_test_esc1_we;
100: logic intr_test_esc2_wd;
101: logic intr_test_esc2_we;
102: logic intr_test_esc3_wd;
103: logic intr_test_esc3_we;
104:
105: // Register instances
106: // R[intr_state]: V(False)
107:
108: // F[esc0]: 0:0
109: prim_subreg #(
110: .DW (1),
111: .SWACCESS("W1C"),
112: .RESVAL (1'h0)
113: ) u_intr_state_esc0 (
114: .clk_i (clk_i ),
115: .rst_ni (rst_ni ),
116:
117: // from register interface
118: .we (intr_state_esc0_we),
119: .wd (intr_state_esc0_wd),
120:
121: // from internal hardware
122: .de (hw2reg.intr_state.esc0.de),
123: .d (hw2reg.intr_state.esc0.d ),
124:
125: // to internal hardware
126: .qe (),
127: .q (reg2hw.intr_state.esc0.q ),
128:
129: // to register interface (read)
130: .qs (intr_state_esc0_qs)
131: );
132:
133:
134: // F[esc1]: 1:1
135: prim_subreg #(
136: .DW (1),
137: .SWACCESS("W1C"),
138: .RESVAL (1'h0)
139: ) u_intr_state_esc1 (
140: .clk_i (clk_i ),
141: .rst_ni (rst_ni ),
142:
143: // from register interface
144: .we (intr_state_esc1_we),
145: .wd (intr_state_esc1_wd),
146:
147: // from internal hardware
148: .de (hw2reg.intr_state.esc1.de),
149: .d (hw2reg.intr_state.esc1.d ),
150:
151: // to internal hardware
152: .qe (),
153: .q (reg2hw.intr_state.esc1.q ),
154:
155: // to register interface (read)
156: .qs (intr_state_esc1_qs)
157: );
158:
159:
160: // F[esc2]: 2:2
161: prim_subreg #(
162: .DW (1),
163: .SWACCESS("W1C"),
164: .RESVAL (1'h0)
165: ) u_intr_state_esc2 (
166: .clk_i (clk_i ),
167: .rst_ni (rst_ni ),
168:
169: // from register interface
170: .we (intr_state_esc2_we),
171: .wd (intr_state_esc2_wd),
172:
173: // from internal hardware
174: .de (hw2reg.intr_state.esc2.de),
175: .d (hw2reg.intr_state.esc2.d ),
176:
177: // to internal hardware
178: .qe (),
179: .q (reg2hw.intr_state.esc2.q ),
180:
181: // to register interface (read)
182: .qs (intr_state_esc2_qs)
183: );
184:
185:
186: // F[esc3]: 3:3
187: prim_subreg #(
188: .DW (1),
189: .SWACCESS("W1C"),
190: .RESVAL (1'h0)
191: ) u_intr_state_esc3 (
192: .clk_i (clk_i ),
193: .rst_ni (rst_ni ),
194:
195: // from register interface
196: .we (intr_state_esc3_we),
197: .wd (intr_state_esc3_wd),
198:
199: // from internal hardware
200: .de (hw2reg.intr_state.esc3.de),
201: .d (hw2reg.intr_state.esc3.d ),
202:
203: // to internal hardware
204: .qe (),
205: .q (reg2hw.intr_state.esc3.q ),
206:
207: // to register interface (read)
208: .qs (intr_state_esc3_qs)
209: );
210:
211:
212: // R[intr_enable]: V(False)
213:
214: // F[esc0]: 0:0
215: prim_subreg #(
216: .DW (1),
217: .SWACCESS("RW"),
218: .RESVAL (1'h0)
219: ) u_intr_enable_esc0 (
220: .clk_i (clk_i ),
221: .rst_ni (rst_ni ),
222:
223: // from register interface
224: .we (intr_enable_esc0_we),
225: .wd (intr_enable_esc0_wd),
226:
227: // from internal hardware
228: .de (1'b0),
229: .d ('0 ),
230:
231: // to internal hardware
232: .qe (),
233: .q (reg2hw.intr_enable.esc0.q ),
234:
235: // to register interface (read)
236: .qs (intr_enable_esc0_qs)
237: );
238:
239:
240: // F[esc1]: 1:1
241: prim_subreg #(
242: .DW (1),
243: .SWACCESS("RW"),
244: .RESVAL (1'h0)
245: ) u_intr_enable_esc1 (
246: .clk_i (clk_i ),
247: .rst_ni (rst_ni ),
248:
249: // from register interface
250: .we (intr_enable_esc1_we),
251: .wd (intr_enable_esc1_wd),
252:
253: // from internal hardware
254: .de (1'b0),
255: .d ('0 ),
256:
257: // to internal hardware
258: .qe (),
259: .q (reg2hw.intr_enable.esc1.q ),
260:
261: // to register interface (read)
262: .qs (intr_enable_esc1_qs)
263: );
264:
265:
266: // F[esc2]: 2:2
267: prim_subreg #(
268: .DW (1),
269: .SWACCESS("RW"),
270: .RESVAL (1'h0)
271: ) u_intr_enable_esc2 (
272: .clk_i (clk_i ),
273: .rst_ni (rst_ni ),
274:
275: // from register interface
276: .we (intr_enable_esc2_we),
277: .wd (intr_enable_esc2_wd),
278:
279: // from internal hardware
280: .de (1'b0),
281: .d ('0 ),
282:
283: // to internal hardware
284: .qe (),
285: .q (reg2hw.intr_enable.esc2.q ),
286:
287: // to register interface (read)
288: .qs (intr_enable_esc2_qs)
289: );
290:
291:
292: // F[esc3]: 3:3
293: prim_subreg #(
294: .DW (1),
295: .SWACCESS("RW"),
296: .RESVAL (1'h0)
297: ) u_intr_enable_esc3 (
298: .clk_i (clk_i ),
299: .rst_ni (rst_ni ),
300:
301: // from register interface
302: .we (intr_enable_esc3_we),
303: .wd (intr_enable_esc3_wd),
304:
305: // from internal hardware
306: .de (1'b0),
307: .d ('0 ),
308:
309: // to internal hardware
310: .qe (),
311: .q (reg2hw.intr_enable.esc3.q ),
312:
313: // to register interface (read)
314: .qs (intr_enable_esc3_qs)
315: );
316:
317:
318: // R[intr_test]: V(True)
319:
320: // F[esc0]: 0:0
321: prim_subreg_ext #(
322: .DW (1)
323: ) u_intr_test_esc0 (
324: .re (1'b0),
325: .we (intr_test_esc0_we),
326: .wd (intr_test_esc0_wd),
327: .d ('0),
328: .qre (),
329: .qe (reg2hw.intr_test.esc0.qe),
330: .q (reg2hw.intr_test.esc0.q ),
331: .qs ()
332: );
333:
334:
335: // F[esc1]: 1:1
336: prim_subreg_ext #(
337: .DW (1)
338: ) u_intr_test_esc1 (
339: .re (1'b0),
340: .we (intr_test_esc1_we),
341: .wd (intr_test_esc1_wd),
342: .d ('0),
343: .qre (),
344: .qe (reg2hw.intr_test.esc1.qe),
345: .q (reg2hw.intr_test.esc1.q ),
346: .qs ()
347: );
348:
349:
350: // F[esc2]: 2:2
351: prim_subreg_ext #(
352: .DW (1)
353: ) u_intr_test_esc2 (
354: .re (1'b0),
355: .we (intr_test_esc2_we),
356: .wd (intr_test_esc2_wd),
357: .d ('0),
358: .qre (),
359: .qe (reg2hw.intr_test.esc2.qe),
360: .q (reg2hw.intr_test.esc2.q ),
361: .qs ()
362: );
363:
364:
365: // F[esc3]: 3:3
366: prim_subreg_ext #(
367: .DW (1)
368: ) u_intr_test_esc3 (
369: .re (1'b0),
370: .we (intr_test_esc3_we),
371: .wd (intr_test_esc3_wd),
372: .d ('0),
373: .qre (),
374: .qe (reg2hw.intr_test.esc3.qe),
375: .q (reg2hw.intr_test.esc3.q ),
376: .qs ()
377: );
378:
379:
380:
381:
382: logic [2:0] addr_hit;
383: always_comb begin
384: addr_hit = '0;
385: addr_hit[0] = (reg_addr == NMI_GEN_INTR_STATE_OFFSET);
386: addr_hit[1] = (reg_addr == NMI_GEN_INTR_ENABLE_OFFSET);
387: addr_hit[2] = (reg_addr == NMI_GEN_INTR_TEST_OFFSET);
388: end
389:
390: assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
391:
392: // Check sub-word write is permitted
393: always_comb begin
394: wr_err = 1'b0;
395: if (addr_hit[0] && reg_we && (NMI_GEN_PERMIT[0] != (NMI_GEN_PERMIT[0] & reg_be))) wr_err = 1'b1 ;
396: if (addr_hit[1] && reg_we && (NMI_GEN_PERMIT[1] != (NMI_GEN_PERMIT[1] & reg_be))) wr_err = 1'b1 ;
397: if (addr_hit[2] && reg_we && (NMI_GEN_PERMIT[2] != (NMI_GEN_PERMIT[2] & reg_be))) wr_err = 1'b1 ;
398: end
399:
400: assign intr_state_esc0_we = addr_hit[0] & reg_we & ~wr_err;
401: assign intr_state_esc0_wd = reg_wdata[0];
402:
403: assign intr_state_esc1_we = addr_hit[0] & reg_we & ~wr_err;
404: assign intr_state_esc1_wd = reg_wdata[1];
405:
406: assign intr_state_esc2_we = addr_hit[0] & reg_we & ~wr_err;
407: assign intr_state_esc2_wd = reg_wdata[2];
408:
409: assign intr_state_esc3_we = addr_hit[0] & reg_we & ~wr_err;
410: assign intr_state_esc3_wd = reg_wdata[3];
411:
412: assign intr_enable_esc0_we = addr_hit[1] & reg_we & ~wr_err;
413: assign intr_enable_esc0_wd = reg_wdata[0];
414:
415: assign intr_enable_esc1_we = addr_hit[1] & reg_we & ~wr_err;
416: assign intr_enable_esc1_wd = reg_wdata[1];
417:
418: assign intr_enable_esc2_we = addr_hit[1] & reg_we & ~wr_err;
419: assign intr_enable_esc2_wd = reg_wdata[2];
420:
421: assign intr_enable_esc3_we = addr_hit[1] & reg_we & ~wr_err;
422: assign intr_enable_esc3_wd = reg_wdata[3];
423:
424: assign intr_test_esc0_we = addr_hit[2] & reg_we & ~wr_err;
425: assign intr_test_esc0_wd = reg_wdata[0];
426:
427: assign intr_test_esc1_we = addr_hit[2] & reg_we & ~wr_err;
428: assign intr_test_esc1_wd = reg_wdata[1];
429:
430: assign intr_test_esc2_we = addr_hit[2] & reg_we & ~wr_err;
431: assign intr_test_esc2_wd = reg_wdata[2];
432:
433: assign intr_test_esc3_we = addr_hit[2] & reg_we & ~wr_err;
434: assign intr_test_esc3_wd = reg_wdata[3];
435:
436: // Read data return
437: always_comb begin
438: reg_rdata_next = '0;
439: unique case (1'b1)
440: addr_hit[0]: begin
441: reg_rdata_next[0] = intr_state_esc0_qs;
442: reg_rdata_next[1] = intr_state_esc1_qs;
443: reg_rdata_next[2] = intr_state_esc2_qs;
444: reg_rdata_next[3] = intr_state_esc3_qs;
445: end
446:
447: addr_hit[1]: begin
448: reg_rdata_next[0] = intr_enable_esc0_qs;
449: reg_rdata_next[1] = intr_enable_esc1_qs;
450: reg_rdata_next[2] = intr_enable_esc2_qs;
451: reg_rdata_next[3] = intr_enable_esc3_qs;
452: end
453:
454: addr_hit[2]: begin
455: reg_rdata_next[0] = '0;
456: reg_rdata_next[1] = '0;
457: reg_rdata_next[2] = '0;
458: reg_rdata_next[3] = '0;
459: end
460:
461: default: begin
462: reg_rdata_next = '1;
463: end
464: endcase
465: end
466:
467: // Assertions for Register Interface
468: `ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni)
469: `ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni)
470:
471: `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o.d_valid, clk_i, !rst_ni)
472:
473: `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni)
474:
475: // this is formulated as an assumption such that the FPV testbenches do disprove this
476: // property by mistake
477: `ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.parity_en == 1'b0, clk_i, !rst_ni)
478:
479: endmodule
480: