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: