保姆级教程超硬核包会,SystemVerilog SV 断言

本文详细介绍了系统验证语言(SVA)在验证程序中的应用,包括断言的类型如即时断言和并发断言,以及SVA中的序列、属性和时钟定义。重点阐述了序列的内置方法、时序关系以及属性的使用,如蕴含操作符和描述延迟的方法。此外,还提及了SVA在功能覆盖率和设计连接中的作用,以及如何利用SVA进行局部变量的定义和覆盖信息的获取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:仿真的时候,需要观察某些程序运行的结果是否符合预期,这一需求一般是通过断言来实现。

断言

  • 对于程序的检查。
  • 断言是设计的属性的描述
  • 如果被检查的属性与期望不同断言失败
  • 如果被禁止在设计中出现的属性在仿真中出现,也断言失败。
  • 断言可以在功能仿真中不断被监视。
  • 相同的断言可以在仿真中也可以在形式验证中复用。

断言的评估和执行包括一下三个阶段:

  • 预备(Preponed)在这个阶段,采样断言变量,而且信号或变量的状态不能改变。这样确保在时隙开始的时候采样到最稳定的值。
  • 观察(Observed)在这个阶段,对所有的属性表达式求值。
  • 相应(Reactive)在这个阶段,调度评估属性成功或失败的代码。

1. 为什么使用SVA语言?

  • SVA是一种描述性语言,可以详细的描述相关的状况, 非常精确且易于维护。
  • 有内嵌函数来测定特定情况,并且可以收集断言覆盖率。

1.1 即时断言

  • 基于仿真事件的语义,与在过程块中其他表达式一样。
  • 即时断言本质与时序无关,立即求值。必须放在过程块的定义中,应用在动态仿真里。
always_comb
begin
	a_aia : assert (a&&b);//assert 断言
end

1.2. 并发断言

  • 基于时钟周期,根据调用的变量采样值计算测试表达式。
  • 一般放在模块接口里。
a_cc : assert property(@(posedge cik) not(a&&b)); //

有property的是并发断言,后边跟的时钟。

2. 建立SVA块

  • 功能由多个逻辑事件组成。这些事件可以是简单的同一个时钟边缘求值的表达式。

2.1 序列

  • SVA用序列sequence来表示这些事件,描述这些发生变化的事件
sequence name_of_sequence;
	< test expression>;
endsequence

-多个序列可以逻辑组合生成更复杂的序列,使用属性property来表示 。例如序列1发生导致序列2发生。

property name_of_property;
	<test expression>; or
	<comples sequence expressions>;
endproperty
2.1.1 序列内建方法
//rose 从0变为1 
	$rose(expression or signal)
//fell 从1变为0
	$fell(expression or signal)
//stable值没发生变化
	$stable(expression or signal)

sequence s2;
	@(posedge clk) $rose(a);//从0变为1
endsequence
2.1.2 序列中的形式参数
  • 定义形式参数,不需要指明对象,使得序列可以复用。
sequence s3_lib (a,b);
	a||b;
endsequence

sequence s3_lib_inst1;
	s3_lib(req1,req2);
endsequence //这两个序列完成了嵌套
2.1.3 序列中的时序关系

## 表示时钟周期延迟。

sequence s4;
	@(posedge clk ) a##2 b; //默认a为高 过两拍后 b是否为高
endsequence

2.2. 属性property

  • property对设计的行为做的描述
  • assert、caver、assume 的对象是property。
  • assert检查在任何时刻对应的属性描述是否成立。
  • cover在认识时候对应的属性是否发生过
  • aassume描述边界激励的属性

在工作中的流程一般为:

  • 建立SVA检查其的步骤:建立布尔表达式; 建立序列表达式;时序上的表达式;建立属性。

2.3 SVA中的时钟定义

  • 在序列、属性和断言语句中都可以定义时钟。
  • 一般在属性中指定时钟,并保持序列独立于时钟,可以提高序列的重用性。

2.4. 禁止属性

  • 属性检查默认都是正确的条件,属性也可以被禁止发生。禁止属性表示期望属性为假,当属性发生时,断言失败。

断言执行块
SV语言被定义在断言检查失败时,仿真器会打印信息,对于成功的断言,仿真器不会打印信息

2.5. 蕴含操作符

蕴含(implication)等效于if then。

  • 蕴含的左边为先行算子(antecedent),右边叫做后续算子(consequent)。
  • 先行算子是约束条件,成功会计算后续算子。
  • 先行算子不成功,整个属性默认为空成功。
  • 蕴含结构只能用在属性的定义中。
  • 蕴含可以分为交叠和非交叠蕴含。

交叠蕴含使用->表示

  • 如果先行算子匹配,则在同一拍计算后续算子成立不成立。

非交叠蕴含使用=>表示

  • 如果先行算子匹配,则在下一拍计算后续算子成立不成立。

2.6 描述延迟的方法

2.6.1 重叠时序窗口
property p12;
	@(posedge clk) (a&&b) |-> ##[1:3] c;
endproperty

a12: assert property(p12);

a和b同时为高后的 1-3个周期内,c至少有一个周期为高。

2.6.2 无限时序窗口
  • $表示时序没有上限,检测器不断地检查表达式是否成功,直到仿真结束。
  • ended使序列可以简单的连接

3. SVA中的一些命令

$past构造

  • 当满足条件时,检查之前的状态是不是在预期。
$past(signal_name, number of clock cycles)

连续重复运算符[ * n]

  • 表面信号或序列将在指定数量的周期内连续的匹配,每次匹配之间都有一个时钟周期的隐藏延迟。
signal or sequence [*n] 
  • 连续重复的次数也可以是一个窗口。
a[ *1:5 ]表示a从某个时钟周期开始重复1-5

[->]跟随重复运算符

  • a[->3]信号a连续或间断的出现3次为高。

非连续重复运算符[=m]

  • 表示一个事件的连续性,需要重复发生m次,但不需要在连续的周期内完成
  • b[=3]表示b必须在3个周期内为1,但并不需要是三个连续的周期

二者区别:

  • 跟随重复表示判断结束跟着执行后面的表达式。
  • 非联系重复表示判断结束后会间隔1拍或者几排再执行后边的表达式。

and

  • and可以用来逻辑地组合两个序列,当两个序列都成功时,属性才算成功。

  • 两个序列必须具有相同的起始点,但是可以有不同的结束点。

  • 检验的起始点是第一个序列的成功时的起始点,结束点是使得属性最终成功的另一个序列成功时的结束点。

sequence s27 a;
 @(posedge clk) a##[1:2] b; //a为高过了1到2拍b为高
endsequence
sequence s27 b;
 @(posedge clk) c##[2:3] d;
endsequence
property p27;
	@(posedge clk)  s27a and s27b;
endproperty 

intersecct

  • 与and类似,但要求两个序列的长度必须相等。即同时开始同时结束。

or

  • 只要一个序列成功就算成功。

first_match

  • 使用and/or可能出现一个检验具有多个匹配的情况。
  • first_match构造可以确保只用第一次序列匹配,而丢弃其他匹配。

throughout

  • ()throughout(时间条件) //要求某个条件必须一直为高时。

within

  • 允许在一个序列中定义另一个序列。
seq1 within seq2

表示seq1在seq2的开始到结束范围内发生
其他

  • $onehot(expr) 检验表达式是否只有一位为1。
  • $onehot0(expr) 检验表达式只有1位或没有任何位为0。
  • $isunknown(expr)检验表达式任何位是否有x,z。
  • $countones(expr)计算向量中为1的位数。

disable iff

  • 可以用来禁止在一些条件下的属性检验。
  • 在复位时一般不需要检验:disable iff (reset)。

expect

  • expect与Verilog中的等类语句类似,用来等待属性的成功检验。 e
  • xpect构造后的代码作为一个阻塞语句来执行。 expect构造语法与assert相似。

4. SVA中的局部变量

  • 在序列或者属性内部可以定义局部变量,并可以赋值。 变量接着子程序放置,用逗号隔开。
  • SVA中调用子程序,在序列每次成功匹配时调用子程序。

5. 将SVA与设计连接

有两种方法可以将SVA检验器连接到设计中。
(1)在模块定义中内建或者内联检验器。
(2)将检验器与模块、模块的实例或者一个模块的多个实例绑定。
注意,定义检验器模块时,他是一个独立的实体。检验器用来检验一组通用的信号,检验器可以与设计中任何的模块或者实例绑定,绑定的语法如下所示。

bind<module_name or instance name>
	<checker name> <checker instance name>
		<design signals>;

6. SVA与功能覆盖率

  • 断言可以用来获得有关协议覆盖的穷举信息。SVA提供了关键词cover来实现这一功能,cover语句的基本语法如下所示。
<cover_name>: cover property (property name)\

cover_name是用户提供的名称,用来标明覆盖语句,property_name是用户想获得覆盖信息的属性名。
cover语句的结果包含下面的信息:
(1)属性被尝试检验的次数。
(2)属性成功的次数。
(3)属性失败的次数。
(4)属性空成功的次数。
检验器mutex_chx在一次模拟中的覆盖日志的实例如下所示:

c_mutex,12 attempts,12 match,0 vacuous match

就像断言(assert)语句一样,覆盖(cover)语句可以有执行块。在一个覆盖成功匹配时,可以调用一个函数(function)或者任务(task),或者更新一个局部变量。

<think>我们正在讨论SystemVerilog断言(SVA)中如何检测重复序列。用户希望了解如何使用SVA来检测重复出现的序列模式。 根据引用[2]和[3],SVA中主要使用sequence和property来定义时序行为,然后用assert来检查。对于重复序列的检测,我们可以使用SVA的重复操作符。 常见的重复操作符括: 1. [*n]:连续重复n次,例如 a[*3] 表示a连续出现3个周期。 2. [->n]:非连续重复(goto重复),表示表达式在n个周期内出现n次,但不要求连续(最后一次出现必须在当前周期)。 3. [=n]:非连续重复(非连续匹配),表示表达式在n个周期内出现n次,不要求连续,且最后一次出现后还可以有额外的周期。 另外,我们还可以使用连续重复操作符来检测重复序列。 假设我们要检测一个序列重复出现两次,我们可以这样写: sequence s1; ... // 定义序列 endsequence 然后,我们可以使用 s1 [*2] 来表示s1连续出现两次。 但是,如果序列s1跨越多个时钟周期,那么s1[*2]表示s1结束后立即开始下一个s1。 例如,假设s1是 a ##1 b,那么s1[*2] 相当于 (a ##1 b) ##1 (a ##1 b),即总共4个周期:a,b,a,b。 如果我们要检测一个信号重复出现,比如信号a连续出现3个周期,我们可以写:a[*3]。 如果我们要检测一个序列重复出现,但中间可能有间隔,那么我们可以使用goto重复或非连续重复。 下面我们通过具体例子来说明。 例1:检测信号a连续重复3次 sequence seq_a3; a[*3]; endsequence 例2:检测序列 (a ##1 b) 连续重复2次 sequence seq_ab2; (a ##1 b)[*2]; endsequence 这等价于:a ##1 b ##1 a ##1 b 例3:检测序列 (a ##1 b) 非连续重复2次(使用goto重复) 我们想检测:在任意长的周期内,a出现后下一个周期b出现,这样的事件发生了2次,且最后一次发生就在当前。 我们可以使用: (a ##1 b)[->2] 例4:检测序列 (a ##1 b) 非连续重复2次(使用非连续匹配) 与goto重复类似,但不要求最后一次匹配在当前周期,可以后面还有周期: (a ##1 b)[=2] 另外,我们还可以使用局部变量来计数,但使用重复操作符通常更简洁。 现在,我们考虑一个更复杂的场景:检测一个序列重复出现,但重复的次数是变量。SVA中可以使用参数化的sequence,但重复次数必须是常量。如果重复次数是变量,可能需要通过其他方式(例如使用局部变量)来计数,但这在SVA中比较复杂,有时可能不适合用断言,而适合用其他方法。 不过,对于固定次数的重复,SVA的重复操作符非常方便。 下面我们写一个具体的例子:检测一个握手信号(req和ack)的序列重复两次,即连续发生两次握手。握手序列定义为:req为高,然后在接下来的1到3个周期内ack为高(即req ##[1:3] ack)。现在要检测这个握手序列连续发生两次。 我们可以这样写: sequence handshake; req ##[1:3] ack; endsequence property two_handshakes; handshake[*2]; endproperty assert property (@(posedge clk) two_handshakes); 注意:这个断言要求两个握手序列是连续的,即第一个握手的ack结束后,下一个握手的req必须紧接着在下一个周期开始。 如果我们希望两个握手序列之间可以有任意间隔,那么我们可以使用: handshake[->2] 或者 handshake[=2] 但是注意,[->2]要求第二个握手序列的ack必须在当前周期结束,而[=2]则允许第二个握手序列的ack之后还有周期。 另外,我们还可以使用“intersect”操作符来确保两个序列在时间上有重叠?不,对于重复序列,我们通常不需要重叠,而是顺序发生。 因此,对于非连续的重复,我们使用[->]或[=]即可。 总结:在SVA中检测重复序列,主要使用重复操作符[*n], [->n], [=n]等。 下面我们根据上述内容生成相关问题。</think>### SystemVerilog SVA 断言检测重复序列 在 SystemVerilog 断言SVA)中检测重复序列,主要利用**重复操作符**和**序列构建**实现。以下是关键语法和示例: #### 1. **基本重复操作符** - `[*n]`:连续重复 `n` 次 示例:检测信号 `a` 连续出现 3 个周期 ```systemverilog sequence s_a3; a[*3]; // a在连续3个周期为高 endsequence ``` - 等价于:`a ##1 a ##1 a` - `[->n]`:非连续重复("goto"重复) 示例:检测 `a` 非连续出现 3 次(最后一次必须匹配当前周期) ```systemverilog sequence s_a_goto3; a[->3]; // 中间可有任意间隔,但最后一次a必须出现在当前周期 endsequence ``` #### 2. **序列重复检测** 检测序列 `s1` 重复两次(`s1` 定义为 `req` 后 1~3 周期内 `ack` 为高): ```systemverilog sequence s_handshake; req ##[1:3] ack; // 握手序列 endsequence property p_two_handshakes; s_handshake[*2]; // 连续重复两次握手 endproperty assert property (@(posedge clk) p_two_handshakes); ``` - 等价时序:`(req ##[1:3] ack) ##1 (req ##[1:3] ack)` #### 3. **带间隔的重复检测** 使用 `[->]` 检测非连续重复序列(允许中间有任意活动): ```systemverilog sequence s_data_phase; start ##2 data_valid; endsequence property p_nonconsecutive; s_data_phase[->2]; // 序列出现两次,不要求连续 endproperty ``` - 匹配场景:`start ##2 data_valid ...(任意周期)... start ##2 data_valid` #### 4. **复杂重复模式** 组合重复操作符检测嵌套序列: ```systemverilog property p_complex_repeat; // 检测:(a且b持续2周期) 重复3次,中间间隔1周期 (a && b)[*2] ##1 (a && b)[*2] ##1 (a && b)[*2]; endproperty ``` #### 5. **动态长度重复** 使用参数化序列实现可变重复次数: ```systemverilog sequence s_dynamic_repeat(int n); a[*n]; // 重复n次 endsequence property p_dynamic; s_dynamic_repeat(4); // 检测a连续4周期为高 endproperty ``` ### 关键注意事项 1. **时序对齐** `[*n]` 要求严格连续,而 `[->n]` 允许间隔但最后一次必须对齐当前周期[^2][^3]。 2. **性能影响** 复杂重复序列可能增加仿真开销,需合理设计范围(如 `##[1:5]` 而非 `##[1:$]`)[^1]。 3. **错误消息** 建议添加自定义错误消息: ```systemverilog assert property (p_two_handshakes) else $error("Handshake sequence failed"); ``` > 示例引用: > 引用[1]说明断言失败时默认打印错误信息,支持自定义消息[^1]。 > 引用[2]展示了序列(sequence)、属性(property)和断言(assert)的基础语法[^2]。 > 引用[3]对比了"|->"(重叠蕴含)与"|=>"(非重叠蕴含)的区别[^3]。 ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值