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
      • Auto Bins vs Explicit Bins
      • Transition Bins
      • Exclusions, Patterns & Filters
      • Bin Design Strategy
    • Cross Coverage
    • Coverage Options & Methods
    • Coverage Closure & Sign-Off
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Bins: Explicit, Auto, Illegal & Ignore
  1. Topics
  2. SystemVerilog
  3. Functional Coverage in SystemVerilog
  4. Bins: Explicit, Auto, Illegal & Ignore
  5. Bin Design Strategy

Part 5 · Functional Coverage · Intermediate

Bin Design Strategy

Intent-driven bins: singleton boundaries, coarse uniform regions, budgets.

On this page

    Why this matters

    A packet-length coverpoint read 100% with the one length past the MTU never sent: auto[16] held 64 to 67 and the neighbours had been hit.

    After this lesson you can: design bins from where the design's behaviour changes, keep the bin count closable, and add open ends and tripwires.

    Bins encode intent, not arithmetic

    A bin plan claims where bugs live. Real hardware fails at boundaries, at discontinuities like page edges and FIFO full or empty, and in error classes like reserved encodings.

    Good bins put one named bucket on each place the spec changes behavior. Uniform regions share one coarse bucket.

    Bins where behaviour changes.
    Check yourself A length field behaves uniformly from 2 to 62. How many bins should that span get?

    One. Uniform behavior earns one coarse bin; the budget goes to the boundaries.

    Managing bin explosion

    Bin count multiplies fast: one [] array and one wide cross can push the goal into thousands of bins. Every declared bin is a promise to hit it, so budget goal bins before writing them.

    • Budget first: tens of goal bins per covergroup, not thousands.

    • Per-value arrays only for enumerable spaces: opcodes, modes, small ID pools.

    • Wide fields get boundary bins plus coarse interior buckets, never per-value resolution.

    • Crosses cover the plan's combinations through binsof selection, not the full product.

    • Audit the tail: a long run of similar unhit bins means an array or cross needs redesign.

    Check yourself The report tail shows 900 unhit bins from one [] array. What failed: stimulus or planning?

    Planning. The array promised resolution the regression cannot deliver; redesign the bins before running more seeds.

    Open ends and tripwires

    The $ token stands for the coverpoint type minimum or maximum. $-bounded edge bins survive width changes that would orphan hand-written constants.

    A default bin catches every value no other bin claims, and it never counts toward coverage. A nonzero hit count on it means the plan missed real behavior, so review it like a failure.

    Check yourself Does a default bin raise coverage when hit?

    No. It sits outside the goal math in both directions; its job is flagging plan holes.

    Worked redesign: packet-length field

    An 8-bit length field: 0 is invalid and dropped, 1 is the minimum packet, 64 is the MTU, above 64 is rejected, and 255 is a reserved escape value.

    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.

    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
    26
    27
    28
    29
    30
    31
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    // BEFORE — naive: no bins (auto), or per-value spray
    covergroup cg_before with function sample(bit [7:0] len);
      cp_len : coverpoint len;          // 64 silent range-buckets
      // ...or the other reflex:
      // cp_len : coverpoint len { bins all[] = {[0:255]}; }  // 256 bins.
    endgroup
    // Auto bins bury len==64 vs len==65 (the MTU edge, the ONE
    // boundary the spec spends a paragraph on) inside auto[16].
    // The per-value array separates them, but spends 256 bins,
    // most on identical paths such as 137 vs 138.
    
    // AFTER — intent-driven: bins mirror the spec's behavior regions
    covergroup cg_after with function sample(bit [7:0] len);
      cp_len : coverpoint len {
        bins invalid_zero = {0};          // dropped-packet path
        bins min_pkt      = {1};          // minimum legal
        bins typical      = {[2:62]};     // uniform normal path
        bins mtu_minus1   = {63};         // boundary approach
        bins mtu          = {64};         // exactly at limit
        bins mtu_plus1    = {65};         // first rejected value
        bins oversize     = {[66:254]};   // uniform reject path
        ignore_bins escape = {255};       // reserved, out of scope (spec 4.3)
        bins unexpected   = default;      // tripwire (see below)
      }
    endgroup
    // 7 goal bins. Every spec behavior change has a named bin;
    // both uniform regions cost exactly one bin each.
    // Here every value 0..255 is already claimed, so the default
    // bin shows the syntax only. It fires on a coverpoint whose
    // named bins leave part of the range uncovered.

    Before

    After

    Bins

    64 (or 256) anonymous bins

    7 named goal bins

    The MTU edge

    Shared with three other values in auto[16]

    mtu and mtu_plus1, each provable

    Closure

    Thousands of random packets, still holes

    A short constraint list hits all 7 quickly

    The report

    auto[0] to auto[63]

    Reads like the spec

    Interview

    Likely task: design bins for a length field. The expected shape is this redesign: singleton bins at boundaries, coarse bins across uniform regions, reserved values excluded, and one sentence on why per-value bins waste the goal budget.

    Check yourself Why do mtu and mtu_plus1 earn separate bins while [2:62] shares one?

    The spec changes behavior at 64 versus 65, the accept-or-reject edge. Values 2 to 62 share one path, so one bin proves the region.

    Testbench

    The bench runs both designs on the same regression: every length from 0 to 255 except 65, the one value just past the MTU.

    Predict first The regression never sends a 65-byte packet. What does each design report?

    The auto bins read 100%: auto[16] holds 64 to 67 and was hit by the others. The planned bins read 6 of 7 and name mtu_plus1 as the hole.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // uses: covmodel
    // The packet-length redesign: auto bins against intent-driven bins, on the same stimulus.
    module tb_bin_design;
      cm_point cp_before = new("cp_len before (auto bins)"), cp_after = new("cp_len after (planned bins)");
      initial begin
        cp_before.add_split("auto", 0, 255, 64);                   // no bins: 64 auto bins of 4 values
        cp_after.add("invalid_zero", 0, 0);   cp_after.add("min_pkt", 1, 1);
        cp_after.add("typical", 2, 62);       cp_after.add("mtu_minus1", 63, 63);
        cp_after.add("mtu", 64, 64);          cp_after.add("mtu_plus1", 65, 65);
        cp_after.add("oversize", 66, 254);    cp_after.add("escape", 255, 255, CM_IGNORE);
        cp_after.add_default("unexpected");
        // A regression that never sends a 65-byte packet: the one value past the MTU.
        for (int len = 0; len <= 255; len++) if (len != 65) begin cp_before.sample(len); cp_after.sample(len); end
        $display("  before: %0.2f%%, and auto[16] holds 64 to 67 with %0d hits", cp_before.get_coverage(), cp_before.bin_list[16].hits);
        cp_after.report();
        if (cp_before.get_coverage() != 100.0 || cp_after.bin_list[5].hits != 0 || cp_after.n_covered() != 6) $fatal(1, "FAIL: redesign");
        $display("PASS: the auto bins read 100%% with 65 never sent; the planned bins named the missing mtu_plus1");
        $finish;
      end
    endmodule
    Terminal
      before: 100.00%, and auto[16] holds 64 to 67 with 3 hits
      coverpoint cp_len after (planned bins): 85.71% (6 of 7 bins)  below goal 100
        invalid_zero   1
        min_pkt        1
        typical        61
        mtu_minus1     1
        mtu            1
        mtu_plus1      0     <- hole
        oversize       189
        escape         1     (ignore)
        unexpected     0     (default)
    PASS: the auto bins read 100% with 65 never sent; the planned bins named the missing mtu_plus1

    Common pitfall

    Copying bins from a previous project with different semantics keeps stale boundaries. The MTU moved; the bins did not. Review bins against the current spec like code.

    Remember

    • One bin per behaviour change, one coarse bin per uniform region.

    • Seven named bins beat 64 anonymous ones.

    • A default bin catches what the plan forgot.

    Rule of thumb: a bin should read like a line of the spec.

    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 every length but 65 sent, the auto bins read 100% and the planned bins read 6 of 7, naming mtu_plus1.

    Related topics

    • Controlling cross explosion

    • Reading the unhit tail

    Previous

    148 / 259

    Next: Cross Coverage

    Up next

    Up nextCross Coverage

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Auto Bins vs Explicit Bins
    • Transition Bins