2026-06-05 15:35:01 +02:00
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain
// SPDX-FileCopyrightText: 2026 Matthew Ballance
// SPDX-License-Identifier: CC0-1.0
// Test default bins - catch-all for values not in other bins
// verilog_format: off
`define stop $stop
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
// Non-covergroup class in the same module - must not interfere with covergroup processing
class DataHelper ;
bit [ 7 : 0 ] val ;
function new ( bit [ 7 : 0 ] v ) ; val = v ; endfunction
endclass
module t ;
bit [ 7 : 0 ] data ;
logic [ 1 : 0 ] idx ;
logic [ 63 : 0 ] data64 ;
logic [ 64 : 0 ] data65 ;
DataHelper helper ;
// Signals for the unlabeled-coverpoint covergroups below
logic [ 1 : 0 ] a ;
logic [ 1 : 0 ] b ;
typedef struct packed {
logic [ 1 : 0 ] hi ;
logic [ 1 : 0 ] lo ;
} pair_t ;
pair_t p ;
covergroup cg ;
coverpoint data {
bins low = { [ 0 : 3 ] } ;
bins high = { [ 12 : 15 ] } ;
bins other = default ; // Catches everything else (4-11, 16+)
}
endgroup
// Covergroup with default as the only bin - catches all sampled values
covergroup cg2 ;
cp_only_default: coverpoint data {
bins all = default ;
}
endgroup
// Covergroup with default + ignore + illegal bins - excluded values must not count toward coverage
covergroup cg3 ;
coverpoint data {
2026-06-06 00:36:55 +02:00
ignore_bins bad = { 255 } ; // excluded from coverage
illegal_bins err = { 254 } ; // illegal value, excluded from coverage
2026-06-05 15:35:01 +02:00
bins normal = { [ 1 : 10 ] } ;
bins other = default ;
}
endgroup
// Auto-bins on a small range with one value excluded by ignore_bins -
// when the range is small enough, one auto-bin per valid value is created; the excluded value is skipped.
covergroup cg4 ;
cp_idx: coverpoint idx {
ignore_bins skip = { 2 } ; // value 2 excluded; auto-bins created for 0,1,3
}
endgroup
// 64-bit signal with auto_bin_max=4
covergroup cg5 ;
cp_data64: coverpoint data64 { bins auto [ 4 ] ; }
endgroup
// 65-bit signal with explicit range bins
covergroup cg6 ;
cp_data65: coverpoint data65 { bins lo = { [ 0 : 15 ] } ; bins hi = { [ 100 : 200 ] } ; }
endgroup
// Unlabeled coverpoint - the signal name is used as the coverpoint name
covergroup cg7 ;
coverpoint data { bins lo = { [ 0 : 7 ] } ; bins hi = { [ 8 : 15 ] } ; }
endgroup
// Multiple unlabeled coverpoints: each gets a unique deterministic name (the variable
// name for a single identifier). Previously two unlabeled coverpoints in one covergroup
// collided on the generated bin-variable name (e.g. duplicate '__Vcov__auto_0').
covergroup cg_plain ;
option . auto_bin_max = 2 ;
coverpoint a ;
coverpoint b ;
endgroup
// Unlabeled coverpoints with compound (member-select) expressions get synthesized names.
covergroup cg_member ;
option . auto_bin_max = 2 ;
coverpoint p . lo ;
coverpoint p . hi ;
endgroup
// A cross referencing unlabeled coverpoints by their derived names.
covergroup cg_cross ;
option . auto_bin_max = 2 ;
coverpoint a ;
coverpoint b ;
ab: cross a , b ;
endgroup
initial begin
cg cg_inst ;
cg2 cg2_inst ;
cg3 cg3_inst ;
cg4 cg4_inst ;
cg5 cg5_inst ;
cg6 cg6_inst ;
cg7 cg7_inst ;
cg_plain cg_plain_inst ;
cg_member cg_member_inst ;
cg_cross cg_cross_inst ;
2026-06-06 00:36:55 +02:00
cg_inst = new ( ) ;
2026-06-05 15:35:01 +02:00
cg2_inst = new ( ) ;
cg3_inst = new ( ) ;
cg4_inst = new ( ) ;
cg5_inst = new ( ) ;
cg6_inst = new ( ) ;
cg7_inst = new ( ) ;
2026-06-06 00:36:55 +02:00
cg_plain_inst = new ( ) ;
2026-06-05 15:35:01 +02:00
cg_member_inst = new ( ) ;
2026-06-06 00:36:55 +02:00
cg_cross_inst = new ( ) ;
helper = new ( 8 'h42 ) ;
data = helper . val ; // Use helper to avoid optimization
2026-06-05 15:35:01 +02:00
// Hit low bin
data = 2 ;
cg_inst . sample ( ) ;
cg2_inst . sample ( ) ;
`checkr ( cg2_inst . get_inst_coverage ( ) , 100.0 ) ; // cg2 has 1 bin (default) -> 100% after first sample
// Hit high bin
data = 14 ;
cg_inst . sample ( ) ;
cg2_inst . sample ( ) ;
// Hit default bin with value 7 (not in low or high)
data = 7 ;
cg_inst . sample ( ) ;
cg2_inst . sample ( ) ;
`checkr ( cg_inst . get_inst_coverage ( ) , 100.0 ) ; // all 3 bins (low, high, other) hit
// Hit another default value (should not increase coverage)
data = 20 ;
cg_inst . sample ( ) ;
cg2_inst . sample ( ) ;
`checkr ( cg_inst . get_inst_coverage ( ) , 100.0 ) ;
`checkr ( cg2_inst . get_inst_coverage ( ) , 100.0 ) ;
// Sample cg3: verify ignore/illegal bins do not contribute to coverage
2026-06-06 00:36:55 +02:00
data = 2 ;
cg3_inst . sample ( ) ; // hits normal bin
2026-06-12 17:40:48 +02:00
`checkr ( cg3_inst . get_inst_coverage ( ) , 100.0 ) ; // 1/1: only 'normal' counts (default/ignore/illegal excluded, LRM 19.5)
2026-06-06 00:36:55 +02:00
data = 7 ;
cg3_inst . sample ( ) ; // hits normal bin again
2026-06-12 17:40:48 +02:00
`checkr ( cg3_inst . get_inst_coverage ( ) , 100.0 ) ; // no new normal bins
2026-06-06 00:36:55 +02:00
data = 255 ;
2026-06-12 17:40:48 +02:00
cg3_inst . sample ( ) ; // ignore_bins value; recorded but excluded from coverage
`checkr ( cg3_inst . get_inst_coverage ( ) , 100.0 ) ;
2026-06-05 15:35:01 +02:00
// note: do not sample 254 (illegal_bins would cause runtime assertion)
2026-06-06 00:36:55 +02:00
data = 100 ;
2026-06-12 17:40:48 +02:00
cg3_inst . sample ( ) ; // hits default (other) bin; recorded but excluded from coverage
`checkr ( cg3_inst . get_inst_coverage ( ) , 100.0 ) ;
2026-06-05 15:35:01 +02:00
// Sample cg4: auto-bins with one excluded value
// idx=2 is in ignore_bins, so auto-bins cover 0, 1, 3 only (3 bins total)
idx = 0 ; cg4_inst . sample ( ) ;
idx = 1 ; cg4_inst . sample ( ) ;
idx = 3 ; cg4_inst . sample ( ) ;
`checkr ( cg4_inst . get_inst_coverage ( ) , 100.0 ) ;
// Sample cg5: 64-bit signal, 4 auto bins; values 0 and 5 both fall in first bin
data64 = 0 ; cg5_inst . sample ( ) ;
`checkr ( cg5_inst . get_inst_coverage ( ) , 25.0 ) ; // 1/4 bins hit
data64 = 5 ; cg5_inst . sample ( ) ;
`checkr ( cg5_inst . get_inst_coverage ( ) , 25.0 ) ; // same bin, no increase
// Sample cg6: 65-bit signal with range bins
2026-06-06 00:36:55 +02:00
data65 = 5 ;
cg6_inst . sample ( ) ; // hits bin lo=[0:15]
2026-06-05 15:35:01 +02:00
`checkr ( cg6_inst . get_inst_coverage ( ) , 50.0 ) ;
2026-06-06 00:36:55 +02:00
data65 = 150 ;
cg6_inst . sample ( ) ; // hits bin hi=[100:200]
2026-06-05 15:35:01 +02:00
`checkr ( cg6_inst . get_inst_coverage ( ) , 100.0 ) ;
// Sample cg7: unlabeled coverpoint
2026-06-06 00:36:55 +02:00
data = 3 ;
cg7_inst . sample ( ) ; // hits bin lo
2026-06-05 15:35:01 +02:00
`checkr ( cg7_inst . get_inst_coverage ( ) , 50.0 ) ;
2026-06-06 00:36:55 +02:00
data = 10 ;
cg7_inst . sample ( ) ; // hits bin hi
2026-06-05 15:35:01 +02:00
`checkr ( cg7_inst . get_inst_coverage ( ) , 100.0 ) ;
// cg_plain: two unlabeled coverpoints (a, b), 2 auto bins each -> distinct names
a = 0 ; b = 3 ; cg_plain_inst . sample ( ) ;
`checkr ( cg_plain_inst . get_inst_coverage ( ) , 50.0 ) ;
// cg_member: unlabeled member-select coverpoints (synthesized names)
p . lo = 0 ; p . hi = 3 ; cg_member_inst . sample ( ) ;
`checkr ( cg_member_inst . get_inst_coverage ( ) , 50.0 ) ;
// cg_cross: cross of unlabeled coverpoints referenced by derived name
a = 0 ; b = 0 ; cg_cross_inst . sample ( ) ;
a = 3 ; b = 3 ; cg_cross_inst . sample ( ) ;
$write ( " *-* All Finished *-* \n " ) ;
$finish ;
end
endmodule