十、SVA断言

SVA

概述

断言是设计的属性的描述,主要用于验证设计的行为。此外,断言可以用来提供功能覆盖,并标记输入激励,用于验证不符合假设的要求。

  • 如果一个在模拟中被检查的属(property)不像我们期望的那样表现,那么这个断言失败。
  • 如果一个被禁止在设计中出现的属性在模拟过程中发生,那么这个断言失败。

即时断言

即时断言(immediate assertions)

  • 基于模拟事件的语义。
  • 测试表达式的求值就像在过程块中的其他Verilog的表达式一样。
  • 它们本质不是时序相关的,而且立即被求值。
  • 必须放在过程块的定义中。
  • 只能用于动态模拟

当语句在过程块中被执行时,即时断言语句是对被执行表达式的测试。该表达式是非时态的,可以理解为与程序中if语句的条件下的表达式相同。换句话说,如果表达式计算结果是X、Z或0,那么它被解释为错误,断言语句被认为失败。否则,表达式将被解释为真,断言语句被认为通过,或者等效地,成功。

always_comb
begin
  a_ia: assert (a && b);  //当信号a或信号b发生变化时,always块被执行
end

并发断言

并发断言(concurrent assertions)

  • 基于时钟周期。

  • 在时钟边缘根据调用的变量的采样值计算测试表达式。

  • 变量的采样在预备阶段完成,而表达式的计算在调度器的观察阶段完成。

  • 可以被放到过程块(procedural block)、模块(module)、接口(interface),或者一个程序(program)的定义中。

  • 可以在静态(形式的)验证和动态验证(模拟)工具中使用。

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

SystemVerilog断言的目标之一是为断言提供一个通用语义,以便它们可以用于驱动各种设计和验证工具。例如形式化验证工具,使用基于周期的语义来计算电路描述,通常依赖于一个或多个时钟信号来驱动电路的计算。任何时钟边沿之间的计时或事件行为都被提取出来。并发断言包含这个时钟语义。虽然这种方法通常简化了电路描述的计算,但在许多场景中,这种基于周期的计算提供了不同于SystemVerilog基于事件计算标准的行为。

在形式化验证中,一般只采用并发断言,因此以下内容只介绍并发断言。
区别即时断言和并发断言的关键词是”property“。

SVA语法

一条SVA并发断言可以看成是由四种不同层次的结构组成:

  • 布尔表达式(booleans)
  • 序列(sequence)
  • 属性(property)
  • 断言声明(assertion statements)

布尔表达式是构成SVA的最基本单元。其一般形式为标准的SystemVerilog的布尔表达式,它由信号及其逻辑关系运算符构成,用以表示某个逻辑事件的发生

序列 sequence

序列是布尔表达式在时间上的组合
SVA用关键词“sequence”来表示这些事件。
序列(sequence)的基本语法是:

sequence name_of_sequence;
  <test expression>;
endsequence

eg:

sequence s1
  @(posedge clk) a;
endsequence

序列s1检查信号“a”在每个时钟上升沿都为高电平。如果信号“a”在任何一个时钟上升沿不为高电平,断言将失败。这相当于“a == 1’b1”。

SVA提供带有边沿检测的原语序列用于监控边沿变化:

  • $rose(boolean expression or signal_name):当信号的LSB从低变为高时返回真。
  • $fell(boolean expression or signal_name):当信号的LSB从高变为低时返回真。
  • $stable(boolean expression or signal_name):信号不发生变化时返回真
sequence s2;
 @(posedge clk) $rose(a);
endsequence

s2将在每个时钟上升沿检查a是否跳变为1

序列可通过带有形式参数的参数列表进行复用。设计中的一些公共属性(如独热码状态机,奇偶校验等)可设置带参数的序列库进行重用。

equence s3_lib(a,b);
      a||b;
endsequence
#s3_lib可复用在任何两个信号中
sequence s3_lib_inst1;
 s3_lib(req1,req2);
endsequence

跨时钟周期的序列
在SVA中,时钟延迟用符号“##”表示。##3代表三个时钟周期。

sequence s4;
   @(posedge clk) a ##2 b;
endsequence

s4在每个时钟沿检测a是否为高,若是则检测两个时钟周期后b是否为高,若是则断言成功

属性 property

属性是在仿真或者形式验证中被验证的单元。属性将序列通过逻辑或者有序地组合起来生成更复杂的序列,SVA提供关键词“property”来表达这些复杂的有序行为。其语法为:

property name_of_property;
  <test expression>;or
  <complex sequence expressions>;
endproperty

SVA在仿真过程中,sequence和property本身是不做任何事的,要想是他们有效,必须通过assert进行声明。 SVA时钟可以在sequence,property甚至assert中进行定义,但应注意: 时钟最好在property中进行定义而不要在sequence中定义,从而保证sequence的独立性,也方便复用。 可以在assert中同时定义时钟和使用sequence,但不允许同时定义时钟和使用property

断言 assert

断言基本语法:

assertion_name: assert property (property_name);
sequence s5a;
 a ##2 b;
endsequence

property p5;
 @(posedge clk) s5;
endproperty

a5: assert property (p5);

禁止属性的定义

关键词"not"用来表示属性应该永远不为真。

sequence s6;
 @(posedge clk) a ##2 b;
endsequence
property p6;
 not s6;
endproperty
a6: assert property (p6);

例中若在某时钟沿a为高点平,且两个时钟后b为高电平则断言失败,否则断言成功。

SVA执行块

systemverilog语言被定义成每当一个断言失败,模拟器在默认情况下都会打印出一条错误信息。模拟器不需要对成功的断言打印任何东西,当然我们可以自定义打印的成功或失败的信息。

property p7;
  @(posedge clk) a ##2 b;
endproperty

a7 : assert property(p7)
		$display("property p7 ok");
	else
		$display("property p7 failed");

蕴含操作符

上述断言中,SVA会在每个时钟沿进行检测,若不符合情况则断言失败,但有时往往关注某信号发生变化后的时序关系,这将导致大量并非我们所关心的断言失败情况产生。为避免这种情况,SVA引入蕴含操作符(Implication)来起一个门控作用。

蕴含操作符类似于if-then结构。蕴含操作符左侧称之为先验部分(antecedent),右侧称之为后验结果(consequent)。若先验部分验证成功,后验结果才进行检查,否则若先验部分验证失败,则认为是“伪成功”。蕴含操作符用于property中,不可用于sequence中!

蕴含操作符包含:交叠蕴含操作符和非交叠蕴含操作符

交叠蕴含操作符(Overlapped implication)

交叠蕴含操作符符号为 |->

交叠蕴含操作符中,若先验部分验证成功,则后验结果在同一时钟进行验证。如下例所示,若某时钟处a变为高电平,则同一时刻b也应为高电平。

property p8;
 @(posedge clk) a |-> b
endproperty
a8:assert property (p8);
非交叠蕴含操作符(Overlapped implication)

非交叠蕴含操作符符号为|=>

非交叠蕴含操作符在先验部分验证匹配后,在下个时钟沿才进行后验部分的检查匹配。相对于蕴含操作符后验部分有一个时钟的滞后。如下例所示,在时钟边沿a为高电平则一个时钟后b也应为高电平。

property p9; 
	@(posedge clk) a |=> b;
endporperty

a9:assert property(p9);
后续算子带固定延迟的蕴含
property p10;
	@(posedge clk) a |-> ##2 b;
endporperty

a10 : assert property(p10);
使用序列最为先行算子的蕴含
sequence s11a;
  @(posedge clk) (a&&b) ##1 c;
endsequence

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

property p11;
 s11a |-> s11b;
endproperty

a11:assert property(p11)

SVA时序窗口

之前示例中时钟延时往往是固定格式的,SVA允许时间窗的引入,其表示形式为##[minperiod : max_period],表示后续部分在min_period到max_period个时钟周期内验证成功则断言通过。示例如下:

property p12;
   @(posedge clk) a && b |-> ##[1:3] c;
endproperty
a12: assert property(p12);

上述断言在时钟沿处若a和b同时为高,则在1至3个时钟周期内c应为高电平。
延时时间上线可以设置为$表示不设上限,将一直检测到断言成功或仿真结束为止 。

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

SVA ended

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

sequence_name.ended

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

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

SVA参数(parameter)列表

SVA允许在sequence或property中使用parameter参数以重定义或适用于不同的场景。

module generic_chk(input logic a,b,clk);
	parameter delay=1;
	property p16;
   		@(posedge clk) a|->##delay b;
	endproperty
	a16:assert property(p16);
endmodule
module top();
   logic a,b,c,d;
   generic_chk #(.delay(2))i1(input logic a,b,clk);
   generic_chk i2(input logic c,d,clk);
endmodule

选择运算符

property p17;
     @(posedge clk) c ? d==a : d==b;
endporperty

p17在上升沿检测c点评,为高时判定d是否等于a,为低时判定d是否等于b。

真值表达式

真值表达式: ture (需自己定义 defien true 1)

使用true表达式,可以在时间上延长SVA检验器,能够使序列的结束点延长一个时钟周期,这可以用来实现同步检测多个属性且需要同时成功检测的复杂协议。

`ddefine true 1

sequence s18a;
	@(posedge clk) a ##1 b;
endsequence

sequence s18a_ext;
    @(posedge clk) a ##1 b ##1 `true;
endsequence;

sequence s18b;
   @(posedge clk) c ##1 d;
endsequence;

property p18;
   s18a.ended |-> ##2 s18b.ended;
endproperty

property p18_ext;
   s18a_ext.ended |=> s18b.ended;
endproperty

a18    : assert property(p18);
a18_ext: assert property(p18_ext);

前向检测$past

SVA提供内建任务$past用于获取之前时钟沿某处的值。其原语为:

$past(signalname,numberof_clock_cycles)

默认缺省情况下,SVA提供前一个时钟沿处的信号值。

property p19;
   @(posedge clk) (c && d) |-> ($past((a && b), 2)==1);
endproperty;

a19:assert property(p19);

a19检测在时钟沿处若c和d同时为1,则在前溯第二个时钟沿处a&&b应为1。

$past允许使用带有时钟门控信号的检测匹配。

$past(signal_name,number_of_clock_cycles,gating_signal);
property p20;
  @(posedge clk) (c&&d)|->($past((a&&b),2,enable)==1);
endproperty
a20:assert property(p20);

a20同a19类似,不过若c和d同时为1,则前溯第二个时钟沿处使能信号enable必须为高且a和b必须为高。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值