测试平台主要用于产生激励,校验数据,覆盖测试计划(验证计划);
SVA主要用于协议检验和协议覆盖,相较于Verilog,更适合处理时序相关的检测。
断言分并发断言和及时断言,并发断言基于时钟周期,及时断言基于事件,类似于时序逻辑和组合逻辑的关系:
a1: assert property(@(posedge clk) not(a&&b));//并发断言,始终上升沿时断言
always_comb begin
a2: assert(a&&b);//及时断言,a或b有变化时断言
end
序列sequence,属性property
序列是逻辑事件的组合,属性是序列的组合。
sequence s1;//建立序列
@(posedge clk) a&&b;
end
sequence s2;
@(posedge clk) a||b;
end
proptery p1;//建立属性
s1 |-> s2;
endproperty
ap1 :assert property(p1);//断言属性
边沿定义的序列
- $rose(sig)//上个时钟沿采样为0,此时钟沿采样时为1。信号在时钟沿时发生变化是采样不到的。
- $fell(sig)
- $stable(sig)//当表达式不发生变化时返回真
参数化序列、属性
sequence s1(a,b);
@(posedge clk) a |-> ##1 b;//蕴含操作符,意为上升沿时检测到先行算子a为真时,则1个clk后b应该为1
endsequence
property p1(c);
c?s1(input1,input2):s1(input3,input4);
endproperty
ap1: assert property(1) $display("assert success\n");
else $display("assert failed\n");
交叠蕴含|->、非交叠蕴含|=>
交叠蕴含在先行算子为真的同周期发起后续算子的判断;非交叠蕴含在先行算子为真的下个clk进行后续算子的判断。
@(posedge clk) a |=> b 等同于 @(posedge clk) a |-> ##1 b;
时序窗口[:]
module assert_test(
input clk,
input a,
input b
);
property t1(s1,s2);
int c;
@(posedge clk) a,c=a |-> b//局部变量,可用于保存某时刻的值,前面必须加上逻辑事件
##[1:2] s1?a&&b:a||b |->//时间窗口,延时1~2个clk;蕴含可以嵌套;选择运算符,优先级最低
(##[1:2] s2?a^b:a==b) and//多个事件都发生,注意and作用范围,加括号。
(##[0:2] b==c);//0是当前clk
endproperty
c1: cover property(1,1) $display("cover c1_1_1");
c2: cover property(2,1) $display("cover c2_2_1");
endmodule
$past(sig,nclk)
表示sig信号nclk个周期前的值,可带门控$past(sig,nclk,en),在en有效时才进行。
重复运算符
- 连续重复:a[*3]; 连续3个周期a为1;可作用于序列
- 跟随重复:a[->3] ##1 b; a重复3次后,一个周期后,b要为1;(正推);不可作用于序列
- 非连续重复:a[=3] ##1 b; b为1的一个周期前,a要重复3次;(倒推);不可作用于序列
重复运算符可和时间窗口结合:a[*1:3],连续重复1~3次。
跟随重复和非连续重复,不要求在先行算子匹配后立即开始有效,即a可以延后为1:
@(posedge clk) b |-> ##1 a[->3] ##1 stop;//检测到b为1的1个延时后,开始等待a重复3次,a可以不在b为1延时1个clk后立即为1。
and、intersect
逻辑组合两个序列,两个序列拥有相同的起始点,可以有不同的结束点。注意and作用的范围,有的地方需要用括号。
和and的不同在于,两个序列必须也要有相同的结束时间(起始点也相同)。
or
略
first_match
使用了逻辑运算符(and和or)的序列中若使用了时间窗,可能出现同一个检验具有多个匹配的情况,使用first_match可以确保只用第一次序列匹配,其他匹配丢弃,。当多个序列组合在一起,只需使用时间窗内的第一次匹配来检验属性剩余部分时,非常有用。
throughout
(expression) throughout (seq),在整个seq检验过程中,expression始终为真。
within
seq1 within seq2,seq1在seq2的开始匹配点与结束点之间。
disable iff
disable iff(expression) <property definition>,当条件为真时,不进行属性的检查。
@(posedge clk) disable iff(reset) a |-> ##1 b;当reset有效时,不进行检查。
属性形参
局部变量
序列或属性中可以定义局部变量,变量可在子序列后赋值,用逗号隔开,如果子序列匹配,变量赋值语句执行,每次序列尝试匹配时,变量产生一个新的备份。
蕴含嵌套
蕴含-if/else
允许在蕴含的属性的后续算子中使用if/else语句:
@(posedge clk) a |-> if(b) (##1 c) else (!c);
当需要根据形参进行不同的序列判断时,最好写成以下形式:
if(para1) (...) else if(para1...) (...) else (...);
不要写成以下形式,否则容易出现莫名其妙的错误,通过序列为真后的打印看,序列是匹配的,但是属性断言却没报成功:
seq1...(para1==...? seq2 : seq3);
序列匹配时调用子程序
类似于在子序列匹配时,可在其后进行局部变量赋值,也可调用子程序,用逗号隔开:
@(posedge clk) a,$display("a=%0d @ %0t",a,$time) |=> b;
连接设计
1.可以向例化设计module一样进行例化,连接设计实例中的任何信号的跨模块引用(top.test1.a),可以,但不推荐。
2.bind top.u1 assert_chk as_u0(top.u1.clk,top.u1.a,top.u1.b);//top.u1是设计的例化,assert_chk是断言module名,as_u0是bind时断言的例化名,clk等是设计的信号。
功能覆盖
可用cover收集断言覆盖情况:
cp1: cover property(p1) begin $display("cp1 matched @ %0t",$time); end//可加执行块,如打印信息等子程序,或局部变量赋值。
仿真log中会打印检验的信息,如匹配次数等。
在vcs编译选项中加如以下参数后,可在覆盖率中查看cover的断言覆盖率:
vcs编译选项:
-assert enable_diag
-assert svaext//根据形参执行不同的sequence时,需要开启此选项,否则会报错。
-cm assert(多个覆盖率项:line+cond+tgl+fsm+assert)
/*下述选项支持断言报告开始、成功时间点
+vpi
-assert vpiSeqBeginTime
-assert vpiSeqFail
*/
simv仿真选项:
-cm assert//不加,覆盖率看不到断言覆盖率
+fsdb+sva_success//波形查看断言成功位置
仿真控制:
查看断言module内信号波形:fsdbDumpSVA
仿真中控制断言开启关闭:assertion off/on -module xxx
bind后的实例化位置是在bind到的rtl module下
断言module里用的信号,要么是全局信号,要么是input接口传进来的,而在bind连接端口时,如果断言module里的信号名和要bind到的module内的信号名一致,可使用(.*),不限于被bind到的module的接口,也包括其内部的信号