【SystemVerilog断言学习笔记4】边沿检测内嵌函数
0赞SVA中内嵌了信号边沿检测函数,方便用户监视信号从一个时钟周期到另一个时钟周期的跳变。其中,有三个非常有用的内嵌函数如下:
(1)$rose(boolean expression or signal_name):当表达式/信号的最低位由0变为1时返回真;
(2)$fell(boolean expression or signal_name):当表达式/信号的最低位由1变为0时返回真;(3)$stable(boolean expression or signal_name):当表达式/信号不发生变化时返回真。
针对上述的描述,可以得出两个结论:
(1)这三个内嵌函数是工作在时钟边沿上的;
(2)这三个内嵌函数只检测信号的最低位,而忽略其他位。
接下来,带着这两个结论以及运用上一篇博客对SVA块的建立步骤对三个内嵌函数进行验证。
1、$rose()函数的验证
为了验证内嵌函数$rose()是工作在时钟边沿上的,这里给出一个简单的反例即不受时钟控制:
/******************************************************* 作者 : CrazyBird 文件 : rose_test.sv 日期 : 2015-5-6 功能 : $rose()函数的验证 ********************************************************/ `timescale 1ns/1ps module rose_test( output reg clk, output reg [1:0] a ); // 时钟的产生 parameter PERIOD = 10; initial begin clk = 0; forever #(PERIOD/2) clk = ~clk; end // 激励的产生 initial begin a = 0; repeat(20)@(negedge clk) begin a = {$random()}%2**2; end @(negedge clk); $stop; end // 断言 always_comb begin a_ia : assert($rose(a)); end endmodule
对该程序进行编译将出现以下错误:
从错误中可以看出,$rose()函数是时钟敏感的。改正后的代码如下所示:
/******************************************************* 作者 : CrazyBird 文件 : rose_test.sv 日期 : 2015-5-6 功能 : $rose()函数的验证 ********************************************************/ `timescale 1ns/1ps module rose_test( output reg clk, output reg [1:0] a ); // 时钟的产生 parameter PERIOD = 10; initial begin clk = 0; forever #(PERIOD/2) clk = ~clk; end // 激励的产生 initial begin a = 0; repeat(20)@(negedge clk) begin a = {$random()}%2**2; end @(negedge clk); $stop; end // 序列的建立 sequence s1; @(posedge clk) $rose(a); // 受时钟边沿控制,正确 //$rose(a); // 不受时钟控制,错误 endsequence // 属性的建立 property p1; s1; endproperty // 断言属性 a_cc: assert property(p1); endmodule
对改正后的代码进行仿真,可得到如下的时序图:
其中,红色光标所在处表示断言成功,而红色下三角表示断言失败。可以很容易分析到,断言成功的地方肯定是当前时刻信号的最低位是高电平,上一时刻信号的最低位是低电平。断言失败的地方信号的最低位要么当前时刻是低电平,上一时刻是高电平,要么当前时刻和上一时刻的电平没有发生变化,不管其他位是如何变化的。从而验证了内嵌函数$rose()只检测信号的最低位,而忽略其他位。
对于内嵌函数$fell()和$stable()的验证与$rose()类似,同样可以验证“内嵌函数是工作在时钟边沿上的”和“内嵌函数只检测信号的最低位,而忽略其他位”这两个结论的正确性。下面只给出他们的仿真结果。
2、$fell()的验证
3、$stable()的验证
先介绍到这吧,待续~~