Dynamically building bins with don't care

I have an array of N bits where I want to make sure that I cover “adjacent” bits, but I don’t necessarily care about the other ones.
Clearly if N was small I could have simply written something like:

mycp: coverpoint var
{
  bins pos0 = {4'b??11};
  bins pos1 = {4'b?11?};
  bins pos2 = {4'b11??};
 }

But if N is large, than it becomes cumbersome. So I thought I could write something like this instead:

typedef logic [N-1:0] bins_queue[$];
mycp: coverpoint var
{
  bins adjacent [] = find_adjacent();
}

function bins_queue find_adjacent();
  bins_queue bq;
  for (int i=0; i < N; i++) begin
    logic [N-1:0] data = 'x;
    data = 2'b11 << i | data;
    bq.push_back(data);
  end
  return bq;
endfunction

besides that it doesn’t work (not sure if it’s a tool vendor issue, but my tool reports that it cannot cover x), is this the right approach? is there any other strategy I can use?

Thanks for any input.

Coverpoint bins do not support don’t cares; it uses the === operator for matching values. The wildcard keyword only works as a don;t care when constructing a single bin by expanding the set of values to be matched.

One approach I can think of is using an array of covergroups, where the coverpoint uses the wildcard equality in its expression.

module tb;
  parameter N = 8;
  typedef logic [N-1:0] data_t;
  typedef data_t bins_queue[$];
  const bins_queue adj = find_adjacent();
  data_t v;
  covergroup cg(ref data_t data, input data_t match);
    option.per_instance = 1;
    mycp: coverpoint data ==? match
    {
      bins is_match  = {1};
    }
  endgroup

  cg cgi[N];
  real c;
  int h,t;
  initial begin
    foreach(cgi[i]) cgi[i] = new(v,adj[i]);
    
    $display(c,,h,,t);

    v=30'b11;
    foreach(cgi[i]) cgi[i].sample();
    c = cg::get_coverage(h,t);
    $display(c,,h,,t);
      v=4'b1100;
    foreach(cgi[i]) cgi[i].sample();
    c = cg::get_coverage(h,t);
    $display(c,,h,,t);
      v='1;
    foreach(cgi[i]) cgi[i].sample();
    c = cg::get_coverage(h,t);
    $display(c,,h,,t);
  end
  
  
function automatic bins_queue find_adjacent();
  bins_queue bq;
  logic [N-1:0] data;
  for (int i=0; i < N-1; i++) begin
    data ='x;
    data[i+:2] = '1;
    bq.push_back(data);
  end
      $displayb("%p",bq);

  return bq;
endfunction
endmodule

Hi Dave,

thanks a lot for your suggestion.
I’ve tried that on edaplayground but I don’t think the results were the ones expected:

# run -all
# '{xxxxxx11, xxxxx11x, xxxx11xx, xxx11xxx, xx11xxxx, x11xxxxx, 11xxxxxx}
# 0           0           0
# 25          2           8
# 37.5        3           8
# 100         8           8
# exit
# End time: 03:37:22 on Aug 14,2025, Elapsed time: 0:00:01

For the value v = 30'b11 the coverage reported is 2, but I’m not sure why, as I expected only the xxxxxx11 should match 30'b11. Then I looked at the number of instances of the cg, and I think it should actually be N-1 as we can only have N-1 combinations meeting the “adjacent” criterion defined by the function.

With that change the result for the first value is correct:

# '{xxxxxx11, xxxxx11x, xxxx11xx, xxx11xxx, xx11xxxx, x11xxxxx, 11xxxxxx}
# 0                  0           0
# 14.28571428571429  1           7
# 28.57142857142857  2           7
# 100                7           7
# exit
# End time: 04:00:05 on Aug 14,2025, Elapsed time: 0:00:01

where v=30'b11 is expected to match only xxxxxx11 but I can’t see why v=4'b1100 is covered twice, as I’d expect it to only match xxxx11xx.

What am I missing?

v=4'b1100 is not being covered twice; it’s just that h returns the cumulative coverage because 'b11 is already covered after the second sample()

how silly could I be!! :roll_eyes: