Necessity of parameter |
We will directly present an example of a simple adder to understand the necessity of
parameter
|
There is nothing fancy about the code above. It is not meant to be real life adder and it does not has carry in or the carry out. However, it explains the concept of the parameter. By changing the line
parameter N = 4;
to
parameter N = 8;
We can chage the 4 bit adder to an 8 bit adder. This provides a huge benefit where we do not have to make changes at several places. This enhances the code reusability. Just by changing
one line of code you are able to change and reuse the design.
We will now write an actual full adder, one with parameter.
|
We may change width of adder to 2, 4 or 8 or anything we wish, just by changing the line that says
parameter N = 4
.
One thing we may wish to note is that, it is not clear which MSB the carry correspond to. So we introduce an intermediate variable
that we call tempsum.
Let is take a look at the following code.
|
Finally we get the carry out from the MSB bit of the tempsum.
Parameter and Module instantiation
Changing the one line of code to change the parameter value is not the only benefit of parameter. Another benefit could be instantiating a module, and while doing so, we can change the value of the parameter.
So we can create two instantiation of the a module each with different value of parameter. That is one big advantage of using parameter. Before we do that, let us take a look at the test bench of the above adder, that instantiate the full adder in the test bench
|
Notice the instantiation of the full adder
|
Immediately after the name of the module being istantiated we can pass the parameter, that can change the value of the parameter. So if we had written
fulladder #(8)
, we would have been instantiating an 8 bit adder. Although, the test bench may not be very good place to do it in real life.
In the above test bench, since we did not want to change the parameter we could have written
|
in place of
|
If we would have liked to check the adder only for two bit width, we could have changed the test bench code as follows
|
Of course, we will also limit the input values between 0 to 2 in that case.
To recap :
Paramter is a constant that can be defined inside a module. The constant is local to the module. However, when we create an instance of the module , the value of the parameter can be changed in the instance. Also, we may have multiple instances of the module, each with different value of the parameter.
Let us consider the adder example once again
|
In this example, we can create two instances of fulladder as follows
|
The first instance has a width of 4 and the second instance has a width of 8. If we do not specify the parameter in instantiation, its value stays unchanged as in
|
which is same as
|
If we have multiple parameters, and if we need to change the value of one of the parameters, we will have to list all the parameters in the order of their appearance. Consider the following example
|
Verilog requires that if you wish to change, say third parameter in instantiation,then you must list 1st to 3rd parameter WITH values, even if their values did not change.
If you wish to change only the second parameter, then you must list 1st and secod parameters with their values.
Engineers have used a trick, where, they list the frequently used parameter as the first parameter, so they do not have to list other parameters.
The rule is - "all parameter values up to and including all values that are changed, must be listed in the instantiation"
So if we wish to change the parameter N in the above example in its instantiation, we should do it like
|
Though following is also correct.
|
You can not omit the values of the first two - so following will be incorrect
|
Can we not pass the parameters by name instead ? Well not is Verilog 1995. But this capability was added in Verilog 2001 and you can now use instantiation like
|
This makes life simpler - does it not ?
Another enhancement in Verilog 2001 is the addition of localparam. With localparam, you do not allow it to be changed directly with instantiation.
However, localparam can be expressed in terms of parameter and when the value of the parameter changes on intantiation, the localparam changes.
The example below shows the usage of localparam
|