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

全加器Testbench仿真失败求助:Vivado硬件正常仿真报错

FPGA全加器Testbench仿真异常问题排查

刚接触FPGA开发,自行设计全加器并编写Testbench时遇到仿真异常:在Vivado 2022.2中运行仿真,首次出现A和B同时为高电平的情况时触发失败,但生成比特流后在Basys3板卡上运行正常。

全加器代码

module full_adder(
  input wire A,
  input wire B,
  input wire INCARRY,
  output logic CARRY,
  output logic SUM
    );
    
    // Full Adder circuit - 3 inputs enter, only 2 outputs leave !
    // So.. the carry is set if two or more inputs are set
    wire logic ab;
    wire logic bc;
    wire logic ac;
    assign ab = A && B;
    assign bc = B && INCARRY;
    assign ac = A && INCARRY;
    assign CARRY = (ab || ac) || bc;
    
    // And the sum is set if either 1 or all 3 inputs are set
    wire logic one_input;
    assign one_input = A ^ B;
    assign SUM = one_input ^ INCARRY;
    
endmodule

Testbench代码

module testbench;
  // The inputs and outputs we care about for testing..
  logic A;
  logic B;
  logic INCARRY;
  logic SUM;
  logic CARRY;
  
  // import the actual logic..
  full_adder u_full_adder (.*);
  
  // Stimulus
  initial begin
    $printtimescale(testbench);
    A = '0;
    B = '0;
    INCARRY = '0;
   
    // And loop through our possible input states..
    for (int i = 0; i < 8; i++) begin
      $display("Setting inputs to A=%1b, B=%1b, INCARRY=%1b", i[0], i[1], i[2]);
      A = i[0];
      B = i[1];
      INCARRY = i[2];
      // and sleep a bit..
      #100;
    end // end of i loop
    $display("PASS: full adder is working");
    $stop;
  end
  
  
  // and the checking logic..
  always @(A, B, INCARRY, CARRY, SUM) begin
  
    // Check that the carry is set when 2 or more inputs are high
    if ((1 < A + B + INCARRY) && CARRY !== 1) begin
      $display("FAIL: Not carrying appropriately");
      $stop;
    end
  
  end // end of always 
endmodule

仿真异常现象

当输入A=1、B=1、INCARRY=0时,Objects面板显示:

NAMEValue
A1
B1
INCARRY0
SUM1
CARRY0

仿真输出日志:

Timescale of (testbench) is 1ns/10ps.
Setting inputs to A=0, B=0, INCARRY=0
Setting inputs to A=1, B=0, INCARRY=0
Setting inputs to A=0, B=1, INCARRY=0
Setting inputs to A=1, B=1, INCARRY=0
FAIL: Not carrying appropriately
$stop called at time : 300 ns : File "whatever.sv"

问题根源

核心是仿真事件队列的执行顺序:当输入A、B同时更新为1时,敏感列表@(A, B, INCARRY, CARRY, SUM)会立即触发检查always块,此时全加器的组合逻辑输出CARRY还未完成更新(组合逻辑的assign语句属于仿真事件队列的后续执行步骤),导致检查时CARRY仍为旧值0,触发误判。

板卡运行正常是因为硬件中组合逻辑的延迟远小于可观测时间,且实际运行时没有这种“同一时刻触发检查”的逻辑。

解决方案

方法1:延迟检查时机

在检查逻辑中加入微小延迟,等待组合逻辑稳定后再判断:

always @(A, B, INCARRY, CARRY, SUM) begin
  #1; // 等待组合逻辑更新完成
  if ((1 < A + B + INCARRY) && CARRY !== 1) begin
    $display("FAIL: Not carrying appropriately");
    $stop;
  end
end

方法2:将检查逻辑移至激励块

在每次设置输入并等待后执行检查,避免敏感列表的即时触发:

// Stimulus
initial begin
  $printtimescale(testbench);
  A = '0;
  B = '0;
  INCARRY = '0;
 
  // And loop through our possible input states..
  for (int i = 0; i < 8; i++) begin
    $display("Setting inputs to A=%1b, B=%1b, INCARRY=%1b", i[0], i[1], i[2]);
    A = i[0];
    B = i[1];
    INCARRY = i[2];
    #100;
    // 输入稳定后执行检查
    if ((1 < A + B + INCARRY) && CARRY !== 1) begin
      $display("FAIL: Not carrying appropriately at A=%1b,B=%1b,INCARRY=%1b",A,B,INCARRY);
      $stop;
    end
  end // end of i loop
  $display("PASS: full adder is working");
  $stop;
end

编写可靠Testbench的建议

  • 避免在输入变化的同一时刻检查组合逻辑输出,务必等待组合逻辑稳定;
  • 优先在激励块中按时序执行检查,逻辑更清晰易维护;
  • 覆盖所有输入组合(如全加器的8种情况),确保测试全面;
  • 仿真时添加波形查看,确认信号时序变化,辅助排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:24:58