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()