reference : http://blog.sina.com.cn/s/blog_4c270c730101f6mw.html

    断言assertion被放在verilog设计中,方便在仿真时查看异常情况。当异常出现时,断言会报警。一般在数字电路设计中都要加入断言,断言占整个设计的比例应不少于30%。以下是断言的语法:

1. SVA的插入位置:在一个.v文件中:
                module ABC ();
                   rtl 代码
                   SVA断言
                endmodule

注意:不要将SVA写在enmodule外面。

2. 断言编写的一般格式是:
   【例】 断言名称1:assert property(事件1)       //没有分号
          $display("........",$time);             //有分号
          else
          $display("........",$time);             //有分号

断言名称2:assert property(事件2)
          $display("........",$time);
          else
          $display("........",$time);

断言的目的是:断定“事件1”和“事件2”会发生,如果发生了,就记录为pass,如果没发生,就记录为fail。注意:上例中没有if,只有else,断言本身就充当if的作用。

上例中,事件1和事件2可以用两种方式来写:
   (1) 序列块: sequence name;
                      。。。。。。。。。; 
                endsequence

(2) 属性块: property name;
                      。。。。。。。。。;
                endsequence

从定义来讲,sequence块用于定义一个事件(砖),而property块用于将事件组织起来,形成更复杂的一个过程(楼)。sequence块的内容不能为空,你写乱字符都行,但不能什么都没有。sequence也可以包含另一个sequence, 如:
                    sequence s1;
                        s2(a,b);
                    endsequence  //s1和s2都是sequence块

sequence块和property块都有name,使用assert调用时都是:“assert property(name);”
    在SVA中,sequence块一般用来定义组合逻辑断言,而property一般用来定义一个有时间观念的断言,它会常常调用sequence,一些时序操作如“|->”只能用于property就是这个原因。
     
   注:以下介绍的SVA语法,既可以写在sequence中,也可以写在property中,语法是通用的。

3. 带参数的property、带参数的sequence
   property也可以带参数,参数可以是事件或信号,调用时写成:assert property (p1(a,b))
   被主sequence调用的从sequence也能带参数,例如从sequence名字叫s2,主sequence名字叫s1:
          sequence s1;
             s2(a,b);
          endsequence

4. property内部可以定义局部变量,像正常的程序一样。
           property p1;
              int cnt;
              .....................
           endproperty

【注】在介绍语法之前,先强调写断言的一般格式:
    一般,断言是基于时序逻辑的,单纯进行组合逻辑的断言很少见,因为太费内存(时序逻辑是每个时钟周期判断一次,而组合逻辑却是每个时钟周期内判断多次,内存吃不消)。
    因此,写断言的一般规则是: time + event,要断定发生什么event,首先要指定发生event的时间,例如
每个时钟上升沿 + 发生某事
                某信号下降时 + 发生某事

5. 语法1:信号(或事件)间的“组合逻辑”关系:
   (1) 常见的有:&&, ||, !, ^
   (2) a和b哪个成立都行,但如果都成立,就认为是a成立:firstmatch(a||b),与“||”基本相同,不同点是当a和b都成立时,认为a成立。
   (3) a ? b:c ———— a事件成功后,触发b,a不成功则触发c

6. 语法2:在“时序逻辑”中判断独立的一根信号的行为:
    @ (posedge clk) A事件; ———— 当clk上升沿时,如果发生A事件,断言将报警。
   边沿触发内置函数:(假设存在一个信号a)
     $rose( a );———— 信号上升
     $fell( a );———— 信号下降
     $stable( a );———— 信号值不变

7. 语法3:在“时序逻辑”中判断多个事件/信号的行为关系:
   (1) intersect(a,b)———— 断定a和b两个事件同时产生,且同时结束。
   (2) a within b    ———— 断定b事件发生的时间段里包含a事件发生的时间段。
   (3) a ##2 b       ———— 断定a事件发生后2个单位时间内b事件一定会发生。
       a ##[1:3] b   ———— 断定a事件发生后1~3个单位时间内b事件一定会发生。
       a ##[3:$] b   ———— 断定a事件发生后3个周期时间后b事件一定会发生。
   (4) c throughout (a ##2 b)    ———— 断定在a事件成立到b事件成立的过程中,c事件“一直”成立。
   (5) @ (posedge clk) a |-> b   ———— 断定clk上升沿后,a事件“开始发生”,同时,b事件发生。
   (6) @ (posedge clk) a.end |-> b ———— 断定clk上升沿后,a事件执行了一段时间“结束”后,同时,b事件发生。
   注:"a |-> b" 在逻辑上是一个判断句式,即:
                    if a
                       b;
                    else
                       succeed;

因此,一旦 a 发生,b 必须发生,断言才成功。如果a没发生,走else,同样成功。

(7) @ (posedge clk) a |=> b   ———— 断定clk上升沿后,a事件开始发生,下一个时钟沿后,b事件开始发生。      
   (8) @ (posedge clk) a |=>##2b ———— 断定clk上升沿后,a事件开始发生,下三个时钟沿后,b事件开始发生。
   (9) @ (posedge clk) $past(a,2) == 1'b1 ———— 断定a信号在2个时钟周期“以前”,其电平值是1。
   (10) @ (posedge clk) a [*3] ———— 断定“@ (posedge clk) a”在连续3个时钟周期内都成立。
        @ (posedge clk) a [*1:3] ———— 断定“@ (posedge clk) a”在连续1~3个时钟周期内都成立。
        @ (posedge clk) a [->3] ———— 断定“@ (posedge clk) a”在非连续的3个时钟周期内都成立。
    
   举一个复杂点的例子:
           property ABC;
              int tmp;
              @(posedge clk) ($rose(a),tmp = b) |-> ##4 (c == (tmp*tmp+1)) ##3 d[*3];
           endproperty 
   上例的一个property说明:当clk上升沿时,断言开始。首先断定信号a由低变高,将此时的信号b的值赋给变量tmp,4个时钟周期后,断定信号c的值是4个周期前b^2+1,再过3个周期,断定信号d一定会起来,再过3个周期,信号d又起来一次。。。。。。。只有这些断定都成功,该句断言成功。otherwise,信号a从一开始就没起来,则断言也成功。

8. 语法4:多时钟域联合断言:一句断言可以表示多个时钟域的信号关系,例如:
                @ (posedge clk1) a |-> ##1 @ (posedge clk2) b
   当clk1上升沿时,事件a发生,紧接着如果过来第二个时钟clk2的上升沿,则b发生。“##1”在跨时钟时不表示一个时钟周期,只表示等待最近的一个跨时钟事件。所以此处不能写成##2或其他。但是可以写成:
                @ (posedge clk1) a |=> @ (posedge clk2) b

9. 语法5:总线的断言函数
   总线就是好多根bit线,共同表示一个数。SVA提供了多bit状态一起判断的函数,即总线断言函数:
   (1) $onehot(BUS)      ————BUS中有且仅有1 bit是高,其他是低。
   (2) $onehot0(BUS)     ————BUS中有不超过1 bit是高,也允许全0。
   (3) $isunknown(BUS)   ————BUS中存在高阻态或未知态。
   (4) countones(BUS)==n ————BUS中有且仅有n bits是高,其他是低。

10. 语法6:屏蔽不定态
    当信号被断言时,如果信号是未复位的不定态,不管怎么断言,都会报告:“断言失败”,为了在不定态不报告问题,在断言时可以屏蔽。
    如: @(posedge clk) (q == $past(d)),当未复位时报错,屏蔽方法是将该句改写为:
         @(posedge clk) disable iff (!rst_n) (q == $past(d))  //rst是低电平有效

10. 语法6:断言覆盖率检测:
name: cover property (func_name)

11. 在modelsim中开启断言编译和显示功能:
    (1)【编译verilog代码时按照system verilog进行编译】  vlog -sv abc.v
    (2)【仿真命令加一个-assertdebug】   vsim -assertdebug -novopt testbench
    (3)【如果想看断言成功与否的分析,使用打开断言窗口的命令】 view assertions

12. 在VCS中加入断言编译和显示功能:
    在fsdb文件中加一句话:$fsdbDumpSVA
    在VCS编译参数:system "vcs $VCS_SIMULATION" 中加入一些options:
           -assert enable_diag\
           -assert vpiSeqBeginTime\
           -assert vpiSeqFail\
           -assert report=路径\
           -assert finish_maxfail=100

***********************************************************************************************
【经验】以下是一些编写断言的经验:
1. 断言的目的:传统的验证方法是通过加激励,观察输出。这种方法对案例的依赖严重,案例设计不好,问题不便于暴露。而断言是伴随RTL代码的,不依赖测试案例,而是相对“静态”。例如:我们要测试一个串行数据读写单元,数据线只有一根,先传四位地址,再传数据。
(1)案例验证法:写一个地址,再写一段数据,然后读取该地址,看输出的是不是刚才写的数据。
(2)断言法:不需要专门设计地址和数据,当发起写时,在地址传输的时间里将地址存储到一个变量里,在数据传输的时间里将数据存储到一个变量里,观察RAM中该地址是否存在该数据就可以了。
    断言设计相当于在电脑上把RTL实现的功能再实现一遍。

2. 断言中可以包含function和task。而且function经常用于断言,因为有的处理很复杂,而断言又是“一句式”的,无法分成好几句进行表达,所以需要function替断言分担工作。

3. 断言允许规定同时发生的事件,就是组合逻辑,你可以写成:a && b,也可以写成 a ##0 b,不能写 ##0.5,不支持小数。

4. 断言是用电脑模仿RTL的运行过程,当RTL功能复杂时,你必须用到变量。断言中支持C语言的int和数组声明,但在赋值时“不能”写成:##4 var = Signal,其中var是断言中的变量,和RTL无关,Signal是RTL中的一个信号。本句是想在第4周期将Signal的值赋给var,以便在后面使用该值。但本句只有变量赋值,没有对RTL信号的任何断言,就会报错,解决方法是:##4 (“废话”,var = Signal),一定要有断言的话我们就写“废话”,例如:data == data 等。如果有多个变量要赋值也可以,##4 (废话,变量1赋值,变量2赋值...........)

5. 关于断言的表达风格:语法介绍的 “a |-> b”,实际上是 “if a, then b”的逻辑,当a不发生,b也不会被判断,该断言自然成功。但当我们的逻辑是
        if a1
        {
           if a2 
              then b
        }
该如何用断言表达???? 或许可以写成:“a1 |-> a2 |-> b”,也可以,但常用的表达是:
       “a1 && a2 |-> b” 或者 “a1 ##3 a2 |-> b”

6. 关于断言的时序:时序逻辑的断言需要注意的一个问题:
   例如:假设当clk上升沿到来时,b<=a。将上述逻辑写成断言时,如果写成“@(posedge clk) b==a”,看起来和 b<=a一样,但实际上是错的。因为当时钟上升时,b还没有得到a的值,a还需要一段保持时间。即,断言中的信号值实际上是时钟沿到来之前的值,而不是时钟沿到来后他们将要编程的值。所以,b<=a逻辑的断言应该是:“@ (posedge clk) (a==a,tmp=a) |=> (b==tmp);”

针对上述几点,举一个复杂的例子:
断言wr的功能是检查串行地址输入是否正确,串行地址输入线是 DataIn 。$time返回值以0.1ns为单位(因为我在testbench中的单位规定是`timescale 1ns/100ps,精度是100ps = 0.1ns),所以$time/10才是ns。
 /
    wr: assert property(wr_p)
    $display("succeed:",$time/10);
    else
        $display("error: ",$time/10);
/
//断言可以声明一个int数组arr[4],
//“@(posedge clk) !vld_pulse_r[0] && !DataIn”是真实的预备条件
//“##4 (read==read, arr[0] = DataIn)”只是为了在特定时间内赋值,有用的语句是“arr[0] = DataIn”,//“read==read”是废话,为了编译通过。
//arr赋值完毕后,进入function进行处理,判断实际地址addr跟junc处理过的数据是否相同。
//“addr == junc(arr[0],arr[1],arr[2],arr[3]);”就是junction调用。

property wr_p;
        int arr[4];
        @(posedge clk) !vld_pulse_r[0] && !DataIn   
            ##4 (read==read, arr[0] = DataIn) 
            ##1 (read==read, arr[1] = DataIn) 
            ##1 (read==read, arr[2] = DataIn) 
            ##1 (read==read, arr[3] = DataIn) |=>
            addr == junc(arr[0],arr[1],arr[2],arr[3]);
    endproperty
//
    function [3:0] junc;
        input a,b,c,d;
        reg [3:0] a1;
        reg [3:0] b1;
        reg [3:0] c1;
        reg [3:0] d1;

a1 = {3'b0,a};
        b1 = {3'b0,b};
        c1 = {3'b0,c};
        d1 = {3'b0,d};
        junc = a1+(b1<<1)+(c1<<2)+(d1<<3);
        $display(junc);
    endfunction

7. 如果想在SVA中使用类似for(){....}的功能,别忘了语法中介绍的[*3],这是在断言中实现for的唯一方式。
                ##4 (废话, cnt = 0, arr[cnt] = DataIn, cnt++)   //初始化一下,
                ##1 (read==read, arr[cnt] = DataIn, cnt++)[*3]  //循环3次

8. 每句断言都是一个小程序:如上例,在##4时间点上,(废话, cnt = 0, arr[cnt] = DataIn, cnt++)就是一个小程序,信号断言必须是第一句,其他运算按照顺序进行。

9. 断言的变量除了可用C语言中的int,float外,还可以是reg [n:0]等数字电路类型。

10. 注意:
像这种写法:
    property ept_p;
        @(posedge rd_clk)   ((rd_num == 0) |-> rd_ept)
                         && (rd_ept |-> (rd_num == 0));
    endproperty
是错误的,写了|->,就不能再用 && 等事件组合逻辑了。
解决方法是使用2个断言,没更好的方法。

芯片设计:verilog断言(SVA)语法相关推荐

  1. verilog断言(SVA)语法

    断言assertion被放在verilog设计中,方便在仿真时查看异常情况. 当异常出现时,断言会报警.一般在数字电路设计中都要加入断言,断言占整个设计的比例应不少于30%.以下是断言的语法: 1. ...

  2. [SV]SystemVerilog 断言(SVA)检查器库(OVL)

    SystemVerilog 断言(SVA)检查器库(OVL) 前言:SystemVerilog 断言(SVA)检查器库由如下两部分组成: 由检查器组成的SystemVerilog验证库(SVL),这些 ...

  3. system verilog断言学习笔记

    文章目录 前言 SVA介绍 什么是断言 SVA术语 并发断言 即时断言 建立SVA块 一个简单的序列 边沿定义的序列 SVA中的时钟定义 禁止属性 一个简单的执行块 蕴含操作符 交叠蕴含 非交叠蕴含 ...

  4. (14)Verilog数据类型-基本语法(二)(第3天)

    (14)Verilog数据类型-基本语法(二)(第3天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)Verilog数据类型-基本语法(二)(第3天) 5)技术 ...

  5. Verilog 实现占空比为50%的三分频 断言SVA查看波形

    1.方法一:异或实现 module d3(input clk,input reset,output div_three ); reg [1:0] cnt=2'b00; reg div_clk1; re ...

  6. Verilog 实现占空比为3/5 2/5 1/5 50% 的五分频信号 断言SVA查看波形

    1. 3/5 2/5 1/5占空比的五分频 module div5(clk,reset,clkout); input clk,reset; output reg clkout;//定义输出端 wire ...

  7. Verilog中generate语法和作用

    Verilog中generate语句的用法 在Verilog-2001中新增了语句generate,通过generate循环,可以产生一个对象(比如一个元件或者是一个模块)的多次例化,为可变尺度的设计 ...

  8. Verilog语言、语法

    Verilog采用模块化的结构来描述电子电路系统,模块是它描述电路的基本单元,像C语言中的函数一样.模块的不同结构实现了不同的功能,对应着硬件上的逻辑实体,同时模块有输入和输出端口,能够和其他模块相连 ...

  9. Verilog语言基础语法

    Verilog基础知识 数字进制格式 标识符 数据类型 寄存器类型 线网类型 参数类型 运算符 运算优先级 数字进制格式 Verilog数字进制格式包括二进制,八进制,十进制,十六进制.常用为二进制, ...

最新文章

  1. 图书馆预约在线课程方法
  2. Django 用 uploadify 实现图片批量上传
  3. nacos配置刷新失败导致的cpu上升和频繁重启,nacos配置中心源码解析
  4. Android应用性能优化之优化列表头像过度绘制[一]
  5. 会翻页GridView-1
  6. 项目管理概论网课作业(用于复习)
  7. 编程珠玑第一章-位图压缩存储
  8. 【学习笔记】吉司机线段树
  9. java解方程_JAVA解N元一次方程组(矩阵) | 学步园
  10. 记录一次获取车载摄像头数量为0同时打开摄像头黑屏的问题分析(基于Android M)
  11. Ubuntu 下查看图片
  12. c语言可编写的游戏,占卜子女兴盛大全篇
  13. 超级牛的网站同步工具软件—端端Clouduolc
  14. python导入文件方法大全
  15. ECSHOP模板堂商品最小起订量插件
  16. matlab实现牛顿下山法
  17. 截取计算机全屏画面的方法有,电脑怎么截图全屏 详细方法介绍
  18. 基于Multisim的AM信号包络检波器
  19. c语言51单片机脉冲计数检测,51单片机计数测速(外部脉冲频率)proteus仿真加源码...
  20. 大数据有哪些工作?岗位技能要求汇总

热门文章

  1. 解决下载的映像文件不是后缀名为.iso的问题
  2. 安卓实现消息提醒(震动和提示音)
  3. C语言转VB6,如何从c语言查询vb6 ide的模式#
  4. 浪潮信息服务器认证,浪潮服务器首批入选自主创新产品目录
  5. 【Splay】[SGU 187]Twist and whirl - want to cheat
  6. TencentOS tiny危险气体探测仪产品级开发
  7. 微信公众号都有哪些营销技巧
  8. 史上全面伊玛尔项目简介大全
  9. 基于Java+Swing+Mysql实现停车场管理系统
  10. win10 蓝牙调试工具 Bluetooth LE Explorer 简单使用