此代码的意外行为,发生了什么?

Unexpected behaviour on this code, what is going on?

module myModule (CLK, A);

input CLK;
output reg [3:0] A = 4'b0000;


reg Sin = 0;

always @(posedge CLK)
begin

//Sin <= ((~A[2]&~A[1]&~A[0])|(A[2]&A[1]));
//A[0] <= A[1];
//A[1] <= A[2];
//A[2] <= A[3];
//A[3] <= Sin;

A <= {(~A[2]&~A[1]&~A[0])|(A[2]&A[1]), A[3], A[2], A[1]};

end


endmodule

当我评论 A <= {(~A[2]&~A[1]&~A[0])|(A[2]&A[1]), A[3], A[2], A[1]}; 并取消注释评论的部分时,即替换它们,我无法再进行相同的工作了。

module myModule (CLK, A);

input CLK;
output reg [3:0] A = 4'b0000;


reg Sin = 0;

always @(posedge CLK)
begin

Sin <= ((~A[2]&~A[1]&~A[0])|(A[2]&A[1]));
A[0] <= A[1];
A[1] <= A[2];
A[2] <= A[3];
A[3] <= Sin;

//A <= {(~A[2]&~A[1]&~A[0])|(A[2]&A[1]), A[3], A[2], A[1]};

end


endmodule

这两行代码在功能上有区别吗?他们似乎和我一样。

A <= {(~A[2]&~A[1]&~A[0])|(A[2]&A[1]), A[3], A[2], A[1]}; 正确,而另一个不正确。

谢谢。

它们是不同的,因为 Sin 是该表达式的注册版本(延迟一个周期)。

您可以对 Sin 使用连续赋值以获得相同的行为:

module myModule (CLK, A);

input CLK;
output reg [3:0] A = 4'b0000;

wire Sin = (~A[2]&~A[1]&~A[0])|(A[2]&A[1]);

always @(posedge CLK)
begin
    A <= { Sin, A[3], A[2], A[1] };
end

endmodule

您的情况略有不同,这使得两个部分的行为有所不同。 Sin <= ((~A[2]&~A[1]&~A[0])|(A[2]&A[1])); 中的非阻塞赋值将延迟其执行直到模拟节拍结束。

因此,A[3] <= Sin;直到结束时钟沿才会被分配。此行为将与合成行为不匹配。

为了修复它,您需要对 Sin.

使用阻塞赋值
Sin = ((~A[2]&~A[1]&~A[0])|(A[2]&A[1]));

这样两个部分在功能上是相同的。