SystemVerilog: Passing Array as parameters

This is a simple post related to passing an array of parameters to module, class or interface, in SystemVerilog.

A parameter is a constant value declared within the module, class or interface. The value of parameter can be used to define a set of attributes for the entity which can alter its behavior as well as its physical representation.

Parameters contains a default value, which can be overridden at the time of instantiation, to alter the behavior of a particular instance. So, we can say parameters are used for generalization of any entity.

Passing a fixed sized array as parameter is pretty much simple. Just provide entire array in curly braces from the instantiating entity. Like following code, will display '{'h4,'h5}

module to_be_instantiated #(parameter int p1[2] = {1,2}) ();
//...
initial
begin
//...
$display("p1 = %p",p1);
end
//...
endmodule

module top();
to_be_instantiated #(.p1({4,5})) mk ();
endmodule

Now, lets introduce a little generalization. The datatype of parameter p1 is int, lets make it generalized by introducing a type parameter.

module to_be_instantiated #(parameter type T=int,T p1[2] = {1,2}) ();
//...
initial
begin
//...
$display("p1 = %0s : %p",$typename(p1[0]),p1);
end
//...
endmodule

module top();
to_be_instantiated #(.T(int),.p1({4,5})) mk ();
endmodule

Now, parameter is somewhat more generalized, the output will be as follows. Note that the $typename system function returns a string that represents the resolved type of its argument. More information on $typename can be found out at SystemVerilog IEEE 1800-2012 Section 20.6.

p1 = int : '{4, 5}

Again, the size of parameter is still fixed. If we want to instantiate a module with variable depth of parameters, then it is still not possible. Intuitively, now we must pass a SIZE parameter which defines size of parameter p1. Lets do that.

module to_be_instantiated #(parameter type T=int,int SIZE=2, T p1[SIZE] = {1,2}) ();
//...
initial
begin
//...
$display("p1 = %m : %0s : %p",$typename(p1[0]),p1);
end
//...
endmodule

module top();
to_be_instantiated #(.T(int),.SIZE(2),.p1({4,5})) mk1 ();
to_be_instantiated #(.T(int),.SIZE(4),.p1({6,7,8,9})) mk2 ();
endmodule

Here, %m displays full hierarchical path of the module. This outputs as follows:


p1 = top.mk1 : int : '{4, 5}
p1 = top.mk2 : int : '{6, 7, 8, 9}

Finally, we can have fully parameterized input arguments depending on parameter size and widths.


module to_be_instantiated #(parameter type T=int,int SIZE=2, int WIDTH=$clog2(SIZE), T p1[SIZE] = '{1,2}) (input [(WIDTH-1) : 0] my_inp, input [(SIZE-1) : 0] my_inp2);
//...
initial
begin
//...
$display("p1 = %m : %0s : %p",$typename(p1[0]),p1);
$display("Input size : %0d",$size(my_inp));
$display("Input2 size : %0d",$size(my_inp2));
end
//...
endmodule

module top();
to_be_instantiated #(.T(int),.SIZE(2),.p1('{4,5})) mk1 (/*...*/);
to_be_instantiated #(.T(int),.SIZE(4),.p1('{6,7,8,9})) mk2 (/*...*/);
endmodule

The output will be as follows. Note the input sizes of both the instances.

p1 = top.mk1 : int : '{4, 5}
Input size : 1
Input2 size : 2
p1 = top.mk2 : int : '{6, 7, 8, 9}
Input size : 2
Input2 size : 4

So, we have seen how parameters can be used to fully customize a module. The same applies to class and interfaces as well.

Regarding synthesis, most of the synthesizers might not support dynamically sized array, and I wonder why it is so… 😉

-Sharvil

profile for sharvil111 at Stack Overflow, Q&A for professional and enthusiast programmers

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: