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

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here6
  • SystemVerilog Language Foundations28
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive36
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
    • Covergroups & Coverpoints
    • Bins: Explicit, Auto, Illegal & Ignore
    • Cross Coverage
    • Coverage Options & Methods
    • Coverage Closure & Sign-Off
      • From Spec to Coverage Plan
      • Hole Analysis and Triage
      • Closing Techniques
      • Exclusions and Waivers
      • Sign-Off Metrics and Review
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Coverage Closure & Sign-Off
  1. Topics
  2. SystemVerilog
  3. Functional Coverage in SystemVerilog
  4. Coverage Closure & Sign-Off
  5. From Spec to Coverage Plan

Part 5 · Functional Coverage · Intermediate

From Spec to Coverage Plan

Turn spec sentences into a plan table of features, bins, and priorities before writing covergroups.

On this page

    Why this matters

    A spec said transfers of 1 to 16 beats are supported, and the covergroup used one range bin. It read 100% for a regression that never sent 1 or 16 beats.

    After this lesson you can: extract coverable features from spec sentences and write a plan table with stable IDs, bins and priorities before any covergroup.

    Reading a spec for coverable features

    A coverage plan is a systematic transcription of the spec into measurable scenarios. Four extraction questions produce the feature list: what values each field takes, what combinations the logic acts on together, what sequences must occur in order, and what boundaries the text calls out.

    Spec sentence

    Coverable feature

    “Transfers of 1 to 16 beats are supported”

    Length bins 1, [2:15], 16, with both boundaries named

    “WRAP bursts must be 2, 4, 8, 16”

    illegal_bins for WRAP × length 1; an assertion checks the other non-pow2 lengths, which the coarse [2:15] bin cannot separate

    “A timeout aborts the transfer and returns the FSM to IDLE”

    Transition bin XFER => IDLE on timeout

    “QoS affects arbitration only when two masters contend”

    Cross of QoS by grant, gated by contention

    “The FIFO asserts full at 64”

    Occupancy bins 0, 63, 64: the boundary and both sides

    Numbers in spec prose are coverage gold. Every explicit constant is a boundary the designers special-cased, and boundaries are where bugs live.

    The plan table

    The plan is a table, one row per feature, written before the covergroups. Each row carries enough to implement the measurement and enough to audit it later.

    ID

    Feature (spec ref)

    Coverpoint or cross

    Bins

    Priority

    CV_LEN

    Burst lengths (s7.2)

    cp_len

    1, [2:15], 16

    P1

    CV_WRP

    Wrap legality (s7.2.1)

    cp_btype × cp_len

    illegal: wrap × 1

    P1

    CV_TMO

    Timeout recovery (s9.4)

    cp_fsm transition

    XFER => IDLE

    P1

    CV_QOS

    QoS under contention (s8.1)

    x_qos_grant

    8 named cells

    P2

    CV_OCC

    FIFO boundaries (s5.3)

    cp_occ

    0, 63, 64

    P1

    CV_RSV

    Reserved encodings (s3.9)

    cp_op

    ignore: [12:15]

    P3

    The ID is a stable handle that code comments and reports refer to. The feature column is one sentence plus the spec section it transcribes; the coverpoint column names the construct that implements it; the bins column lists the buckets, including planned illegal and ignore bins; and the priority drives weights, closing order and waiver scrutiny.

    • Plan IDs are stable and boring: CV_LEN style, never renumbered, only appended.

    • Covergroup elements carry the ID in a comment on the same line as the bin they implement.

    • option.comment on the covergroup names the plan section it serves, so the report self-documents.

    • Bin names echo the feature, not the value: timeout_recovery, not b3. Reports are read by people who did not write the code.

    The listing below is not run in this course's checks: the open simulators do not count covergroups, so the lesson's bench counts it with the bins model.

    dma_cov_if.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
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    interface dma_cov_if(input logic clk);
      logic       desc_done;
      logic [1:0] btype;   // 0 INCR, 1 FIXED, 2 WRAP
      logic [4:0] blen;    // 1..16
    
      covergroup dma_cg @(posedge clk iff desc_done);
        option.comment = "coverage plan CV_LEN, CV_WRP — spec s7.2";
    
        cp_btype : coverpoint btype {
          bins incr  = {0};
          bins fixed = {1};
          bins wrap  = {2};
        }
        cp_len : coverpoint blen {       // CV_LEN
          bins one     = {1};            // CV_LEN: lower boundary
          bins mid     = {[2:15]};       // CV_LEN: interior
          bins max_len = {16};           // CV_LEN: upper boundary
        }
        x_wrap : cross cp_btype, cp_len {
          illegal_bins wrap_bad = binsof(cp_btype.wrap) &&
                                  binsof(cp_len.one);   // CV_WRP: spec s7.2.1
        }
      endgroup
    endinterface

    Plan review before coding

    The plan is reviewed as a document, with the spec open, before implementation. Reviewing a finished covergroup conflates intent with code, and intent mistakes found late invalidate regression data already collected.

    1. Walk the spec section by section: does every must sentence have a plan row or a written reason it does not?

    2. Are boundary values from spec prose present as named bins, not buried in ranges?

    3. Is every cross justified by logic that actually examines the fields together?

    4. Are priorities assigned, and do P1 rows cover the features whose failure is unshippable?

    5. Are planned illegal and ignore bins listed up front, not improvised at 87%?

    6. Can each row be measured from observable signals, or must instrumentation be requested now?

    Interview

    “Should this covergroup live in a class or a module?” Signal timing belongs near the pins, in a module or interface covergroup on a clock. Transaction coverage belongs in a class, constructed once and sampled per transaction, with constructor arguments separating the instances.

    Common pitfall

    Writing covergroups first and reverse-engineering a plan for the review. The model covers what was easy, not what matters, and spec-named boundaries get buried inside ranges.

    Check yourself A spec sentence says transfers of 1 to 16 beats are supported. Which bins does the plan need?

    Three named bins: 1, [2:15], and 16. Both boundaries get their own evidence instead of hiding inside one range.

    Check yourself Why must every plan row carry its spec section?

    So review can verify each requirement sentence has a row, and sign-off can audit each number. Rows without references are unverifiable.

    Testbench

    The bench builds plan rows CV_LEN and CV_WRP with the bins model, next to the same length field written as one range bin, and runs a regression that sends every burst type with lengths 2 to 15 only.

    Predict first No burst of 1 or 16 beats is ever sent. What do the range bin, cp_len and the cross read?

    The range bin reads 100%: every value from 2 to 15 lands in it. cp_len reads 1 of 3 and names one and max_len as holes. The cross reads 3 of 8: WRAP × one is illegal and leaves the goal, and the five other boundary cells are holes.

    design.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
    // uses: covmodel
    // Plan rows CV_LEN and CV_WRP as bins, against a single range bin, over a regression that never sends 1 or 16 beats.
    module tb_dma_plan;
      cm_point cp_btype = new("cp_btype"), cp_len = new("cp_len  (CV_LEN)"), cp_range = new("cp_len  (one range bin)");
      cm_cross x_wrap;
      initial begin
        cp_btype.add("incr", 0, 0); cp_btype.add("fixed", 1, 1); cp_btype.add("wrap", 2, 2);
        cp_len.add("one", 1, 1);                  // CV_LEN: lower boundary
        cp_len.add("mid", 2, 15);                 // CV_LEN: interior
        cp_len.add("max_len", 16, 16);            // CV_LEN: upper boundary
        cp_range.add("len", 1, 16);               // "1 to 16 beats", transcribed as one range
        x_wrap = new("x_wrap  (CV_WRP)", cp_btype, cp_len);
        x_wrap.illegal(x_wrap.sel("wrap", "one"));                 // CV_WRP: spec s7.2.1
        // The regression: every burst type, lengths 2 to 15 only.
        for (int t = 0; t < 3; t++)
          for (int len = 2; len <= 15; len++) begin
            cp_btype.sample(t); cp_len.sample(len); cp_range.sample(len); x_wrap.sample();
          end
        cp_range.report(); cp_len.report(); x_wrap.report();
        if (cp_range.get_coverage() != 100.0 || cp_len.n_covered() != 1 || x_wrap.n_bins() != 8 || x_wrap.n_covered() != 3)
          $fatal(1, "FAIL: plan bins");
        $display("PASS: the range bin read 100%%; the planned bins named both untested boundaries");
        $finish;
      end
    endmodule
    Terminal
      coverpoint cp_len  (one range bin): 100.00% (1 of 1 bins)
        len            42
      coverpoint cp_len  (CV_LEN): 33.33% (1 of 3 bins)  below goal 100
        one            0     <- hole
        mid            42
        max_len        0     <- hole
      cross x_wrap  (CV_WRP): 37.50% (3 of 8 bins)
        hole: <incr, one>
        hole: <incr, max_len>
        hole: <fixed, one>
        hole: <fixed, max_len>
        hole: <wrap, max_len>
    PASS: the range bin read 100%; the planned bins named both untested boundaries

    Remember

    • Values, combinations, sequences, boundaries: four questions per sentence.

    • Every number in spec prose is a boundary bin.

    • Plan IDs go in the bin comments and the report.

    Rule of thumb: write and review the plan before the covergroup.

    How this was checked

    Counted with the course's bins model (rich/coverage/cov_model.sv, listed on the Coverage hub) on Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown. Verilator 5.048 parses covergroups with a COVERIGN warning and ignores their bins, and Icarus 13 has none, so each covergroup listing is marked not run and its bench counts the same bins with the model.

    With lengths 2 to 15 only, the range bin read 100% and the planned bins read 1 of 3, naming one and max_len.

    Related topics

    • Covergroup basics

    • Covergroup options and methods

    Previous

    158 / 259

    Next: Hole Analysis and Triage

    Up next

    Up nextHole Analysis and Triage

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Closing Techniques
    • Exclusions and Waivers
    • Sign-Off Metrics and Review