SystemVerilog TIPs
SystemVerilog(8-9)
定义
1.covergroup
定义范围:module/program/interface/class/package等结构体
语法:
1 |
|
2.coverpoint
定义范围:covergroup内
1 |
|
覆盖点内会有对应的一组分组柜 (bin),计数器可以是用户自定义的或者是自动创建的
采样方式(两种):
- 法1:在covegroup后的<expr>使用@或wait自动采样
- 法2:手动调用covergroup实例的sample()方法
- iff主要做补充采样条件(常用于复位)
示例:
1 |
|
3.bins 分组柜
定义范围:coverpoint内
4.cross 交叉覆盖点
定义范围:covergroup内(可以理解为另一种由coverpoint组合成的coverpoint)
定义:对两个或者多个覆盖点指定交叉覆盖点,交叉覆盖点是其定义中覆盖点成员的分类柜的所有组合情况
要点:覆盖点变量、覆盖点表达式、binsof
结构
1 |
|
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46//覆盖点变量交叉示例:
bit [3:0] a, b;
covergroup cov @(posedge clk);
aXb: cross a, b;
endgroup
//覆盖点表达式交叉示例:
bit [3:0] a,b,c;
covergroup cov2 @(posedge clk);
BC:coverpoint b+c;
aXb:cross a, BC;
endgroup
//交叉覆盖点中交叉分组柜的总数就是其定义的成员覆盖点分组柜的所有组合情况
bit [31:0] a_var;
bit [3:0] b_var;
covergroup cov3 @(posedge clk);
A:coverpoint a_var {bins yy[] = {[0:9]};}
CC: cross b_var, A;
endgroup
//binsof结构示例
bit [7:0] v_a, v_b;
covergroup cg @(posedge clk);
a:coverpoint v_a//a定义了4个分组柜
{
bins a1 = {[0:63]};
bins a2 = {[64:127]};
bins a3 = {[128:191]};
bins a4 = {[192:255]};
}
b:coverpoint v_b//b定义了4个分组柜
{
bins b1 = {0};
bins b2 = {[1:84]};
bins b3 = {[85:169]};
bins b4 = {[170:255]};
}
c:cross a,b//c定义了3个交叉分组柜
{
//c1其指定了覆盖点a中没有和数值范围100到200有交集的分组柜
bins c1 = !binsof(a) intersect {[100:200]};//4 cross products
//c2指定了交叉项中或者存在分组柜a2,或者存在分组柜b2
bins c2 = binsof(a.a2) || binsof(b.b2);//7 cross products
//c3定义了交叉项必须同时包括a1和b4
bins c3 = binsof(a.a1) && binsof(b.b4);//1 cross products
//其他可能在自动生成交叉分组柜中出现的但在本例中没有显示定义出来的交叉项,不是交叉覆盖点关心的对象,其是否被击中不会在任何统计中影响交叉覆盖点c
}
endgroup
例1:覆盖组cov中定义了两个4比特变量a和b的交叉覆盖点aXb,系统会自动为a和b两个变量分别创建两个覆盖点。每个覆盖点默认情况下是16个分组柜,那么因为a和b的分组柜之间存在256种组合,所以交叉覆盖点aXb就会自动产生256个分组柜
例2:BC就是事先定义好的对应表达式b+c的覆盖点,因为b+c应该是一个4比特的数值,所以可以为该覆盖点分配16个分组柜;而 a可以分配8个分组柜,最后交叉覆盖点aXb,总共可以分配128个分组柜,来表示a和b+c的各种组合情况
例3:我们对于变量 a_var只关心0到9十个数值,为此在覆盖点 A中显性的定 义了yy[0],yy[1],…yy[9]十个分组柜,作为交叉覆盖点CC中定义的成员分别是b_var和A。 系统会为变量b_var自动创建16个分组柜(auto[0],auto[1],…auto[15])。由于没有显示定义分组柜,系统会自动为交叉覆盖点CC分配交叉分组柜,其总数为:16*10=160;如下所示:
为此,我们在定义的时候要小心使用交叉覆盖点,以免系统自动创建大量冗余的分组 柜,因为每个交叉分组柜都是一个计数器,频繁采样统计,会对仿真速度带来影响
补充概念:
交叉项——组成——>分组柜——组成——>交叉覆盖点
SVA
5层语法结构
- Assertion units(断言封装层,通过module/class/program/interface封装,从而实现重用)
- Directives(断言指示层,使用
assert
对特定properties检查,或对sequences行为检查;或者采用cover
做统计) - Properties(属性层,重要的封装方式,属性内部可定义蕴涵操作符:
|->
、|=>
) - Sequences(序列层,一种封装格式,有操作符时隙、重复、序列等等)
- Boolean Expressions(布尔表达式,与verilog相同)
操作符:
- 时隙延时:
##n
,n表示延时n个时钟周期 - 指定窗口:
[m:n]
##
和[m:n]
一起用,如:##[1:5]
,表示后续事件在[1:5]
周期内都成立,补充举例##[1:5] z
1 |
|
- 蕴含操作符:
|->
,|=>
|->
:表示当前置表达式成立后同一时钟检查后置表达式|=>
:表示要延迟一个时钟,等效于|-> ##1
- 使用于
property
使用示例:
1 |
|
bind结构
像 sva_test这样用模块封装的断言能否不影响设计结构,直接探测到设计内部某个例化层次的接口上呢?答案是可以的。 下面我们将通过一个石头、剪刀、布的例子来讲述,如何采用bind这个结构,让SVA断言和设计分离
SV支持通过bind(绑定)将断言属性封装 模块绑定到任意的设计模块或者其特定例化中。这个功能可以实现以下几个目的:
- 验证工程师可以最少的改动原有的设计代码和文件结构
- 验证IP可以方便的绑定到特定的设计模块或者例化中
- 对现有的断言没有任何语法上的影响,断言可以通过这种方式实现层次化的访问
bind可访问的接口:bind的能力不仅可以捕获例化模块接口上的信号,还可以探测到这个例化模块内部的信号
bind的语法结构如下:
1 |
|
- target一般是设计对象,可以是模块名或者是例化名,也就是我们可以通过层次性的例化名访问设计内部例化
- container是断言的封装载体,可以使用module、interface或者program来封装
- 例化名就是本次绑定的例化名
bind定义位置:可以在module/interface或者编译层次内定义
针对所有例化的使用示例:
1 |
|
- cpu是设计的模块名
- fpu_props是一个封装了属性或断言的program/interface/module
- fpu_rules_1是例化名
- 例化端口(a, b, c)获取来自cpu模块的信号
- cpu的每个例化都被绑定了这个断言
针对特定实例的使用示例:
1 |
|
使用SVA的五点注意:
- 断言描述的是设计的属性
- 断言应该绝对正确
- bind保证验证和设计分离
- 验证关心顶层接口
- 更多的使用OVL
系统函数
get_coverage()
:查询整个验证环境中的覆盖率
专题补充
覆盖率
SV复习(七)覆盖率:https://blog.csdn.net/whddddddddddd/article/details/126809571
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!