Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here5
  • SystemVerilog Language Foundations28
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive39
  • SystemVerilog Assertions — Interview-Critical Deep Dive41
  • Functional Coverage in SystemVerilog25
  • Testbench Architecture in SystemVerilog24
  • Advanced Language & Integration26
  • Senior & Interview Preparation23
    • Senior Debug Playbook
    • Reviewing Verification Code
    • Verification Strategy: Spec to Sign-Off
    • SystemVerilog Interview Q&A Bank
    • Capstone: Verify a Parameterized FIFO
      • Spec Analysis and Verification Plan
      • Interface and Harness
      • Generator, Driver and Environment
      • Monitor, Scoreboard and Model
      • Assertions and Coverage
      • Regression, Holes and Sign-off
  • Principal-Level Verification34
Loading lesson

←Capstone: Verify a Parameterized FIFO
  1. Topics
  2. SystemVerilog
  3. Senior & Interview Preparation
  4. Capstone: Verify a Parameterized FIFO
  5. Regression, Holes and Sign-off
On this page

    Part 8 of 9, lesson 23 of 23Part 8 of 9/Senior & Interview Prep/Lesson 23 of 23Intermediate

    Regression, Holes and Sign-off

    Regression tiers, a planted bug caught by a bound assertion, hole analysis with written dispositions, and the sign-off evidence bundle.

    Regression tests and tiers

    One environment, many tests. Each test is a thin recipe over scenarios, knobs and length, mapping straight back to plan rows.

    Diagram
    TEST VARIANTS
    
      Test            │ Recipe                              │ Plan rows
      ────────────────┼─────────────────────────────────────┼───────────────
      smoke           │ 20 pushes, 20 pops, fixed seed      │ F-01,04 (sanity)
      stress_mixed    │ 2000 txns SCN_MIXED, max_gap 0-1    │ F-01,07, wrap
      burst_drain     │ fill→full, hold, drain→empty, x10   │ F-02,03,05,06,10
      corner_simul    │ park at full / at empty, OP_BOTH    │ F-07,08
      reset_storm     │ random resets mid-traffic, restart  │ F-09
      error_probe     │ in_valid at full, out_ready at      │ F-05,06
                      │ empty held for windows              │
      param_min       │ rebuild DEPTH=2, run all the above  │ F-11
      param_w1        │ rebuild WIDTH=1, smoke + stress     │ F-11
    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    // snippet: a test is a recipe over the generator and scoreboard above
    task test_burst_drain(generator #(8) gen, fifo_sb #(8) sb);
      repeat (10) begin
        gen.run_scenario(SCN_BURST_FILL, 24);    // past DEPTH: park at full
        gen.run_scenario(SCN_BACKPRESSURE, 10);  // hold full under pressure
        gen.run_scenario(SCN_DRAIN, 24);         // past DEPTH: park at empty
      end
    endtask
    Diagram
    REGRESSION TIERS
    
      per-checkin   smoke + 1 seed of stress_mixed            ~2 min
      nightly       all tests x 10 seeds x {DEPTH=16}         ~1 hr
                    + param_min, param_w1 x 3 seeds
      weekly soak   stress_mixed x 200 seeds, reset_storm     coverage
                    x 50 seeds, merge ALL coverage            closure run
    
      bookkeeping per run: seed, test, RTL version, pass/fail, ucdb path
      → failures reproducible with one command; coverage merge automatic

    A hole that finds a bug

    Every uncovered bin gets a written disposition after the soak merge. Three findings are typical, and the first one runs below.

    The bench below runs that finding. It instantiates two FIFOs on the same stimulus: a clean one, and one with the planted bug. The corner test fills both to full and then offers pushes while popping, which is exactly the hole. The bound checker counts violations in an action block instead of stopping, so one run reports both.

    fifo.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    module fifo #(parameter int WIDTH = 8, parameter int DEPTH = 16, parameter bit BUG = 1'b0) (
      input  logic             clk, rst_n,
      input  logic             in_valid,
      output logic             in_ready,
      input  logic [WIDTH-1:0] in_data,
      output logic             out_valid,
      input  logic             out_ready,
      output logic [WIDTH-1:0] out_data,
      output logic             full, empty
    );
      localparam int AW = $clog2(DEPTH);
      logic [WIDTH-1:0] mem [DEPTH];
      logic [AW-1:0] wr_ptr, rd_ptr;
      int count;
      assign full      = (count == DEPTH);
      assign empty     = (count == 0);
      assign in_ready  = BUG ? (!full || out_ready) : !full;   // BUG: a pop at full opens in_ready
      assign out_valid = !empty;
      assign out_data  = mem[rd_ptr];
      wire push = in_valid && in_ready;
      wire pop  = out_valid && out_ready;
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin wr_ptr <= '0; rd_ptr <= '0; count <= 0; end
        else begin
          if (push) begin mem[wr_ptr] <= in_data; wr_ptr <= wr_ptr + 1'b1; end
          if (pop)  rd_ptr <= rd_ptr + 1'b1;
          count <= count + (push && !pop) - (pop && !push);
        end
    endmodule
    
    module fifo_sva #(parameter int DEPTH = 16) (
      input logic clk, rst_n, in_valid, in_ready, out_valid, out_ready, full, empty
    );
      int viol_push_full = 0, viol_ready_def = 0;
      wire push = in_valid && in_ready;
      default clocking cb @(posedge clk); endclocking
      default disable iff (!rst_n);
      a_ready_def:    assert property (in_ready == !full)  else viol_ready_def++;
      a_no_push_full: assert property (full |-> !push)     else viol_push_full++;
    endmodule
    
    bind fifo fifo_sva #(.DEPTH(DEPTH)) u_sva (.*);
    

    Read the summary line. The clean FIFO has zero violations. The bugged FIFO fires a_no_push_full repeatedly, yet the scoreboard sees no data errors: a push accepted at full while a pop frees the same slot loses nothing. Only the assertion notices it, which is why the plan pairs F-08 with a_no_push_full and a corner test. The fix is in_ready = !full, and rerunning the clean FIFO is the regression.

    PacketFIFO step: change W to 9 and D to 4 and rerun. The bench is unchanged because the packet format lives in the testbench. Then list which plan rows need a packet-level check on top: byte order inside a packet, last on the check byte only, and the XOR check byte.

    1. cp_offer_at_full at 0 hits: the generator never offered a push during a pop while parked at full. Fix: corner_simul parks at full, then issues OP_BOTH bursts. Re-run covered it, and a_no_push_full exposed a real RTL bug: in_ready rose at full whenever out_ready was high, so a push was accepted at full, against Q-003.

    2. cp_count.almost_full thin in 200 seeds: mixed traffic crosses the boundary too fast. Fix: SCN_BACKPRESSURE weight raised in stress_mixed. Now hundreds of hits.

    3. param_w1 by reset_storm uncovered nothing new after 3 seeds. Waiver: WIDTH 1 has no width-dependent reset logic. Documented, approved, closed.

    Sign-off

    Sign-off is an evidence bundle, not a feeling. Plan closure, merged coverage, assertion health, scoreboard volume and a converged bug rate each contribute one line.

    Diagram
    SIGN-OFF SUMMARY — fifo v1.2 (example of the bundle)
    
      plan rows           11/11 closed (10 covered+checked, 1 waived: F-11/W1 note)
      functional coverage 17/17 bins hit after merge (illegal_bins excluded by design)
      assertions          8 properties, 0 failures final regression,
                          every antecedent cover hit (no vacuous-only passes)
      scoreboard          every word compared across the soak, 0 differences
      bugs found          3 RTL (incl. push accepted at full), 2 TB, all closed
      bug-rate            0 new bugs in final 2 weekly soaks
      residual risk       async use unverified (out of scope: sync FIFO only)

    Three ways to fake closure: covering one seed and declaring victory, waiving holes without written rationale, and skipping the DEPTH 2 config that found pointer bugs DEPTH 16 never showed.

    Likely question: “How do you know you are done?”

    • Plan. Every row closed, each with stimulus, check and coverage.

    • Merge. Coverage merged across the whole soak, never one seed.

    • Story. The hole-analysis bug: a coverage gap that caught real RTL.

    Check yourself cp_offer_at_full sits at 0 hits after the soak. What is the disposition?

    A directed fix, not a waiver. Park at full, issue OP_BOTH bursts, re-run to cover. The gap once exposed a real RTL bug: a push accepted at full during a pop.

    Check yourself The suite passes on one seed with full coverage. Is the design signed off?

    No. Closure needs the merged soak across seeds and configs. One seed proves the mechanisms run, not that the corners are covered.

    Related topics

    • The PacketFIFO Project

    • Coverage: closure

    • Asynchronous FIFO

    Previous

    241 / 275

    Next: Principal-Level Verification

    Up next

    Up nextPrincipal-Level Verification

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Spec Analysis and Verification Plan
    • Interface and Harness
    • Generator, Driver and Environment