Wildcard based functional coverage

Hi, I want to write for 12 bit signal, using wildcard.

Here is sample code.


module fcov_rate
(
   // Clock and Resets
   input [12:0]  i_rx_config
);

covergroup client_rate;
      option.per_instance = 1;

      RX_CLIENT_RATE : coverpoint i_rx_config
      {
         wildcard bins RATE_0      = {12'b????_????_??10};
         wildcard bins RATE_1      = {12'b????_????_??01};
         wildcard bins RATE_2      = {12'b????_????_01??};
         wildcard bins RATE_3      = {12'b????_??01_????};
         wildcard bins RATE_4      = {12'b????_01??_????};
         wildcard bins RATE_5      = {12'b???1_????_????};
         wildcard bins RATE_6      = {12'b??1?_????_????};
         wildcard bins RATE_7      = {12'b?1??_????_????};
      }

endgroup

client_rate cov_config_inst;

//////////////////////////////////////////////////

initial begin
  cov_config_inst = new();
end

endmodule

With this wildcard method, I am able to achieve desired coverage, but let’s say if I have 32 bit register and want to write coverage on that, then wildcard will be messy,

I can not use 32’b???..??? (?/X for 32 bits). So, I tried with following code,


module fcov_rate
(
   // Clock and Resets
   input [31:0]  i_tx_config
);

covergroup client_rate;
      option.per_instance = 1;

      TX_CLIENT_RATE : coverpoint i_tx_config
      {
         wildcard bins RATE_0      = {i_tx_config[1:0] == 2'b10};
         wildcard bins RATE_1      = {i_tx_config[1:0] == 2'b01};
         wildcard bins RATE_2      = {i_tx_config[3:2] == 2'b01};
         wildcard bins RATE_3      = {i_tx_config[5:4] == 2'b01};
         wildcard bins RATE_4      = {i_tx_config[7:6] == 2'b01};
      }
endgroup

client_rate cov_config_inst;

//////////////////////////////////////////////////

initial begin
  cov_config_inst = new();
end

endmodule

Above code is compile clean, but not able to hit bins.

Is there any other way to just part-select of coverpoint reference.

I know that I can achieve this using multiple coverpoint, but I don’t want to write new coverpoint for each case like,


      FCOV_TX_CLIENT_RATE : coverpoint i_tx_config[1:0]
      {
         wildcard bins RATE_0      = {2};
         wildcard bins RATE_1      = {1};
      }

      FCOV_TX_CLIENT_RATE : coverpoint i_tx_config[3:2]
      {
         wildcard bins RATE_2      = {1};
      }

      FCOV_TX_CLIENT_RATE : coverpoint i_tx_config[5:4]
      {
         wildcard bins RATE_3      = {1};
      }

Is there any better solution ?

In reply to J_M:

It’s hard to find a generic algorithm for the bins in your code, but there are a couple approaches you can take.

You can use a bin set expression to create a list of matching bin values

bit [12:0] rate[8][] = '{ {12'b????_????_?010,12'b????_????_?110}.
                          {12'b????_????_??01}.
                           ...
                        }; // you can use whatever procedural code you want to
                           // construct this array before constructing the covergroup

covergroup client_rate;
      option.per_instance = 1;
 
      RX_CLIENT_RATE : coverpoint i_rx_config
      {
         wildcard bins RATE_0      = rate[0];
         wildcard bins RATE_1      = rate[1];
         wildcard bins RATE_2      = rate[2];
         wildcard bins RATE_3      = rate[3];
         wildcard bins RATE_4      = rate[4];
         wildcard bins RATE_5      = rate[5];
         wildcard bins RATE_6      = rate[6];
         wildcard bins RATE_7      = rate[7];
      
endgroup

You can send your coverpoint values through a function and use its return value to select a bin.

bit [12:0] rate[8][] = '{ {12'b????_????_?010,12'b????_????_?110}.
                          {12'b????_????_??01}.
                           ...
                        }; // you can use whatever procedural code you want to
                           // construct this array before constring the covergroup

covergroup client_rate;
      option.per_instance = 1;
 
      RX_CLIENT_RATE : coverpoint somefunc(i_rx_config)
      {
         bins RATE[8]      = {[0:7]};
      }
endgroup

function int somefunc(bit [12:0] samp);
   return ... some value between 0 and 7

Hi Dave,

Thanks for your reply, yes definitely I can use ?/X and pass it using variable or function.

Here I used defined based coverage and using ‘iff’ I am hitting the bins.



`define CLIENT_RATE(DIR, REF, ID) \
``DIR``_CLIENT_RATE_``ID : coverpoint 1 iff (!i_sample)  \
{ \
  bins RATE_0 = {1} iff (``REF[``ID][0]); \
  bins RATE_1 = {1} iff (``REF[``ID][1]); \
  bins RATE_2 = {1} iff (``REF[``ID][2]); \
  bins RATE_3 = {1} iff (``REF[``ID][3]); \
  bins RATE_4 = {1} iff (``REF[``ID][4]); \
  bins RATE_5 = {1} iff (``REF[``ID][5]); \
  bins RATE_6 = {1} iff (``REF[``ID][6]); \
  bins RATE_7 = {1} iff (``REF[``ID][7]); \
  bins RATE_8 = {1} iff (``REF[``ID][8]); \
  bins RATE_9 = {1} iff (``REF[``ID][9]); \
}
module fcov_rate
(
   // Clock and Resets
   input [9:0][12:0]  i_rx_config
);
 
covergroup client_rate;
  option.per_instance = 1;

  `CLIENT_RATE(RX,i_rx_cfg,0)
  `CLIENT_RATE(RX,i_rx_cfg,1)

endgroup
 
client_rate cov_config_inst;
 
initial begin
  cov_config_inst = new();
end

endmodule

Above code serves my purpose and able to use same define multiple times by just passing different reference to the define.

Now let say I have 8 different client_cfg(client_cfg[8]) and I am passing different cfg instance in define reference. but client_cfg 0 to 6 support RATE_0 to RATE_9 and client_cfg only support RATE_0 to RATE_5. So I my coverage goal is not achieving 100% as RATE_6 to RATE_9 are not present for client_cfg[7], client_cfg[8] and client_cfg[9].

Do we have any method to not define bins if certain condition is not matched/satisfied?

Line below example,


`define CLIENT_RATE(DIR, REF, ID) \
``DIR``_CLIENT_RATE_``ID : coverpoint 1 iff (!i_sample)  \
{ \
  bins RATE_0 = {1} iff (``REF[``ID][0]); \
  bins RATE_1 = {1} iff (``REF[``ID][1]); \
  bins RATE_2 = {1} iff (``REF[``ID][2]); \
  bins RATE_3 = {1} iff (``REF[``ID][3]); \
  bins RATE_4 = {1} iff (``REF[``ID][4]); \
  bins RATE_5 = {1} iff (``REF[``ID][5]); \
  bins RATE_6 = {1} iff (``REF[``ID][6]); \
  if(``ID < 7) begin \
    bins RATE_7 = {1} iff (``REF[``ID][7]); \
    bins RATE_8 = {1} iff (``REF[``ID][8]); \
    bins RATE_9 = {1} iff (``REF[``ID][9]); \
  end \
}

In reply to J_M:

The is no way to evaluate an expression as part of a macro, and there is no way to conditionally create a named bin within a coverpoint. You can control the size of an array of bins, and the values in each bin at construction.

If you want to pursue using a macro, you could do

`define CLIENT_RATE(DIR, REF, ID) \
DIR``_CLIENT_RATE_``ID : coverpoint 1 iff (!i_sample)  \
{ \
  bins RATE_0 = {1} iff (REF[ID][0]); \
  bins RATE_1 = {1} iff (REF[ID][1]); \
  bins RATE_2 = {1} iff (REF[ID][2]); \
  bins RATE_3 = {1} iff (REF[ID][3]); \
  bins RATE_4 = {1} iff (REF[ID][4]); \
  bins RATE_5 = {1} iff (REF[ID][5]); \
  bins RATE_6 = {1} iff (REF`ID][6]); \
  bins RATE_7 = {1} iff (REF[ID][7] || ID >=7); \
  bins RATE_8 = {1} iff (REF[ID][8] || ID >=7); \
  bins RATE_9 = {1} iff (REF[ID][9] || ID >=7); \
  end \
}

This will slightly skew partial coverage results, but not what’s needed to get 100%

BTW: you do not need to be using all over the place except when you need to concatenate an identifier like: DIRCLIENT_RATE``ID