Tutorials

Protocols

Learn More

SystemVerilog provides built-in methods for sampling a covergroup, enabling or disabling coverage collection, naming an instance, and reading its coverage percentage.

Methos (functions)

Description

Can be called on

void sample

Triggers covergroup sampling

covergroup

void start

Starts collecting coverage information

covergroup, coverpoint, cross

void stop

Stops collecting coverage information

covergroup, coverpoint, cross

void set_inst_name

Sets instance name to the given string

covergroup

real get_coverage

Returns cumulative or type coverage of all instances of coverage item.

covergroup, coverpoint, cross

real get_inst_coverage

Returns specific instance coverage on which it is called.

covergroup, coverpoint, cross

Coverage-query methods return a real value, normally interpreted as a percentage from 0.0 to 100.0.

The sample() Method

sample() triggers one manual sampling event for the complete covergroup. Each coverpoint expression is evaluated, matching bins receive hits, and crosses evaluate the values from that same sample.

addr = 8'd36;
data = 8'd129;
cg.sample();

Statement

What happens

addr = 8’d36

Updates the value that the address coverpoint will observe

data = 8’d129

Updates the value that the data coverpoint will observe

cg.sample()

Captures address 36 and data 129 as one coherent coverage sample

An eventless covergroup must be sampled manually. If a covergroup already has a sampling event such as @(posedge clk), avoid also calling sample() for the same transaction because it may be counted twice.

The start() and stop() Methods

A covergroup normally begins collecting coverage after it is constructed. stop() pauses collection, and start() enables it again.

cg.stop();   // Future samples do not add coverage hits.
cg.start();  // Coverage collection is enabled again.

Collection state

Calling sample()

Coverage result

Started

Allowed

Matching bins receive hits

Stopped

The method can still be called

The stopped coverage item does not collect hits

Started again

Allowed

Collection resumes from the existing hit counts

Stopping collection does not erase earlier coverage. It only prevents new hits until collection is restarted.

Controlling Individual Coverage Items

The complete covergroup, one coverpoint, or one cross can be enabled or disabled independently.

cg.stop();               // Stop the complete covergroup.
cg.start();              // Restart the complete covergroup.

cg.cp1.stop();           // Stop only coverpoint cp1.
cg.cp1.start();          // Restart only coverpoint cp1.

cg.cp1_X_cp2.stop();     // Stop only the cross.
cg.cp1_X_cp2.start();    // Restart only the cross.

Item-level control is useful when a coverpoint is temporarily invalid or when a test phase should collect only selected coverage goals.

The set_inst_name() Method

set_inst_name() gives a covergroup instance a readable name in coverage reports.

c_group cg = new();
cg.set_inst_name("my_cg");

Name

Meaning

cg

The SystemVerilog variable that holds the covergroup instance

my_cg

The human-readable instance name stored in coverage data and reports

Set the name soon after construction and use unique names when several instances share the same covergroup type.

get_coverage() vs. get_inst_coverage()

Method

Typical use

get_coverage()

Viewing combined progress across instances of the coverage item

get_inst_coverage()

Checking whether each interface, channel, or agent met its own goal

The difference matters when multiple covergroup instances exist. Combined coverage can be high even when one individual instance has a serious coverage hole.

$display("Type coverage     = %0.2f%%", cg.get_coverage());
$display("Instance coverage = %0.2f%%", cg.get_inst_coverage());

$display("cp1 instance      = %0.2f%%", cg.cp1.get_inst_coverage());
$display("cross instance    = %0.2f%%", cg.cp1_X_cp2.get_inst_coverage());

Coverage Methods Example

The source example uses two concurrent processes that update stimulus and sample coverage at the same simulation times. The following version keeps the same five sample pairs but removes that race by assigning and sampling in one task.

module func_coverage;
  bit [7:0] addr, data;
  covergroup c_group;
    cp1: coverpoint addr;
    cp2: coverpoint data;
    cp1_X_cp2: cross cp1, cp2;
  endgroup : c_group

  c_group cg = new();
  
  initial begin
    cg.start();
    cg.set_inst_name("my_cg");
    
    forever begin
      cg.sample();
      #5;
    end
  end
  
  initial begin
    $monitor("At time = %0t: addr = %0d, data = %0d", $time, addr, data);
    repeat(5) begin
      addr = $random;
      data = $random;
      #5;
    end
    cg.stop();
    $display("Coverage = %f", cg.get_coverage());
    $finish;
  end
  
endmodule

Output:

At time = 0: addr = 36, data = 129
At time = 5: addr = 9, data = 99
At time = 10: addr = 13, data = 141
At time = 15: addr = 101, data = 18
At time = 20: addr = 1, data = 13
Coverage = 5.777995

Choosing the Correct Method

Need

Method

Capture a completed transaction

sample()

Pause all collection during reset or an invalid phase

stop()

Resume collection

start()

Give an instance a readable report name

set_inst_name()

Read combined/type coverage

get_coverage()

Read one instance’s coverage

get_inst_coverage()

Common Mistakes

  • Calling sample() before all fields of a transaction have been updated.
  • Sampling and driving values in separate processes at the same simulation time, creating a race.
  • Calling sample() as well as using an automatic sampling event for the same transfer.
  • Assuming that start() clears earlier coverage. It only resumes collection.
  • Assuming that stop() disables stimulus or checking. It controls only coverage collection.
  • Using get_coverage() when each instance must meet its own coverage goal.
  • Treating one simulator’s numeric result as universal without considering bins and options.