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
相关产品推荐
相关产品推荐

