首页 > 解决方案 > RTL if 语句与模拟不匹配

问题描述

我很难理解为什么输出会在 0 和 1 之间闪烁,因为 000 的归约或门是 0 而不是 1,所以输出应该始终保持为 0。

当我尝试不同的位宽时,问题突然消失了。但是,我想知道发生了什么,而不是依赖随机性来确保正确性。

项目测试.sv

`timescale 1ns/1ns

module project_test 
( input logic clk, rst, 
    input logic in,
    output logic [2:0] c
);

logic [2:0] out;


always@(posedge clk or posedge rst) begin
    if(rst) 
        out <= 'b0;
    else if(in) begin
        if(|out)
            out <= 'b0;
    end
    else
        out <= out + 1'b1;
end

assign c = out;

endmodule: project_test

测试台.sv

`timescale 1ns/1ns
module testbench;
 logic clk, rst;
 logic in;
 logic [2:0] c;

project_test project_test(
.clk(clk),
.rst(rst),
.in(in),
.c(c)
);

initial begin
clk = 0;
rst = 1;
in = 0  ;
#30
rst = 0;
#20;
in = 1;
#500;
rst=1;
#100ns;
$stop();
end

always@(clk) begin
  #10ns clk <= !clk;
end

endmodule

模拟输出: 在此处输入图像描述

RTL 查看器: 在此处输入图像描述

标签: verilogsystem-verilog

解决方案


这是在测试台中生成时钟信号的不正确方法。您不应该clk在灵敏度列表中包含该信号,因为它会不断重新触发该always模块。您的时钟生成器可能会将事件添加到 Verilog 事件队列,这可能会导致奇怪的行为。事实上,当我在 Cadence 模拟器上运行您的代码时,我根本没有看到时钟切换。

这是生成时钟的更标准方法:

always begin
    #10ns clk = !clk;
end

推荐阅读