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