../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: