官方答案:
module top_module (
input [254:0] in,
output reg [7:0] out
);
always @(*) begin // Combinational always block
out = 0;
for (int i=0;i<255;i++)
out = out + in[i];
end
endmodule
我的正确答案:
module top_module(
input [254:0] in,
output [7:0] out );
reg [7:0] i,j;
always//@(in)
begin
//j <= 0;
for (i=0;i<=254;i=i+1)
begin
if (i==0) j=0;
if(in[i]==1) j = j+1;
else j = j+0;
end
out = j;
end
//assign out= j;
endmodule
遇到的错误:
module top_module(
input [254:0] in,
output [7:0] out );
reg [7:0] i,j;
always//@(in)
begin
//j <= 0;
for (i=0;i<=254;i=i+1)
begin
if (i==0) j<=0;
if(in[i]==1) j <= j+1;
else j <= j;
end
out <= j;
end
//assign out= j;
endmodule
在for循环中使用非阻塞赋值时,发现out并没有被赋值。
但整段代码和前面我的正确答案只差for循环中的阻塞与非阻塞赋值,因此猜测时always中非阻塞赋值的特性决定了,所有非阻塞的算式右边的值时等到always结束后赋值给左边的,而对于for循环中自加的过程,j最终会被赋予等于循环数个值(比如此例中256个值在always执行完毕后被赋给j),这种同时给j赋予多个不同的值的过程导致了错误,因此j最终值不确定。
而对于阻塞赋值,等号右边的值立马被赋给左边,因此不会导致问题,每一次循环后j的值都会更新,而不是最终一次更新。
但并不代表for循环中不能用非阻塞赋值,猜测只是这种涉及在for循环中多次更新变量值的运算需要小心。当然另一个更重要的是,用(*)的时候就是组合逻辑 严格是要用阻塞赋值,虽然用非阻塞赋值也可以进行仿真 但是在一定条件下 会有赋值错误的bug(群友原话)。
不过我猜测在时序逻辑中应该也不能在for循环中写非阻塞,毕竟能预料到也会出现赋多个值的问题。
顺便补充一下,always(*)和always直接写(无括号内的敏感条件)的本质区别在于,后者是不可综合的。
这是我遇到阻塞与非阻塞赋值差异最大的一次,主要是由于对硬件理解不够。