|
|
|
|
|
|
|
|
|
|
|
|
covergroup
|
|
|
The covergroup construct is a user-defined type. The type definition is written once, and multiple instances of that type can be created in different contexts. Similar to a class, once defined, a covergroup instance can be created via the new() operator. A covergroup can be defined in a package, module, program, interface, or class. |
|
|
|
|
|
A covergroup can contain following constructs. |
|
|
|
|
|
- clocking event : Defines the event at which coverage points are sampled. If the clocking event is omitted, users must procedurally trigger the coverage sampling.
- coverage points : A coverage point can be a variable or an expression.
- cross coverage : Coverage group can also specify cross coverage between two or more coverage points or variables.
- coverage options : This are used to control the behaviour of the covergroup.
- Optional formal arguments : This is arguments that are passed when a instance of covergroup is created.
|
|
|
|
|
|
|
|
|
If a clocking event is specified, it defines the event at which coverage points are sampled. If the clocking event is omitted, users must procedurally trigger the coverage sampling. This is done via the built-in sample method. |
|
|
|
|
|
The identifier associated with the covergroup declaration defines the name of the coverage model. A covergroup can specify an optional list of arguments. When the covergroup specifies a list of formal arguments, its instances must provide to the new operator all the actual arguments that are not defaulted. This is same as in the case of constructor of a class. Actual arguments are evaluated when the new operator is executed. |
|
|
|
|
|
A covergroup can contain one or more coverage points. A coverage point can be a variable or an expression. Each coverage point includes a set of bins associated with its sampled values or its value transitions. |
|
|
|
|
|
A coverage group can also specify cross coverage between two or more coverage points or variables. Any combination of more than two variables or previously declared coverage points is allowed. |
|
|
|
|
|
A coverage group can also specify one or more options to control and regulate how coverage data are structured and collected. Coverage options can be specified for the coverage group as a whole or for specific items within the coverage group, that is, any of its coverage points or crosses. |
|
|
|
|
|
|
|
|
Example : covergroup
|
|
|
|
|
|
1 //+++++++++++++++++++++++++++++++++++++++++++++++++
2 // Define the interface with coverage
3 //+++++++++++++++++++++++++++++++++++++++++++++++++
4 interface mem_if (input wire clk);
5 logic reset;
6 logic we;
7 logic ce;
8 logic [7:0] datai;
9 logic [7:0] datao;
10 logic [7:0] addr;
11 //=================================================
12 // Clocking block for testbench
13 //=================================================
14 clocking cb @ (posedge clk);
15 output reset, we, ce, datai,addr;
16 input datao;
17 endclocking
18 //=================================================
19 // Coverage Group in interface
20 //=================================================
21 covergroup memory @ (posedge ce);
22 address : coverpoint addr {
23 bins low = {0,50};
24 bins med = {51,150};
25 bins high = {151,255};
26 }
27 data_in : coverpoint datai {
28 bins low = {0,50};
29 bins med = {51,150};
30 bins high = {151,255};
31 }
32 data_out : coverpoint datao {
33 bins low = {0,50};
34 bins med = {51,150};
35 bins high = {151,255};
36 }
37 read_write : coverpoint we {
38 bins read = {0};
39 bins write = {1};
40 }
41 endgroup
42 //=================================================
43 // Instance of covergroup
44 //=================================================
45 memory mem = new();
46
47 endinterface
48 //+++++++++++++++++++++++++++++++++++++++++++++++++
49 // DUT With interface
50 //+++++++++++++++++++++++++++++++++++++++++++++++++
51 module simple_if (mem_if mif);
52 // Memory array
53 logic [7:0] mem [0:255];
54
55 //=================================================
56 // Read logic
57 //=================================================
58 always @ (posedge mif.clk)
59 if (mif.reset) mif.datao <= 0;
60 else if (mif.ce && ! mif.we) mif.datao <= mem[mif.addr];
61
62 //=================================================
63 // Write Logic
64 //=================================================
65 always @ (posedge mif.clk)
66 if (mif.ce && mif.we) mem[mif.addr] <= mif.datai;
67
68 endmodule
69
70 //+++++++++++++++++++++++++++++++++++++++++++++++++
71 // Testbench
72 //+++++++++++++++++++++++++++++++++++++++++++++++++
73 module coverage_covergroup();
74
75 logic clk = 0;
76 always #10 clk++;
77 //=================================================
78 // Instianciate Interface and DUT
79 //=================================================
80 mem_if miff(clk);
81 simple_if U_dut(miff);
82 //=================================================
83 // Default clocking
84 //=================================================
85 default clocking dclk @ (posedge clk);
86
87 endclocking
88 //=================================================
89 // Test Vector generation
90 //=================================================
91 initial begin
92 miff.reset <= 1;
93 miff.ce <= 1'b0;
94 miff.we <= 1'b0;
95 miff.addr <= 0;
96 miff.datai <= 0;
97 ##1 miff.reset <= 0;
98 for (int i = 0; i < 3; i ++ ) begin
99 ##1 miff.ce <= 1'b1;
100 miff.we <= 1'b1;
101 miff.addr <= i;
102 miff.datai <= $random;
103 ##3 miff.ce <= 1'b0;
104 $display ("@%0dns Write access address %x, data %x",
105 $time,miff.addr,miff.datai);
106 end
107 for (int i = 0; i < 3; i ++ ) begin
108 ##1 miff.ce <= 1'b1;
109 miff.we <= 1'b0;
110 miff.addr <= i;
111 ##3 miff.ce <= 1'b0;
112 $display ("@%0dns Read access address %x, data %x",
113 $time,miff.addr,miff.datao);
114 end
115 #10 $finish;
116 end
117
118 endmodule
You could download file coverage_covergroup.sv here
|
|
|
|
|
|
Simulation : covergroup
|
|
|
|
|
|
@90ns Write access address 00, data 24
@170ns Write access address 01, data 81
@250ns Write access address 02, data 09
@330ns Read access address 00, data 24
@410ns Read access address 01, data 81
@490ns Read access address 02, data 09
|
|
|
|
|
|
|
|
|
|
|
|
Report : Coverage
|
|
|
|
|
|
Variables for Group coverage_covergroup.miff::memory
VARIABLE EXPECTED UNCOVERED COVERED PERCENT GOAL WEIGHT
address 3 2 1 33.33 100 1
data_in 3 3 0 0.00 100 1
data_out 3 2 1 33.33 100 1
read_write 2 0 2 100.00 100 1
|
|
|
|
|
|
CoverGroup Inside a Class
|
|
|
As said earlier, covergroup can be embedded inside a class, interface, or module. When emebedded inside a class, it allows to generate coverage on subset of class properties. Important difference between a covergroup in module and covergroup in class is that, it is optional to create the instance of covergroup in class. as this is kind of automatic i.e the coverage group is implicitly declared. An embedded covergroup can define a coverage model for protected and local class properties without any changes to the class data encapsulation. Class members can become coverage points or can be used in other coverage constructs, such as conditional guards or option initialization. A class can have more than one covergroup. |
|
|
|
|
|
Below example shows all this. |
|
|
|
|
|
Example : covergroup in class
|
|
|
|
|
|
1 //+++++++++++++++++++++++++++++++++++++++++++++++++
2 // Define the interface with coverage
3 //+++++++++++++++++++++++++++++++++++++++++++++++++
4 interface mem_if (input wire clk);
5 logic reset;
6 logic we;
7 logic ce;
8 logic [7:0] datai;
9 logic [7:0] datao;
10 logic [7:0] addr;
11 //=================================================
12 // Clocking block for testbench
13 //=================================================
14 clocking cb @ (posedge clk);
15 inout reset, we, ce, datai,addr;
16 input datao;
17 endclocking
18 //=================================================
19 // Modport for testbench
20 //=================================================
21 modport tb (clocking cb, input clk);
22
23 endinterface
24 //+++++++++++++++++++++++++++++++++++++++++++++++++
25 // DUT With interface
26 //+++++++++++++++++++++++++++++++++++++++++++++++++
27 module simple_if (mem_if mif);
28 // Memory array
29 logic [7:0] mem [0:255];
30
31 //=================================================
32 // Read logic
33 //=================================================
34 always @ (posedge mif.clk)
35 if (mif.reset) mif.datao <= 0;
36 else if (mif.ce && ! mif.we) mif.datao <= mem[mif.addr];
37
38 //=================================================
39 // Write Logic
40 //=================================================
41 always @ (posedge mif.clk)
42 if (mif.ce && mif.we) mem[mif.addr] <= mif.datai;
43
44 endmodule
45
46 //+++++++++++++++++++++++++++++++++++++++++++++++++
47 // Testbench
48 //+++++++++++++++++++++++++++++++++++++++++++++++++
49 module coverage_class();
50
51 logic clk = 0;
52 always #10 clk++;
53 //=================================================
54 // Instianciate Interface and DUT
55 //=================================================
56 mem_if miff(clk);
57 simple_if U_dut(miff);
58 //=================================================
59 // Default clocking
60 //=================================================
61 default clocking dclk @ (posedge clk);
62
63 endclocking
64
65 //=================================================
66 // Test Vector generation
67 //=================================================
68 class mem_driver;
69 virtual mem_if.tb cif;
70
71 //=================================================
72 // Coverage Group in class
73 //=================================================
74 covergroup memory @ (negedge cif.cb.ce);
75 address : coverpoint cif.cb.addr {
76 bins low = {0,50};
77 bins med = {51,150};
78 bins high = {151,255};
79 }
80 endgroup
81
82 covergroup datac @ (negedge cif.cb.ce);
83 data_in : coverpoint cif.cb.datai {
84 bins low = {0,50};
85 bins med = {51,150};
86 bins high = {151,255};
87 }
88 data_out : coverpoint cif.cb.datao {
89 bins low = {0,50};
90 bins med = {51,150};
91 bins high = {151,255};
92 }
93 read_write : coverpoint cif.cb.we {
94 bins read = {0};
95 bins write = {1};
96 }
97 endgroup
98
99 function new (virtual mem_if.tb cif);
100 this.cif = cif;
101 this.datac = new();
102 this.memory = new();
103 endfunction
104
105 task automatic drive ();
106 cif.cb.reset <= 1;
107 cif.cb.ce <= 1'b0;
108 cif.cb.we <= 1'b0;
109 cif.cb.addr <= 0;
110 cif.cb.datai <= 0;
111 @ (cif.cb) cif.cb.reset <= 0;
112 for (int i = 0; i < 3; i ++ ) begin
113 ##1 cif.cb.ce <= 1'b1;
114 cif.cb.we <= 1'b1;
115 cif.cb.addr <= i;
116 cif.cb.datai <= $random;
117 repeat (3) @ (cif.cb) cif.cb.ce <= 1'b0;
118 $display ("@%0dns Write access address %0x, data %x",
119 $time,i,cif.cb.datai);
120 end
121 for (int i = 0; i < 3; i ++ ) begin
122 @ (cif.cb) cif.cb.ce <= 1'b1;
123 cif.cb.we <= 1'b0;
124 cif.cb.addr <= i;
125 repeat (4) @ (cif.cb) cif.cb.ce <= 1'b0;
126 $display ("@%0dns Read access address %0x, data %x",
127 $time,i,cif.cb.datao);
128 end
129 endtask
130
131 endclass
132
133 mem_driver driver = new(miff);
134
135 initial begin
136 driver.drive();
137 #10 $finish;
138 end
139
140 endmodule
You could download file coverage_class.sv here
|
|
|
|
|
|
Simulation : covergroup in class
|
|
|
|
|
|
@90ns Write access address 0, data 24
@170ns Write access address 1, data 81
@250ns Write access address 2, data 09
@350ns Read access address 0, data 24
@450ns Read access address 1, data 81
@550ns Read access address 2, data 09
|
|
|
|
|
|
Report : Coverage
|
|
|
|
|
|
VARIABLE EXPECTED UNCOVERED COVERED PERCENT GOAL WEIGHT
address 3 2 1 33.33 100 1
VARIABLE EXPECTED UNCOVERED COVERED PERCENT GOAL WEIGHT
data_in 3 2 1 33.33 100 1
data_out 3 3 0 0.00 100 1
read_write 2 0 2 100.00 100 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|