Functional Coverage Options in System Verilog

In short: Functional coverage options in SystemVerilog tune how a covergroup collects and reports data. The everyday ones are option.comment to label a group, option.per_instance to report each instance separately, option.at_least to set how many hits a bin needs, option.cross_num_print_missing to show empty bins, and option.goal to set the target percentage. They change reporting, not the design.

Functional coverage tells you whether your tests actually exercised the scenarios in the verification plan. Options are the small settings that make a covergroup report exactly what you need, so numbers are trustworthy when you sign off. This page walks through the most useful ones with a short example each.

A simple way to picture it

Think of a covergroup as a checklist on a clipboard and options as the settings on the clipboard. One setting writes a note at the top so anyone reading knows what the list is for (comment). Another gives each inspector their own copy so results are not mixed together (per_instance). Another says a box only counts as ticked after you see it happen a set number of times (at_least). And another sets the pass mark for the whole checklist (goal). The items being checked do not change; only how you count and read them does.

1. option.comment: label the report

Adds a human-readable note to the coverage report so a reader knows what a group is checking. This is small but valuable when a report has dozens of groups.

covergroup cg_comment;
  option.comment = "Register access, spec section 1.1";
  cp_reg: coverpoint reg_addr;
endgroup

2. option.per_instance: separate reports per instance

By default, SystemVerilog merges coverage from every instance of a covergroup. If you have two generators sending different traffic, merged numbers hide which one covered what. Setting option.per_instance = 1 keeps a separate report for each instance.

covergroup cg_per_inst;
  option.per_instance = 1;
  cp_bytes: coverpoint tr.byte_cnt;
endgroup

3. option.at_least: hits needed per bin

A bin normally counts as covered after a single hit. With option.at_least = N, a bin is only considered covered after it has been sampled N times. This is useful when one hit is not convincing enough, for example when you want to see a corner case several times before trusting it.

covergroup cg_at_least;
  // A bin needs 10 hits before it counts as covered
  option.at_least = 10;
  cp_len: coverpoint tr.length;
endgroup

4. option.cross_num_print_missing: show empty bins

By default a report shows only bins that got samples. But a verification engineer needs to see the bins that were missed, since those are the gaps in testing. This option asks the report to print up to a given number of empty cross bins so you can see exactly what was not covered.

covergroup cg_missing;
  cp_bytes:  coverpoint tr.byte_cnt;
  cp_len:    coverpoint tr.length;
  x_bl:      cross cp_bytes, cp_len;
  option.cross_num_print_missing = 1000;
endgroup

With this set, the report lists missing cross combinations (up to 1000 here), turning a pass-looking report into an honest to-do list of untested cases.

5. option.goal: set the target

The goal is the percentage at which a group or point is treated as fully covered. The default is 100, but you can lower it when hitting every bin is not realistic or required.

covergroup cg_goal;
  // Consider this group done at 80 percent
  option.goal = 80;
  cp_len: coverpoint tr.length;
endgroup

type_option vs option

One point that trips people up: option settings apply per instance of the covergroup, while type_option settings apply to the covergroup type as a whole, across all instances. For example, type_option.comment and type_option.goal set a comment and goal for the merged type-level report. Reach for type_option when you care about the combined result rather than each instance.

covergroup cg_type;
  type_option.goal    = 90;   // applies to the whole type
  type_option.comment = "merged view";
  cp_len: coverpoint tr.length;
endgroup

Options at a glance

OptionWhat it doesTypical value
option.commentAdds a note to the reportA short spec reference
option.per_instanceReports each instance separately1
option.at_leastHits a bin needs to count as covered1 by default, higher for corner cases
option.cross_num_print_missingPrints empty cross binsA large number like 1000
option.goalTarget percent for full coverage100 by default, lower if needed
type_option.*Same ideas, at the type levelApplied across all instances

When to use which

  • Use option.comment on every group so reports stay readable months later.
  • Use option.per_instance when multiple generators or agents feed the same covergroup.
  • Use option.at_least for corner cases you want to see several times before trusting.
  • Use option.cross_num_print_missing during closure to expose untested cross combinations.
  • Use type_option.goal when the merged, type-level number is what you sign off on.

Common mistakes to avoid

  • Confusing option (per instance) with type_option (whole type) and getting reports you did not expect.
  • Leaving cross_num_print_missing off and thinking a clean report means full coverage, when empty bins are just hidden.
  • Setting a high at_least everywhere, which can make coverage look low for no real reason.
  • Forgetting per_instance and then trying to explain merged numbers from two different traffic sources.

Expected output, in plain words

These options change the coverage report, not the simulation itself: comments appear as labels, per-instance produces one section per instance, at_least holds a bin uncovered until it reaches the count, cross_num_print_missing lists empty bins, and goal sets the percent shown as the target. Note: this describes the intended behaviour from the IEEE 1800 rules, not a captured tool run, and report formatting varies by simulator. Confirm on your own tool.

Coverage options work hand in hand with a good coverage model. For the wider picture see the functional coverage category, and for the language features these rely on see SystemVerilog. For revision, browse the interview questions.

Frequently asked questions

What are coverage options in SystemVerilog?

Coverage options are settings on a covergroup that tune how it collects and reports data. Common ones include option.comment, option.per_instance, option.at_least, option.cross_num_print_missing, and option.goal. They change reporting, not the design behaviour.

What is the difference between option and type_option?

option settings apply per instance of a covergroup, so each instance is tracked separately. type_option settings apply to the covergroup type as a whole, across all instances, giving a merged type-level view.

What does option.per_instance do?

By default SystemVerilog merges coverage from all instances of a covergroup. Setting option.per_instance = 1 keeps a separate report for each instance, which is useful when different generators send different traffic.

What is option.at_least used for?

option.at_least sets how many times a bin must be sampled before it counts as covered. The default is one. Raising it is useful for corner cases you want to observe several times before trusting the result.

How do I see bins that were never hit?

Use option.cross_num_print_missing set to a large number. By default a report shows only bins with samples, so this option prints the empty cross bins, turning the report into a list of untested combinations.

What does option.goal control?

option.goal sets the percentage at which a covergroup or coverpoint is treated as fully covered. The default is 100, but you can lower it when hitting every bin is not realistic or required for sign-off.

Similar Posts

2 Comments

  1. Very well written. Even though working on SV Functional Coverage for some time, did not know few options.
    Thank you.

Comments are closed.