You've got the order wrong. When using module-instance parameter value assignment (the rather wordy terminology for this method), the syntax is:
module-name #(parameter-assignment) instance-name (module-terminal-list) ;
where the parameter assignment can be by name or by the order of the values. You're already familiar with the module terminal list, so I'll just give the parameter BNF:
parameter-assignment ::= (values-by-name / values-by-order)
values-by-name ::= .parameter-name(parameter-value)*[, parameter-name(parameter-value)]
values-by-order ::= parameter-value*[, parameter-value]
So your example should be one of the following:
add #(.wd(8)) len_plus_1(.a(len),.b(8'h1),.o(lenPlus1));
add #(8) len_plus_1(.a(len),.b(8'h1),.o(lenPlus1));
The former (named) version is preferred, because it maintains its behavior if you add another parameter.
The following example gives additional options (this is adapted from Figure 9-4 in Verilog HDL: A Guide to Digital Design and Synthesis by Palnitkar)
module bus_master;
// Note: These could also be ANSI C-style parameter declarations with
// module bus_master (#parameter delay1 = 2, delay2 = 3, delay3 = 7);
parameter delay1 = 2;
parameter delay2 = 3;
parameter delay3 = 7;
...
<module internals>
...
endmodule
module top;
// Assignment by name:
bus_master #(.delay2(4), delay3(8)) b1();
//delay1 = 2 (default), delay2 = 4, delay3 = 8
bus_master #(.delay1(1), delay3(6)) b2();
//delay1 = 1, delay2 = 3 (default), delay3 = 6
// Assignment by order:
bus_master #(7, 8, 9) b3();
//delay1 = 7, delay2 = 8, delay3 = 9
bus_master #(1, 3, 5) b4();
//delay1 = 1, delay2 = 3 (default, but by assignment), delay3 = 5
bus_master #(1, 5) b5();
//delay1 = 1, delay2 = 5, delay3 = 7 (default)
endmodule
There is also another method which uses the defparam
keyword to define the values before instantiation like this:
module top;
defparam b6.delay1 = 1;
bus_master b6();
//delay1 = 1, delay2 = 3 (default), delay3 = 7 (default)
endmodule;
but that's considered poor style (though personally, I'd prefer it to the values-by-order syntax).
If I understood your question correctly, I think the following module does what you want. You can very simply specify the gate by its operator (^
,&
,|
, etc) and nothing else. Plus only the desired assignments are generated (which is I think what you are looking for).
`timescale 1 ns / 1 ps
module selectable_gate(input [7:0] in, output out);
parameter [7:0] SELECT = 8'b10010100;
function integer count_ones;
input [7:0] v;
integer ret;
integer i;
begin
ret = 0;
for(i=0;i<8;i=i+1) begin
if (v[i]) begin
ret = ret+1;
end
end
count_ones = ret;
end
endfunction
function integer nth_one;
input integer n;
input [7:0] v;
integer i,ret,cnt;
begin
ret = -1;
cnt = 0;
for(i=0;i<8;i=i+1) begin
if (v[i]) begin
if (cnt == n) begin
ret = i;
end
cnt = cnt+1;
end
end
nth_one = ret;
end
endfunction
localparam integer w = count_ones(SELECT);
wire [w-1:0] y;
generate
genvar i;
for(i=0 ; i<w ; i=i+1) begin
assign y[i] = in[nth_one(i,SELECT)];
end
endgenerate
assign out = ^y; // specify gate here (e.g. ^y, &y, |y, etc)
endmodule;
The above module for the default SELECT = 8'b10010100
should end up generated as:
assign y[0] = in[2];
assign y[1] = in[4];
assign y[2] = in[7];
assign out = ^y;
Which is the same as xor(in[2],in[4],in[7])
.
Since genvars are always unrolled as constants inside the generates, the trick was to find constants that allow the proper conditions for the generate, and use functions for any temporary variable manipulation necessary to calculate them.
Best Answer
There's usually no need to do this in Verilog. (You must be coming from VHDL) Numeric literals get implicitly padded with 0's or truncated to fit into the assignment LHS variable. This also happens when used in most expressions.
There are a few exceptions that require the exact size, like in the middle of a concatenation. For that you can use a bitwise OR.
SystemVerilog has a bit-sizing cast that makes this a little simpler