hw/ip/rv_timer/rtl/rv_timer_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 rv_timer_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 rv_timer_reg_pkg::rv_timer_reg2hw_t reg2hw, // Write
16: input rv_timer_reg_pkg::rv_timer_hw2reg_t hw2reg, // Read
17:
18: // Config
19: input devmode_i // If 1, explicit error return for unmapped register access
20: );
21:
22: import rv_timer_reg_pkg::* ;
23:
24: localparam int AW = 9;
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 ctrl_qs;
73: logic ctrl_wd;
74: logic ctrl_we;
75: logic [11:0] cfg0_prescale_qs;
76: logic [11:0] cfg0_prescale_wd;
77: logic cfg0_prescale_we;
78: logic [7:0] cfg0_step_qs;
79: logic [7:0] cfg0_step_wd;
80: logic cfg0_step_we;
81: logic [31:0] timer_v_lower0_qs;
82: logic [31:0] timer_v_lower0_wd;
83: logic timer_v_lower0_we;
84: logic [31:0] timer_v_upper0_qs;
85: logic [31:0] timer_v_upper0_wd;
86: logic timer_v_upper0_we;
87: logic [31:0] compare_lower0_0_qs;
88: logic [31:0] compare_lower0_0_wd;
89: logic compare_lower0_0_we;
90: logic [31:0] compare_upper0_0_qs;
91: logic [31:0] compare_upper0_0_wd;
92: logic compare_upper0_0_we;
93: logic intr_enable0_qs;
94: logic intr_enable0_wd;
95: logic intr_enable0_we;
96: logic intr_state0_qs;
97: logic intr_state0_wd;
98: logic intr_state0_we;
99: logic intr_test0_wd;
100: logic intr_test0_we;
101:
102: // Register instances
103:
104: // Subregister 0 of Multireg ctrl
105: // R[ctrl]: V(False)
106:
107: prim_subreg #(
108: .DW (1),
109: .SWACCESS("RW"),
110: .RESVAL (1'h0)
111: ) u_ctrl (
112: .clk_i (clk_i ),
113: .rst_ni (rst_ni ),
114:
115: // from register interface
116: .we (ctrl_we),
117: .wd (ctrl_wd),
118:
119: // from internal hardware
120: .de (1'b0),
121: .d ('0 ),
122:
123: // to internal hardware
124: .qe (),
125: .q (reg2hw.ctrl[0].q ),
126:
127: // to register interface (read)
128: .qs (ctrl_qs)
129: );
130:
131:
132: // R[cfg0]: V(False)
133:
134: // F[prescale]: 11:0
135: prim_subreg #(
136: .DW (12),
137: .SWACCESS("RW"),
138: .RESVAL (12'h0)
139: ) u_cfg0_prescale (
140: .clk_i (clk_i ),
141: .rst_ni (rst_ni ),
142:
143: // from register interface
144: .we (cfg0_prescale_we),
145: .wd (cfg0_prescale_wd),
146:
147: // from internal hardware
148: .de (1'b0),
149: .d ('0 ),
150:
151: // to internal hardware
152: .qe (),
153: .q (reg2hw.cfg0.prescale.q ),
154:
155: // to register interface (read)
156: .qs (cfg0_prescale_qs)
157: );
158:
159:
160: // F[step]: 23:16
161: prim_subreg #(
162: .DW (8),
163: .SWACCESS("RW"),
164: .RESVAL (8'h1)
165: ) u_cfg0_step (
166: .clk_i (clk_i ),
167: .rst_ni (rst_ni ),
168:
169: // from register interface
170: .we (cfg0_step_we),
171: .wd (cfg0_step_wd),
172:
173: // from internal hardware
174: .de (1'b0),
175: .d ('0 ),
176:
177: // to internal hardware
178: .qe (),
179: .q (reg2hw.cfg0.step.q ),
180:
181: // to register interface (read)
182: .qs (cfg0_step_qs)
183: );
184:
185:
186: // R[timer_v_lower0]: V(False)
187:
188: prim_subreg #(
189: .DW (32),
190: .SWACCESS("RW"),
191: .RESVAL (32'h0)
192: ) u_timer_v_lower0 (
193: .clk_i (clk_i ),
194: .rst_ni (rst_ni ),
195:
196: // from register interface
197: .we (timer_v_lower0_we),
198: .wd (timer_v_lower0_wd),
199:
200: // from internal hardware
201: .de (hw2reg.timer_v_lower0.de),
202: .d (hw2reg.timer_v_lower0.d ),
203:
204: // to internal hardware
205: .qe (),
206: .q (reg2hw.timer_v_lower0.q ),
207:
208: // to register interface (read)
209: .qs (timer_v_lower0_qs)
210: );
211:
212:
213: // R[timer_v_upper0]: V(False)
214:
215: prim_subreg #(
216: .DW (32),
217: .SWACCESS("RW"),
218: .RESVAL (32'h0)
219: ) u_timer_v_upper0 (
220: .clk_i (clk_i ),
221: .rst_ni (rst_ni ),
222:
223: // from register interface
224: .we (timer_v_upper0_we),
225: .wd (timer_v_upper0_wd),
226:
227: // from internal hardware
228: .de (hw2reg.timer_v_upper0.de),
229: .d (hw2reg.timer_v_upper0.d ),
230:
231: // to internal hardware
232: .qe (),
233: .q (reg2hw.timer_v_upper0.q ),
234:
235: // to register interface (read)
236: .qs (timer_v_upper0_qs)
237: );
238:
239:
240: // R[compare_lower0_0]: V(False)
241:
242: prim_subreg #(
243: .DW (32),
244: .SWACCESS("RW"),
245: .RESVAL (32'hffffffff)
246: ) u_compare_lower0_0 (
247: .clk_i (clk_i ),
248: .rst_ni (rst_ni ),
249:
250: // from register interface
251: .we (compare_lower0_0_we),
252: .wd (compare_lower0_0_wd),
253:
254: // from internal hardware
255: .de (1'b0),
256: .d ('0 ),
257:
258: // to internal hardware
259: .qe (),
260: .q (reg2hw.compare_lower0_0.q ),
261:
262: // to register interface (read)
263: .qs (compare_lower0_0_qs)
264: );
265:
266:
267: // R[compare_upper0_0]: V(False)
268:
269: prim_subreg #(
270: .DW (32),
271: .SWACCESS("RW"),
272: .RESVAL (32'hffffffff)
273: ) u_compare_upper0_0 (
274: .clk_i (clk_i ),
275: .rst_ni (rst_ni ),
276:
277: // from register interface
278: .we (compare_upper0_0_we),
279: .wd (compare_upper0_0_wd),
280:
281: // from internal hardware
282: .de (1'b0),
283: .d ('0 ),
284:
285: // to internal hardware
286: .qe (),
287: .q (reg2hw.compare_upper0_0.q ),
288:
289: // to register interface (read)
290: .qs (compare_upper0_0_qs)
291: );
292:
293:
294:
295: // Subregister 0 of Multireg intr_enable0
296: // R[intr_enable0]: V(False)
297:
298: prim_subreg #(
299: .DW (1),
300: .SWACCESS("RW"),
301: .RESVAL (1'h0)
302: ) u_intr_enable0 (
303: .clk_i (clk_i ),
304: .rst_ni (rst_ni ),
305:
306: // from register interface
307: .we (intr_enable0_we),
308: .wd (intr_enable0_wd),
309:
310: // from internal hardware
311: .de (1'b0),
312: .d ('0 ),
313:
314: // to internal hardware
315: .qe (),
316: .q (reg2hw.intr_enable0[0].q ),
317:
318: // to register interface (read)
319: .qs (intr_enable0_qs)
320: );
321:
322:
323:
324: // Subregister 0 of Multireg intr_state0
325: // R[intr_state0]: V(False)
326:
327: prim_subreg #(
328: .DW (1),
329: .SWACCESS("W1C"),
330: .RESVAL (1'h0)
331: ) u_intr_state0 (
332: .clk_i (clk_i ),
333: .rst_ni (rst_ni ),
334:
335: // from register interface
336: .we (intr_state0_we),
337: .wd (intr_state0_wd),
338:
339: // from internal hardware
340: .de (hw2reg.intr_state0[0].de),
341: .d (hw2reg.intr_state0[0].d ),
342:
343: // to internal hardware
344: .qe (),
345: .q (reg2hw.intr_state0[0].q ),
346:
347: // to register interface (read)
348: .qs (intr_state0_qs)
349: );
350:
351:
352:
353: // Subregister 0 of Multireg intr_test0
354: // R[intr_test0]: V(True)
355:
356: prim_subreg_ext #(
357: .DW (1)
358: ) u_intr_test0 (
359: .re (1'b0),
360: .we (intr_test0_we),
361: .wd (intr_test0_wd),
362: .d ('0),
363: .qre (),
364: .qe (reg2hw.intr_test0[0].qe),
365: .q (reg2hw.intr_test0[0].q ),
366: .qs ()
367: );
368:
369:
370:
371:
372: logic [8:0] addr_hit;
373: always_comb begin
374: addr_hit = '0;
375: addr_hit[0] = (reg_addr == RV_TIMER_CTRL_OFFSET);
376: addr_hit[1] = (reg_addr == RV_TIMER_CFG0_OFFSET);
377: addr_hit[2] = (reg_addr == RV_TIMER_TIMER_V_LOWER0_OFFSET);
378: addr_hit[3] = (reg_addr == RV_TIMER_TIMER_V_UPPER0_OFFSET);
379: addr_hit[4] = (reg_addr == RV_TIMER_COMPARE_LOWER0_0_OFFSET);
380: addr_hit[5] = (reg_addr == RV_TIMER_COMPARE_UPPER0_0_OFFSET);
381: addr_hit[6] = (reg_addr == RV_TIMER_INTR_ENABLE0_OFFSET);
382: addr_hit[7] = (reg_addr == RV_TIMER_INTR_STATE0_OFFSET);
383: addr_hit[8] = (reg_addr == RV_TIMER_INTR_TEST0_OFFSET);
384: end
385:
386: assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
387:
388: // Check sub-word write is permitted
389: always_comb begin
390: wr_err = 1'b0;
391: if (addr_hit[0] && reg_we && (RV_TIMER_PERMIT[0] != (RV_TIMER_PERMIT[0] & reg_be))) wr_err = 1'b1 ;
392: if (addr_hit[1] && reg_we && (RV_TIMER_PERMIT[1] != (RV_TIMER_PERMIT[1] & reg_be))) wr_err = 1'b1 ;
393: if (addr_hit[2] && reg_we && (RV_TIMER_PERMIT[2] != (RV_TIMER_PERMIT[2] & reg_be))) wr_err = 1'b1 ;
394: if (addr_hit[3] && reg_we && (RV_TIMER_PERMIT[3] != (RV_TIMER_PERMIT[3] & reg_be))) wr_err = 1'b1 ;
395: if (addr_hit[4] && reg_we && (RV_TIMER_PERMIT[4] != (RV_TIMER_PERMIT[4] & reg_be))) wr_err = 1'b1 ;
396: if (addr_hit[5] && reg_we && (RV_TIMER_PERMIT[5] != (RV_TIMER_PERMIT[5] & reg_be))) wr_err = 1'b1 ;
397: if (addr_hit[6] && reg_we && (RV_TIMER_PERMIT[6] != (RV_TIMER_PERMIT[6] & reg_be))) wr_err = 1'b1 ;
398: if (addr_hit[7] && reg_we && (RV_TIMER_PERMIT[7] != (RV_TIMER_PERMIT[7] & reg_be))) wr_err = 1'b1 ;
399: if (addr_hit[8] && reg_we && (RV_TIMER_PERMIT[8] != (RV_TIMER_PERMIT[8] & reg_be))) wr_err = 1'b1 ;
400: end
401:
402: assign ctrl_we = addr_hit[0] & reg_we & ~wr_err;
403: assign ctrl_wd = reg_wdata[0];
404:
405: assign cfg0_prescale_we = addr_hit[1] & reg_we & ~wr_err;
406: assign cfg0_prescale_wd = reg_wdata[11:0];
407:
408: assign cfg0_step_we = addr_hit[1] & reg_we & ~wr_err;
409: assign cfg0_step_wd = reg_wdata[23:16];
410:
411: assign timer_v_lower0_we = addr_hit[2] & reg_we & ~wr_err;
412: assign timer_v_lower0_wd = reg_wdata[31:0];
413:
414: assign timer_v_upper0_we = addr_hit[3] & reg_we & ~wr_err;
415: assign timer_v_upper0_wd = reg_wdata[31:0];
416:
417: assign compare_lower0_0_we = addr_hit[4] & reg_we & ~wr_err;
418: assign compare_lower0_0_wd = reg_wdata[31:0];
419:
420: assign compare_upper0_0_we = addr_hit[5] & reg_we & ~wr_err;
421: assign compare_upper0_0_wd = reg_wdata[31:0];
422:
423: assign intr_enable0_we = addr_hit[6] & reg_we & ~wr_err;
424: assign intr_enable0_wd = reg_wdata[0];
425:
426: assign intr_state0_we = addr_hit[7] & reg_we & ~wr_err;
427: assign intr_state0_wd = reg_wdata[0];
428:
429: assign intr_test0_we = addr_hit[8] & reg_we & ~wr_err;
430: assign intr_test0_wd = reg_wdata[0];
431:
432: // Read data return
433: always_comb begin
434: reg_rdata_next = '0;
435: unique case (1'b1)
436: addr_hit[0]: begin
437: reg_rdata_next[0] = ctrl_qs;
438: end
439:
440: addr_hit[1]: begin
441: reg_rdata_next[11:0] = cfg0_prescale_qs;
442: reg_rdata_next[23:16] = cfg0_step_qs;
443: end
444:
445: addr_hit[2]: begin
446: reg_rdata_next[31:0] = timer_v_lower0_qs;
447: end
448:
449: addr_hit[3]: begin
450: reg_rdata_next[31:0] = timer_v_upper0_qs;
451: end
452:
453: addr_hit[4]: begin
454: reg_rdata_next[31:0] = compare_lower0_0_qs;
455: end
456:
457: addr_hit[5]: begin
458: reg_rdata_next[31:0] = compare_upper0_0_qs;
459: end
460:
461: addr_hit[6]: begin
462: reg_rdata_next[0] = intr_enable0_qs;
463: end
464:
465: addr_hit[7]: begin
466: reg_rdata_next[0] = intr_state0_qs;
467: end
468:
469: addr_hit[8]: begin
470: reg_rdata_next[0] = '0;
471: end
472:
473: default: begin
474: reg_rdata_next = '1;
475: end
476: endcase
477: end
478:
479: // Assertions for Register Interface
480: `ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni)
481: `ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni)
482:
483: `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o.d_valid, clk_i, !rst_ni)
484:
485: `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni)
486:
487: // this is formulated as an assumption such that the FPV testbenches do disprove this
488: // property by mistake
489: `ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.parity_en == 1'b0, clk_i, !rst_ni)
490:
491: endmodule
492: