Tutorials

Protocols

Learn More

A coverpoint is an integral expression or variable that has to be covered on sampling the covergroup. A covergroup can have one or more coverage points that can be labeled. Each coverpoint is associated with single or multiple bins that can be explicitly defined.

In simple words:

– The coverpoint tells us what to observe.
– The bins tell us which values are important.
– Sampling tells us when to observe the value.

Syntax:

covergroup <covergroup_name>;
  <coverpoint label>: coverpoint <variable_or_expression>;
  <coverpoint label>: coverpoint <variable_or_expression>;
  ...
endgroup

//Example:
covergroup cg @(posedge clk); 
  cp1: coverpoint addr; 
  cp2: coverpoint data; 
endgroup : cg

The label is not compulsory, but meaningful labels make coverage reports much easier to read.

Coverpoint Example

module coverpoint_example;
  logic       clk;
  logic [3:0] addr;
  logic [2:0] data;

  covergroup bus_cg @(posedge clk);
    cp_addr: coverpoint addr;
    cp_data: coverpoint data;
  endgroup

  bus_cg bus_cov = new();
endmodule

At every positive edge of `clk`:

– `cp_addr` samples the current value of `addr`.
– `cp_data` samples the current value of `data`.

Because no bins are explicitly declared, the simulator creates automatic bins.

Bins in functional coverage

A bin is a coverage bucket. When a sampled value belongs to a bin, the hit count of that bin increases.

Suppose a two-bit signal can have values 0, 1, 2, and 3. If the coverage model has one bin for each value, sampling value 2 increases the hit count of the bin that represents value 2. Bins help us see which values occurred and which values are still missing.

The construct bins provide a facility to create a set of bins for a particular range or all possible values in the range for the mentioned coverpoint variable.

  1. The bins can be generated automatically or explicitly written by an engineer.
  2. They can be excluded or ignored from the coverage. 
  3. They can also be marked as illegal.

Syntax:

covergroup <covergroup_name>;
<coverpoint label>: coverpoint <coverpoint_name> {bins <bin_name> = {<values>} };
  ...
endgroup

Automatic Bins

When a coverpoint does not contain an explicit bin declaration, SystemVerilog creates automatic bins.

module automatic_bins_example;
  logic [3:0] addr;
  logic [2:0] data;
  logic       en;

  covergroup automatic_cg;
    cp_addr: coverpoint addr;
    cp_data: coverpoint data;
    cp_en:   coverpoint en;
  endgroup

  automatic_cg automatic_cov = new();

  initial begin
    addr = 4'd5;
    data = 3'd3;
    en   = 1'b1;
    automatic_cov.sample();
  end
endmodule

Since bins are not explicitly specified. They are auto-generated as follows.

variables

bins

addr

cp1.auto[0], cp1.auto[1], … cp1.auto[15]

data

cp2.auto[0], cp2.auto[1], … cp2.auto[7]

en

cp3.auto[0], cp3.auto[1]

When sample() is called:

  • The bin for address 5 is hit.
  • The bin for data 3 is hit.
  • The bin for enable 1 is hit.

For a large integral range, the simulator limits and distributes automatic bins according to the auto_bin_max option. Use explicit bins when the values need to be grouped according to the specification.

Explicit bins

Explicit bins allow the verification engineer to decide how values should be grouped.

Syntax:

covergroup <covergroup_name>;
  <label>: coverpoint <variable_or_expression> {
    bins <bin_name> = {<values_or_ranges>};
  }
endgroup

Explicit bins are useful for:

  • Important individual values
  • Boundary values
  • Groups of related values
  • Small, medium, and large ranges
  • Legal, ignored, or illegal values
module func_coverage;
  logic [3:0] addr; 
  logic [2:0] data;
  logic en;

  covergroup c_group; 
    cp1: coverpoint addr {bins b1 = {1, 10, 12};
                          bins b2[] = {[2:9], 11};
                          bins b3[4] = {0:7};
                         }
    cp2: coverpoint data {bins b1 = {4,$};
                          bins b2[] = {2, 3, 6};
                         }
    cp3: coverpoint en {bins b1 = {1}; }
  endgroup

  c_group cg = new();
  ...
  ...
endmodule

variables

bins

Description

addr

bins b1 = {1, 10, 12};

Constructs single bin for 1, 10, 12 value. 

 

bins b2[] = {[2:9], 11};

Constructs 9 bins i.e.
b2[0] = 2, b2[1] = 3, b2[2] = 4, b2[3] = 5, b2[4] = 6, b2[5] = 7, b2[6] = 8, b2[7] = 9
b2[8] = 11.

 

bins b3[4] = {0:7};

Constructs 4 bins with possible values as
b3[0] = 0 ~1,
b3[1] = 2~3,

b3[2] = 4~5,

b3[3] = 6~7

data

bins b1 = {4,$};

Constructs single bin for 4~7

 

bins b2[] = {2, 3, 6};

Constructs 3 bins as

b2[0] = 2,

b2[1] = 3,

b2[2] = 6,

en

bins b1 = {1};

Constructs single bin for value = 1

Common Mistakes

Expecting a List to Create Separate Bins

bins selected = {1, 10, 12};

This creates one bin containing three values. To create a separate bin for each value, use an unsized bin array:

bins selected[] = {1, 10, 12};

Writing a Range Without Square Brackets

Incorrect: bins groups[4] = {0:7};

Correct: bins groups[4] = {[0:7]};

Using a Comma When a Range Is Intended

bins upper = {4, $};

This lists two values: 4 and the maximum value. To include every value from 4 through the maximum, write:

bins upper = {[4:$]};

Forgetting to Sample

An eventless covergroup does not collect coverage just because a variable changes. Call its sample() method after assigning the values to be measured.

Best Practices

  • Give each coverpoint and bin a meaningful name.
  • Define bins from the specification, not from convenience.
  • Separate important boundary values when they need individual attention.
  • Group ordinary values when individual bins would not provide useful insight.
  • Sample only stable and valid transaction data.
  • Avoid overlapping bins unless the overlap is intentional and documented.
  • Investigate unhit bins before changing or excluding them.