covergroup: similar to class,you should declare then instance;
It can contains one or more coverpoint. and will be sampled at the same time.
It can be used in class or interface program or moudle;
a. It can sample any varible.such as varia,signal of interface,port of module.
b. A class can contain many covergroup. when you have many independent covergroup,ervery covergroup can enalbe or disable itself.
c.Every covergroup can define the sample triggle perponally,allow collect data from many source.
d.Note:covergroup must be instanted to sample data;
Eg:
covergroup cov_grp @(posedge clk iff rstn);
cov_p1:coverpoint a;
endgroup
cov_grp cov_inst = new()
//way2
covergroup cov_grp;
cov_p1:coverpoint a;
endcovergroup
cov_grp coc_inst = new();
@(posedge clk iff rst_n) cov_inst.sample();
The neccersy component:
1.coverage points : that is the port.
2.one clk event to trigger synamlly sample the coverpoint.
3.the choose options–tf_port list
4.Cross coverage between coverage points.
5.Coverage options.
Eg:
covergroup covergroup_identifier[(tf_port_list)||(coverage_event)]
{coverage_spec_or_option}
endgroup:covergroup_identifier
coverage_spec_or_option ::=
{attribute_instance} coverage_spec
| {attribut_instance} covergae_option;
coverage_option ::=
option.member_identifier = expression
| type_option.member_identifier = constant_expression
coverage_spec ::=
cover_point
| cover_cross
coverage_event ::=
clocking_event
| with function sample{[tf_port_list]}
bin is obviously specify your interesting valur_range; which can use bin to points the some range.
//temple
covergroup cov_grp_1 @(posedge clk);
cp_1 : coverpoint vara1 {
bins bin_1 = {range};
bins bin_2 = {range};
}
cp_2 : coverpoint vara2 {
bins bin1 = {range};
bins bin2 = {range};
}
endgroup:cov_grp_1
//eg1
bin[7:0] addr;
covergroup cg @(posedge clk);
cp1 : coverpoint addr {
bins b1 = {2,7};
bins b2 = {[30:40]};
}
endgroup: cg
//eg2: switch to directly
value1 ->value2
range_list_1 -> range_list_2
covergroup cg @(posedge clk);
cp1 : coverpoint addr{
bins b1 = {10==>20==>30};
bins b2 = {0==>2[=2]-->1};s
}
endgroup
//eg3: special bins
* ignore bins: ignore the value wo dont care;
* illeagl_bins : if appear then err report;
* wildcard bins:
* with: similar to extra_constraint;
//eg4: corss coverpoint
if want sample many varia's different group,must use cross to cover.
bit[3:0] a,b;
covergroup cg @(posedge clk);
c1 : coverpoint a;
c2 : coverpoint b;
c1Xc2 : cross c1,c2;
endcovergroup
//--another way
bit[3:0] a,b;
covergroup cov@(posedge clk);
aXb : cross a,b ; // impolicitly specify the coverpoint for a and b;
endgroup
//eg5 : covergroup with param, then pass param by new(); Note the varia(sampled) must ref type
covergroup cg1(ref logic[7:0] addr, input int low, int high) @(posedge clk);
option.per_instance = 1;
addr_val : coverpoint addr{
bins low = {[0:low]};
bins mid = {[low:high]};
}
endgroup
addr_cov acov_low = new(addr,5,10);
addr_cov acov_mid = new(addr_11,20);
addr_cov acov_high = new(addr,21,30);
the option can control the behaviour of covergroup,coverpoint and cross;
There are two types of option : option && type_option;
option can pass param,but type_option only use const;
如果例化了一个covergroup cg,那么可以通过句柄cg.option来改变一些选项来改变使该实例与其他实例不同,而type_option是对整个covergroup的设置,两者之间互不干扰;
当一个covergroup被多次例化时,建议将per_instance设为1,并且将option.name=param,由new例化时传入,方便调试;
covergroup addr_cov (ref log[7:0] addr,input int low,int high,string instname) @(posedge clk);
option.per_instance = 1;
option.name = instname;
addr_val : coverpoint addr{
bins low = {[0,low]};
bins mid = {[low:high]};
}
endgroup:addr_cov
addr_cov acov_low = new(addr,5,10,"inst_1");
addr_cov acoc_mid = new(addr,5,10."inst_2");
addr_cov acov_high = new(addr,21,30,"inst_3");
interface is the interview between tb with dut. So the covergroup inside interface can be used n interface directly.
interface apb_if (input clk, input rstn);
logic[31:0] paddr;
logic pwrite;
logic psel;
logic pnenable;
logic[31:0] pwdata;
logic[31:0] prdata;
logic pready;
//coverage flags
bit has_coverage = 1'b1;
//APB command coverage
covergroup cg_apb_command @(posedge clk iff rstn);
option.per_instance = 1;
option.name = "cov_apb_command";
pwrite : coverpoint pwrite{
type_option.weight = 0; //do ot count covergae
bins write = {1};
bins read = {1};
}
psel : coverpoint psel{
tpe_option.weight = 0; //do no count coverage
bins sel = {1};
bins unsel= {0};
}
cmd : cross pwrite,psel{
bins cmd_write = binsof{psel.sel} && binsof{pwrite.write};
bins cmd_read = binsof{psel.sel} && binsof{pwrite.read};
bins cmd_idle = binsof{psel.unsel};
}
endgroup: cf_apb_command
initial begin : coverage_control
if(has_coverage) begin
cg_apb_command cg0 = new();
end
end
endinterface: apb_if
For some occasions releated with dut, what we care about is the compination between signal and signal or signal inside dut. As a result, we need to dev specify component for collecting functionCov;
//tb_cov
//1. Create a interface to declare what we care
interface cov_if{
input logic clk_400M,
input logic reset_n,
inut logic[6:0] dma_cs,
input logic[31:0] tdes0,
input logic[31:0] tdes1
};
endinterface : cov_if;
//2.Use bind to connect the signal of dut with those of interface. the bind.sv file should `include inside top_tb;
bind tob_tb cov_if cov_if_inst(
.clk_400M (clk_400M),
.reset_n (reset_n),
.dma_cs (topb_tb.dut_top_inst.dma_inst.cs),
.tdes0 (top_tb.dut_top_inst.dma_inst.tdes0),
.tdes1 (top_tb.dut_top_inst.dma_inst.tdse1)
);
//3 Use config_db for sending interface to the instance of cov; Note: cov_if_inst由于在bind在tb中,因此需要利//用“tob_tb.”对cov_if_inst进行索引
uvm_config_db# (virtual cov_if) :: set(uvm_root::get(),"uvm_test_top.env.cov","vif",top_tb.cov_if_inst);
//4. 1.Define a component--class for collecting function Coverage,then instant in env.
2.In new() function, use config_db# to get vif from tob_tb;
3.in new() instant any covergroup;
4.in task run_phase, use for..join to sample at the same time;
5.define param: cov_flag. test can config_db::set to control whether covergroup smaple or not;
Tips: config_db#() the 3th param should be the instname of covergroup for control and debug;
6.can define param in task--sample() to do some control logic and call .sample(), if simple sample,you can define after covergroup directly.
7.declare the needed covergroup and sample() using vif;
8.In the top-level to insital param ,and then using config to pass into cov.
class cov extends uvm_component();
virtual cov_if vif;
bit has_coverage;
`uvm_component_utils(cov)
function new(string name = "cov",uvm_component parent);
super.new(name,parent
);
//get configuration from tb
if(!uvm_config_db#(virtual cov_if)::get(this,"","vif",vif)) begin
`uvm_fatal("GETVIF","CANNOT get cov_if object from config DB");
end
//Get has_coverage from tb or test
if(!uvm_config_db#(bit)::get(this,"","coverage_control",has_coverage)) begin
has_coverage = 1;
end
this.dma_desp_tdes_group = new();
endfunction: new
task run_phase();
fork
if(has_coverage) begin
this.do_dma_tdes_sample();
//........other sample task
end
join
endtask
//Macro used to get the cov_flag
//"default" tasks affect when config config_db::get failed
//"cov_name" is a string representing the name of covergroup
`define GET_COV_FLAG(default_value,cov_name) \
bit cov_flag;
if(!uvm_config_db #(bit)::get(this,"",cov_name,cov_flag)) begin \
cov_flag = default_value;
end
task do_dma_tdes_sample();
`GET_COV_FLAG(0,"dma_desp_tdes_group")
if(cov_flag) begin
forever begin
@(posedge vif.clk_400M iff vif.reset_n) begin
dma_desp_tdes_group.sample();
end
end
end
endtask
covergroup dma_desp_tdes_group;
desp_ic : coverpoint vif .tdes1[31];
desp_ter: coverpoint vif.tdes2[25];
buf2_size:coverpoint vif.tdes1[21:11];{
bins size_bound[] = {0,11'h7ff};
bins size_others = default;
}
buf1_size : coverpoint vif.tdes1[] {
bins size_bound[] = {0,11'7ff};
bins size_others = default;
}
endgroup : dma_desp_tdes_group
end class
//--best practise
class child_test extends base_test;
bit cov_flag;
bit has_coverage
function new(string name = "child_test",uvm_component parent = null);
super.new(name,parent);
cov_flag = 1;
has_coverage = 1;
uvm_configdb #(bit) ::set(this,"env.cov","dma_desp_tdes_group",cov_flag); //set flag to cov
uvm_configdb#(bit):: set(this,"env.cov","covergae_control",has_coverage);
end:new
endclass
Recommand: 建议将cov_if_inst直接bind在top_tb下,不要bind到DUT层次,以方便区分验证环境与DUT