前言
2023.3.8 一直都没懂覆盖率和断言,今天开始慢慢学
2023.3.11 打卡学习
2023.4.4
一、断言
1、简介:对设计违例进行检查
断言不仅可以进行时序的检测
,还可以进行覆盖率的收集
,因为covergroup只适合对功能点的测试,但是信号与信号之间的时序是否正确可能不能很好的覆盖,使用断言更加方便。
- 用来与设计功能和时序作比较的属性描述
- 检查设计内容
- 提供设计的可视度和调试能力
- 检查设计特性在验证中是否覆盖
- Verilog不支持断言
(1)特点:可以自由打开或关闭、小部分可以综合或移植到emulation,实现跨平台的移植
(2)优势:
- 断言代码简单,能够缩短开发时间
- 断言是可以观测的,能够通过断言直接看到是哪里的bug
- 能够提供覆盖率收集
(3)断言是在observed
阶段执行,保证采样到稳定的信号
2、断言类型
(1)立即断言/immediate assertion非时序的
、执行时如同过程语句
、在initial/always/task/function
中使用(不能影响设计代码),用来检测待测设计的信号值,可以理解为设计中的条件判断if
。它在程序执行到这个程序块时立即执行。只能用于动态仿真。
name: assert(expression) [pass_statement] [else fail_statement]
assert(myfunc(a,b)) count = count + 1; else ->event1;
assert(y==0) else flag = 1;
always@(state)
assert(state==$onehot) else $fatal;
(2)并发断言/concurrent assertion时序性的
、检查很多个周期
、property
关键词(区分立即断言和并发断言)、与设计模块一同并行执行
。
并行断言离不开时钟,在时钟边沿激活,变量的值是采样到的值。
并发断言可以在module
、interface
、program
中定义。
在静态(形式)验证及动态仿真工具中均可以应用
Request-Grant协议描述: request拉高,在2个周期后,grant拉高,
在1个周期后,request拉低,在1个周期后,grant拉低。
property req_grant_prop;
@(posedge clk) req ##2 gnt ##1 !req ## !gnt;
endproperty
assert property req_grant_prop else $error("violation");
3、sequence激励
(1)定义:一个或多个时钟周期内的时序描述
,是property的基本构建模块,并经过组合来描述复杂的功能属性。可以在module
、interface
、program
、clocking
、package
块中声明,不可以在类
里面声明。
断言建议可以放到interface里面。
sequence s1;
@(posedge clk) a ##1 b ##1 c;
endsequence
4、assert使用
一般而言,会先编写好sequence和property,然后通过assert进行一个断言检测,调用比较简单,如图所示。断言里基本不做是什么操作,必要的操作在property中做。
蕴含操作符
- 交叠蕴含overlapped implication:|-> 同一个周期有效
- 非交叠蕴含:|=> 下一个周期有效
(1)assertion可以直接包含一个property,也可以独立声明property,在property内部可以有条件地关闭
//直接包含property
assert property((@posedge clk)
disable iff(!reset)
a |=> b ##1 c); //a为高的下一个周期b为高,再下个周期c为高
//独立声明
property p_my_prop;
@(posegde clk) disable iff(!reset)
a |=> b ##1 c;
endproperty
a_my_prop: assert property(my_prop);
(2)property块可以直接包含一个或多个sequence
,sequence也可以独立声明
这个sequence不是UVM的,而是SV的sequence,用来描述时序
sequence s2;
@(posedge clk) a ##1 c;
endsequence
property p1;
@(posedge clk) disable iff(!reset)
s1 |=> s2;
endproperty
5、并发断言中常见表达式
APB协议断言检查
(1)一些常见操作
$rose
:上升沿检测,检测从0/x/z变成1$fell
:下降沿检测,从1/x/z变为0$stable
:检测当前边沿采样状态和上一边沿采样状态没有发生变化
property sadjn;
@(posedge clk) $rose(a) |=> $rose(b); //a上升后下个周期b也上升
@(posedge clk) $rose(a) |-> not ($isunknown(b)); //a上升时b必须是0或1,不能是x或z
endproperty;
$past
:追溯过去任意时钟,默认为1
//ack拉高的前两个周期,req信号为高
@(posedge clk) $rose(ack) |-> $past(reg,2);
$onehot
:用于检测表达式中只有1bit为1其他bit为0或高阻或X态$onehot0
:检测表达式中所有bit都为0或只有1bit为1
$isunknown
:检测信号为高阻态或者X态
$countones
:统计表达式中bit为1的个数$countbits
(expression,control_bit):计算expression中匹配control_bit的位数
$assertion(level, list of module, instance or assertion)
:开启断言,0表示当前模块或者层次下的所有assertion,n表示当前模块或者层次下n层范围内的assertion$assertoff(...)
:关闭不处于活动状态下断言$assertkill(...)
:杀死所有断言
$asssertoff(0, top_tb.cpu_inst1);
(2)时序相关##m
:延迟采样m个周期##[m:n]
:延迟采样m至n个周期
[*m]
:重复m次,连续 (重复操作符)[*m:n]
:重复m至n次,连续
[=m]
:重复m次,不连续 (间隔重复操作符)[=m:n]
:重复m至n次,不连续
[->m]
:重复m次,不连续,但是与后面的序列之间无间隔 (重复可有间隔操作符)[->m:n]
:重复m至n次
and、or、intersect
:操作符是两个sequence之间的,都必须从同一起点开始
throughout
:左边逻辑表达式/信号,右边sequence,表示检查一个信号在贯穿整个序列时是否满足
sequence burst;
@(posedge clk)
$fell(burst_mode) ##0
//前面条件为真,才检查后面的时序
(!burst_mode) throught (##2 ((trdy==0)&&(irdy==0))[*7]);
endsequence
within
:一个序列与另外一个序列在部分周期上的重叠intersect
:同时开始同时结束
a ##1 b[*2]; 相当于 a ##1 b ##1 b 连续发生
a |=> b[=2] ##1 c;
相当于b不连续重复两个周期,第二周期的b延时一个周期为c
b和c之间最小间隔为1clk,可以间隔更多的周期
a |=> b[=2:5] ##1 c;
b只要在a的下个周期或更长周期开始第一次满足,然后接下来再满足2-5次,都是可以的
意思是只要大于它规定的周期,所以c可以在b结束后至少一个周期或者更多周期满足,这样就可以
a |=> b[->2:5] ##1 c;
这种情况c必须在最后一个满足b条件后的下一个周期为1,否则失败
6、断言的绑定bind
断言既可以嵌入到设计中,也可以在设计外部定义。但是嵌入到设计内部,就需要考虑是否可以综合的问题,需要考虑添加编译定向。而在设计外部定义,不需要担心可综合的问题。
采用bind
方法可以满足在设计外部定义断言
,将断言绑定到设计内部或者接口
上面;
bind 可以将包含断言的模块与设计模块或者实例进行绑定,既可以满足对设计信号的可视性,又能满足断言模块的独立性;
使用方法:bind design_block_or_instance_name block_with_assertion
使用绑定的优势:无需修改原有设计代码,也不需要添加监测信号,就可以实现断言的添加。
在interface中声明property,然后绑定到dut上面,实际上会例化在dut内部
区别:interface作驱动,可以改变数值,同时可以看到内部信号。这里只做检测,不能修改数据,看不到内部信号,只有边界信号看得到
interface range(input clk,enable);
property pt;
@(posedge clk) enable |-> ....
endproperty
a_pt: assert property(pt);
endinterface
bind unit pt p1(clk,enable);
7、property使用
用来描述设计的确切行为
在验证中可以做assumption、checker、coverage
可以在module
、interface
、clocking
、package
在声明,也可以有形式参数
- 当使用
assert
键词时,可以用作checker来检查设计是否遵循property的描述。 - 当使用
assume
关键词时,可以作为环境的假设条件,对于仿真环境和形式验证均起到对激励进行假设的作用。 - 当使用
cover
挺键词时,可以将property是否真正通过作为断言覆盖率来衡量。
expect
语句:阻塞行为,等到断言执行完毕才会执行接下里的代码,可以在task中调用assert、assume、cover
语句:非阻塞的,不会影响仿真的运行
//仿真在200ms开始,如果在连续的三个周期内依次看到abc分别为1,则expect语句通过
initial begin
#200ms;
expect( @(posedge clk) a ##1 b ##1 c) else $error("fail");
end
8、property中的时钟(单时钟和多时钟)
(1)建议使用一个时钟作采样##1
使用的是前一个时钟,两个时钟之间的间隔要等一拍。多时钟没有办法使用and、or、intersect。
@(posedge clk0) sig0 ##1 @(posedge clk1) sig1
下面这些都是错误的,要使用的话这些关键词只能代表逻辑运算
@(posedge clk0) sig0 ##0 @(posedge clk1) sig1
@(posedge clk0) sig0 ##2 @(posedge clk1) sig1
@(posedge clk0) sig0 intersect @(posedge clk1) sig1
(2)多时钟的优先级:
- 显示声明断言时钟
- 继承断言所嵌入环境的时钟
- 继承默认的时钟
9、断言覆盖率
断言检查:测试时序协议
断言覆盖率:时序协议有没有发生,测试功能-assertdebug
:调试断言-assertcover
:收集覆盖率文章来源:https://www.toymoban.com/news/detail-493938.html
最后再加上一个对整个assertion控制:文章来源地址https://www.toymoban.com/news/detail-493938.html
initial begin: assertion_control
fork
forever begin
wait(rstn == 0) ;
$assertoff();
wait(rstn 1) ;
$asserton () ;
end
join none
end
到了这里,关于UVM学习笔记1——断言和断言覆盖率的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!