如何跳过SVA的首次评估?语法报错问题求助
解决SVA断言复位后首次评估失败的问题
你的问题核心是想跳过复位后signal_a首次上升沿对应的断言检查,而你尝试的!first_match(p_0)写法不符合SVA语法规则——first_match()是用来从序列的多个匹配中选取第一个,不能直接对整个property取反来实现跳过逻辑。下面给你几种可行的解决方案:
方法1:利用复位信号延迟开启断言
最直接的方式是让断言在复位释放后延迟一段时间再生效,确保硬件稳定后再开始检查。你可以先定义一个标志信号,在复位释放后等待若干周期或时间后置位,然后让断言仅在该标志为高时执行:
// 定义复位稳定标志 logic rst_stable; always @(posedge clk or posedge hw_rst) begin if (hw_rst) begin rst_stable <= 1'b0; end else begin // 复位释放后等待3个时钟周期再开启断言(可根据实际调整周期数) rst_stable <= ##3 1'b1; end end // 修改原属性,加入rst_stable作为前置条件 property p_0; @(posedge clk) rst_stable && $rose(signal_a) |-> $rose(signal_b); endproperty p_0_a : assert property(p_0) else `uvm_fatal("ASSERT_ERR", "signal_b didn't rise after signal_a");
方法2:标记并跳过首次signal_a上升沿
如果你只想跳过复位后的第一次signal_a上升沿,而不是固定延迟,可以用一个寄存器来标记首次上升沿是否已经发生,之后的上升沿才触发断言检查:
// 标记首次signal_a上升沿是否已过 logic first_rose_a_done; always @(posedge clk or posedge hw_rst) begin if (hw_rst) begin first_rose_a_done <= 1'b0; end else if ($rose(signal_a)) begin first_rose_a_done <= 1'b1; end end // 修改属性,仅在首次上升沿过后才检查 property p_0; @(posedge clk) first_rose_a_done && $rose(signal_a) |-> $rose(signal_b); endproperty p_0_a : assert property(p_0) else `uvm_fatal("ASSERT_ERR", "signal_b didn't rise after signal_a");
方法3:用序列语法直接跳过首次匹配
你也可以在property内部用序列逻辑来实现“跳过首次$rose(signal_a)”的效果,不需要额外的寄存器:
property p_0_skip_first; @(posedge clk) // 先等待首次$rose(signal_a)发生,之后的$rose(signal_a)才触发检查 (first_match($rose(signal_a)) ##0 1) throughout ($rose(signal_a) |-> $rose(signal_b)); endproperty p_0_a : assert property(p_0_skip_first) else `uvm_fatal("ASSERT_ERR", "signal_b didn't rise after signal_a");
为什么你原来的写法会报错?
first_match()的作用是从一个序列的多个潜在匹配中选取最早的那个,它只能作用于序列(sequence),不能直接包裹整个property后取反。SVA的property评估是时序性的,!first_match(p_0)这种写法不符合语法规则,编译器无法解析这种逻辑。
内容的提问来源于stack exchange,提问作者El_Gahaf
相关产品推荐
相关产品推荐

