I've implemented a (working) ripple-carry adder using generation to create 16 different full_adder
instances (the full_adder
works as intended):
module ripple_adder16 (a, b, cin, sum, cout);
input [15:0] a, b; input cin;
output [15:0] sum; output cout;
wire [15:0] a, b; wire [15:0] sum; wire cout;
// intermediate nets.
// Since the carries cascade, we have to tell
// verilator that it can't "flatten" or whatever.
/* verilator lint_off UNOPTFLAT */
wire [16:0] carries;
/* verilator lint_on UNOPTFLAT */
assign carries[0] = cin;
assign cout = carries[16]; // output.
genvar i;
generate for(i=0; i < 16; i = i + 1)
begin
full_adder adder (
.a(a[i]),
.b(b[i]),
.sum(sum[i]),
.cin(carries[i]),
.cout(carries[i+1])
);
end
endgenerate
endmodule
Now I'm trying to modify the adder so that I can keep an array of adders. Below is an example of the code I'm trying to get working:
input [15:0] a, b; input cin;
output [15:0] sum; output cout;
wire [15:0] a, b; wire [15:0] sum; wire cout;
full_adder adders [15:0] (
.a(a),
.b(b),
.cin(),
.sum(sum), // output.
.cout()
);
// DIFFERENCES START HERE
assign adders[0].cin = cin;
assign cout = adders[15].cout; // output.
genvar i;
generate
for(i=0; i < 15; i = i + 1)
assign adders[i+1].cin = adders[i].cout;
endgenerate
// DIFFERENCES END HERE
endmodule
However, I get a ASSIGNIN error from Verilator (documentation says "Error that an assignment is being made to an input signal. This is almost certainly a mistake, though technically legal.") on the lines assign adders[0].cin = cin;
and assign adders[i+1].cin = adders[i].cout;
. I have two questions:
ripple_adder16
module.assign adders[15:1].cin = adders[14:0].cout;
, though this is a syntax error by itself. Is there any way to do something like this without straight-up inlining the full_adder
?Thank you!
PS. If it's relevant, the full_adder
is implemented entirely with wires.
Array of instances in verilog is a type of a generate
block and instantiates a module several times, adding array index to its name and doing some job with ports. Array of instances are usually not well understood and seldom used in behavioral verilog.
Since it is a generate block, you cannot use ranges on array instances. 'adders[15:1]' is illegal. You need to use a generate loop to access them instance by instance. Also 'assign adders[15:1].cin' represents a connection to an internal signal of the submodule instance, not to its input port. So, the compiler is absolutely correct.
You left unconnected ports of the module instances and trying to access their internal signals. It is a bad practice in the first place. To fix it you should figure out how to use port connections instead. An extra code will be needed to reassign vector to satisfy your algorithm, at least around 'carries'.