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. Exclusions, Patterns & Filters

Part 5 · Functional Coverage · Intermediate

Exclusions, Patterns & Filters

Illegal and ignore bins, wildcard patterns, and with filters with guards.

On this page

    Why this matters

    A reserved opcode left as an ordinary bin capped a coverpoint at 87.5% for a month. Moving it to ignore_bins took a minute and made 100% reachable.

    After this lesson you can: choose between ignore_bins and illegal_bins, work out the percentage after exclusions, and use wildcard bins and with filters.

    Two exclusions with opposite personalities

    ignore_bins and illegal_bins both remove values from the coverage goal. A sample in an ignore_bin is silently discarded, while the same value in an illegal_bins raises a runtime error the moment it is sampled.

    Ignore says out of scope. Illegal says this must never happen, and failure must be loud. A value claimed by both an ordinary bin and an illegal_bins is illegal.

    Ordinary bin

    ignore_bins

    illegal_bins

    Hit count

    Increments

    Discarded

    Run-time error

    In the goal math

    Yes

    Removed from numerator and denominator

    Removed from the goal; the run may stop

    Meaning

    A scenario

    Out of scope

    Must never occur

    On a hit

    Progress

    Nothing

    The test fails

    A coverpoint iff guard runs first. Skipped samples hit nothing, and they do not fire illegal_bins.

    Check yourself A sampled value sits in both a named bin and an illegal_bins. Covered or error?

    Error. Illegal takes precedence, and the value never counts as covered.

    The percentage math, worked

    ignore_bins shrink the denominator, which makes remaining coverage easier to close. That is correct for out-of-scope values and the abuse vector reviewers watch for.

    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
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    covergroup cg with function sample(bit [2:0] mode);
      cp_mode : coverpoint mode {
        bins m[] = {[0:7]};            // start: 8 goal bins
        ignore_bins  rsv  = {6};        // reserved encoding, out of scope
        illegal_bins bad  = {7};        // spec says: must never occur
      }
    endgroup

    The bench counts exactly this coverpoint with the bins model: values 0, 1, 2 and 4, then a 6, then a 7.

    Predict first What is the coverage after 0, 1, 2 and 4? What do the later 6 and 7 change?

    4 of 6, 66.67%: ignore_bins and illegal_bins remove 6 and 7 from the goal, so the denominator is 6, not 8. The 6 is discarded silently. The 7 is reported at once, and the percentage does not move.

    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
    32
    33
    34
    35
    // uses: covmodel
    // ignore_bins, illegal_bins, wildcard bins and a with filter, counted with the bins model.
    module tb_bins_excl;
      cm_point cp_mode = new("cp_mode"), cp_parity = new("cp_parity"), cp_align = new("cp_align");
      initial begin
        int m[$];
        // bins m[] = {[0:7]}; ignore_bins rsv = {6}; illegal_bins bad = {7};
        cp_mode.add("rsv", 6, 6, CM_IGNORE);
        cp_mode.add("bad", 7, 7, CM_ILLEGAL);
        for (int v = 0; v <= 5; v++) cp_mode.add($sformatf("m[%0d]", v), v, v);   // m[6] and m[7] removed
        // wildcard bins even = {8'b???????0}; odd = {8'b???????1};
        cp_parity.add_wild("even", 8'b0000_0000, 8'b0000_0001);
        cp_parity.add_wild("odd",  8'b0000_0001, 8'b0000_0001);
        // bins cacheline_aligned = {[0:255]} with (item % 64 == 0);  the filter runs once, over the set
        for (int item = 0; item <= 255; item++) if (item % 64 == 0) m.push_back(item);
        cp_align.add_values("cacheline_aligned", m);
        begin
          int modes[4] = '{0, 1, 2, 4};
          foreach (modes[i]) cp_mode.sample(modes[i]);
        end
        $display("modes 0, 1, 2 and 4: %0.2f%%", cp_mode.get_coverage());
        cp_mode.sample(6);                                   // reserved: silently discarded
        cp_mode.sample(7);                                   // must never happen: reported at once
        cp_mode.report();
        begin
          int addrs[3] = '{8'h10, 8'h3F, 8'h80};
          foreach (addrs[i]) begin cp_parity.sample(addrs[i]); cp_align.sample(addrs[i]); end
        end
        cp_parity.report(); cp_align.report();
        $display("  the with filter kept %0d values: 0, 64, 128 and 192", cp_align.bin_list[0].vals.size());
        if (cp_mode.n_bins() != 6 || cp_mode.n_covered() != 4 || cp_mode.illegal_hits != 1 || cp_align.bin_list[0].hits != 1) $fatal(1, "FAIL: exclusion math");
        $display("PASS: coverage is 4 of 6, not 4 of 8; the reserved value vanished and the illegal one was reported");
        $finish;
      end
    endmodule
    Terminal
    modes 0, 1, 2 and 4: 66.67%
      [cov] cp_mode: illegal bin bad hit by 7
      coverpoint cp_mode: 66.67% (4 of 6 bins)  below goal 100
        rsv            1     (ignore)
        bad            1     (illegal)
        m[0]           1
        m[1]           1
        m[2]           1
        m[3]           0     <- hole
        m[4]           1
        m[5]           0     <- hole
      coverpoint cp_parity: 100.00% (2 of 2 bins)
        even           2
        odd            1
      coverpoint cp_align: 100.00% (1 of 1 bins)
        cacheline_aligned 1
      the with filter kept 4 values: 0, 64, 128 and 192
    PASS: coverage is 4 of 6, not 4 of 8; the reserved value vanished and the illegal one was reported
    Check yourself The m[] = {[0:7]} bins above, with ignore_bins {6}, illegal_bins {7} and four bins hit. What is the coverage, and what does a later sample of the illegal value change?

    66.7%, four of six. Each exclusion empties a single-value bin, and an exclusion removes a bin only when it empties it. The illegal sample raises a runtime error and changes no math.

    Reserved values and configuration limits

    Exclusions need a reason on the line. 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
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    covergroup cg with function sample(bit [3:0] burst, bit [2:0] size,
                                       bit [7:0] id);
      cp_burst : coverpoint burst {
        bins fixed = {0};
        bins incr  = {1};
        bins wrap  = {2};
        ignore_bins reserved = {[3:15]};    // spec: encodings 3-15 reserved
      }
      cp_size : coverpoint size {
        bins b[] = {[0:7]};
        // this DUT's bus is 64-bit: sizes above 3 unreachable by config
        ignore_bins over_width = {[4:7]};
      }
      cp_id : coverpoint id {
        bins used[4] = {[0:127]};
        ignore_bins out_of_pool = {[128:255]}; // ID pool limited by env cfg
      }
    endgroup
    • Reserved spec encodings take ignore_bins with a comment citing the spec section.

    • Configuration-unreachable values take ignore_bins per build configuration.

    • Must-never-occur violations take an assertion first, with illegal_bins as documented backup.

    • Every ignore_bins needs a justifying comment. Uncommented ignores read as coverage-goal gaming.

    Common pitfall

    Burying unhit bins in ignore_bins before a deadline fabricates closure. Assertions stay the load-bearing check; illegal_bins is the redundant tripwire beside them.

    Check yourself Where does the primary protocol-violation check live: assertion or illegal_bins?

    The assertion. It watches every cycle, while an illegal_bins fires only if the covergroup samples at the guilty moment.

    Patterns and computed subsets

    Prefixing a bin with wildcard makes x, z and ? act as don't-care bit positions. One pattern then matches a whole value family in a single bin.

    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
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    covergroup cg with function sample(bit [7:0] addr, bit [3:0] tag);
      cp_parity : coverpoint addr {
        wildcard bins even = {8'b???????0};   // LSB 0 → 128 values, ONE bin
        wildcard bins odd  = {8'b???????1};
      }
      cp_region : coverpoint addr {
        wildcard bins io_page = {8'b1111_????};  // 0xF0-0xFF
      }
      cp_tag : coverpoint tag {
        wildcard bins grp_a[] = {4'b00??};    // [] → 4 bins: 0,1,2,3
      }
    endgroup

    Without the wildcard keyword those bits are literal X and Z matches. Sampled 2-state data never equals them, so the bin silently never hits.

    bins with (expression) keeps the set values where the item predicate holds. The filter runs at elaboration over the candidate set, so it must be a constant function of item alone.

    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
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    covergroup cg with function sample(bit [7:0] addr, bit [7:0] len);
      cp_align : coverpoint addr {
        bins cacheline_aligned = {[0:255]} with (item % 64 == 0);
        // → {0, 64, 128, 192} in one bin
        bins word_aligned[]    = {[0:31]}  with (item % 4 == 0);
        // → 8 separate bins: 0,4,8,...,28
      }
      cp_len : coverpoint len {
        bins powers_of_two[] = {[1:128]} with ((item & (item - 1)) == 0);
        // → 1,2,4,8,16,32,64,128
        bins primes[] = {[2:31]} with (is_prime(item));  // constant function
      }
    endgroup
    
    function automatic bit is_prime(int unsigned n);
      if (n < 2) return 0;
      for (int unsigned d = 2; d * d <= n; d++)
        if (n % d == 0) return 0;
      return 1;
    endfunction

    The subset is defined by

    Use

    Fixed bit positions

    wildcard bins {8'b1111_????}

    Arithmetic on the value

    bins ... with (item % 64 == 0)

    Hand-picked plan values

    bins b = {0, 64, 255}

    A run-time condition, not a property of the value

    iff (expr) on the coverpoint: with cannot see other signals

    with and wildcard select which values belong to a bin, a static per-value question. iff decides whether the sample counts at all, a dynamic per-sample question. 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
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    covergroup cg with function sample(bit [7:0] addr, bit is_dma,
                                       bit rst_n);
      // DMA traffic only, reset excluded; bins select aligned subsets
      cp_dma_align : coverpoint addr iff (rst_n && is_dma) {
        bins burst_aligned = {[0:255]} with (item % 16 == 0);
        wildcard bins hi_page = {8'b11??_????};
        ignore_bins low_rsv   = {[0:15]};   // reserved region, any source
      }
    endgroup

    Interview

    Likely task: cover only 64-byte-aligned addresses. The expected answer is with (item % 64 == 0). Add that wildcard covers the same case when alignment is a power of two.

    Check yourself A with predicate references a DUT ready signal. What happens?

    It cannot compile as intended. with sees only item; the ready condition belongs in iff.

    Check yourself A with predicate is never true over its range. What does coverage show?

    A permanently unhittable bin. Most tools warn; treat the warning as an error and fix the range or predicate.

    Remember

    • Both leave the goal: ignore is silent, illegal is an error.

    • Excluded bins leave the numerator and the denominator.

    • wildcard matches bit patterns; with filters by arithmetic.

    Rule of thumb: if a hit means filing a bug, the bin is illegal.

    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.

    Modes 0, 1, 2 and 4 read 4 of 6, not 4 of 8; the reserved 6 vanished and the illegal 7 was reported at once.

    Related topics

    • Selecting cross combinations with binsof

    Previous

    147 / 259

    Next: Bin Design Strategy

    Up next

    Up nextBin Design Strategy

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Auto Bins vs Explicit Bins