我想测试一个简单的 Verilog 模块,如果在 3 变量输入中找到最小项
1
、2
、3
或 5
,则输出 7
。
模块如下所示:
module modified_prime_detector(
input [2:0] in,
input clk,
output reg out
);
always @ (posedge clk)
begin
out <= (~in[2] && in[1] && ~in[0]) || (~in[2] && in[1] && in[0]) || (in[2] && ~in[1] && in[0]) || (in[2] && in[1] && in[0]);
end
endmodule
我还开发了一个测试平台,以便使用 EDA Playground 运行我的模拟:
module modified_prime_detector_tb();
reg [2:0] in;
reg clk;
wire out;
modified_prime_detector uut (
.clk(clk),
.in(in),
.out(out)
);
always #5 clk = ~clk;
always @(posedge clk) begin
if (in == 3'b111)
in <= 3'b000;
else
in <= in + 1'b1;
end
always @ (posedge clk) begin
$display("Time: %t, in: %b, out: %b", $time, in, out);
end
initial begin
$dumpfile("dump.vcd");
$dumpvars(1, modified_prime_detector_tb);
clk = 0;
in = 0;
#5;
#100;
$finish;
end
endmodule
基本上,我在每个时钟周期增加
in
的 3 位值。然后,我希望看到 out
的值设置为 1
,其值包括:010
、011
、101
和 111
。
但是,我看到模块针对以下值输出
1
:011
、100
、110
和 000
?我不知道为什么会这样。我认为这可能与模拟有关,因为波形是这样的:
输出似乎“右移”了一位,而且我的模块似乎没有为输入提供输出
000
。不幸的是,我不确定为什么会发生这种情况以及如何进一步调查这个问题。
可能是什么问题?
输出没有问题,它是正确的,但你的直觉是错误的。在您的模块中,您正在使用非阻塞语句
<=
,这是非阻塞语句的标准行为,即输出在一个时钟周期后发生。这与为什么在 000
条件下看不到输出的原因相同,因为输出将在一个周期后到达。
如果您希望输出在输入到达时发生,那么您应该使用组合逻辑,将敏感度列表中的
posedge clk
替换为 in
并使用 =
。
always @ (in) begin
out = (~in[2] && in[1] && ~in[0]) || (~in[2] && in[1] && in[0]) || (in[2] && ~in[1] && in[0]) || (in[2] && in[1] && in[0]);
end
现在如果你这样做,你的逻辑就不再依赖于时钟。其次,我注意到您的输入是 3 位,并且在测试台中您正在检查是否为
in == 3'b111
,然后将其重置为 in <= 3'b000
,但无需检查这一点。因为如果你在 3'b111 中添加 1
,它就会自动变成 '0'。所以你可以简单地在你的测试台上写下这个:
always @(posedge clk) begin
in <= in + 1'b1;
end