【SVA】SVA基础知识

一、断言

断言是设计的属性的描述:
1.如果一个设计属性在仿真中不像我们期望那样表现,那么这个断言失败
2.如果一个不期望出现的设计属性在仿真中发生,那么这个断言失败
断言分为即时断言和并发断言

1.即时断言

即时断言特点:
  (1)即时断言与时序无关
  (2)必须放在过程块中
  (3)只能用于动态模拟(仿真)
如:

always_comb
	begin
	   a_ia: assert(a&b);
	end

注:always_comb为sv语法,可自动嵌入敏感列表

2.并发断言

并发断言特点:
  (1)并发断言与时序相关
  (2)可以放在过程块、模块(module)、接口(interface)或者一个程序(program)中
  (3)可以在静态(形式的)验证和动态模拟(仿真)工具中使用
如:

a_ib:assert property(@(posedge clk) not(a&b));

3.即时断言和并发断言的区别

并发断言有关键词“property”
即时断言无关键词“property”

二、SVA块

1.序列(sequence)

基本语法

sequence name_of_sequence;
	    <test expression>; (即:逻辑事件的组合)
endsequence

注:sequence可以参数化,如:

sequence para_exs(para1,para2);
	para1 || para2;
endsequence
property para_exp;(即:时钟上升沿,a或b有一个信号为高即断言成功)
	@(posedge clk) para_exs(a,b);
endproperty

2.属性(property)

基本语法

property name_of_property;
	<test expression>;(即:逻辑事件的组合)
	//or
    //<name_of_sequence>;(即:引用序列)
endproperty

3.断言(assert)

基本语法

name_of_assertion:assert property(name_of_property);//并发断言

4.两段式断言/三段式断言

(1)三段式断言

sequence name_of_sequence;
	<test expression>;
endsequence
	
property name_of_property;
	<complex sequence expressions>;
endproperty
	
name_of_assertion:assert property(name_of_property);//并发断言

(2)两段式断言

property name_of_property;
	<test expression>;
endproperty

name_of_assertion:assert property(name_of_property);//并发断言

注:1.两段式的断言结构应用更多
  2.同一个断言相关的属性(property)和断言(assert)只能有一个时钟定义

三、SVA内嵌函数

1.$rose(boolean expression or name of signal):当信号/逻辑表达式由低变高时返回真
注:rose采样的是电平变化,而非上升沿,见下图。clk2时,信号a被采样为低电平;clk3时,信号a被采样为高电平。在clk3处,信号a被认为由低变高,$rose(a)为真。
2.$fell(boolean expression or name of signal):当信号/逻辑表达式由高变低时返回真
注:fell采样的是电平变化,而非下降沿,见下图。clk2时,信号b被采样为高电平;clk3时,信号b被采样为低电平。在clk3处,信号b被认为由高变低,$fell(b)为真。
在这里插入图片描述
3. $stable(boolean expression or name of signal):当表达式不发生变化时返回真
4. $onehot(expression):检验表达式满足"one-hot",即:表达式只有一位为高
5. $onehot0(expression):检验表达式满足"zero one-hot",即:表达式只有一位为高或者没有任何位为高
6. $isunknow(expression):检验表达式的任何位是否是X或者Z
7. $countones(expression):计算向量中为高的位的数量

四、断言的执行块

SystemVerilog语言中每当一个断言检查失败,仿真器在默认情况下都会打印一条错误信息,对成功的断言不会打印任何东西。因此如果设计者想要自定义断言成功或失败之后的信息,可以通过断言的执行块进行。
执行块语法

assertion_name:assert property(name_of_property)
  <success message>;
else
  <fail message>;

五、蕴含(implication)

蕴含的主要作用为:检测起始点无效时忽略这次检查。蕴含等效于一个if-then结构。蕴含的左边叫做“先行算子”,右边叫做“后续算子”。先行算子是约束条件,先行算子成功时,后续算子才会被计算。蕴含结构只能被用在属性定义中,不能在序列中使用。蕴含分为:交叠蕴含(overlapped implication)和非交叠蕴含(non-overlapped implication)。

1.SVA检测器的时序窗口

(1)SVA中,时钟周期延迟用“##”表示。如:##2表示延迟2个时钟周期
(2)##[1:3]表示时间窗口,延迟1~3个时钟周期。时间窗口下限可以为0,如果为0则表示不延迟,在同一个时钟周期发生
(3)时序窗口的上限可以为“$”,表示时序没有上限。这叫做“可能性”(eventuality)运算符,如:

property even_exp;
	@(posedge clk) a |-> ##[1:$] b ## [1:$] c;
endproperty
even_exa:assert property(even_exp);

属性even_exp在时钟上升沿检查信号a是否为高,如果为高,下个时钟上升沿检查信号b是否为高,如果是高则再下一个时钟周期检查信号c是否为高(没有时序上限,一直检查直到c为高之后断言成功),如果b在a为高后的下个时钟不为高,则需要等待b为高之后($,没有时序上限一直检查)再检查c是否为高。

2.交叠蕴含(|->)

如果先行算子匹配成功,在同一个时钟周期计算后续算子表达式。用符号“|->”表示。如:

property over_imp_exp;
    @(posedge clk) a |-> b;
endproperty
over_imp:assert property(over_imp_exp);

属性over_imp_exp在时钟上升沿检查信号“a”是否为高,如果是高,信号“b”在同一个时钟边沿也为高,则断言成功,否则失败。
在这里插入图片描述

3.非交叠蕴含(|=>)

如果先行算子匹配成功,那么在下一个时钟周期计算后续算子表达式。用符号“|=>”表示。如:

property over_nonimp_exp;
    @(posedge clk) a |=> b;
endproperty
over_nonimp:assert property(over_imp_exp);

属性over_nonimp_exp在时钟上升沿检查信号“a”是否为高,如果是高,信号“b”在下一个时钟边沿也为高,则断言成功,否则失败。
在这里插入图片描述

4.后续算子带固定延迟

property ex;
    @(posedge clk) a |-> ##2 b;
endproperty
ex_a:assert property(ex);

在这里插入图片描述
注:交叠蕴含表达式:a |-> ##1 b
非交叠蕴含表达式:a |=> b
所检验的属性相同

5.使用序列做先行算子/后续算子

sequence slla;
    @(posedge clk) (a && b) ##1 c;
endsequence

sequence sllb;
    @(posedge clk) ##2 !d;
endsequence

property p11;
    slla |-> sllb;
endproperty

a11:assert property(p11);

属性p11检查,在时钟上升沿,如果a和b均为高,那么一个周期后c为高,两个时钟周期后,d为低,则断言成功,否则断言失败。

6.嵌套的蕴含

嵌套的蕴含,即在一个表达式中多次使用蕴含,如:

`define all_high (a && b && c && d)
property p_nest;
   @(posedge clk) $fell(a) |=> (!b && !c && !d) |-> ##[6:10] `all_high;
endproperty
a_nest:assert property(p_nest);

属性p_nest在时钟上升沿检查a的下降沿,当a有一个下降沿时,下个时钟周期检查信号b/c/d均为低电平,在6-10个周期内信号a/b/c/d均为高电平,则断言成功。需要注意的是,只有当“信号b/c/d均为低电平”这个条件匹配时,才会检查all_high是否为真。
当然,p_nest属性(嵌套蕴含中无else分支)可以改写为不使用嵌套蕴含的方式,

`define all_high (a && b && c && d)
property p_nest1;
   @(posedge clk) $fell(a) ##1 (!b && !c && !d) |-> ##[6:10] `all_high;
endproperty
a_nest:assert property(p_nest);

7.在蕴含中使用if/else

蕴含中可以使用if/else来实现优先级,如:

property if_else_exp;
   @(posedge clk) $fell(start) ##1 (a||b) -|>
	 if(a)begin
	    c ##1 e;
	  end
	  else begin
	     d ##1 f;
	 end
endproperty
if_else_exa:assert property(if_else_exp);

属性if_else_exp中,信号start下降沿被检查到,一个周期后,如果a||b为高,则先行算子匹配成功,开始检查后续算子:
(1)如果a为高,则与(a||b)同一时钟周期c为高,且下个时钟周期e为高
(2)如果a为低,则与(a||b)同一时钟周期d为高,且下个时钟周期f为高

六、SVA构造

1.“ended”结构

连接(concatenation)机制:将多个序列以系列的起始点作为同步点,来组合成时间上的连续检查。
“ended”构造:使用序列的结束点作为同步点的连接机制。语法:
  name_of_sequence/name_of_signal.ended
如:

sequence s1a;
	@(posedge clk) a ##1 b;
endsequence
	
sequence s1b;
	@(posedge clk) c ##1 d;
endsequence
	
property p1a;
	s1a |=> s2b;
endproperty
	
property p1b;
	s1a.ended |-> ##2 s1b.ended;//s1a序列结束,两个时钟周期后,s1b序列结束
endproperty

a1a:assert property(p1a);
a1b:assert property(p1b);

a1a和a1b的检验方法相同,同步序列的起点不同:
(1)a1a:以起始点同步序列
(2)a1b:以结束点同步序列
a1a和a1b的区别见下图
在这里插入图片描述
使用true表达式的SVA检验器
使用true表达式,可以在时间上延长SVA检验器。这代表一种忽略状态,它使得序列延长了一个时钟周期,即:将序列的成功点往后移一个时钟周期。如:

`define true 1
	
sequence s2a;
	@(posedge clk) a ##1 b;
endsequence
	
sequence s2a_ext;
	@(posedge clk) a ##1 b ##1 `true;
endsequence
	
sequence s2b;
	@(posedge clk) c ##1 d;
endsequence
	
property p2a;
   @(posedge clk) s2a.ended |-> ##2 s2b.ended;
endproperty
	
property p2a_ext;
   @(posedge clk) s2a_ext.ended |=> s2b.ended;//s2a_ext序列被延长了一个时钟周期
endproperty
	
a2:assert property(p2a);
a2_ext:assert property(p2a_ext);

a2和a2_ext检验的情况相同,但是a2_ext的开始点会比a2晚一个周期。

在这里插入图片描述

2.“$past”构造

$past是SVA提供的一个系统任务,它可以得到信号在几个时钟周期之前的值。默认情况下,它提供信号在前一个时钟周期的值。语法:
  $past(signal_name,number of clock cycles)
如:

property p3;
  @(posedge clk) (c && d) |-> ($past(a && b,2)==1'b1); 
endproperty
a3:assert property(p3)

属性p3检验的是在每个时钟上升沿,如果c和d均为高,则两个时钟前,a和b为高。

带时钟门控的$past构造
$past构造可以由一个门控信号(gating signal)控制。比如,在一个给定的时钟沿,只有当门控信号的值为真时才检查后续算子的状况。门控信号的$past构造的基本语法是:
  $past(signal_name,number of clock cycles,gating signal)
如:

property p4;
   @(posedge clk) (c && d) |-> ($past(a && b,2,enb)==1'b1); 
endproperty
a4:assert property(p4)

属性p4与属性p3检验的情况相同,但是只有当enb为高时,检验才能被激活。

3.“and”构造

二进制运算符“and”可以用来逻辑地组合两个序列。当两个序列都成功时整个属性才成功。两个序列必须具有相同的起始点,但是可以有不同的结束点。如:

property p5;
    @(posedge clk) (a ##[1:2] b) and (c ##[2:3] d);
endproperty
a5:assert property(p5);

只有当表达式(a ##[1:2] b)和表达式(c ##[2:3] d)均满足时,断言成功。需要注意的是and构造要求两个表达式的起始点相同,也就是说在这个例子里面,要使断言成功,a和c的表达式相同,即:在同一时钟边沿拉高。
在这里插入图片描述

4.“intersect”构造

intersect构造和and构造相同,即:用来逻辑地组合两个系列,当两个序列都成功时整个属性才成功。intersect构造要求两个序列必须在相同时刻开始且在相同时刻结束,即:两个序列的起始点和结束点都要相同。如:

property p61;
    @(posedge clk) (a ##[1:2] b) intersect (c ##[2:3] d);
endproperty
a61:assert property(p61);

只有当表达式(a ##[1:2] b)和表达式(c ##[2:3] d)均满足时,断言成功。需要注意的是intersect构造要求两个表达式的起始点和结束点均相同,也就是说在这个例子里面,只有(a##2b)和(c##2d)才能断言成功
在这里插入图片描述
使用intersect控制序列的长度
如,

property p62;
	@(posedge clk) 1[*2:5] intersect
	    (a ##[1:$] b ##[1:$] c);
endproperty
a62:assert property(p62);

属性P62中,
(1)表达式a ##[1:KaTeX parse error: Expected 'EOF', got '#' at position 5: ] b #̲#[1:] c表明,如果信号a为高,那么从下一个时钟周期开始信号b最终将为高,接着在下一个时钟周期开始信号c最终也会为高。也就是说这个序列每当信号a为高时就开始,并且可能一直到整个仿真结束时才成功
(2)使用1[*2:5] intersect来加以约束,1[*2:5]表示1持续2~5个周期
*注:关于符号“[2:5]”见《七、重复运算符》
(3)最终属性P62的含义为:从序列的开始有效点(信号a为高)到序列成功的结束点(信号c为高),一共经过2~5个时钟周期

5.“or”构造

二进制运算符“or”可以用来逻辑地组合两个序列。只有其中一个序列成功,整个属性就成功。两个序列的起始点和结束点均可以不相同。如:

property p7;
    @(posedge clk) (a ##[1:2] b) or (c ##[2:3] d);
endproperty
a6:assert property(p7);

当表达式(a ##[1:2] b)和表达式(c ##[2:3] d)其中一个满足时,断言成功。在clk7,a拉高,2个时钟周期后b拉高,表达式a##[1:2]b成功,or构造成功。
在这里插入图片描述

6.“first_match”构造

当使用逻辑运算符(如“and”和“or”)的序列中指定了时间窗,就有可能出现同一个检验具有多个匹配的情况。“first_match”构造可以确保只用第一次序列匹配,而丢弃其他的匹配。当多个序列被组合在一起,其中只需时间窗内的第一次匹配来检验属性剩余的部分时,或在蕴含中先行算子只需要第一次匹配来执行后续算子时,“first_match”构造非常好用。如:

property p8;
    @(posedge clk) first_match((a ##[1:3] b) or (c ##[2:3] d));
endproperty
a8:assert property(p8);

如图中所示,两次检验成功的点:第一次检验成功是基于序列a##1b(红线);第二次检验成功是基于序列c##2d(绿线)
在这里插入图片描述

7.“throughout”构造

蕴含:允许定义前提条件的一项技术。如,要对一个指定的序列进行检验,必须某个前提条件为真(先行算子)。蕴含只在时钟边沿检验前提条件一次,然后就开始检验后续算子部分,因此它不检测先行算子是否一直保持为真。
“throughout”运算符:保证某些条件在整个序列的验证过程中一直为真。其基本语法是:
   (expression) throughout (sequence definition)
例如:

property p9;
	@(posedge clk) $fell(start) |-> 
	    (!start) throughout (##1 (!a && !b) ##1 (c[->3]) ##1 (a&&b));
endproperty
a9:assert property(p9);

属性p9检查以下内容:
(1)在信号start的下降沿开始检查(先行算子:$fell(start))
(2)start下降沿一个周期后,检查a和b是否均为0,如果为0则继续检查c[->3],如果匹配成功,则一个周期后检查a和b是否均为1,即:检查表达式(##1 (!a && !b) ##1 (c[->3]) ##1 (a&&b))
(3)序列检查在信号a和b下降沿(!a&&!b)与信号a和b上升沿(a&&b)之间,信号c应该连续或间断地出现3次高电平(c[->3])
注:关于符号“[->3]”见《七、重复运算符》
(4)在整个检验过程中,信号start保持为低( (!start) throughout),如图所示
在这里插入图片描述在第二个点,虽然表达式(##1 (!a && !b) ##1 (c[->3]) ##1 (a&&b))成立,但是start后面变为高电平,使整个序列失败。

8."within"构造

“within”构造允许在一个序列中定义另一个序列。基本语法:
  seq1 within seq2
表示seq1在seq2的开始到结束的范围内发生,且序列seq2的开始匹配点必须在seq1的开始匹配点之前,序列seq2的结束匹配点必须在seq1的结束匹配点之后,即:seq2将seq1包在里面。例如:

property p10;
    @(posedge clk) $fell(start) |->
        ((!a&&!b) ##1 (c[->3]) ##1 (a&&b)) within
        ($fell(start) ##[5:10] $rose(start))
endproperty
a10:assert property(p10)

属性p10检查以下内容:
(1)在信号start的下降沿开始检查(先行算子:$fell(start))
(2)检查表达式 ((!a&&!b) ##1 (c[->3]) ##1 (a&&b))的开始点是否在($fell(start) ##[5:10] $rose(start))的开始点之后;表达式 ((!a&&!b) ##1 (c[->3]) ##1 (a&&b))的结束点是否在($fell(start) ##[5:10] $rose(start))的结束点之后。
(3)检查表达式 ((!a&&!b) ##1 (c[->3]) ##1 (a&&b))是否成立
(4)检查表达式($fell(start) ##[5:10] $rose(start))是否成立
在这里插入图片描述

9.“disable iff”构造

在某些设计中,如果一些条件为真,则不执行检验。换句话说,这就像是一个异步复位,使得检验在当前时刻不工作。SVA提供关键词“disable iff”来实现这种功能。基本语法:
  disable iff(expression) <property definition>
例如:

property p11;
    @(posedge clk) disable iff(rst_n==1'b0)
    $rose(start) |=> a[=2] ##1 b[=2] ##1 !start;
endproperty
a11:assert property(p11);

属性p11检查以下内容:
(1)当rst_n==1’b0时,该属性停止检验(disable iff(rst_n==1’b0))
(2)在信号start的上升沿开始检查(先行算子:$rose(start))
(3)有效开始后($rose(start)的下一周期),信号a重复两次高(a[=2]),接着信号b重复两次高(b[=2]),然后start为低
注:关于符号“[=2]”见《七、重复运算符》
在这里插入图片描述

10.“matched”构造

任何时候如果一个序列定义了多个时钟,构造“matched”可以用来检测第一个子序列的结束点。具体见如下例子:

sequence s_a;
    @(posedge clk1) $rose(a);
endsequence

sequence s_b;
    @(posedge clk2) $rose(b);
endsequence

property p_match;
    @(posedge clk2) s_a.matched |=> s_b;
endproperty
a_match:assert property(p_match);

其中,序列s_a查找信号a的上升沿,此时采样时钟是clk1;序列s_b查找信号b的上升沿,此时采样时钟是clk2。属性p_match验证在给定时钟clk2的上升沿,如果序列s_a匹配,那么在一个周期后,序列s_b也必须为真。
注:理解“matched”构造的使用方法的关键在于,序列被自己时钟域采样到匹配的值一直被保存到另一个时钟域的最近的下一个时钟边沿。
在这里插入图片描述

11.“expect”构造

expect构造与Verilog中的等待结构相似,expect语句等待的是属性的成功检验。expect语句允许在一个属性成功或者失败之后使用一个执行块。如下所示:

initial begin
    @(posedge clk);
    #2ns cpu_ready=1'b1;
    expect ((@posedge clk) ##[1:16] memory_ready==1'b1);
        $display("Hand shake successful");
    else begin
        $display("Hand shake failed:exiting\n");
        $finish();
    end

    for(i=0;i<64;i++)begin
        send_packet();
        $display("PACKET %d sent\n");
    end
end

在信号“cpu_ready”被拉高后,expect等待信号“memory_ready”在1~16个周期内的任意周期拉高。如果信号“memory_ready”如预期的被拉高,那么显示一个成功信息,并且开始执行for循环代码。如果信号“memory_ready”没能如预期的被断言,那么显示错误信息,仿真结束($finish())。

七、重复运算符

SVA提供三种不同的重复运算符:连续重复,跟随重复和非连续重复。

1.连续重复

连续重复:信号或者序列将在指定数量的时钟周期内都连续地匹配,用符号“[*n]”表示,基本语法如下:
  signal or sequence [*n]
其中,n为表达式应该匹配的次数,如:
(1)a[*3]=a ##1 a ##1 a
(2)(a##1b)[*3]=(a##1b) ##1 (a##1b) ##1 (a##1b)

(1)信号的连续重复

如:

property p11;
   @(posedge clk) $rose(start) |=> a[*3] ##1 stop;
endproperty
a11:assert property(p11)

属性p11检查到strat上升沿后,下个时钟周期开始信号a连续三个时钟周期为高,然后再过一个时钟周期,stop拉高
在这里插入图片描述

(2)序列的连续重复

如:

property p12;
	@(posedge clk) $rose(start) |=>
	    (a ##2 b)[*3] ##1 stop;
endproperty
a12:assert property(p12);

属性P12检查到start上升沿后,下个时钟开始表达式(a##2b)连续重复3次,然后再过一个时钟周期,stop拉高
在这里插入图片描述

(3)带延迟窗口的序列重复

如:

property p13;
	@(posedge clk) $rose(start) |=>
	    (a ##[1:3] b)[*3] ##1 stop;
endproperty
a13:assert property(p12);

属性P13检查到start上升沿后,下个时钟开始表达式(a##[1:3])连续重复3次,然后再过一个时钟周期,stop拉高
在这里插入图片描述

(4)连续运算符和可能性运算符

属性P13中a##[1:3]b的表达式中,##[1:3]是个时序窗口。同样,重复的次数也可以是个窗口。如:a[*1:5]表示信号“a”连续重复1~5次。重复窗口的边界规则与延迟窗口的相同。左边的值必须小于右边的值。右边的值可以是符号“$”,这表示没有重复次数的限制,即:一直重复。如:

property p14;
   @(posedge clk) $rose(strat) |=> a[*1:$] ##1 stop;
endproperty
a14:assert property(p14);

属性p14检查到上升沿start后,从下一个时钟周期开始信号a一直保持为高,直到信号stop为高
在这里插入图片描述

2.跟随重复

跟随重复:一个表达式将匹配达到指定的次数,而不一定在连续的时钟周期上发生,这些匹配可以是间隙的。跟随重复的主要要求是被检验重复的表达式的最后一个匹配应该发生在整个序列匹配结束之前。需要注意的是,跟随重复只能用于信号,不能用于序列。基本语法如下:
  signal[->n]
其中,n为表达式应该匹配的次数,如:
   start ##1 a[->3] ##1 stop
这个序列需要信号a的匹配(即:信号a的第三次,最后一次重复的匹配)正好发生在stop成功之前,即:在stop匹配的前一个时钟周期,信号a有一次匹配。如下所示:

property p2;
    @(posedge clk) $rose(start) |=> a[->3] ##1 stop;
endproperty
a2:assert property(p1);

在这里插入图片描述

3.非连续重复

非连续重复与跟随重复相似,即:一个表达式将匹配达到指定的次数,而不一定是连续的时钟周期上发生,这些匹配可以是间隙的。但是非连续重复不要求信号的最后一次重复匹配发生在整个序列匹配前的那个时钟周期。需要注意的是,非连续重复只能用于信号,不能用于序列。基本语法如下:
  signal[=n]
其中,n为表达式应该匹配的次数,如:
  start ##1 a[=3] ##1 stop
这个序列信号a的最后一次重复匹配,不需要正好发生在stop成功之前,即:在stop匹配的前一个时钟周期,信号a可以不需要匹配。如下所示:

property p3;
    @(posedge clk) $rose(start) |=> a[=3] ##1 stop;
endproperty
a3:assert property(p1);

在这里插入图片描述

八、其他

1.使用局部变量的SVA

在序列或者属性的内部可以局部定义变量,而且可以对这种变量进行赋值。变量接着子序列放置,用逗号隔开。如果子序列匹配,那么变量赋值语句执行。每次序列被尝试匹配前,会产生变量的一个新的备份。

property p_1var_accum;
    int lvar;
    @(posedge clk) $rose(start) |=>
        (enable1 ##2 enable2,lvar=lvar+aa)[*4]
        ##1 (stop && (aout==lvar));
endproperty
a_lvar_accum:assert property(p_1var_accum);

属性p_lvar_accum检查下列内容:
(1)在信号start的上升沿开始检查(先行算子:$rose(start))
(2)在一个周期后,判断表达式(enable1 ##2 enable2),即:一个周期后,信号“enable1”必须检测为高,两个周期后,“enable2”应该被检测为高,这个子序列连续重复4次
(3)在子序列(enable1 ##2 enable2)的每次重复中,向量aa的值在序列内部被累加。在重复结束时,局部变量保存着向量“aa”累加4次的值
(4)在重复结束的下一个时钟周期,期望信号“stop”为高,且局部变量保存的值与输出向量“aout”的值相等

2.SVA中的条件表达语句

property p1;
    @(posedge clk) c? d==a:d==b;
endproperty
a1:assert property(p1);

属性p1检查,如果c为高,那么信号d的值与信号a的值相等;如果c为低,则信号d的值与信号b的值相等

3.在属性中使用形参

property arb(a,b,c,d);
    @(posedge clk) ($fell(a) ##[2:5] $fell(b)) |->
        ##1 ($fell(c) && $fell(d)) ##0 
        (!c&&!d)[*4] ##1 (c&&d) ##1 b;
endproperty
a_arb1:assert property(arb(a1,b1,c1,d1));//调用属性arb
a_arb1:assert property(arb(a2,b2,c2,d2));
a_arb1:assert property(arb(a3,b3,c3,d3));

4.SVA与功能覆盖

功能覆盖分为:协议覆盖和测试计划覆盖。SVA可以用来获得协议副高的穷举信息,使用关键词“cover”来实现这一功能。
“cover”的基本语法如下:
  <cover_name>:cover property(property_name)
cover语句的结果包含下面的信息
(1)属性被尝试检验的次数
(2)属性成功的次数
(3)属性失败的次数
(4)属性空成功的次数

5.SVA中的多时钟定义

SVA允许序列或者属性使用多个时钟定义来采样独立的信号或者子序列。SVA会自动地同步不同信号或子序列使用的时钟域。例如:

sequence s_multiple_clocks;
    @(posedge clk1) a ##1 @(posedge clk2) b;
endsequence

序列s_multiple_clocks检验在时钟clk1的任何上升沿,信号a为高,接着在时钟clk2的上升沿,信号b为高。在时钟ckl1的上升沿,如果a为高,则序列开始匹配。接着“##1”延迟构造将检验时间移到时钟clk2的最近的上升沿,检验信号b是否为高。
SVA中多时钟需要注意的是:
(1)当在一个序列中使用了多个时钟信号时,只允许使用“##1”延迟构造。“##0”和“##2”等被禁止使用
(2)禁止在两个不同时钟驱动的序列之间使用交叠蕴含运算符(|=>)。因为先行算子的结束和后续算子的开始重叠,可能引起竞争的情况,这是非法的。

九、参加文献

SystemVerilog Assertion应用指南.pdf

  • 4
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
回答: SVA (SystemVerilog Assertions)是一种用于验证硬件设计的语言扩展,其中包括属性(property)的定义和使用。属性是一种描述设计行为的语句,可以用于检查设计是否满足特定的规范或约束。 在SVA中,属性可以使用蕴含(implication)结构来定义。蕴含结构由先行算子(antecedent)和后续算子(consequent)组成,先行算子是约束条件,只有约束条件成功时,后续算子才会被计算。蕴含结构可以分为交叠蕴含和非交叠蕴含两种形式。 交叠蕴含使用符号"|->"表示,表示如果先行算子匹配,在固定个时钟周期后计算后续算子表达式。例如,在每个时钟上升沿,检查信号a是否为高电平,如果a为高,那么b在接下来两个时钟沿后也必须为高。\[2\] 非交叠蕴含使用符号"|=>"表示,表示如果先行算子匹配,在下一个时钟周期计算后续算子表达式。例如,在每个时钟上升沿,检查信号a是否为高电平,如果a为高,那么b在下一个时钟沿也必须为高。\[3\] 通过使用蕴含结构,我们可以在属性定义中指定约束条件和期望的行为,以便进行设计验证。 #### 引用[.reference_title] - *1* *2* *3* [SVA介绍----蕴含操作符](https://blog.csdn.net/qq_39556143/article/details/94591578)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

er橙汁儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值