目录
(一)从断言的功能上来说,广义的断言分为四类,分别满足不同的验证需要。
(二)从断言的触发方式上来分,断言又可以分成两大类:即时断言和并发断言。
(三)分析所有 assert 断言的 COI 集合,并且报告出在 COI 之外的电路:
一、什么是断言?
- 布尔表达式(booleans):构成SVA的最基本单元。其一般形式为标准的SystemVerilog的布尔表达式,它由信号及其逻辑关系运算符构成,用以表示某个逻辑事件的发生。
- 序列(sequence):布尔表达式在时间上的组合。
- 属性(property):是在仿真或者形式验证中被验证的单元。属性将序列通过逻辑或者有序地组合起来生成更复杂的序列,SVA提供关键词“property”来表达这些复杂的有序行为。
- 断言声明(assertion statements):属性要在断言声明中被调用才能发挥作用,否则它们会被编译器忽略掉。
二、断言分类?
(一)从断言的功能上来说,广义的断言分为四类,分别满足不同的验证需要。
- assert :通常直接被称为断言,也是狭义范畴所指的断言。Assert 是断言中最常见的用法,用于描述电路的逻辑行为和属性。这类断言无论在形式化验证还是动态仿真中,都作为一个待验证的目标,并且期望这个断言在整个验证过程中和所有的验证场景中,永远为真。否则,验证工具会给出验证错误的结果。
- cover:覆盖断言。在形式化验证和动态仿真中,都用来检验验证工作的完备性。与 assert 类似,cover 也是一类验证目标。但是和 assert 不同的是,cover 不要求在所有的验证场景中永远为真,只要在某些验证场景中 cover 可以出现真的情况(哪怕只出现了一次),这个 cover 的验证结果即是通过,否则验证出错。
- assume:约束断言。在形式化验证中,assume 断言所描述的电路行为在整个验证过程中,也必须永远为真。但是和 assert 不同的是,assume 所描述的电路行为由工具来保证其永远为真,即是说形式化验证工具不会去验证导致 assume 为假的验证场景。通常 assume 是用来规范电路的输入激励的。
- restrict:restrict 断言在形式化验证中的作用和 assume 完全一致,通常不会使用。
(二)从断言的触发方式上来分,断言又可以分成两大类:即时断言和并发断言。
- 即时断言:即时断言一般出现在 always 顺序执行块中,于其他的 RTL 语句混在一起,只有当该顺序语句所在的分支被执行的时候才会被触发,其触发条件和顺序语句的触发条件完全一致。即时断言在形式化验证中并不常用。
- 并发断言:并发断言是形式化验证中常用的一类的断言。并发断言可以出现在 always 顺序块中或者在always 块之外单独出现。并发断言的触发条件一定是某一个时钟的跳变沿。因此,在并发断言中通常会用@(clock event)来定义断言的触发条件,而即时断言不能在断言中定义触发条件。
- 举个例子:
ast_con : assert property(@(posedge clk) !a ##1 a |-> ##2 b==2‘b0);
除了出现的位置不同,是否需要定义触发时钟沿,并发断言和即时断言在语法上最重要的区别是并发断言需要有关键词”property”,而即时断言没有。因为即时断言的内容只能是一个简单的布尔表达式,而并发断言的内容通常由以下四部分组成:
- 布尔表达式(boolean)。表示信号的组合逻辑关系。比如上面例子中的!a、a、b==2’b0都是布尔表达式。
- 序列(sequence)。表达信号间的时序关系,比如上面例子中的!a ##1 a 以及##2 b==2‘b0。
- 属性(property)。表示序列间的相互关系,比如上面例子中的@(psoedge clk) !a ##1 a |-> ##2 b==2’b0。
- 断言(assert)。最后需要将属性声明成 assert、cover、assume、restrict 中的某一种。
三、如何在 RTL 设计中嵌入 SVA 断言
-
有两种方式将 SVA 断言和 RTL 结合到一起。
- 方法一:直接在 RTL 模块里写入 SVA 断言。
- 方法二:单独写一个 SVA 检查模块,将所需要用到的 RTL 信号全部当作检查模块的 input。
举个例子:
generate
genvar ii;
for(ii=0 ; ii<NUM_PORTS; ii=ii+1)
begin
asm_request_stable : assume property(
@(posedge clk) disable iff(rst)
request[ii] && !grant[ii] |-> ##1 request[ii]);
asm_request_cancel : assume property(
@(posedge clk) disable iff(rst)
request[ii] && grant[ii] |-> ##1 !request[ii]);
end
endgenerate
module arbiter(…) …
arbiter_checker my_checker(.clk(clk), rst(rst), request(request) … ); …
Endmodule
四、assert和cover的查看、删除和恢复
(一)show_prop查看
- -only_cover
- -only_assert
- -summary(会显示所有的assertion+最后的汇总消息)
- -only_summary(只显示最后的汇总消息)
(二)rm_prop删除
删除 assert 和 cover 操作并不会真的从验证环境中删除这些验证目标,而是将其设置为无效状态,在验证中不再验证这些验证目标。用户可以随时恢复这些验证目标。默认删除assert,要对cover操作,需加上-cover,不能同时操作assert和cover,可以使用通配符。可选参数:
- -cover
(三)add_prop恢复
- -cover
- -restore
五、约束及其种类
(一)常量
- -postreset ,表示该常量只在复位后的形式化验证阶段有效,不影响复位阶段寄存器初始值的生成。
- -reset ,表示该常量只在复位阶段有效,只影响寄存器初始值的生成,不影响形式化证明。
(二)SVA约束
SVA 约束即是在 SVA 章节中提到的 assume 断言。也是形式化验证中最常用的约束形式。这种约束方式最灵活多变,几乎可以满足所有的验证需求。SVA assume 断言约束会随着验证文件一起读入,被 AveMC 识别。同样地,使用add_cons和rm_cons进行添加何删除约束
(三)时钟域约束
当设计存在多个时钟时,AveMC 可以根据电路逻辑,进行综合分析,识别内部寄存器所在的时钟域。但是对于顶层的输入信号,如果不指定其时钟域,默认所有信号会跟随最快的系统时钟进行跳变,有时候会发生误报。这时候需要用户对于输入信号和无驱动进行时钟域的说明。定义时钟域的命令为 strobe,可选参数
- -all 表示将为所有的非时钟和非复位信号定义时钟域
- -clock 是所属时钟域的时钟名称
- -edge posedge/negedge 表示信号在时钟域上沿跳变还是下沿跳变。
用户可以进行多次 strobe 约束操作,但是同一个信号只能被约束一次,否则 AveMC 会报出错误信息并忽略第二次操作,注意 strobe 命令只能对顶层输入和无驱动信号进行约束。移除strobe 约束,可以使用 unstrobe 命令。
(四)SVA断言在不同声明类型中的转换
- 用 rm_prop/rm_prop -cover/rm_cons 命令将需要改变类型的 SVA 断言移除
- 用 add_prop/add_prop -cover/add_cons 命令将移除的 SVA 断言添加成需要改变的类型
六、检查COI
- -assertion : 表示对指定断言分析其 COI。
- -cover : 表示分析所有断言的 COI 行程 COI 集合,最后列出不在这个 COI 集合内的所有信。
- -cover+: 分析过程同-cover,但是最后会列出所有的信号,无论其在不在 COI 集合内。
- -depth N : 表示只分析目标往前推 N 级时序寄存器,默认为无限,即一直追踪到顶层输入止。
- -dump : 把 COI 分析结果存到结果目录的 fanin.rep 文件中,多次执行 fanin -dump 命令会覆盖之前的文件。
- -dump+ : 和-dump 类似,但是会将分析结果添加而不是覆盖之前的文件。
- -list : 显示 COI 分析结果的信号列表。
- -net : 表示分析指定信号的 COI。
- -type : 用来指定分析的 COI 报告中需要列出的信号类型。