UVM学习笔记1——断言和断言覆盖率


前言

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关键词(区分立即断言和并发断言)、与设计模块一同并行执行
并行断言离不开时钟,在时钟边沿激活,变量的值是采样到的值。
并发断言可以在moduleinterfaceprogram中定义。
静态(形式)验证动态仿真工具中均可以应用

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的基本构建模块,并经过组合来描述复杂的功能属性。可以在moduleinterfaceprogramclockingpackage块中声明,不可以在里面声明。
断言建议可以放到interface里面。

sequence s1;
	@(posedge clk) a ##1 b ##1 c;
endsequence

4、assert使用

一般而言,会先编写好sequenceproperty,然后通过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
可以在moduleinterfaceclockingpackage在声明,也可以有形式参数

  • 当使用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:收集覆盖率

最后再加上一个对整个assertion控制:

initial begin: assertion_control
	fork
		forever begin
			wait(rstn == 0) ;
			$assertoff();
			wait(rstn 1) ;
			$asserton () ;
		end
	join none
end

  • 9
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
UVM验证,测试用例和覆盖率是被广泛关注的两个重要方面。 测试用例是验证工程师编写的针对设备或系统的特定功能或场景的输入。它们是一系列的测试向量,用于模拟各种可能的工作条件和输入情况,以确保设计在各种情况下都能正常工作。测试用例是验证过程的核心,通过执行它们,我们可以发现设计的错误、漏洞或不足之处。 覆盖率是用来衡量测试用例的有效性以及对设计进行全面覆盖的度量标准。它能够量化验证环境对设计的测试覆盖程度,从而帮助验证工程师评估验证品质。通常有三种常见的覆盖类型:语句覆盖、分支覆盖和条件覆盖。测试用例的执行结果与设计的各种语句、分支和条件的覆盖情况相比较,从而确定验证工作的完整性。 测试用例和覆盖率之间存在着密切的关系。通过对测试用例进行分析,可以确定哪些部分没有得到充分的测试,进而有针对性地编写新的测试用例。同时,覆盖率分析也可以评估现有测试用例的覆盖范围和覆盖质量。通过监控覆盖率的变化,可以有效地跟踪验证的进展,并及时进行调整和改进。 总结而言,测试用例和覆盖率UVM验证都是非常重要且不可或缺的。它们共同构成了验证活动的核心,并通过不断迭代与完善,使验证工程师能够发现设计的问题,并为设计团队提供优质的验证结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值