Part 5 · Functional Coverage · Intermediate
wildcard bins & with Filtering
Pattern-matching wildcard bins, with-expression filtering for computed subsets like primes and aligned addresses, and combining filters with iff guards.
wildcard bins: matching bit patterns
Prefixing a bin with wildcard makes x, z and ? in the bin's values act as don't-care bit positions. One pattern then matches a whole family of values — every even number, every value in a tag class, every address with a fixed prefix — without enumerating them.
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
}
endgroupWithout the wildcard keyword those x/z/? bits would be literal X/Z match values — which sampled 2-state data never equals, so the bin would silently never hit. The keyword changes the matching semantics, not just the syntax. Note that a wildcard bin is still one bin (unless you add []): hitting any matching value covers it.
with filtering: computed subsets
bins name = {[lo:hi]} with (expression) keeps only the values in the set for which the expression — evaluated per candidate value, referenced as item — is true. This is how you bin subsets that are defined by arithmetic rather than bit patterns: alignment, divisibility, population count, range arithmetic. The filter runs at elaboration over the candidate set, so the expression must be a constant function of item.
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;
endfunctionCHOOSING THE SUBSET TOOL
subset 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 runtime condition (NOT a iff (expr) on the coverpoint —
property of the value itself) with() cannot see other signalsCombining with iff guards
with() and wildcard select WHICH VALUES belong to a bin — a static, per-value question. iff decides WHETHER THIS SAMPLE counts at all — a dynamic, per-sample question about the rest of the world. They compose naturally: the iff guard runs first (skip or sample), then the value is matched against the bins.
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
}
endgroupwith() expressions see only item — sampling-time signals belong in iff, not in the filter.
Filters apply per bin, so one coverpoint can mix filtered, wildcard, plain, and ignore bins freely.
An empty filtered set (predicate never true over the range) is a silent always-zero bin — most tools warn; treat the warning as an error.
Interview angle: “cover only 64-byte-aligned addresses” — the expected answer is with (item % 64 == 0), plus knowing wildcard handles the same when alignment is a power of two (low bits zero).
Key takeaways
wildcard makes x/z/? don't-care positions — one pattern, a whole value family, one bin (add [] for per-value).
with (expression) keeps set values where the item-predicate is true — alignment, powers of two, primes.
with/wildcard pick values statically; iff gates samples dynamically — different questions, freely combined.
with() filters are evaluated at elaboration — the predicate must be a constant function of item only.
Common pitfalls
Writing pattern bins without the wildcard keyword — ? bits become literal X/Z matches that never hit 2-state data.
Referencing other signals inside with() — it cannot see them; that condition belongs in iff.
A with() predicate that is never true over the range — an unhittable bin permanently capping coverage below 100%.
Huge ranges with [] plus a permissive filter — bin explosion through the back door.