HomeSV VerificationDay 14

Advanced Coverage

Coverage exclusions, merging, identifying gaps, and planning tests to achieve 100% functional coverage.

Coverage Exclusions & Illegal Bins

Not all bins are possible. Some combinations are invalid by protocol or design. Use illegal_bins and ignore_bins:

covergroup axi_cg; cp_burst: coverpoint burst_type { bins fixed = { 2'b00 }; bins incr = { 2'b01 }; bins wrap = { 2'b10 }; illegal_bins reserved = { 2'b11 }; // Not valid per spec } cp_len: coverpoint len { bins small = { [0:15] }; bins medium = { [16:127] }; bins large = { [128:255] }; } // Cross: illegal combination (WRAP + length > 64 not allowed) cross burst_len: cross cp_burst, cp_len { illegal_bins wrap_too_big = binsof(cp_burst) matches { 2'b10 } && binsof(cp_len) matches { [128:255] }; } endgroup

illegal_bins: Marks impossible combinations. Simulator reports error if hit.

ignore_bins: Marks valid but uninteresting bins (don't count toward coverage %).

Merging Covergroups

When you have multiple monitors or agents, merge their coverage:

// Two separate monitors, each with own covergroup class Write_Monitor; covergroup write_cg; ... endgroup endclass class Read_Monitor; covergroup read_cg; ... endgroup endclass // Merge in a test class class Test; Write_Monitor wr_mon; Read_Monitor rd_mon; covergroup merged_cg; // This scope samples from both monitors cp_combined: coverpoint {wr_mon.active || rd_mon.active} { bins any = {1}; } endgroup function void report_coverage(); real total = 0.0; real wr_cov = wr_mon.write_cg.get_coverage(); real rd_cov = rd_mon.read_cg.get_coverage(); total = (wr_cov + rd_cov) / 2.0; // Average $display("Overall coverage: %0.1f%%", total); endfunction endclass

Coverage Gap Analysis

After simulation, identify which bins weren't hit:

module protocol_tb(); Monitor mon = new(); initial begin // Run tests... #100000 $finish; end final begin // Print uncovered bins $display("=== Coverage Holes ==="); // Get coverage data int total_bins = mon.cg.get_bin_count(); int covered_bins = 0; // Report coverage percentage real coverage = mon.cg.get_coverage(); $display("Coverage: %0.2f%% (%0d/%0d bins)", coverage, (coverage/100*total_bins), total_bins); // For uncovered cross combinations, write directed test end endmodule

Directed Tests for Coverage Closure

When random tests miss scenarios, write specific directed tests:

task close_coverage_gap(); // Analysis showed: READ at high address + long length = uncovered bit [31:0] addr = 32'hFFFF_0000; // High address bit [7:0] len = 255; // Long transfer bit write = 0; // READ command // Send explicitly send_transaction(addr, len, write); // Other gaps: // WRITE with all byte masks for(int mask = 0; mask < 256; mask++) begin send_transaction(32'h1000_0000, 1, 1, mask); end endtask

Coverage Goals & Thresholds

Plan for realistic coverage targets:

Typical coverage targets:
• Individual coverage points: 95-100%
• Cross-coverage: 80-95% (some combinations naturally rare)
• Full functional coverage: 75-90%
• Code coverage (lines, branches): 100%

Key Takeaways

Tomorrow (Day 15): Coverage-driven randomization — let coverage guide which tests to generate.