module And(a,b);
input [31:0]a;
output reg b;
integer i;
initial assign b=a[0];
initial begin
for(i=1;i<=31;i=i+1) begin
assign b=b&a[i];
end
end
endmodule
module tb;
wire b;
reg [31:0]a;
And gate(.a(a),.b(b));
initial begin
$monitor(" a=%b b=%b",a,b);
a=32'd757038;#10 a=32'b11111111111111111111111111111111;
end
endmodule
The error was as shown:
[2023年07月31日 13:25:14 UTC] iverilog '-Wall' design.sv testbench.sv && unbuffer vvp a.out
a=00000000000010111000110100101110 b=x
a=11111111111111111111111111111111 b=x
Done
1 Answer 1
The issue is that you are trying to assign multiple signals to the same variable.
You have an assign b = a[0]
, which performs continuous assignment (basically connects the two signals together. Fine. However you then have a loop which then assigns b
to a[1]
, also to a[2]
, also to ... and so on. As a result b
is being driven by multiple sources and so you get x
indicating contention - there is no way of knowing what value b
should take.
From what I can gather, you are trying to perform the "Unary Reduction AND" function - basically AND all of the bits in the input signal together to get the output signal. In which case there is an operator for that:
module And(a,b);
input [31:0] a;
output b;
assign b = &a;
endmodule
The unary &
operator performs the AND operation across all bits in the input resulting in a single output bit which is high only when all inputs are high.
If you are set on using a loop to do this, you should not be using initial
or assign
. Instead you should use the blocking assignment operator =
in an always
block.
always @ * begin
b = a[0];
for (i = 1; i < 32; i = i + 1) begin
b = b & a[i];
end
end
This doesn't drive b
with multiple signals. Instead it will assign to an internal version of b
, which then be reassigned during each pass of the loop using the temperary b
value it calculated on the pass before. Eventually once the loop is over the resulting value will be assigned back to the real b
. This loop will resolve to simply a large chain of AND gates performing unary reduction.
-
\$\begingroup\$ I should perhaps ask this as a separate question. My apologies for taking a short-cut here. Do you know, off-hand, if existing synthesis and logic equivalence tools, seeing these two different approaches to the same goal, and given the same target FPGA architecture and overall context would then yield identical implementations? My experience is decades old and, back then, I could not count on anything much at all. Very likely I'd get two completely different results. I found myself having to code towards results I desired and forced to manual floorplanning, to boot. Been out of it too long. +1 \$\endgroup\$periblepsis– periblepsis2023年08月01日 07:05:45 +00:00Commented Aug 1, 2023 at 7:05
-
1\$\begingroup\$ @periblepsis In all likelihood both implementations (loop vs unary op) will result in exactly the same hardware on an FPGA. Both are combination circuits taking a 32 bit input and giving a 1 bit output, as such they will both end up being nothing more than a single 32-input LUT. This LUT will be made using a tree of smaller 4/5/6-in LUT primitves from the FPGA (whichever size is supported). \$\endgroup\$Tom Carpenter– Tom Carpenter2023年08月01日 15:56:05 +00:00Commented Aug 1, 2023 at 15:56