0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SVA断言的用法教程

FPGA设计论坛 ? 来源:FPGA设计论坛 ? 2025-05-15 11:39 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、SVA是什么

SVA是System Verilog Assertion的缩写,即用SV语言来描述断言。断言是对设计的属性的描述,用以检查设计是否按照预期执行。

断言常用来验证总线时序或其他特定的时序逻辑,找出设计中的违例等。

断言可以分为立即断言和并行断言两种常见类型。

立即断言:非时序,执行时如同过程语句,可以在initial/always过程块或者task/function中使用。立即断言可以结合$fatal、$error、$warning、$info给出不同严重等级的消息提示。

格式如下,[ ]内为可选内容。

[name:]assert(expression)[pass_statement][else fail_statement];

//如果状态为REQ,但是req1或者req2均不为1时,断言将失败

always @ (posedge clk) begin

if(state == REQ)

assert(req1||req2) //立即断言

else begin

t = $time;

#5$error("assert failed at time %0t", t);

end

end

always @ (state)

assert (state == $onehot) else $fatal;

并行断言:时序性的,需要使用关键词property,与设计模块并行执行,并行断言只会在时钟边沿激活,变量的值是采样到的值。

立即断言很简单,无需赘述,本文主要讲述并行断言的用法。

二、SVA如何使用

SVA使用"assert"关键词来表示一个断言属性。而在进行对属性断言之前,我们需要进行属性(property)的声明。

property property_name;  ;endproperty

声明之后便可以对property进行断言,即 认为property中描述的属性为真,否则断言失败。

assertproperty(property_name);

以上是单独写一个property描述时序,然后assert调用它,对于较为简单的时序,也可直接在括号内写上property的内容。而对于较复杂的时序,也可以写定义序列sequence,再由sequence组成property.

SVA用在哪里呢?主要有2种:

直接嵌入RTL代码的module块中,通常用于设计人员;

module fifo(input clk, rst_n, read, output empty, ...)

//Actual FIFO code:

...

//Assertion: FIFO must not underflow

input_no_underflow: assert property( @(posedge clk) !(read && empty));

endmodule

对于验证人员,通常定义一个单独的sva模块,在其中进行property的声明和调用,然后和DUT或者平台顶层top进行绑定。module fifo_checker (input clk, rst_n, read, empty);

//FIFO must not underflow

input_no_underflow: assert property ( @(posedge clk) !(read && empty) );

endmodule

bind fifo fifo_checker fifo_checker_inst(.clk(clk),.rst_n(rst_n),.read(read),.empty(empty));

三、SVA语法简介

SVA具有层次结构,由低到高为布尔表达式-->序列sequence-->属性property,sequence描述的是一个时序过程,而property则是某种逻辑状态,或者多个时序过程应该符合的关系,也是我们要断言的对象。sequence和property的区别如下:

sequence property
层次 低层次,只能例化sequence 高层次,可以例化sequence和property
例化 直接调用 需要使用assert、cover、assume关键字
使用限制 不能使用蕴含操作符|-> |=> 可以使用蕴含操作符|-> |=>

对于较为简单的时序逻辑关系,可以不单独定义sequence,将sequence的内容直接写在property中;而对于时序关系较复杂的,或者为了提高复用性,可以将一些时序逻辑定义为单独的sequence,然后在property中调用。

logic clk = 0;

logic req,gnt;

logic a,b;

//=================================================

// Sequence Layer with args (NO TYPE)

//=================================================

sequence notype_seq (X, Y);

(~X & Y) ##1 (~X & ~Y);

endsequence

//=================================================

// Sequence Layer with args (NO TYPE)

//=================================================

sequence withtype_seq (logic X, logic Y);

(~X & Y) ##1 (~X & ~Y);

endsequence

//=================================================

// Property Specification Layer

//=================================================

property req_gnt_notype_prop(M,N);

@ (posedge clk)

req |=> notype_seq(M,N);

endproperty

property a_b_type_prop(logic M, logic N;

@ (posedge clk)

a |=> withtype_seq(M,N);

endproperty

//=================================================

// Assertion Directive Layer

//=================================================

req_gnt_notype_assert : assert property (req_gnt_notype_prop(req,gnt));

a_b_type_assert : assert property (a_b_type_prop(a,b));

3.1 蕴含操作符

蕴含操作符只能在property中使用。

关键字 描述 说明
a |-> b 如果a成立,那么在当前时刻b必须成立 assertion成立的条件:
条件满足且结论为真
条件不满足(空成功)
a |=> b 如果a成立,那么在下一时刻b必须成立

addce638-2eea-11f0-9310-92fbcf53809c.png

ae0a3642-2eea-11f0-9310-92fbcf53809c.png

3.2 延时操作符

用##操作符来表示延时。

关键字 描述 说明
a ##n b a成立,且n个时钟周期后b成立
a ##[n:m] b a成立,且n-m周期中任何一个时期b成立
a ##[*] b a成立,且在当前周期到仿真结束的任何一个周期b成立,等价于##[0:$] 避免使用
a ##[+] b a成立,且在下一周期到仿真结束的任何一个周期b成立,等价于##[1:$] 避免使用

aee1023a-2eea-11f0-9310-92fbcf53809c.png

logic clk = 0;

logic req,gnt;

logic a,b;

//=================================================

// Sequence Layer with args (NO TYPE)

//=================================================

sequence notype_seq (X, Y);

(~X & Y) ##1 (~X & ~Y);

endsequence

//=================================================

// Sequence Layer with args (NO TYPE)

//=================================================

sequence withtype_seq (logic X, logic Y);

(~X & Y) ##1 (~X & ~Y);

endsequence

//=================================================

// Property Specification Layer

//=================================================

property req_gnt_notype_prop(M,N);

@ (posedge clk)

req |=> notype_seq(M,N);

endproperty

property a_b_type_prop(logic M, logic N;

@ (posedge clk)

a |=> withtype_seq(M,N);

endproperty

//=================================================

// Assertion Directive Layer

//=================================================

req_gnt_notype_assert : assert property (req_gnt_notype_prop(req,gnt));

a_b_type_assert : assert property (a_b_type_prop(a,b));

3.3 重复操作

关键字 描述 说明
a[*n] a连续n个时钟周期成立
a [->n] b a成立n次后(不要求连续),下一个时钟b成立
a [=n] b a成立n次后(不要求连续),在后续任意时钟b成立

//连续3个时钟a均成立,则断言成功

property con_cycle1(a,b);

@ (posedge clk) a[*3];

endproperty

//a成立3次后(不要求连续),在下一个时钟b成立则断言成功

property con_cycle2(a,b);

@ (posedge clk) a[->3]b;

endproperty

//a成立3次后(不要求连续),b成立(后续任意一时钟)

property con_cycle3(a,b);

@ (posedge clk) a[=3]b;

endproperty

3.4 匹配操作

关键字 描述 说明
intersect(a,b) a和b同时成立,且同时结束,则断言成功
a and b a发生时b也发生(不要求同时结束),则断言成功 && 只能连接两个表达式,而and可以连接两个sequence
a or b a发生或b发生,则断言成功 || 只能连接两个表达式,而or可以连接两个sequence
a within b a发生的时间段内b也发生,则断言成功
a througnt seq 在序列seq成立的过程中,a事件一直成功
first_match(seq) 在seq第一次成功时检测,之后便不再检测

举例说明first_match(seq)的使用:

seq_a再clk 3 4 5时刻均满足,但是assert(first_match(seq_a))仅会在clk 3时成功匹配一次,之后便不再检测。

sequence seq_a;

a[*1:2] ##1 b[*2:3];

endsequence

property first_match_property;

first_match(seq_a);

endproperty

af06c02e-2eea-11f0-9310-92fbcf53809c.png

3.5 sequence 同步

默认情况下,多重sequence的组合是以后一个sequence的起始时间作为同步标志的,SVA提供ended结构以sequence的结束时间作为序列同步点。

若使用ended,则sequence必须定义时钟。关键字ended存储一个反映在指定时钟处序列是否匹配成功的布尔值。该布尔值仅在同一时钟内有效。

af1874d6-2eea-11f0-9310-92fbcf53809c.png

sequence s1;

@(posedge clk) a##1 b;

endsequence

sequence s2;

@(posedge clk) c ##1 d;

endsequence

property p1;

s1|=>s2; //s1的成功匹配点滞后一时钟周期是s2匹配的起点

endproperty

property p2;

s1|=>##1 s2.ended; //s1成功匹配点滞后两个时钟周期是s2成功匹配点,即s1匹配成功则再过两个时钟周期s2必须匹配成功

endproperty

property p3;

s1.ended|=>s2; //s1的成功匹配点滞后一时钟周期是s2匹配的起点

endproperty

property p4;

s1.ended|=> ##1 s2.ended;//s1成功匹配点滞后两个时钟周期是s2成功匹配点,即s1匹配成功则再过两个时钟周期s2必须匹配成功

endproperty

3.6内建函数

函数名 描述 举例
$onehot () 只有1bit为1则返回1 assert property( @(posedge clk)$onehot0( {GntA, GntB, GntC} ) )
//任何时刻,有且仅有一个grant
$onehot0 () 最大只有1bit为1,则返回1 assert property( @(posedge clk)$onehot0( {GntA, GntB, GntC} ) )
//任何时刻,最多只有一个grant
$countones () 返回1的数量 assert property (@(posedge clk)$countones(Valid & Dirty) <=4 ) )
//dirty有效bit不超过4
$stable (boolean expression or signalname) 在时钟沿到来时,信号没有发生变化则返回1 assert property (@(posedge clk) !Ready |=>$stable(Data) )
//如果ready为0, Data必须保持不变
$past (signalname, nums) 将nums个周期之前的值赋给signalname
nums默认缺省情况下,SVA提供前一个时钟沿处的信号值。
assert property( @(posedge clk) active |->$past(cmd) != IDLE )
//如果active为1,cmd不能为IDLE
$rose (boolean expression or signalname) 在时钟沿到来时,信号跳变为1则返回1 assert property( @(posedge clk) Req |=>$rose(Valid) )
//req有效之后,vld必须为上升沿
$fell (boolean expression or signalname) 在时钟沿到来时,信号跳变为0则返回1 assert property( @(posedge clk)$fell(Done) |-> Ready )
//Done由1变0后,Ready须为有效

四、一些使用技巧

4.1 可变延时范围

延时操作或者重复范围(即 ##n 或 a[*n])只可以使用常数,不可以使用变量。

如下的操作是非法的:

property variable_delay(cfg_delay);

@(posedge clk) disable iff (!rstn)

a ##cfg_delay b;

endproperty

但是如果我们还是想实现相同的可变延时,该怎么做呢?

可以定义一个seqence,间接实现相同的效果。

//delay sequence

sequence delay_seq(v_delay);

int delay;

(1,delay=v_delay) ##0 first_match((1,delay=delay-1) [*0:$] ##0 delay <=0);

endsequence

//calling assert property

a_1: assert property(@(posedge clk) a |-> delay_seq(cfg_delay) |-> b);

使用delay_seq来替代变量cfg_delay. 下面解释这个seqence的实现:

首先定义了一个sequence内的局部变量,sequence内部是可以定义变量来做辅助逻辑表达的。

int delay -> 定义了一个整型变量delay,用于存储当前的延迟时间。

(1,delay=v_delay) -> 在序列的起始位置,生成一个事件(1,delay=v_delay),这个事件表示,在第一个时钟上升沿时,将delay的值设置为v_delay。

(1,delay=delay-1) -> (1,delay=delay-1)表示在每个时钟上升沿时,将delay的值减 1。

first_match((1,delay=delay-1) [*0:$] ##0 delay <=0) ? -> 对事件(1,delay=delay-1)重复若干次,直到delay的值为0. 此处相当是一个循环操作。

综上所述,这个序列表示:在第一个时钟上升沿时,将delay的值设置为v_delay,然后每个时钟上升沿时,将delay的值减 1,直到delay的值小于等于 0。

4.2 Glue Logic

在验证或建模复杂行为时,引入辅助逻辑来观察和跟踪时间可以大大简化编码,这种辅助逻辑通常称为"glue logic".

如下的一个例子,对interface的SOP和EOP进行检查,DUT规范要求:

packets不能重合(SOP-EOP始终是匹配的)

允许单拍packet(SOP和EOP在同一cycle)

packet是连续的(SOP-EOP之间vld不能有缺口)

af38bbce-2eea-11f0-9310-92fbcf53809c.png

单纯用SVA编写的代码如下,可以发现比较复杂。

sequence sop_seen; //当sop出现后,该序列会持续成立

sop ##1 1'b1[*0:$];

endsequence

no_holes: assert property(//sop 到 eop之间的vld一直有效

sop |-> vld until_with eop

);

sop_first: assert property (vld && eop |-> sop_seen.ended); //eop之前或者当拍一定有sop

eop_correct: assert property(

not (!sop throughout ($past(vld && eop) ##0 vld && eop[->]) )

);

sop_correct: assert property(

vld && sop && !eop |=> not(!$past(vld && eop) throughout (vld && sop[->1]))

);

可已采用一些中间变量进行辅助,这样可以更简洁。

af4d785c-2eea-11f0-9310-92fbcf53809c.png

reg in_packet;//中间变量

always @(posedge clk) begin

if(!rstn || (eop&&vld) )

in_packet <= 1'b0;

else if (sop&&vld) in_packet <= 1'b1;

end

no_holes: assert property( //中间不能有空缺

in_packet |-> vld

);

eop_correct: assert property( //eop拍之前或者当拍一定有sop

vld && eop |-> in_packt || sop

);

sop_correct: assert property( //不会有重复sop拍

vld && sop |-> !in_packet

);

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 模块
    +关注

    关注

    7

    文章

    2790

    浏览量

    50677
  • Verilog
    +关注

    关注

    29

    文章

    1367

    浏览量

    112417
  • System
    +关注

    关注

    0

    文章

    166

    浏览量

    37950
  • 时序
    +关注

    关注

    5

    文章

    399

    浏览量

    38135

原文标题:SVA断言简明使用指南

文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    什么是断言?C语言中断言的语法和用法

    在软件开发过程中,我们经常需要处理各种错误和异常情况。为了提高代码的健壮性和可靠性,我们需要使用一些工具和技术来检测和处理这些问题。本篇博客将深入探讨C语言中断言的使用,帮助读者更好地理解和应用断言,提高代码的质量和可维护性。
    发表于 08-03 10:34 ?3530次阅读

    解析C语言断言函数的使用

    对于断言,相信大家都不陌生,大多数编程语言也都有断言这一特性。简单地讲,断言就是对某种假设条件进行检查。 在 C 语言中,断言被定义为宏的形式(assert(expression)),
    发表于 08-08 09:51 ?693次阅读
    解析C语言<b class='flag-5'>断言</b>函数的使用

    何为断言断言的作用有哪些?断言的种类 断言层次结构

    断言主要用来检查仿真过程中存在的时序问题,如果存在异常情况,断言会报警。一般在数字电路设计中都要加入断言断言占整个设计的比例应不少于30%。
    的头像 发表于 08-28 11:16 ?9304次阅读
    何为<b class='flag-5'>断言</b>?<b class='flag-5'>断言</b>的作用有哪些?<b class='flag-5'>断言</b>的种类 <b class='flag-5'>断言</b>层次结构

    断言(ASSERT)的用法

    STM32中经常出现assert函数,网上看了篇博客分享下:我一直以为assert仅仅是个报错函数,事实上,它居然是个宏,并且作用并非“报错”。  在经过对其进行一定了解之后,对其作用及用法有了一定
    发表于 08-23 09:33

    SVA断言是基于边沿还是电平呢?

    SVA断言是一个强时序的技术,很多时候SVA的实际时序和验证工程师的期望可能不同,这种不同很难调试定位。下面是一个SVA断言的示例,验证工程
    发表于 08-25 15:57

    SVA上广电D2560彩电电路图

    SVA上广电D2560彩色电视机电路图,SVA上广电D2560彩电图纸,SVA上广电D2560原理图。
    发表于 05-15 16:44 ?188次下载
    <b class='flag-5'>SVA</b>上广电D2560彩电电路图

    SVA上广电D2972-73系列彩电电路图

    SVA上广电D2972-73彩色电视机电路图,SVA上广电D2972-73彩电图纸,SVA上广电D2972-73原理图。
    发表于 05-23 10:55 ?175次下载
    <b class='flag-5'>SVA</b>上广电D2972-73系列彩电电路图

    SVA系列(通用)彩电电路图(1)

    SVA系列彩色电视机电路图,SVA系列彩电图纸,SVA系列原理图。
    发表于 05-25 09:25 ?185次下载
    <b class='flag-5'>SVA</b>系列(通用)彩电电路图(1)

    SVA系列(通用)彩电电路图(2)

    SVA系列彩色电视机电路图,SVA系列彩电图纸,SVA系列原理图。 
    发表于 05-25 09:28 ?90次下载
    <b class='flag-5'>SVA</b>系列(通用)彩电电路图(2)

    SystemVerilog断言及其应用

    在介绍SystemVerilog 断言的概念、使用断言的好处、断言的分类、断言的组成以及断言如何被插入到被测设计(DUT)的基础上,本文详细
    发表于 05-24 16:35 ?0次下载
    SystemVerilog<b class='flag-5'>断言</b>及其应用

    如何得当使用C语言的特殊的用法

    C语言有很多特殊的用法,如果这些特殊用法使用得当,会是你的代码变得更加有健壮,更加容易维护。 比如我们在使用STM32库的断言(assert),你会发现官方提供了包含__FILE__
    的头像 发表于 09-27 10:41 ?2197次阅读
    如何得当使用C语言的特殊的<b class='flag-5'>用法</b>

    STM32函数库Assert断言机制

    编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。可以在任
    发表于 02-08 15:29 ?2次下载
    STM32函数库Assert<b class='flag-5'>断言</b>机制

    介绍使用SVA的几个优势

    SVA支持多时钟域(clock domain crossing (CDC))逻辑,例如异步FIFO。
    的头像 发表于 01-13 16:00 ?1242次阅读

    使用SVA的几个好处

    SVA支持多时钟域(clock domain crossing (CDC))逻辑,例如异步FIFO。 2. SVA是一种描述语言,可读性比较强。
    的头像 发表于 03-21 14:49 ?981次阅读

    防御式编程之断言assert的使用

    防御式编程的重点就是需要防御一些程序未曾预料的错误,这是一种提高软件质量的辅助性方法,断言assert就用于防御式编程,编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设。使用断言
    的头像 发表于 04-19 11:35 ?981次阅读