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