此代码的意外行为,发生了什么?
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]));
这样两个部分在功能上是相同的。
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]));
这样两个部分在功能上是相同的。