目录
assertion based verification ABV方法学定义assertion如何被使用,包括:
first_match表示从多次满足的序列中选择第一次满足的时刻,放弃其他时刻
throughout检查一个信号或表达式在贯穿一个seq时是否满足要求
within检查一个seq与另一个seq在部分clk长度上的重叠
用来与设计功能和时序做比较的属性描述。???
越短越好!
- [name:] assert(expression)[pass_statement][else fail_statement]
-
- time t;
-
- always @(posedge clk)
- if (state==REQ)
- assert (req1||req2)
- else begin
- t=$time;
- #5 $error("assert failed at time %0t", t);
- end
-
- //结合$fatal $error $warning $info
- assert (myfunc(a,b)) count1=count+1; else -> event1;
- assert (y==0) else flag=1;
- always @(state) assert (steate==$onehot) else $fatal;
- base_rule1: assert property (cont_prop(rst, in1, in2)) pass_stat else fail_stat;
- //req拉高,2个clk后grant拉高,1个clk后req拉低,1个clk后grant拉低
- property req_grant_prop
- @(posedge clk) req ## 2 gnt ##1 !req ## !gnt;
- endproperty
并行断言只会在clk边沿激活,变量的值是采样到的值
- assert property (@(posedge clk)) disable iff(!reset) a | => b ##1 c);
-
- assert property(my_prop);
- property my_prop;
- @(posedge clk))
- disable iff(!reset) a | => b ##1 c;
- endproperty
property块可以直接包含sequence
复杂的property可以独立声明多个sequence
sequence是property的基本构建模块,经过组合来描述复杂的功能属性
描述时序,不是做激励
- sequence s1;
- @(posedge clk) a ##1 b ##1 c;
- endsequence
-
- sequence s2;
- @(posedge clk) a ##1 c;
- endsequence
-
- property p1;
- @(posedge clk) disable iff(!reset)
- s1 |=>s2;//如果出现s1序列则马上跟着出现s2序列
- endproperty
sequence可以在module interface program clocking package中声明
- sequence t2;
- (a ## [2:3] b) or (c ##[1:2] d);
- endsequence
- sequence s20_1 (data, en);//参数为data和en
- (!frame && (data==data_bus)) ##1 (c_be[0:3] == en);
- endsequence
表示:如果property中左边的先行算子成立,那么右边的后续算子才会被计算
如果先行算子antecedent不成功,整个属性就默认被认为成功,这是空成功vacuous success
只能在property中定义,不能在seq中定义
分类
交叠蕴含overlapped implication
- property p_req_ack;
- @(posedge clk) mem_en |-> (req ##2 ack);
- endproperty
非交叠蕴含noi
##n表示在n个clk后
##0表示在当前周期,即交叠周期,相当于逻辑与&&
- sequence a_b
- @(posedge clk) a ##1 b;
- endsequence
min和max必须是非负数,seq会在从min到max时间窗口中最早的时间来匹配?
在1个clk就出现b,则后面的clk就不会看了,最早的意思就是这样
- sequence a_b
- @(posedge clk) a ##[1:5] b;
- endsequence
将max换成$,增大仿真评估序列的负担,不推荐
n非负数,不能为$
表示b必须在两个连续的clk为真
- sequence a_b
- @(posedge clk) a ##1 b[*2];
- endsequence
如果是[*2:5],表示b必须在2-5个连续clk为真(相当于逻辑或)
a[*0]表示没有在任何正数clk内有效:如果a不满足,则忽略了,继续找b和c等其他事件
a[*0:3] ##1 b表示:b、a ##1 b、a ##1 a ##1 b、a ##1 a ##1 a ##1 b
需要重复发生m次,但不用在连续的clk发生
例如在实战1中的burst read测试,期望读的data和ack信号在接下来的4个clk内返回,但是不需要连续4个clk
[=m:n]表示从最小m到最大n的非连续clk
SEQ1 and SEQ2

and左右可以是信号
和and类似,区别在于两个seq时序要在同一个clk内匹配
SEQ1 or SEQ2,逻辑或||

对于and和or的应用:如果burst write的长度为4,则写的长度可以为1、2或4
- property burstlengthvalid
- @(posedge clk) disable iff(!rst)
- ((burstlen==4) |-> (wrlen--1) or (wrlen==2) or (wrlen==4))
- endproperty
-
- assert property (bustlengthvalid)
- sequence t1;
- te1 ## [2:5] te2;//2-5次te2,共4种情况
- endsequence
-
- sequence ts1;
- first_match (te1 ## [2:5] te2);//上述4种情况中的第一次匹配的时刻
- endsequence
-
- sequence t2;
- (a ## [2:3] b) or (c ## [1:2] b);
- endsequence
-
- sequence ts2;
- first_match(t2);
- endsequence
每一次PCI总线进入idle时状态机也应该返回idle,所以时序要求frame和irdy信号保持至少两个clk以上为高时系统状态为idle
- sequence checkbusidle
- (## [2:$] (frame && irdy));//宁可写成100也不要$
- endsequence
-
- property first_match_idle
- @(posedge clk) first_match (checkbusidle) |-> (state==busidle);
- endproperty
Sig1/Exp1 throughout Seq,左边和右边不一样
在burst模式信号拉低后2个clk时,irdy/trdy要连续7个clk保持为低,同时burst模式信号在这连续的clk中也为低。(也就是burst模式信号至少比右边seq的时间还要长)
- sequence burst_rule1;
- @(posedge mclk)
- $fell (burst_mode) ##0//看做一个seq:burst_mode在这一拍拉低了
- (!burst_mode) throughout (##2 ((trdy==0) && (irdy==0)) [*7]);
- endsequence
SEQ1 within SEQ2,当seq1满足在seq2的一部分连续clk内成立,则表达式成立
trdy需要再irday下拉的1个clk后保持7个clk为低,同时irday也将保持8个clk为低:
!trdy[*7] within (($fell irdy) ##1 !irdy [*8])
SEQ.ended
在某一时刻序列抵达终点,则条件满足
- sequence e1;
- @(posedge sysclk) $rose(ready) ##1 proc1 ##1 proc2;
- endsequence
- //在inst为高的下一个clk,e1应该结束或者已经结束
- sequence rule;
- @(posedge sysclk) reset ##1 inst ##1 e1.ended ##1 branch_back;
- endsequence

- sequence arbseq (aFell, bRose);
- @(posedge clk) $fell(aFell) ##1
- $rose(bRose);
- endsequence
-
- property endcycle;
- @(posedge clk) $rose(c) |=> arbseq(a,b).ended;
- endproperty
- //这个property是不满足的,因为是在c拉高的时刻才开始这个property,a至少要在下个clk拉低
- $rose(c) && $fell(a) |=> $rose(b)
可以在sequence或者property中使用,会伴随他们动态创建
每一个sequence实例都会有它自己的变量拷贝
- sequence rs_cache_done
- ##[1:5] rdDone;
- endsequence
- //在cache rdDone拉高后读出的rdData会在2个clk后,在其基础上加1,并作为wrData写入
- sequence check_reg_wr_data;
- int local_data;//局部变量
- (rs_cache_done, local_data==cache_rd_data) ##2 (reg_wr_data == (local_data+1));
- endsequence
- property checkreadidack;
- int loc_id;
- //read拉高,伴随readid,下一次read必须在这一次read对应的readack返回之后才可以发起,用局部变量来存储
- ($rose(read), loc_id=readid) |=>//满足序列后执行逗号后的表达式
- not ($rose(read) && readid==loc_id) ##0 ($rose(readack) && readackid==loc_id);
- endproperty
- //先满足($rose(readack) && readackid==loc_id)
- //not ($rose(read) && readid==loc_id)没有相同readid的read发起
- //##0 表示逻辑与
序列匹配时可以调用task,void function、系统函数
- sequence s1;
- logic v,w;
- (a, v=e) ##1 (b[->1], w=f, $display("b after a with v = %h, w = %h \\n", v,w));
系统函数用来访问指定类型的变量采样:访问当前和上一个周期采样值,检测采样变量的变化
- $rose(expression[, clocking_event])
- $fell(expression[, clocking_event])
- //与上一个采样周期相比,变量最低位是否跳变为1或0,满足则返回1,否则返回0
- //clocking_event在sequence中不需要单独提供,一般会指定采样clk
- $stable(expression[, clocking_event])
- //表示在连续两个clk内表达式的值保持不变,满足则返回1,否则返回0
- $past(expr[, num_cycles][, gating_expr][, clocking_event])
- //访问在过去若干个采样周期前的数值,默认num_cycle为1,采样1个clk前的数值
- property reqcauseack;
- @(posedge clk) $rose(ack) |-> $past(req, 2);
- endproperty
- //在ack拉高时的前两个clkreq应该为高
- property cache_read_chk;
- @(posedge clk) (state==CACHE_READ) |-> ($past(state) != CACHE_MISS);
- endproperty
- //如果当前是CACHE_READ,则上一个状态不应该是miss
$rose fell stable可以在过程块语句和连续赋值中使用
- always @(posedge clk)
- testdone<=stimulus_over & $rose(unit_done);
-
- always @(posedge clk) begin
- if($stable(my_sig)) begin $display(); end
- end
-
- assign intr_cleared=$fell(intr, @(posedge clk));//class里面能不能指定clk
- assign intr_set=$rose(intr, @posedge clk);
系统函数也可以在seq,pro,assertion中使用
$countbits(expression, control_bit)计算expression中匹配control_bit数值的位数
$countones相当于$countbits(expression, ‘1)
$onehot(expression)相当于$countbits(expression, ‘1)==1
$isunknown(expression)相当于$countbits(expression, ‘x, ‘z)!=0
$assertoff(level, [list of module, instance or assertion_identifier]);
$assertkill(level, [list of module, instance or assertion_identifier]);
$asserton(level, [list of module, instance or assertion_identifier]);
level=0表示当前模块或者层次下所有assertion,level=n表示当前模块或层次下n层范围中的assertion
identifier表示property的名字或者assertion的label
- module assert_control();
- initial begin
- @(negedge top_tb.reset_n) $display();
- $assertoff(0, top_tb.cpu_inst1);
- @(posedge top_tb.reset_n) $display();
- $asserton(0, top_tb.cpu_inst1);
- end
- endmodule
- //在reset阶段停止所有assertion,复位之后开启