搬运:SystemVerilog断言与bind实践 - 知乎
在集成电路前端工作中,设计和验证都会用到断言(SVA), 设计用断言初步保证状态机等按设想跳转, 而验证希望用断言覆盖信号级的功能点。在使用断言时,即使你是设计人员, 也不太推荐将断言写在RTL代码的同一文件里,因为按照理解,RTL是可综合的,是芯片上的实际器件,而SVA不是;另外,rtl代码可能被某些EDA tool使用,但是该tool未必支持SVA。
废话少说,看如下一个FIFO,如何给它用bind添加断言?
就用这个写法:
而SVA写在一个module里:
这里注意点是:1.SVA module里的端口包括DUT的全部接口,以及你想检查的内部信号,注意方向上接口取反,内部信号均为input;
2.bind 写法是bind dut_module sva_module inst_name(.), 之所以SVA module端口添加了全部DUT接口(你可能并不需要检测全部接口),就是因为可以.*通配,非常方便;
bind一个SVA module,可以连接到如下两种情况:
1)某个module的全部实例;
这样所有的fifo1的实例全部会做SVA check。
另外,这个bind语句写在哪里比较合适呢?写在top_tb里就好,和DUT是平级的,层次比较清楚。
2)某个module的单个实例;
不推荐这么干!!!原因有二:这个写法在新VCS里是认的,但是老版VCS可能不认,所以自找麻烦;此外一个module的运行规则应该是一致的,如果你认为有不一致的地方,找找自身问题,设计问题或者验证决策问题,不该用断言来验证了。
再来看下个问题,如何bind断言至有参数的module?
要点就是,SVA module也同时参数化就行!我们之前说过,SVA module的接口和DUT是镜像的吧?那么参数也复制过来就行,如下面这个assert module,有一个参数SIZE,用法和DUT module一样就行。
这里还有一个技巧,就是断言的名字要长,有足够的信息量,在断言中不用$display打印信息,因为检查断言是否有检测到错本身就会在log打印了,之后需求去波形check,如果名字信息量够,往往无需再看断言怎么写的是什么功能,如下图大家看看,一目了然:
SVA concurrent与immediate的选择?
并发断言在周期结束时,每个周期只对所有重要信号采样一次,就在信号在下一个时钟边缘发生变化之前,就像实际的硬件寄存器采样一样。对于简单的SVA使用,我们通常不关心循环期间的组合沉降或故障,我们只关心循环结束时的最终值。下图是immediate断言:
即时断言在调用时按需采样信号。即时断言对于测试复位、预设和锁存启用等异步控制信号非常有用。如果任何异步控制信号出现故障,它们确实会立即引起变化,可能需要立即评估。
一般RTL里95%以上的信号可以在一个周期结束时进行采样,并进行适当评估,而可能只有约5%的异步
需要立即对控制信号进行采样和评估。这最能描述我自己的用法并发断言和即时断言的比率。
请记住,立即断言使用关键字assert,他们不会等到采样周期结束。
一些有用的宏:
这是并发断言的两个宏,并发断言以clk为依据,所以用宏来避免重复劳动。iff(!rst_n)代表复位时不用检测。
上面的宏使用和不使用的对比如下:
最后总结下本文的重点:
1.使用bind file
2.不要把sva写入rtl同文件
3.sva的label要长,比如ERR_AVALID_TOO_LONG,不要在断言中加display和uvm_info等
4.大多数断言都使用并发断言(
clk),不要立即断言(除非验证异步复位等情况)
5.使用宏来避免重复劳动