Part 5 · Functional Coverage · Intermediate
illegal_bins & ignore_bins
Runtime-error semantics of illegal_bins vs silent goal exclusion of ignore_bins, worked coverage math, the checker-vs-coverage debate, and reserved-value patterns.
Two exclusions with opposite personalities
ignore_bins and illegal_bins both remove values from the coverage goal, but they react to a hit in opposite ways. A sampled value landing in an ignore_bin is silently discarded — no error, no count, no effect on percentage. The same value landing in an illegal_bin raises a runtime error the moment it is sampled. ignore says “out of scope”; illegal says “this must never happen, and if it does, fail loudly”. illegal_bins also take precedence: a value claimed by both an ordinary bin and an illegal_bin is illegal.
WHAT HAPPENS WHEN A SAMPLE LANDS IN...
ordinary bin ignore_bins illegal_bins
hit count increments discarded runtime ERROR
in goal math YES removed from removed from
numerator AND goal (and sim
denominator may abort)
meaning scenario out of scope must never occur
on hit progress ✓ nothing test FAILSThe percentage math, worked
ignore_bins shrink the denominator — which means ignoring values makes the remaining coverage easier to close. That is exactly what you want for genuinely out-of-scope values, and exactly the abuse vector reviewers watch for.
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
}
endgroupGOAL MATH, STEP BY STEP
declared value bins: m[0]..m[7] 8 bins
ignore_bins {6}: m[6] removed 7 remain
illegal_bins {7}: m[7] removed 6 goal bins
simulation hits values: 0,1,2,4 → 4 goal bins hit
coverage = 4 / 6 = 66.7% ◄── NOT 4/8 (50.0%)
later, a sample of mode==7 arrives:
→ runtime error from illegal_bins "bad"; test FAILS
→ coverage math unchanged (illegal never counts)
a sample of mode==6:
→ silently discarded; still 66.7%Is illegal_bins doing the checker's job?
There is a genuine methodology debate here, and interviewers love it. The case against illegal_bins as checkers: error detection belongs in assertions and scoreboards, which run on every cycle or every transaction regardless of sampling; an illegal_bin only fires if the covergroup happens to sample at the guilty moment, fires once where an assertion gives waveform-linked debug, and buries a check inside a measurement construct where nobody looks for it. The case for : the covergroup is already sampling exactly the fields in question, the illegal encoding is part of the same value-space story the bins tell, and a one-line illegal_bin documents the constraint precisely where a reviewer reads the bin plan. Pragmatic resolution: assert the property in the RTL or interface as the primary check, and keep the illegal_bin as documentation plus a redundant tripwire — defense in depth, with the assertion as the load-bearing layer.
Reserved-value exclusion patterns
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
}
endgroupReserved spec encodings → ignore_bins, with a comment citing the spec section.
Configuration-unreachable values (narrower bus, smaller ID pool) → ignore_bins per build configuration.
Must-never-occur protocol violations → assertion first, illegal_bins as documented backup.
Every ignore_bins needs a justifying comment — uncommented ignores are presumed coverage-goal gaming until proven otherwise.
Key takeaways
ignore_bins silently remove values from numerator and denominator; illegal_bins error at runtime on a hit.
ignore_bins make coverage easier to close — legitimate for out-of-scope values, an abuse vector otherwise.
illegal_bins only fire when the covergroup samples — assertions are the primary checker; illegal_bins are backup.
Work the goal math: 8 bins, 1 ignored, 1 illegal → percentage is hits over 6, not 8.
Common pitfalls
Using ignore_bins to bury bins the team failed to hit before a deadline — false closure, audit risk.
Relying on illegal_bins as the only protocol check — violations between samples go completely undetected.
Forgetting illegal_bins precedence — a value in both a named bin and an illegal_bin errors; it is not covered.
Uncommented ignore_bins — reviewers cannot distinguish out-of-scope from coverage-gaming.