在RTL设计或者是使用Formal Verification的工具时, 常用assertion来描述设计意图。本篇就主要介绍一下systemverilog的assertion。
- Immediate Assertions
常常用于仿真, 当某个条件满足的时候打印一些debug信息, 相当于if语句, 比如:
1 | assert (A == B) $display ("OK. A equals B"); |
- Concurrent Assertions
这种assertion相当于增加某种约束,下面举两个例子:
1 | assert property (!(Read && Write)); |
代表的是读写不能同时assert
1 | assert property (@(posedge Clock) Req |-> ##[1:2] Ack); |
上面的assertion经常出现在某种总线协议的握手过程, 表示的是req置位后1-2个clock cycle ack 信号assert。这个表达中的->
符号解释如下:
- s1 |-> s2: 如果s1 是match的, 那么s2也必然要match; 如果s1不匹配, 那么这个squence的结果就是true
- s1 |=> s2: 代表的是s1在下一个clock在进行判断,这种写法等价于下面的描述:
1 | ‘define true 1 |
- 独立申明property和sequence
上面的示例中, property和##[1:2] Ack
这种sequence都可以独立申明:
1 | property not_read_and_write; |
也可以组合成为更复杂的assertion描述
1 | sequence request |
- assertion clock
1 | property p; |
也可以直接写成:
1 | assert property (@(posedge clk) a ##1 b); |
- 异步复位
1 | property p1; |
- sequence
下面是一些sequence的例子: 其中##
符号代表的是延迟指定个数的时钟周期:
1 | a ##1 b // a must be true on the current clock tick |
*
符号代表的是左边sequence描述的重复:(注意带括号的)
1 | a ##1 b [*3] ##1 c // Equiv. to a ##1 b ##1 b ##1 b ##1 c |
$
可以拓展时间窗口, 但是可以没有范围:
1 | a ##1 b [*1:$] ##1 c // E.g. a b b b b c |
- coverage 描述
可以用cover property来确认某些sequence或者约束在电路中有没有被验证过:
1 | module Amod2(input bit clk); |
- assertion中的系统函数
$rose
, $fell
, $stable
表示的是某些信号的值是否在两个clock中间变化:
1 | assert property |
上述表示的是: 如果in在clock的上升沿由0变成1, 那么下个周期, dedect信号变成1
1 | assert property |
上述assert表示的是如果enable=0, 那么data不应该变化
1 | assert property |
函数$past
表示的是括号中表达式前一个周期的值。此外, 如果expr中只有一个bit是high,$onhot(expr)
返回true。
- binding
在用assert, assume等property做形式验证是, 我们常常希望property文件和design分开, 那么就可以用binding 把assertion和要验证的设计绑定。
比如说design如下:
1 | module M_v (...); |
针对这个文件写的assert等如下所示:
1 | module M_sva(....) |
然后就可以用binding 进行绑定
1 | bind M |