Parameterized Macro Definition
What is a macro ?
A macro is a literal name used in a program that is substituted by some
value before the program is compiled. Macros are useful as an alias
without using program resources. They are not variables, so you can not
assign a value to a macro from within a program. Almost all modern languages,
including Verilog, support macro definition.
Macros in Verilog
Macros in Verilog are specified by using `define compiler
directive. Here is an example:
`define MY_DELAY 2
...
r1 = #`MY_DELAY 1'b1;
What is Parameterized Macro Definition ?
Parameterized macro definition (PMD) is something new in Verilog LRM2.0,
although it has been there in other languages like C from the beginning.
In a PMD, the definition of a macro contains zero or more parameters. An
example of a PMD is shown below.
`define MAX(p,q) (p)>(q)?(p):(q)
...
r1 = #`MAX(setup_delay, rise_delay) 1'b1;
After preprocessing, the actual program that is passed to the compiler
looks like:
r1 = #((setup_delay)>(rise_delay)?(setup_delay):(rise_delay))
1'b1;
Note that the substitutions are literal. And, in the macro definition each
term must be parenthesized.
My simulator does not support Parameterized Macro Definition.
What can I do?
First off, do not worry. You are not alone. Most of the simulators do
not support this. The sole purpose of this page is to provide you with
a freeware which converts this new construct
to one which a regular simulator can understand.
I wrote this preprocessor program as a part of a global conversion program
between LRM2.0 to LRM1.0. This was presented in International Verilog Conference
(IVC) in 1996. However, this program is a stripped off version of the main
program without error checking etc.While the original program was written
in C, to make it easier to install, I have used standard UNIX/C utility
programs, such as nawk and m4. Install GNU gawk and m4 if you do not have
these utilities.
How to download ?
Here is the all important file. This is a shell script. Save it as pmd.csh
(or any other name) in a separate directory.
nawk ' \
#---------------------------
# Detect multiline comments
#---------------------------
/\/\*/ { ml_comment = 1 }
/\*\// { ml_comment = 0 }
#------------------------------
# Create a new verilog file
# without the macro definition
# and an m4 definition file
#------------------------------
{
if (($1 == "`define")
&& (ml_comment == 0) && (match($2,"[(]"))) {
# find out the macro name
paren_start = match($2, "[(]")
macro_name = substr($2, 1, paren_start-1)
# argument list
arg_list = substr($2, paren_start+1, length($2)-1-paren_start)
# remove white spaces from the argument list
gsub("\t","", arg_list)
gsub(" ","", arg_list)
# store all the parameters in an array
n_arg = split(arg_list, arg_array, ",")
# now print the m4 definition
printf "define("macro_name"," > "_m4"
#find out the position of $3
start_defn = index($0, $3)
defn = substr($0, start_defn, length($0)-1-paren_start)
for (i=1; i<=n_arg; i++) {
initial_val = "\("arg_array[i]"\)"
final_val = "\$"i
gsub(initial_val, final_val, defn)
}
print defn")" > "_m4"
macro_name_array[j++] = macro_name;
}
else {
for (k=0;k<j;k++) gsub("\`"macro_name_array[k],macro_name_array[k])
print $0
}
}' $1 > _v
m4 _m4 _v
|
How to run it ?
%pmd.csh test1.v
There are two temporary files created by the program. They are called
_m4
and _v. So do not use these two file names. The output appears on
the standard output.
The program can easily be modified to have more than one Verilog file
in the command line:
%pmd test1.v test2.v ...
Example
Here is a sample Verilog program that uses PMD.
/* This is an example of parameterized macro definition.
This file goes to the input of the preprocesor.
*/
`define MIN(a,b) (a)<(b)?(a):(b)
`define SQR(m) (m)*(m)
module myModule ;
integer s, s1, s2, bo ;
initial begin
s1 = 1 ;
s2 = 2 ;
s = `MIN(s2,s1) ; // This is a comment
bo = `SQR(s2);
s = `MIN(s2,s1) + SQR(s2);
s = `SQR(`MIN(s2,s1)) ;
end
endmodule
Here is the output of the preprocessor:
/* This is an example of parameterized macro definition.
This file goes to the input of the preprocesor.
*/
module myModule ;
integer s, s1, s2, bo ;
initial begin
s1 = 1 ;
s2 = 2 ;
s = (s2)<(s1)?(s2):(s1) ; // This
is a comment
bo = (s2)*(s2);
s = (s2)<(s1)?(s2):(s1) + (s2)*(s2);
s = ((s2)<(s1)?(s2):(s1))*((s2)<(s1)?(s2):(s1))
;
end
endmodule
Note that the PMD definitions do not appear in the output.
|