Panel For Example Panel For Example Panel For Example
SystemVerilog Coverage Syntax Explained

SystemVerilog Coverage Syntax Explained

Author : Adrian September 04, 2025

In hardware verification, there are typically two types of coverage: code coverage and functional coverage. Code coverage is automatically extracted from the design code by EDA tools, while functional coverage is user-specified to measure the progress of testing the design intent and functionality. Therefore, functional coverage has two key aspects:

  • It is specified by the user, not automatically inferred from the design code.
  • It is based on the design requirements and is independent of the actual design code and structure.

Functional coverage is primarily composed of covergroups, coverage points (coverpoints), cross coverage, coverage options, and coverage methods.

 

1. Covergroup

A covergroup is used to build a coverage model, encapsulating the model and its specifications. It can contain the following components:

  • A clocking event for synchronizing and sampling coverpoints.
  • Coverpoints.
  • Cross coverage.
  • Optional parameters.
  • Coverage options.

A covergroup is a user-defined type and can be defined within a package, module, program, interface, checker, or class. Similar to a class, a covergroup can be instantiated multiple times using the new() constructor. As shown below, covergroup name is "cg". An instance of cg, named cg_inst, was created through the new() constructor.

covergroup cg; ... endgroup cg cg_inst = new;

Parameters can be passed to a covergroup via the new() constructor. The parameter types can only be ref (treated as const ref) or input, but not

output or inout.

The timing for coverage sampling can be specified using an@event or the sample() method. A covergroup can contain one or more coverpoints. A coverpoint can cover a variable or an expression. Within a coverpoint, a set of bins can be defined to collect values or value transitions. Bins that collect a set of values are called state bins, while those that collect value transitions are called transition bins.

A common practice is to embed a covergroup definition within a class. This is known as an embedded covergroup declaration, which provides a simple way to cover class properties while preserving encapsulation.

 

2. Coverage Point

The sampling of a coverpoint expression (including an iff condition) occurs when the covergroup is sampled. A coverpoint creates a hierarchical scope and can have an optional label. If a label is used, it becomes the name of the coverpoint. This name can be used in cross coverage and for accessing the coverpoint's methods. If no label is specified and the coverpoint is associated with a single variable, the variable's name can be used as the coverpoint name. In other cases, the name is implementation-defined by the tool. Such automatically generated names are only for reporting and cannot be referenced elsewhere in the code.

A coverpoint bin associates a name and a count with a set of values or a sequence of value transitions. The corresponding count is incremented each time the specified value or transition sequence is matched. Each bin can be followed by an iff construct to specify a sampling condition; if the condition is false, the count will not be incremented. For transition bins, the count can increase by at most 1 per sample, regardless of how many times the same bin is hit.

You can create a separate bin for each value in a given range list by appending [] to the bin name. To distribute the values in a range list into a specific number of bins, you can specify a positive integer expression within the brackets []. If the fixed number of bins is less than the number of specified values, the tool attempts to distribute them evenly, with the last bin containing any remainder. If the number of bins is greater than the number of values, some bins will be empty.

A single bin can be created for a list of values by enclosing the values in {} after the assignment operator.

For range lists, you can use the notations [ expression : $ ] or [ $ : expression ].

If no bins are explicitly specified, they are created automatically. The maximum number of auto-created bins is determined by the auto_bin_max ( coverage option) .

The default keyword can be used to cover all other values not specified in the explicit bins. The default bin is not considered in the calculation of coverpoint coverage or cross coverage. Similarly, default sequence covers all other transitions not specified in explicit transition bins. A default or default sequence bin cannot be explicitly ignored. An error will occur if a bin is specified as both an ignore_bins and a default or default sequence.

wildcard bin allows X, Z, or ? to be treated as 0 or 1. For example:

wildcard bins g12_15 = { 4'b11?? };

If the sampled values are 1100, 1101, 1110, and 1111, the count for g12_15 will be incremented for each match.

Wildcard bins can also be used to create separate bins:

wildcard bins g12_15_array[] = { 4'b11?? };

The above code creates four separate bins: 1100, 1101, 1110, and 1111.

Wildcard bins can also be used for transition bins:

wildcard bins T0_3 = (2'b0x => 2'b1x);

The count for the T0_3 bin increases whenever any of the following value transitions occur, which is similar to the (0,1=>2,3) syntax:

00 => 10, 00 => 11, 01 => 10, 01 => 11

Specifying Transition Bins

The syntax for specifying transitions is as follows:

value1(range_list1) => value2(range_list2): This specifies that the sample following value1 must be value2. If range lists are used, SystemVerilog expands the transition to cover all combinations. For example:

1,5 => 6, 7

This is equivalent to:

( 1=>6 ), ( 1=>7 ), ( 5=>6 ), ( 5=>7 )

trans_item[* repeat_range]: This indicates that trans_item must be repeated repeat_range times consecutively. For example:

3 [* 5]

This is equivalent to:

3=>3=>3=>3=>3

You can also specify a range for the repetitions:

3 [* 3:5]

This is equivalent to:

( 3=>3=>3 ), ( 3=>3=>3=>3 ), ( 3=>3=>3=>3=>3 )

trans_item[-> repeat_range] or trans_item[= repeat_range]: This indicates the number of times trans_item appears, regardless of any other values in between. For example:

3 [-> 3]

This is equivalent to:

...=>3...=>3...=>3, where ... represents any sequence of transitions not containing the value 3. Another example:

1 => 3 [ -> 3] => 5

This is equivalent to:

1...=>3...=>3...=>3 =>5

 

3. Cross Coverage

A covergroup can specify cross coverage between two or more coverpoints or variables. If a variable is specified, SystemVerilog implicitly defines a coverpoint for it before including it in the cross. Therefore, the inputs to cross coverage are essentially coverpoints. Expressions cannot be used directly in a cross; they must first be defined as coverpoints.

Cross coverage provides an optional label, which creates a hierarchical scope for the bins defined within the cross. An iff condition can also be used to enable or disable the cross coverage calculation for a given sample.

Bins defined as defaultignored, or illegal in a coverpoint are not included in the cross. Cross coverage only allows crossing between coverpoints within the same covergroup; referencing a coverpoint from another group will result in a compilation error.

In addition to automatically generated bins, SystemVerilog allows users to define specific cross coverage bins using a bin selection expression. User-defined cross bins and auto-generated bins can coexist in the same cross. Any auto-generated bins not superseded by user-defined cross bins will be retained. For example:

int i,j; covergroup ct; coverpoint i { bins i[] = { [0:1] }; } coverpoint j { bins j[] = { [0:1] }; } x1: cross i,j; x2: cross i,j { bins i_zero = binsof(i) intersect {0}; } endgroup

The results for the x1 cross are:

<i[0],j[0]> <i[1],j[0]> <i[0],j[1]> <i[1],j[1]>

The results for the x2 cross are:

i_zero // user-specified bin for <i[0],j[0]> and <i[0],j[1]> <i[1],j[0]> // an automatically generated bin that is retained <i[1],j[1]> // an automatically generated bin that is retained

The binsof construct produces the bins of its expression, which can be an explicit coverpoint, a variable (for which a coverpoint is implicitly generated), or a coverpoint bin. The resulting bins can be further refined using the intersect syntax to select or exclude certain values. Multiple values can be selected using a comma-separated list, including single values, ranges of values, or open-ended ranges. For example:

[ $ : value ] => The set of values less than or equal to value [ value : $ ] => The set of values greater than or equal to value

Bin selections can also be combined using logical operators (&&,||) for more complex filtering.

 

4. Coverage Options

Coverage options control the behavior of covergroups, coverpoints, and crosses. There are two types of options: those that specify the behavior of a covergroup instance and those that specify the behavior of a covergroup type. Specifying multiple values for the same option will cause an error.

Covergroup Instance Options

Instance-specific options can be set with different values at initialization for each instance. These initial values only affect their corresponding instance.

Instance-specific options can be set within the covergroup definition using the following syntax:

option.member_name = expression;

Every covergroup, coverpoint, and cross has a built-in member named option. Assignment statements to this member within a covergroup definition take effect when the covergroup is instantiated. The per_instance and get_inst_coverage options can only be set within the covergroup definition. The auto_bin_max and  detect_overlap options are effective only when set in a covergroup or coverpoint definition. Other instance-specific options can be set by assignment after the covergroup has been instantiated.

All instance options can be specified at the covergroup level. Except for weightgoalcomment, and per_instance, all other options set at the covergroup level also serve as the default values for the corresponding options in all coverpoints and crosses within that covergroup. Individual coverpoints or crosses can override these defaults. When set at the covergroup level, the weightgoalcomment, and per_instance options do not affect the default values of the corresponding options at lower levels (coverpoint and cross).

Covergroup Type Options

Type options describe properties of the covergroup type as a whole. They behave like static data members in a class and apply to all instances.

Covergroup type options can be set within the covergroup definition using the following syntax:

type_option.member_name = constant_expression;

type_option is a built-in static member of every covergroup, coverpoint, and cross. Different instances cannot have different values for type options. These options can only be set at initialization using a constant expression. The strobe type option can only be set in the covergroup definition. Other type options can be assigned during simulation using the scope resolution operator (::). For example:

covergroup gc @(posedge clk); a : coverpoint a_var; b : coverpoint b_var; endgroup ... // Set the comment for all covergroups of type "gc" gc::type_option.comment = "Here is a comment for covergroup g1"; // Set the weight for coverpoint "a" of all covergroups of type gc gc::a::type_option.weight = 3; gc g1 = new;

Settings at the covergroup level do not affect the settings at lower levels.

 

5. Coverage Methods

Covergroups provide several methods that can be called at any time:

 

get_coverage() returns the type coverage, which is the cumulative coverage of all instances of that type. It is a static method and can be called using the :: or . operator. get_inst_coverage() returns the coverage for a specific instance. It is associated with a particular instance, is not a static method, and can only be called using the . operator. Additionally, the sample() function in a covergroup can be overridden using the with keyword.

SystemVerilog provides the following system tasks and functions to help manage coverage data collection:

  • $set_coverage_db_name ( filename ): Sets the filename for the coverage database where coverage information will be saved at the end of the simulation.

  • $load_coverage_db ( filename ): Loads cumulative coverage information for all covergroup types from the given file.

  • $get_coverage(): Returns a real number between 0 and 100 representing the overall coverage for all covergroup types, calculated as previously described.