[381] 有几种方式为一个设计编写断言?
sequence是编写property或断言的基本构建块。sequence可以认为是在单个时钟边沿求值的简单布尔表达式,也可以是在多个周期内求值的事件sequence。property可能涉及检查在不同时间开始的一个或多个sequence行为。因此,可以使用逻辑或sequence组合的多个sequence来构造property。
sequence的基本语法是:
sequence name_of_sequence;
<boolean expression >
endsequence
例如,下面的sequence在检查每个周期的上升沿是否a和b始终相等
sequence s_a_eq_b;
@posedge(clk) (a ==b);
endsequence
@posedge(tst_signal)会在每个上升沿进行采样,检查tst_signal是否为1。但是,rose()是一个系统任务,它检查信号的采样值在先前采样和当前采样之间(先前采样可能是0 / x / z)是否变为1。因此,rose()需要两个采样值进行判断,从原来的非1变成1。例如:在下面的sequence中,仅当信号“a”在时钟的两个正沿之间从0/x/ z的值变为1时,
sequence S1;
@(posedge clk) $rose(a)
endsequence
sequence S1;
@(posedge clk) $rose(a);
endsequence
第二种情况下会捕获成功,$rose()检查的是两次采样,第一次非1,第二次为1,@(posedge clk)表示在上升沿时采样。
以上所有地方都可以
不能,并发断言不能再类中实现
req ##2 gnt ##1 !req
当gnt信号在req信号为高电平后的两个周期变为高电平,然后一个周期后req信号被置为零时,该sequence的值为真。
如果需要对一个sequence表达式进行一次以上的迭代求值,则可以使用重复运算符来构造一个更长的sequence,而不是编写一个长sequence。SVA支持三种类型的重复运算符:
a ##1 b [*5]
a ##1 b [->2:10] ##1 c
a ##1 b [=2:10] ##1 c
module test (input clk, input a, input b);
assert_1: assert ( a && b);
endmodule;
立即断言只能在程序块中使用
property a_min_2_max_6:
@(posedge clk) $rose(a) |-> a[*2:6] ##1 (a==0)
endproperty
assert property (a_min_2_max_6);
蕴含操作符用于指定检查的先决条件,描述当先决条件发生后,再继续匹配。蕴含操作符只能再property这一级别使用。蕴含操作符有两种
assert property prop_name ( sequence_expr |-> property_expr )
assert property prop_name ( sequence_expr |=> property_expr )
当蕴含操作符左侧发生后,才会匹配右侧
assert property abc_overlap (@posedge clk (a==1) |-> b ##1 c )
assert property abc_overlap (@posedge clk (a==1) |=> b ##1 c )
不能,只能在property中使用
1) @(posedge clk) req |=> ##2 $rose(ack);
2) @(posedge clk) req |-> ##3 $rose(ack);
是的,参考[392]
允许,下面就是一个例子
a |=> b |=> c
匹配的就是a为高,下个周期b为高,再下个周期c为高
这个系统函数能够从之前的时钟周期中获得信号
使用系统函数$isunknown(signal)可以进行此项检查。
assert property (@(posedge clk) ! $isunknown(mysignal));
使用系统函数isonehot()或者countones()可以进行此项检查
assert property (@(posedge clk) $isonehot(state));
assert property (@(posedge clk) $countones(state)==1);
property p_req_grant; @(posedge clk) $rose (req) |-> ##[2:5] $rose (gnt); endproperty
使用“disable iff”可以实现
assert property (@(posedge clk) disable iff (reset) a |=> b);
SystemVerilog中的bind构造用于将checker于模块、模块的示例或者一个模块的多个示例进行绑定。通过绑定可以分离断言和设计diamagnetic。下面是示例语法
bind <target module/instance> <module/interface to be instantiated> <instance name with port map>
当我们有下面的一个接口,并且内嵌断言
interface range (input clk, enable, int minval, expr);
property crange_en;
@(posedge clk) enable |-> (minval <= expr);
endproperty
range_chk: assert property (crange_en);
endinterface
bind cr_unit range r1(c_clk,c_en,v_low,(in1&&in2));
bind cr_unit:cr_unit_1 range r1(c_clk,c_en,v_low,(in1&&in2));
使用$assertoff()系统函数可以实现,缺省情况下会关掉所有断言。也可以指定关闭哪些断言。
$assertoff[(levels[, list])]
第一个参数指定关闭哪个层次的断言,第二个参数指定关闭具体哪些property
sequence seq1;
@(posedge clk) a ##1 b;
endsequence
property prop1;
not seq1;
endproperty
assert property (prop1);
property prop1;
@(posedge clk) not (a ##1 b);
endproperty
assert property (prop1);
always @(posedge clk) assert property (not (a ##1 b));
clocking master_clk @(posedge clk);
property prop1;
not (a ##1 b);
endproperty
endclocking
assert property (master_clk.prop1);
default clocking master_clk ; // master clock as defined above
property p4;
not (a ##1 b);
endproperty
assert property (p4);
assert property (@(posedge clk) disable iff (!rst_n) (wordcnt>31 |-> fifo_full));
assert property (@(posedge clk) disable iff (!rst_n) (wordcnt==31 && write_en && !read_en |=> fifo_full));
注意第二条,使用的是非交叠蕴含操作符,满标志位要在下个周期拉高。
本系列完结!