Parameterization
Modules, Structs, Unions, and Interfaces can all be parameterized. To do so, include a parameter list after the name in its declaration:
// This module has a single parameter "width", which is a natural number
module MyAdder(width: Nat) {
input a: Int(width),
input b: Int(width),
output out: Int(width),
} {
assign out = a + b;
}
// This struct has a logic type parameter "t"
struct MyStruct(t: LogicType) {
a: t,
b: t,
}
Then, pass a value for each parameter when instantiating it:
mod adder = MyAdder(32);
// adder.a, .b, and .out are all Int(32)
logic my_struct: MyStruct(Bits(64));
// my_struct.a and .b are both Bits(64)
[Once if, for, etc... are supported that will be documented here]
Using parameterized modules and types may look like function calls, and that's because they are. You can learn more about that in the language reference. Since Neo parameters are more flexible than SystemVerilog, parameterized modules will apply their parameters upon instantiation and generate a static SystemVerilog module. Type parameterization is also applied at generation time, though this is less apparent as the types themselves don't translate into SystemVerilog and are instead converted into simple wires.