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