You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Verilog断言失败时如何获取property内部data变量并打印?

解决SystemVerilog断言中获取Property内部变量的问题

在SystemVerilog里,property的内部局部变量默认没法直接在assert的else块中引用,但我们有几种实用的办法可以把data的值传递出来,或者直接在能访问到它的地方完成打印。下面是几个可行的方案:

方案一:在Property内部直接处理错误打印

这是最省心的方式——既然property内部能直接访问到data变量,我们可以把错误打印逻辑直接写到property的失败分支里,不用在assert的else块里额外处理:

property p1;
    logic [31:0] data;
    @(posedge clk) 
        (trigger, data = data) |=> (!resolve[*0:$] ##1 resolve && checkPassed) 
        else ($error("Assertion failed. data = %h", data));
endproperty

// 调用时无需额外else块,错误信息会在property失败时自动输出
assert property(p1);

这种方式的优势是逻辑紧凑,不需要额外的变量传递,直接在变量的作用域内完成打印。

方案二:用序列局部变量+模块级变量传递值

如果一定要在assert的else块里处理逻辑,我们可以用序列局部变量(SLV)捕获trigger时刻的data值,再把它赋值给一个模块级变量,这样else块就能访问到这个值了:

// 定义模块级变量存储捕获到的data值(避免全局变量的污染)
logic [31:0] captured_assert_data;

sequence s_capture_data;
    logic [31:0] local_data;
    @(posedge clk) 
        (trigger, local_data = data) ##0 (1'b1, captured_assert_data = local_data);
endsequence

property p1;
    s_capture_data |=> !resolve[*0:$] ##1 resolve && checkPassed;
endproperty

// 断言失败时直接调用模块级变量打印
assert property(p1) else begin 
    $error("Assertion failed. data = %h", captured_assert_data); 
end

注意:如果有多个断言实例使用这个property,要给每个实例单独分配模块级变量,防止值被覆盖。

方案三:将Property改为带输出参数的形式

我们可以把property定义成带输出参数的形式,在trigger触发时把data的值赋值给这个输出参数,这样assert调用时就能拿到这个值:

property p1(output logic [31:0] out_data);
    logic [31:0] data;
    @(posedge clk) 
        (trigger, data = data, out_data = data) |=> !resolve[*0:$] ##1 resolve && checkPassed;
endproperty

// 定义变量接收property输出的data值
logic [31:0] assert_data;

// 调用断言时传入输出变量
assert property(p1(assert_data)) else begin 
    $error("Assertion failed. data = %h", assert_data); 
end

这种方式更模块化,也避免了全局/模块级变量的副作用,适合需要在else块里做更多复杂处理的场景。


内容的提问来源于stack exchange,提问作者Eivind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:39:05