Skip to content

SystemVerilog · Module 11

Wildcard, Illegal & Ignore Bins

The three special-purpose bin forms — wildcard for bit-pattern matching, illegal for must-never-occur scenarios that fire runtime errors, and ignore for valid-but-irrelevant values. The decision tree for picking between illegal, ignore, narrower bins, and constraints, plus the tool-specific severity model.

Module 11 · Page 11.5

Three Special-Purpose Bin Forms

Module 11.4 covered the four counted named-bin forms — single-value, range, multi-value, and array. This page covers three special-purpose forms that change what the coverage measurement means:

  • wildcard bins — pattern-matches values using ? as a don't-care bit, so one bin covers every value matching a bit pattern.
  • illegal_bins — declares values the design must never produce; the simulator raises a runtime error or warning if any sample lands in the bin.
  • ignore_bins — declares valid-but-uninteresting values that are silently excluded from the coverage denominator.

Each form solves a problem the counted forms cannot. Knowing when to reach for each — and when not to reach for it (the alternatives are often better) — is the discipline this page builds.

Wildcard Bins — Bit-Pattern Matching

wildcard bins lets you declare a bin whose value set is described by a bit pattern with ? as the don't-care character. Any sampled value whose non-? bits match the pattern lands in the bin. The form is useful when the verification plan's scenario is "any value sharing this bit pattern" rather than a specific value or a contiguous range.

Syntax and semantics

SystemVerilog — wildcard bins for bit-pattern coverage
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
covergroup cg_addr_patterns;
    cp_addr: coverpoint addr {
        // Match: top nibble is all-1s — values 0xF0..0xFF
        wildcard bins high_nibble_f = {8'b1111_????};
 
        // Match: low nibble is all-0s — values 0x00, 0x10, 0x20, ..., 0xF0
        wildcard bins low_nibble_0  = {8'b????_0000};
 
        // Match: any byte where bits[7] == 1 AND bit[0] == 1
        //        (an odd value in the upper half)
        wildcard bins odd_upper     = {8'b1???_???1};
 
        // Multiple patterns share one bin — OR semantics inside {}
        wildcard bins low_or_high   = {8'b0000_????, 8'b1111_????};
    }
endgroup

What this does. Four wildcard bins. The first matches any byte whose top nibble is 1111 — sixteen distinct values lighting one bin. The second matches any byte whose low nibble is 0000. The third matches any byte where bit 7 is set and bit 0 is set, regardless of the bits in between — sixty-four distinct values. The fourth combines two patterns under one named bin via OR semantics inside the {} literal.

Where wildcard bins earn their keep. Protocol fields whose semantics are bit-position-driven rather than value-driven:

  • AXI AWUSER / ARUSER sideband bits where specific bit positions encode independent flags.
  • Interrupt vectors where the active line is identified by a single set bit.
  • DMA descriptor flags whose "any one of these mode bits set" is the scenario.
  • Address aliasing — "any address ending in 0x00" maps to "page-aligned access" as a single scenario.

Writing the equivalent as named bins would require enumerating every matching value (sixteen for an 8-bit one-nibble pattern, sixty-four for a two-bit-fixed pattern); the wildcard form names the scenario directly.

Wildcard semantics — what ? actually matches

The ? character in a wildcard bin matches 0 and 1 in that bit position. Critically, it does not match x or z — values containing x/z bits do not land in a wildcard bin (or any bin) at all. This is the source of every "the simulation drove the pattern but the bin didn't hit" debugging session involving wildcard bins.

SystemVerilog — what wildcard bins match (and what they don't)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
covergroup cg;
    cp: coverpoint signal_8b {
        wildcard bins all_ones_low = {8'b????_1111};
    }
endgroup
 
// signal_8b = 8'b0000_1111  → matches all_ones_low      ✓
// signal_8b = 8'b1010_1111  → matches all_ones_low      ✓
// signal_8b = 8'b1111_1111  → matches all_ones_low      ✓
// signal_8b = 8'b1010_1110  → does NOT match            ✗ (bit 0 ≠ 1)
// signal_8b = 8'b1010_111x  → does NOT match            ✗ (x in low nibble)
// signal_8b = 8'b1010_111z  → does NOT match            ✗ (z in low nibble)
//
// X/Z propagation kills the sample silently — no error, no warning,
// the bin just doesn't increment. If your design has X-propagation,
// audit it before trusting wildcard-bin coverage numbers.

Illegal Bins — Catching "Must Never Occur"

illegal_bins declares values that the design must never produce during a correct simulation. They are not counted in coverage (they have no role in the 100% calculation). When a sample lands in an illegal bin, the simulator raises a runtime error or warning — making the violation immediately visible rather than letting it corrupt the coverage database silently.

Syntax and behaviour

SystemVerilog — illegal_bins for protocol violations
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
typedef enum bit [2:0] {
    OP_NOP  = 3'b000,
    OP_READ = 3'b001,
    OP_WRITE = 3'b010,
    OP_RFR  = 3'b011
    // Encodings 3'b100..3'b111 are reserved — spec says they must never occur
} cmd_e;
 
covergroup cg_cmd;
    cp_cmd: coverpoint command {
        // ── Legal commands — counted toward coverage ───────────────
        bins nop      = {OP_NOP};
        bins rd       = {OP_READ};
        bins wr       = {OP_WRITE};
        bins rfr      = {OP_RFR};
 
        // ── Illegal — spec violation if produced ──────────────────
        illegal_bins reserved = {[3'b100 : 3'b111]};
    }
endgroup
 
// If command == 3'b100 is ever sampled:
//   • Simulator raises: "Coverage illegal bin 'reserved' was hit"
//   • Severity is tool-dependent (warning vs error vs fatal)
//   • The illegal bin is NOT counted toward cp_cmd's denominator
//   • cp_cmd's 100% is { nop, rd, wr, rfr } all hit

The intent rule: illegal_bins describes a design contract. The contract is "this value will never appear at this point of the design." Sampling the bin means the contract is broken — either the RTL has a bug, or the spec has a hole that the RTL is filling unexpectedly.

Tool-specific severity

The LRM allows simulators discretion in how strictly to enforce illegal_bins. Major simulators differ:

SimulatorDefault behaviourOverride knob
VCSWarning per hit-cm_warn_illegal_bins fatal
Questa / ModelSimWarning per hitset CovIllegalSeverity fatal (.do script)
XceliumWarning per hit-coverage_options error_on_illegal_bin
VerilatorWarning per hit (cov enabled)+verilator+coverage+illegal-fatal

The pattern is consistent: default is warning-per-hit; the verification environment opts into fatal severity. For coverage models inside CI regressions, fatal severity is the right default — a hit on an illegal bin should stop the simulation, not be lost in the warning torrent that nightly regressions produce. For interactive debug runs, warning severity is sometimes more useful (so the simulation continues past the violation and the engineer can inspect what happened next).

You can also force fatal severity per covergroup via type_option:

SystemVerilog — force fatal illegal-bin severity at type scope
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
covergroup cg_critical;
    type_option.illegal_bins_error = 1;     // any illegal-bin hit → fatal
 
    cp_state: coverpoint state {
        bins legal_states = {IDLE, ACTIVE, DONE};
        illegal_bins encoding_error = {2'b11};
    }
endgroup

Illegal bins vs assertions — the trade-off

The same "must never happen" intent can often be expressed as a SystemVerilog Assertion (SVA) instead of an illegal bin:

SystemVerilog — same intent, two implementations
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ── Form A — illegal_bins (Module 11) ──────────────────────────────
covergroup cg_state;
    cp_state: coverpoint state {
        bins legal = {IDLE, ACTIVE, DONE};
        illegal_bins encoding_error = {2'b11};
    }
endgroup
 
// ── Form B — concurrent assertion (Module 12) ──────────────────────
property p_state_valid;
    @(posedge clk) state inside {IDLE, ACTIVE, DONE};
endproperty
assert property (p_state_valid);

Both detect the violation. The choice:

Aspectillegal_binsSVA assertion
Trigger granularityAt each sample eventAt each clock edge (or other property event)
ReportsSurfaces in coverage report alongside the bin definitionSeparate assertion-fail log
Timing windowsPostponed region only — sub-cycle illegal values missedConfigurable region — can catch sub-cycle transients
Coverage integrationThe bin name appears in the coverage audit naturallyA separate map links assertions to verification-plan rows
Severity controlillegal_bins_error / per-tool knobassert / assume / cover modifiers + $error / $fatal
PerformanceCheap — coverage was already being sampledPer-edge property evaluation, can be more expensive

The rule that works in practice: use illegal_bins when the violation is naturally a coverage event (specific value in a specific field at sample time), use an SVA assertion when the violation is naturally a temporal property (value sequence across cycles, ordering relations between signals, no-glitch requirements). Many environments use both for the same scenario — the assertion catches the temporal version, the illegal bin documents the scenario in the coverage audit.

Ignore Bins — Excluding Valid-but-Irrelevant Values

ignore_bins declares values that are legal for the design but irrelevant for the coverage measurement. They are not counted in coverage (they contribute nothing to the denominator) and they do not fire any error when hit. The simulator silently skips the sample for this coverpoint.

Syntax and behaviour

SystemVerilog — ignore_bins for valid-but-uninteresting values
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
covergroup cg_packet_type;
    cp_type: coverpoint packet_type {
        // ── Counted bins ──────────────────────────────────────────
        bins data_pkt    = {[0:3]};
        bins control_pkt = {[4:7]};
 
        // ── Reserved encoding range — valid per spec, not in plan
        //     (typically test-mode-only or future-feature values)
        ignore_bins reserved = {[8:15]};
    }
endgroup
 
// Coverage denominator = 2 bins (data_pkt + control_pkt)
// If packet_type ∈ [8:15] appears:
//   • No error, no warning
//   • The sample is silently dropped for cp_type
//   • Other coverpoints in the same covergroup still sample normally
//
// Without ignore_bins, automatic-bin behaviour would create bins for
// values [8:15] too, making 100% impossible unless the test layer
// deliberately drives reserved values.

When ignore_bins is the right tool

The legitimate uses for ignore_bins:

  • Reserved encodings the spec defines as valid but the plan doesn't test. Future-feature opcodes, test-mode flags, calibration values — they exist in the value space but aren't part of the verification scope.
  • Unreachable values inside a range. A bit [3:0] burst_len field whose RTL is hardcoded to only ever drive 1, 2, 4, 8 leaves the other twelve values unreachableignore_bins others = {3, [5:7], [9:15]}; keeps them out of the denominator.
  • Cross-coverage combinations the architecture forbids. A cross between opcode and operand-size where some combinations are architecturally impossible — the ignore_bins form inside the cross (ignore_bins div_large = binsof(cp_opcode) intersect {DIV} && binsof(cp_size.large);) drops only those combinations.
  • Values that exist because the SystemVerilog type is wider than the design uses. A 16-bit field where the RTL only drives the low 8 bits — ignore_bins upper_unused = {[16'h0100 : 16'hFFFF]}; reflects the actual reachable scope.

When ignore_bins is the wrong tool

The misuse case is using ignore_bins to make a coverage number look better by excluding values the test layer simply hasn't reached. That is converting a verification gap into a verification cover-up — the dashboard improves while the spec rows still aren't exercised.

SystemVerilog — the ignore_bins anti-pattern
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
covergroup cg_addr;
    cp_addr: coverpoint paddr {
        bins csr_region = {[32'h0000_0000 : 32'h0000_00FF]};
        bins ram_region = {[32'h1000_0000 : 32'h1FFF_FFFF]};
 
        // ── ANTI-PATTERN: regression couldn't hit the MMIO region,
        //                  so it was ignored to "close" coverage
        ignore_bins mmio_region = {[32'h2000_0000 : 32'h2FFF_FFFF]};
    }
endgroup
 
// Dashboard: cp_addr 100%.
// Verification plan: MMIO region row says "exercise base, mid, last byte."
// Reality: the MMIO region was never exercised. The ignore_bins entry hides it.

Every ignore_bins declaration needs a documented justification: "this value range is unreachable because [architectural reason]," or "this range is reserved per spec section X and is intentionally out of scope." A reviewer should be able to read the ignore_bins line, read the cited reason, and verify the reason is real. Without that audit step, ignore bins become the gap-hiding tool the dashboard reads but the spec doesn't.

Illegal vs Ignore vs Narrower Bin vs Constraint — A Decision Tree

The same coverage outcome ("this value range is not part of my coverage measurement") can be achieved four different ways. They are not equivalent and the choice matters at audit time.

ApproachWhat it doesUse when
illegal_binsNot counted; fires error if hitThe value must never occur — design contract violation
ignore_binsNot counted; silent if hitThe value is legal but architecturally out of scope
Narrower bins (exclude by omission)Sample silently drops if no bin matchesThe value is one of several you simply don't plan to track
Test-layer constraintValue is never generated, so never sampledThe test should not produce the value at all

The differences in audit semantics are decisive:

  • illegal_bins documents "this is a contract violation, surface it loudly." A reviewer reading the covergroup sees the design promise.
  • ignore_bins documents "this is intentionally out of scope, and here is why." A reviewer reading the covergroup with the option.comment sees the architectural justification.
  • Exclusion by omission documents nothing — a reviewer reading the covergroup cannot tell whether the engineer forgot the bin or deliberately omitted it. Almost always the wrong choice for sign-off coverage.
  • Test-layer constraint is the right tool when the value should not be generated in the first place. It does not appear in the coverage source at all; the constraint controls the input distribution. Use this for "we never drive these opcodes in any test" rather than for "we have a coverpoint that ignores these opcodes."

A simple working rule: if the spec calls the value "illegal," use illegal_bins. If the spec calls the value "reserved" or "test-mode-only" or "future-feature," use ignore_bins with a citation. If the value is legal but the test simply doesn't drive it, write a test or a constraint — not a coverage bin.

A Complete Working Example — All Three Forms in One Covergroup

The pattern below combines all three special-purpose bin forms in a realistic memory-controller covergroup, alongside named bins from Module 11.4.

SystemVerilog — wildcard, illegal, and ignore bins together
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
typedef enum bit [2:0] {
    CMD_NOP   = 3'b000,
    CMD_READ  = 3'b001,
    CMD_WRITE = 3'b010,
    CMD_RFR   = 3'b011
    // 3'b100..3'b111 are reserved — spec says they must never appear
} mem_cmd_e;
 
class mem_txn;
    rand mem_cmd_e   cmd;
    rand bit [15:0]  addr;
    rand bit [ 7:0]  flags;
 
    covergroup cg_mem;
        // ── Named bins on commands; illegal bin on reserved encodings
        cp_cmd: coverpoint cmd {
            bins nop = {CMD_NOP};
            bins rd  = {CMD_READ};
            bins wr  = {CMD_WRITE};
            bins rfr = {CMD_RFR};
            illegal_bins reserved = {[3'b100 : 3'b111]};
            option.comment = "vplan §4.1 — legal cmd encodings + reserved violation";
        }
 
        // ── Range bins on addr; ignore bin on architecturally unused
        cp_addr: coverpoint addr {
            bins boot_rom = {[16'h0000 : 16'h0FFF]};
            bins sram     = {[16'h1000 : 16'h3FFF]};
            bins dram     = {[16'h4000 : 16'hBFFF]};
            bins mmio     = {[16'hC000 : 16'hEFFF]};
            // The 0xF000..0xFFFF region is reserved for future test-mode
            // registers. Documented out of scope for the current release.
            ignore_bins test_mode_reserved = {[16'hF000 : 16'hFFFF]};
            option.comment = "vplan §4.2 — release-N memory regions; "
                              + "F000+ reserved for release-N+1";
        }
 
        // ── Wildcard bins on flags — bit-pattern scenarios
        cp_flags: coverpoint flags {
            // Privilege flag (bit 7) set, all other bits free
            wildcard bins privileged = {8'b1???_????};
            // Cache-hint bits (bits 3:2) both set, others free
            wildcard bins cache_hint = {8'b????_11??};
            // Reset shape: bits 7 and 0 both set, middle bits free
            wildcard bins handshake  = {8'b1???_???1};
            option.comment = "vplan §4.3 — flag-bit scenarios per AXI sideband spec";
        }
    endgroup
 
    function new();
        cg_mem = new();
    endfunction
 
    function void post_randomize();
        cg_mem.sample();
    endfunction
endclass

What this code does. Models a memory-controller transaction with three coverpoints, each using a different special-purpose bin form alongside named bins. cp_cmd uses illegal_bins for the reserved encodings — if the constraint solver ever produces one, the simulator fires an error and surfaces the contract violation immediately. cp_addr uses ignore_bins for the future-feature region — those addresses can legally appear but they are not counted in the coverage denominator. cp_flags uses wildcard bins to express three bit-pattern scenarios that would otherwise require enumerating dozens of matching values.

How to simulate it. Compile with coverage enabled, run 1000 randomised transactions, dump coverage with the simulator's reporter.

Expected output (urg-style, partial).

cg_mem coverage report
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
Group  cg_mem                                  coverage   91.7%
  cp_cmd      nop                              100.0%   ( 242 hits )
              rd                               100.0%   ( 278 hits )
              wr                               100.0%   ( 268 hits )
              rfr                              100.0%   ( 212 hits )
              reserved                       ILLEGAL    (   0 hits )   ← good
  cp_addr     boot_rom                         100.0%   ( 261 hits )
              sram                             100.0%   ( 251 hits )
              dram                             100.0%   ( 230 hits )
              mmio                             100.0%   ( 258 hits )
              test_mode_reserved              IGNORE    (   0 hits — excluded)
  cp_flags    privileged                       100.0%   ( 514 hits )
              cache_hint                       100.0%   ( 244 hits )
              handshake                          0.0%   (   0 hits )   ← gap
 
(coverage denominator excludes illegal_bins and ignore_bins)

What to read out of this. The reserved illegal bin reads ILLEGAL — 0 hits, which is the right outcome — the design contract held, no reserved encoding ever appeared. The test_mode_reserved ignore bin reads IGNORE — excluded, meaning the coverage denominator does not count it; if any sample landed there, it was silently dropped. The wildcard bin handshake is at 0%, a real gap — random stimulus happened not to produce a flags value with both bit 7 and bit 0 set; the next directed test is the closure path.

Debug Lab — "The Illegal Bin Reads Zero. Are We Safe, or Is the Simulator Lying?"

A subtle failure mode: an illegal_bins declaration that reads zero hits can mean either "the design contract held" (good) or "the illegal bin is silently disabled / mis-scoped / never sampled" (the bug ships). Distinguishing the two takes diligence.

Buggy code
SystemVerilog — an illegal bin that reads zero for the wrong reason
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
covergroup cg_state @(posedge clk);
    cp_state: coverpoint state {
        bins         legal       = {IDLE, ACTIVE, DONE};
        illegal_bins encoding_err = {2'b11};
    }
endgroup
 
// In the testbench:
initial begin
    // ── BUG: the covergroup is constructed AFTER the first reset
    //          pulse, during which the RTL momentarily produces 2'b11.
    rst_n = 0;
    @(posedge clk);
    state = 2'b11;        // illegal encoding briefly held during reset
    @(posedge clk);
    rst_n = 1;
 
    cg_state cg = new();   // ← constructed too late, the violation already passed
end
 
// After regression:
//   cp_state.legal          100.0%
//   cp_state.encoding_err   ILLEGAL  (0 hits)
//   No simulator error.
//   Engineers conclude the design contract held.
Symptom

The covergroup compiles, the regression runs, the report says encoding_err: ILLEGAL (0 hits). The verification lead reviews the report and concludes the design has never produced the illegal encoding — confidence in the contract is high, sign-off proceeds. Bring-up later discovers a reset-window glitch where state briefly holds 2'b11 for one cycle before the FSM moves to IDLE. The illegal encoding was happening in simulation too — the covergroup simply wasn't constructed in time to see it.

Root cause

Three independent factors converged on the false-clean report:

  1. The covergroup was constructed after the first reset pulse. Any @(posedge clk) sampling event that fired during reset was lost — the handle was null.
  2. The illegal_bins check runs as part of coverage sampling; if sampling does not happen, the check does not run. An illegal bin that never gets sampled cannot fire a violation report — it simply reads zero, indistinguishable from a real clean.
  3. The reporting tool does not distinguish "zero hits because the contract held" from "zero hits because the bin was never sampled." Both render as ILLEGAL (0 hits).

The bug is structural: the illegal-bin contract is enforced only at sample time, and the engineer never verified that the sampling event covered the windows where the violation could occur. A clean illegal bin is informative only when the bin was sampled at the moments the contract applies.

Fix

Two-part fix. First, ensure the covergroup is constructed before any simulation activity that could violate the contract — typically in an initial block before the first reset edge. Second, add a sanity check that confirms the illegal bin was exposed to values it could have hit, not just that it didn't hit them.

SystemVerilog — fixed construction order plus exposure audit
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Construct the covergroup before any clock activity.
cg_state cg = new();   // top-level instantiation, lives at time 0
initial begin
    rst_n = 0;
    @(posedge clk);
    state = 2'b11;
    @(posedge clk);
    rst_n = 1;
end
 
// In a separate audit covergroup, deliberately sample all state encodings
// (including the illegal one) into a parallel coverpoint with no illegal_bins.
// This proves the sampling path was exercising the value space.
covergroup cg_state_audit @(posedge clk);
    cp_state_raw: coverpoint state {
        bins idle     = {IDLE};
        bins active   = {ACTIVE};
        bins done     = {DONE};
        bins reserved = {2'b11};   // counted here — confirms exposure
    }
endgroup
 
// If cg_state_audit.cp_state_raw.reserved is nonzero AND
//    cg_state.cp_state.encoding_err is zero,
// the discrepancy means the illegal_bins covergroup is mis-constructed —
// not that the design is clean.

The discipline rule that prevents recurrence: a clean illegal bin is only evidence when the sampling event has been audited to cover the windows where the contract applies. For RTL contracts that apply at reset, the covergroup must be alive at time 0. For contracts that apply at specific protocol phases, the covergroup's sampling event must fire during those phases. Without that audit, an illegal_bins ILLEGAL (0) report is a guess, not a proof.

The complementary tool: write an SVA assertion for the same property. The assertion's sub-cycle granularity catches the reset-window glitch the illegal_bins form misses. Many production environments use both — the assertion is the temporal contract, the illegal bin is the coverage-report audit trail.

Industry Context — Where These Forms Earn Their Keep

  • AXI/AXI-Lite/AHB protocol verification. illegal_bins on the encoded response codes — the spec defines OKAY, EXOKAY, SLVERR, DECERR (2-bit BRESP/RRESP), and reserved encodings are illegal. The covergroup makes them illegal bins; the assertion library makes them assertion violations; both surface the same violation differently.
  • DDR4 / LPDDR5 controller verification. Wildcard bins on the command pattern (RAS/CAS/WE/CS 4-bit combinations) — every legal DDR command is a 4-bit pattern, the reserved combinations are wildcard-binned as illegal. The bit-pattern form makes the coverage source legible against the JEDEC command-encoding table.
  • PCIe TLP-type coverage. Ignore bins on TLP types the device class doesn't implement (a Root Complex's coverage model on an Endpoint's exclusive TLP types, for instance). The ignore-bin form documents the device-class scope cleanly.
  • UVM register-model coverage. The UVM library's built-in coverage hooks routinely use illegal_bins on register fields whose RAL access modes are RO, where any write activity is a contract violation — the illegal bin surfaces the bug, the RAL report ties it to the field name, the dashboard shows the violation.
  • Aerospace/defence flows. DO-254 and ARP4754A artefacts require traceability between every spec row and its verification evidence; illegal_bins with option.comment citing the spec section becomes part of the certification package.

The form choice is rarely controversial in mature flows — protocol spec violations are illegal bins, out-of-scope encodings are ignore bins with citations, bit-pattern scenarios are wildcard bins. The discipline is consistent enough across vendors that an engineer moving between teams reads the same shapes.

Interview Q&A — Ten Questions You Will Be Asked

A counted bin whose value set is described by a bit pattern with ? as a don't-care character. Any sampled value whose non-? bits match the pattern lands in the bin. Useful for protocol fields whose verification scenarios are described by bit position rather than by specific values — privilege flags, interrupt vectors, AXI sideband bits.

Coding Guidelines — Seven Rules for Special-Purpose Bin Discipline

  1. Match the bin form to the spec language. "Illegal" → illegal_bins. "Reserved" / "test-mode-only" / "future-feature" → ignore_bins with citation. "Bit pattern" → wildcard bins. "Value range" / "value list" → counted bins. The reviewer should read the bin form and recognise the verification-plan row directly.
  2. Every ignore_bins cites an architectural reason in option.comment. Either the value is unreachable (cite the RTL constraint that makes it unreachable) or it is out-of-scope (cite the verification-plan row). Code review rejects ignore-bin additions without the citation.
  3. For CI regression covergroups, force fatal severity on illegal bins. Default warning severity loses violations in the warning torrent. Use type_option.illegal_bins_error = 1 or the simulator's fatal-on-illegal flag. Interactive debug runs can opt out per-tool.
  4. Audit illegal-bin exposure with a parallel counted bin. A clean illegal_bins ILLEGAL (0) is evidence only when paired with an audit coverpoint that confirms the value space was being sampled. Production covergroups maintain the audit pair on every contract-critical illegal bin.
  5. Construct covergroups before any simulation activity that could violate the contract they audit. For reset-window contracts, the covergroup must be alive at time 0 — typically declared at module/program scope rather than inside an initial block.
  6. Pair illegal_bins with SVA for sub-cycle temporal contracts. illegal_bins runs in the Postponed region — sub-cycle violations are invisible. SVA assertions run with configurable region granularity. Use both for the same scenario when the contract has a sub-cycle component.
  7. Wildcard bins are for bit-pattern scenarios, not value ranges. When the spec describes "any value where bit N is set," use wildcard bins. When it describes "any value in [lo:hi]," use a range bin. The choice matters for source legibility, not for coverage outcome.

Summary

wildcard bins, illegal_bins, and ignore_bins are the three special-purpose bin forms that extend named-bin discipline beyond counted partitioning. Wildcard bins handle bit-pattern scenarios. Illegal bins encode "must never happen" design contracts and fire runtime violations. Ignore bins document architectural out-of-scope with the discipline rule that every ignore bin cites its reason. Each form has a correct use case and a misuse case the protocol identifies — the value of the page is the decision tree that picks the right tool. Module 11.6 builds the cross-coverage primitive, which inherits all three special-purpose forms (illegal and ignore versions inside cross use the binsof/intersect syntax to scope across the cross's Cartesian product).