01_SVA断言语法介绍

1 Assertion介绍
  1. 什么是断言:断言是用来与设计功能和时序做比较的属性描述;
  2. 断言可以用来完成
  • 检查设计的内容;
  • 提高设计可视度和调试能力;
  • 检查设计特性是否在验证中被覆盖;
  • 可以自由打开和关闭;
  • 一小部分可以用来综合或者移植到emulation中,用来完成跨平台的移植;
  1. 类型划分
  • 立即断言
  1. 非时序;
  2. 执行过程如同过程语句;
  3. 可以在initial/always活成块或者task/function中使用;
  • 并行断言
  1. 时序性的;
  2. 关键词property用来区分立即断言和并行断言;
  3. 之所以称之为并行,是因为它们与设计模块异同并行执行;
  4. 并行断言只在时钟边沿激活,变量的值是采样到的值;
  5. 在property内部、外部关闭property;
2 sequence定义
  1. sequence是用来表示一个或多个时钟周期内时序描述;
  2. 是property的基本构建模块,并经过组合来描述复杂功能属性;
  3. sequence用来提供下列的场景描述:
    3.1. 第一个时钟周期,第一个表达式成立;
    3.2. 接下来若各个时钟周期,第二个表达式也成立;
    3.3. 以此类推,在接下来的若干时钟周期,后续表达式也成立;
    3.4. sequence可以在module、interface、program、clocking块和package中声明,不可以在类中声明;
    3.4. sequence可以提供形式参数,用来提高复用性;
    3.5. 蕴含操作符:如果property中左边的先行算子成立,那么property右边的后续算子才会被计算;
    3.6. 如果先行算子不成功,那么整个属性就默认为成功,这叫做“空成功”;
    3.7. 蕴含结构只能用在属性定义中,不能在序列中使用;
  4. 基本操作符
  • ##用来表示周期延迟符号,例如##n表示在n个周期后,##0表示在当前周期,即交叠周期;a ##0 b可以表示为a && b;
  • ##[min:max]表示在一个范围内的时钟周期延迟,min、max必须是非负数,序列从min到max时间窗口中最早的时间来匹配;
  • 事件也可以通过[*n]操作符号来表示重复,n为非负数;
  • 类似,也可以使用[*m:n]来表示一定范围内的重复事件;
  • [=3]用来表示一个事件的连续重复,需要重复发生m次,但并不需要在连续周期内发生;
  • 类似的,[=m:n]用来表示从最小m到最大n的重复发生的非连续周期次数;
  • a[*0]用来表示没有在任何正数时钟周期内有效;
  • 例如a[*0:3] ##1 b ##1 c与那些清醒匹配呢?
  1. (b ##1 c)
  2. (a ##1 b ##1 c)
  3. (a ##1 a ##1 b ##1 c)
  4. (a ##1 a ##1 a ##1 b ##1 c)
  • and操作符
  1. and用来表示两个序列需要保持匹配;
  2. 用法:SEQ1 and SEQ2
  3. 下列情形将满足此操作符:
    3.1. 在同一个起始点开始,seq1和seq2均满足;
    3.2. 满足的时刻发生在两个序列都满足的周期,即稍晚时刻序列的满足时刻;
    3.3. 两个序列的满足时间可以不同;
  4. 如果操作符两边的序列都是用来衡量采样信号而非事件序列,那么要求在相同周期内,and左右两边的序列都应该满足条件;
  • intersect操作符
  1. 用法:与and操作符相似,要求操作符两边的事件序列在同一时刻开始,同一时刻结束;
  • or操作符
  1. 用法:用来表示两个序列至少有一个满足;
  2. 下列情形将满足此操作符:
    2.1. seq1和seq2都从同一时刻被触发;
    2.2. 最终满足seq1或者满足seq2;
    2.3. 每个序列的结束时间可以不同,结束时间移序列满足最后一个序列时间为准;
  • first_match
  1. 用法:first_match用来从多次满足的序列中选择第一次满足时刻,从而放弃其他满足时刻;
  2. first_match(SEQ),只会选择所有seq中最短的序列;
  • throughout
  1. 可以用来检查一个信号或者表达式在贯穿一个序列时是否满足要求;
  2. 用法:Sig/Exp1 throughout Seq
  3. 例如,在burst信号拉低2拍后,irdy/trdy也应该在连续7拍内拉低,并且burst信号也应在这一连续周期内保持为低;
sequence burst_rul1;
    @(posedge clk)
    $fell(burst) ##0
    (!burst) throughout (##2 (!irdy && !trdy) [*7]);
endsequence
  • within操作符
  • 用来检查一个序列与弄一个序列在部分周期长度上的重叠;
  1. 局部变量
  • 局部变量可以在sequence或者property中使用;
  • 这些变量会伴随着sequence、property动态创建;
  • 每个sequence实例都会有它自己的变量拷贝;
  • 在记录变量时,局部变量与sequence采用“,”分隔开来;
  • 例如,在cache rdDone拉高后,读出的rdData会在2个周期后,在其基础上加1,并作为wrData写入;
sequence check_reg_wr_data;
    int local_data;
    (rdDone && local_data = cache_rd_data) ##2 (reg_wr_data == local_data + 1);
endsequence
  • 例如,如果read拉高,伴随readId,则在下一次read必须在这一次readAck返回之后,再发起;
property checkReadIdAck;
    int local_id;
    ($rose(read), local_id = readId) |=> (not ($rose(read) && readId)) && ($rose(read) && readAckId == local_id); 
endproperty
  1. 调用方法
  • 在序列匹配时,可以调用task, void function和系统函数;
  • 例如,可以在s1序列末尾,分别打印出e和f变量被采样时的数值;
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));
endsequence
3 断言中常见的函数
  1. 访问采样的方法
  • $stable(expression, clocking_event),用来表示在连续的两个采样周期内,表达式的值保持不变,如果满足,返回1,否则返回0;
  • $past(expr, [num_cycle])用来访问在过去若干采样周期前的数值,num_cycle默认为1;
  • $rose、$fell、$stable也可以在过程块和连续赋值语句中使用;
  • 在sequence/propety/assertion中使用:
    1.1. $countbits 计算向量位宽
    1.2. $onehot 检查表达式中是否只有1位为1
    1.3. $isunknown 检查表达式中是否有x或者z
    1.4. $countones 计算表达式中为1的位数
  • 这些系统函数也可以一般在过程语句块和赋值语句块中;
  • 在assertion或者property中,可以通过“disable iff”来给assertion做局部的条件控制;
  • 在全局控制方面,可以通过系统函数对property模块或者实例作出控制:
    a. $asserton,默认控制,用来打开所有assertion;
    b. $assertoff, 暂时停止assertion运行;
    c. $assertkill,终止所有运行的assertion;
  • 例如,在reset阶段停止所有assertion,并且在其复位之后,使能所有assertion;
module assert_control;
    initial begin
        @(negedge rst_n)
        $assertoff(0, top_tb.cpu_inst1);
        @(posedge rst_n)
        $asserton(0, top_tb.cpu_inst1);
    end
endmodule
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值