SVA中的$rose和$fell

SVA中内嵌了边沿检测的函数,用户可以通过这些函数检查信号在采样时钟的前后的高低变化情况。常用的边沿检测函数有$rose和$fell。

1 $rose

在仿真中$rose并不是单纯的判断信号的跳边沿,而是判断时钟采样信号前后是否存在0->1/x->1/z->1的变化。其格式如下:

$rose(expression);

需要注意这里的$rose不是上升沿!

【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic       clk;
logic [2:0] sig0;
logic       sig1;

initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end

initial begin
       sig0 = 3'b000; sig1 = 1'b0;
    #2 sig0 = 3'b001;
    #2 sig1 = 1'b1;   sig0 = 3'b000;
    #2 sig1 = 1'b0;#2 sig0 = 3'b100;
    #2 sig1 = 1'b1;#2 sig1 = 1'b0;
    #4 $stop;
end
// property p
property p;
    @(posedge clk) $rose(sig0) |-> ##1 sig1;
endproperty // p
// assertion
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
【仿真结果】 
示例中3ns时,sig[0]被采样到高电平,先序算子在此刻成功,注意先序算子并没有在2ns时触发。这是因为在该采样时钟之前的上一个采样时钟沿采样到的sig0[0]为低电平,3ns时当前采样时钟采样到sig[0]为高电平,$rose感知到sig[0]在前后2个采样时钟周期存在低高变化,即该函数此时返回为真,所以在仿真中$rose并不是单纯的判断信号的跳变沿,而是判断连续两个时钟采样周期信号是否存在0->1/x->1/z->1。同时,需要注意,$rose仅对表达式最低位的跳变变化敏感,对于非最低位信号的变化并不敏感。

2 $fell

在仿真中$fell并不是单纯的判断信号的跳边沿,而是判断时钟采样信号前后是否存在1->/x->0/z->0的变化。其格式如下:

$fell(expression);

需要注意这里的$fell不是下降沿!

【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1;

initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end
initial begin
       sig0 = 1'b1;sig1 = 1'b0;
    #2 sig0 = 1'b0;#2 sig1 = 1'b1;
       sig0 = 1'b1;#2 sig1 = 1'b0;
    #4 $stop;
end
// property p_fell
property p;
    @(posedge clk) $fell(sig0) |-> ##1 sig1;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
【仿真结果】 

示例中3ns时,sig0被采样到低电平,先序算子在此刻成功,注意先序算子并没有在2ns时触发。这是因为在该采样时钟之前的上一个采样时钟沿采样到的sig0为高电平,3ns时当前采样时钟采样到sig0为低电平,$fell感知到sig0在前后2个采样时钟周期存在高低变化,该函数此时返回为真。

$rose和$fell并不像posedge和negedge那样判断信号的跳边沿,$rose和$fell是基于相邻两个采样周期,判断信号在两个连续的采样周期被采样的值的变化情况。

3 $stable

当表达式在连续两个采样时钟周期保持不变时返回真。其格式如下:

$stable(expression);

【示例】
`timescale 1 ns / 1 ps
module top_tb;
bit clk;
bit sig0,sig1; // default value : 0

initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end
initial begin 
       sig0 = 1'b0;   sig1 = 1'b0;
    #2 sig0 = 1'b1;#4 sig1 = 1'b1;
    #4 sig0 = 1'b0;#2 sig1 = 1'b0;
    $stop;
end
// property p_stable
property p;
    @(posedge clk) $stable(sig0) |-> ##1 sig1;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule

【仿真结果】 
1ns时,因为sig0类型为bit,其默认值为0,在1ns时$stable认为sig0当前值与前一周期值一样也是0,所以1ns时$stable为真,但是在3ns时sig1为0,所以此时属性断言失败。在5ns时,因为sig0在前一周期(3ns)处的值和5ns处的值都为高,且一个时钟周期后sig1为高,所以此时属性断言成功,后续时刻点操作类似,不再赘述。这里需要注意$stable检测时信号的类型,示例中如果sig0为logic类型,那么仿真结果是不一样的,因为logic类型的变量的默认值为不定态,这样sig0在0时刻和1时刻的值就是不一样的,此时$stable就会返回假。

4 $past

$past主要用于检查当前表达式前一个时钟周期(如果不指定number_of_ticks,默认指向前一个时钟周期)值是否为真,如果为真则$past返回为真。其格式如下:

$past(expression[,number_of_ticks]);

其中number_of_ticks可以指定检查当前时刻之前number_of_ticks个周期的采样值。

【示例】
`timescale 1 ns / 1 ps
module top_tb;
bit clk;
bit sig0,sig1; // default value : 0

initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end

initial begin
       sig0 = 1'b0;sig1 = 1'b0;
    #2 sig0 = 1'b1;
    #2 sig1 = 1'b1;   sig0 = 1'b0;
    #4 sig0 = 1'b1;#2 sig1 = 1'b1;
    #4 $stop;
end
property p;
    @(posedge clk) $past(sig0) |-> ##1 sig1;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
【仿真结果】 
在5ns时,$past(sig0)指的时在3ns时刻时钟采样sig0的值,3ns时sig0的值为1,所以此时$past(sig0)返回真。后续时刻$past(sig0)计算方式与此相同,不再赘述。

5 $changed

格式:

$changed(expression);

当表达式发生变化(不管是高低变化还是低高变化)时返回真,返回值类型为布尔类型。


【示例】
`timescale 1 ns / 1 ps
module top_tb;
bit clk;
bit sig0,sig1; // default value : 0

initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end

initial begin
       sig0 = 1'b0;sig1 = 1'b0;
    #2 sig0 = 1'b1;
    #2 sig1 = 1'b1;sig0 =1'b0;
    #2 sig0 = 1'b1;
    #2 sig1 = 1'b0;#4 $stop;
end
property p;
    @(posedge clk) $changed(sig0) |-> ##1 sig1;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule
【仿真结果】

示例中,在3ns时,sig0被采样到为高电平,在1ns时即前一个采样周期sig0被采样到为低电平,所以在3ns时$changed感知到sig0在连续2个时钟周期存在电平值变化,此时$changed(sig0)返回真。5ns时,sig0被采样到为低电平,而此采样点前一周期的3ns处sig0被采样到为高电平,所以此时$changed(sig0)检测到sig0在连续两个时钟周期存在边沿变化,该函数返回真,后续$changed(sig0)变化类似,不再赘述。



全部评论
感谢大神分享
点赞 回复 分享
发布于 2022-10-19 09:36 河南

相关推荐

评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务