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.

systemverilog
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 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.

systemverilog
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
diagram
CHOOSING 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 signals

Combining 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.

systemverilog
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
  • with() 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.