SystemVerilog Functional Coverage

 Functional Coverage 

Functional coverage is a user-defined metric that measures how much of the design specification has been exercised in verification.

 Defining the coverage model: 

Coverage model is defined using Covergroup construct.

The covergroup construct is a user-defined type. The type definition is written once, and multiple instances of that type can be created in different contexts.

Similar to a class, once defined, a covergroup instance can be created via the new()operator. A covergroup can be defined in a module, program, interface, or class.

Each covergroup specification can include,
  • A clocking event that synchronizes the sampling of coverage points
  • A set of coverage points
  • Cross coverage between coverage points
  • Optional formal arguments
  • Coverage options

 Example-1: 

covergroup cov_grp @(posedge clk);
  cov_p1: coverpoint a;
endgroup

cov_grp cov_inst = new();

 Example-2: 

covergroup cov_grp;
  cov_p1: coverpoint a;
endgroup

cov_grp cov_inst = new();
@(abc) cov_inst.sample();

In the example-1 clocking event specifies the event at which coverage points are sampled.
In the example-2 coverage sampling is triggered by calling built-in sample() method.

 Defining coverage points: 

A covergroup can contain one or more coverage points. A coverage point can be an integral variable or an integral expression. Each coverage point is associated with “bin”.On each sample clock simulator will increment the associated bin value.

The bins will automatically created or can be explicitly defined.

Automatic/Implicit Bins:

Automatically single bin will be created for each value of the coverpoint variable range. These are called automatic, or implicit, bins.
For an “n” bit integral coverpoint variable, 2^n number of automatic bins will get created.

module cov;
  logic       clk;
  logic [7:0] addr;
  logic       wr_rd;

  covergroup cg @(posedge clk);
    c1: coverpoint addr;
    c2: coverpoint wr_rd;
  endgroup : cg
  cg cover_inst = new();
  ...
endmodule

Below are the bins, will get created automatically,
    for addr:     c1.auto[0] c1.auto[1] c1.auto[2] … c1.auto[255]
    for wr_rd:   c2.auto[0]

Explicit bins:

bins” keyword is used to declare the bins explicitly to an variable.
Separate bin is created for each value in the given range of variable or a single/multiple bins for the rage of values.

Bins are explicitly declared with in curly braces { } along with the bins keyword followed by bin name and variable value/range, immediately after the coverpoint identifier.

Example on Bins Declaration,
module cov;
  logic       clk;
  logic [7:0] addr;
  logic       wr_rd;

  covergroup cg @(posedge clk);
    c1: coverpoint addr { bins b1 = {0,2,7};
                        bins b2[3] = {11:20};
                        bins b3   = {[30:40],[50:60],77};                        
                        bins b4[] = {[79:99],[110:130],140};
                        bins b5[] = {160,170,180};
                        bins b6    = {200:$};
                        bins b7 = default;}
    c2: coverpoint wr_rd {bins wrrd};
  endgroup : cg
  
  cg cover_inst = new();
  ...
endmodule
bins b1    = {0,2,7 };               //bin “b1” increments for addr = 0,2 or 7
bins b2[3] = {11:20};                //creates three bins b2[0],b2[1] and b2[3].and The 11 possible values are 
                                     //distributed as follows: (11,12,13),(14,15,16) and (17,18,19,20) respectively.
bins b3    = {[30:40],[50:60],77};   //bin “b3” increments for addr = 30-40 or 50-60 or 77
bins b4[]  = {[79:99],[110:130],140};//creates three bins b4[0],b4[1] and b4[3] with values 79-99,50-60 and 77 respectively
bins b5[]  = {160,170,180};          //creates three bins b5[0],b5[1] and b5[3] with values 160,170 and 180 respectively
bins b6    = {200:$};                //bin “b6” increments for addr = 200 to max value i.e, 255.
default bin;                         // catches the values of the coverage point that do not lie within any of the defined bins.

bins for transitions:

Transition of coverage point can be covered by specifying the sequence,
value1 =>  value2

It represents transition of  coverage point value from value1 to value2.
sequence can be single value or range,
value1 => value2 => value3 ….
range_list_1 => range_list_2

Example,
covergroup cg @(posedge clk);
  c1: coverpoint addr{ bins b1   = (10=>20=>30);
                       bins b2[] = (40=>50),(80=>90=>100=>120);
                       bins b3   = (1,5 => 6, 7);}
  c2: coverpoint wr_rd;
endgroup : cg

bins b1   = (10=>20=>30);                // transition from 10->20->30
bins b2[] = (40=>50),(80=>90=>100=>120); // b2[0] = 40->50 and b2[1] = 80->90->100->120
bins b3 = (1,5 => 6, 7);}                // b3 = 1=>6 or 1=>7 or 5=>6 or 5=>7

 ignore_bins 

A set of values or transitions associated with a coverage-point can be explicitly excluded from coverage by specifying them as ignore_bins.

covergroup cg @(posedge clk);
  c1: coverpoint addr{ ignore_bins b1 = {6,60,66};
                       ignore_bins b2 = (30=>20=>10); }
endgroup : cg

 illegal_bins 

A set of values or transitions associated with a coverage-point can be marked as illegal by specifying them as illegal_bins.

covergroup cg @(posedge clk);
  c1: coverpoint addr{ illegal_bins b1 = {7,70,77};
                       ignore_bins b2 = (7=>70=>77);}
endgroup : cg