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

Vivado中$display未正确显示Verilog变量赋值结果的问题排查

Verilog仿真结果异常排查

问题描述

编写的阶乘计算Verilog代码,预期仿真输出res is 3.000000,但实际输出为res is 0.000000,需排查问题原因。

原Verilog代码

`timescale 1ns / 1ps
module factorial(
input  i_n,
output reg  res,
input  i_clk
    );
integer j;
initial
begin:a
for (j=1;j<=i_n;j=j+1)begin
res<=res*j;
end

res<='d3;
$display("res is %f",res);//as res is 'd3,should display 3.0
end
endmodule

module u_f;
reg  i_n;
wire  res;
reg i_clk;
initial
begin
i_n<=3;
i_clk=1'b0;
end

 always 
 begin
 #10 i_clk<=~i_clk;
 end
factorial  u2(
    .i_n(i_n),
    .i_clk(i_clk),
    .res(res)
    );
   
endmodule

实际仿真输出

Time resolution is 1 ps
res is 0.000000

问题原因分析

  1. 非阻塞赋值的执行时序问题:
    代码中res<='d3使用了非阻塞赋值(<=),Verilog里非阻塞赋值的变量更新会被放到当前时间片的NBA(Non-Blocking Assignment)阶段执行,而$display属于Active阶段的语句,会在NBA阶段之前跑。也就是说,执行$display时,res还没被更新成3,依然保持之前的初始状态。

  2. reg变量未初始化:
    res是output reg类型,代码里没有显式初始化,它的初始值是未知态(x)。虽然之后尝试赋值3,但因为非阻塞赋值的时序问题,$display读取的还是这个未知态x。当用%f格式化输出未知态时,仿真器会把它解析成0.000000。

  3. 额外的时序隐患:
    测试模块里i_n<=3也用了非阻塞赋值,仿真0时刻factorial模块的initial块执行时,i_n还没被赋值成3,依然是初始值x,导致for循环的条件j<=i_n不成立,循环根本不会执行。不过这不是本次输出异常的直接原因,但也是代码里的潜在问题。

修复建议

  • 把res<='d3改成阻塞赋值:res='d3,阻塞赋值会立刻更新变量值,$display就能读取到正确的3。
  • 或者在$display前加#0,让语句延迟到NBA阶段之后执行:
    res<='d3;
    #0 $display("res is %f",res);
    
  • 同时建议显式初始化res,比如在output reg res后加=0;,避免未知态带来的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:05:05