全加器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面板显示:
| NAME | Value |
|---|---|
| A | 1 |
| B | 1 |
| INCARRY | 0 |
| SUM | 1 |
| CARRY | 0 |
仿真输出日志:
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
相关产品推荐
相关产品推荐

