SystemVerilog测试台task输出波形与$display结果不一致排查
问题排查&修复方案
这是Verilog/SystemVerilog仿真时的典型问题,按优先级往下查,基本都能解决:
1. 先核对$display打印的信号层次
这是最高发的坑,十个人里九个踩过:
- 如果你在task里直接写
$display("%h", rx_out);这类不带层次的信号名,打印的根本不是DUT输出的真实硬件信号,是testbench作用域下你提前存测试预期的同名临时变量,值当然和你写的8'haa完全一致,但和波形里抓的DUT实际输出没关系。 - 修复方式:打印时必须写全信号的层次路径,比如
$display("输出观测值:%h", tb_top.dut_inst.rx_serial_out);,保证你打印的信号和波形窗口里添加观测的信号是同一个层次的同一个信号。
2. 调整打印/采样时机,消除delta cycle竞争
如果确认层次没写错,就是仿真时间槽的执行顺序导致的时序偏差:
- Verilog的仿真器跑的时候,同一个时间点是分区域执行事件的:
$display、阻塞赋值这类事件会在最靠前的活跃区执行,而DUT里的时序逻辑基本都用非阻塞赋值<=写,这类赋值的信号值要等到活跃区之后的非阻塞更新区才会真正生效,波形数据库存的就是这个更新后的实际硬件值。 - 如果你写task的时候图省事,在时钟上升沿触发之后零延迟就读信号、打打印,
$display读到的是testbench侧刚写进去的预期值,DUT的实际输出要等一个delta cycle才会更新,自然就出现打印值对、波形值错的问题。 - 修复方式:在时钟沿之后、读信号/打印之前加1个最小时间单位的小延迟,等DUT的信号完全稳定再采样,参考写法:
task send_test_seq; input [7:0] test_dat; begin // 等复位释放后再发激励 wait(rst_n == 1'b1); repeat(2) @(posedge clk); tx_valid <= 1'b1; tx_data <= test_dat; @(posedge clk); tx_valid <= 1'b0; // 加1ns小延迟,等DUT内部所有非阻塞赋值更新完成 #1; // 带完整层次路径打印真实输出 $display("观测到DUT输出:%h", tb_top.dut_inst.rx_out); end endtask
3. 检查initial块的调用时序
- 不要在initial块里零延迟直接调用task,必须等时钟起振、复位完全释放之后,再启动task发送激励。
- 如果task内部有对信号的force/release操作,记得release之后留足够的延迟再采样,不要立刻读值。
改完重新跑仿真,$display打印的值和波形窗口观测到的实际输出会完全对齐,不会再有偏差。
内容的提问来源于stack exchange,提问作者Robin Y
相关产品推荐
相关产品推荐

