In Verilog, a `define
macro is a powerful feature that allows for global text substitution in your code. It is a compiler directive that enables developers to define reusable code snippets or constants that can be easily referenced throughout the design.
`define WIDTH 16 // Define macro WIDTH, substitute 16
`define EN_ADDR // Define macro EN_ADDR, substitute nothing
wire [`WIDTH-1:0] addr; // Declares a 16-bit wire
`ifdef EN_ADDR // Instantiate an adder if EN_ADDR macro is defined
genvar i;
generate
// Code to instantiate an adder
endgenerate
`endif
Read more on Verilog `define Macros !
`define without default arguments
When using formal arguments in a macro, enclose the list of argument names in parentheses directly after the macro name. Each argument name should be a simple identifier, separated by commas and optional whitespace. White space is allowed between the text macro name and the left parenthesis in the macro usage.
`define ADD(name, a, b) $display("%s a=%0d b=%0d sum=%0d", name, a, b, a + b);
module tb;
bit [3:0] a;
bit [3:0] b;
initial begin
std::randomize(a, b);
// The macro below will be replaced by the display statement
// Remember ! `define is not a function, it is text substitution
// before compilation
`ADD("", a, b)
// ERROR ! Hierarchical name component lookup failed for 'ADDR' at 'tb'
// First argument in the display statement requires it to be a string
// `ADD(ADDR, a, b)
// Text substitute a with 3 and b with 4
`ADD("ADDER", 3, 4)
// Notice the extra space in the first argument
`ADD(" INST ", 3, 4)
// ERROR ! Macro is missing trailing arguments that have no default values
// 'b' does not have a default argument and none is passed during macro call
//`ADD(3, )
// ERROR ! Macro is missing trailing arguments that have no default values (1 instead of 3)
// `ADD(5)
// ERROR ! Too many actual macro arguments (4 instead of 3)
//`ADD("STH", 4, 5, 6)
// Whitespace between `ADD and (
`ADD ("SPACE", 1, 1)
end
endmodule
xcelium> run a=6 b=7 sum=13 ADDER a=3 b=4 sum=7 INST a=3 b=4 sum=7 SPACE a=1 b=1 sum=2 xmsim: *W,RNQUIE: Simulation is complete.
`define with default arguments
If fewer actual arguments are provided than the number of formal arguments, and all remaining formal arguments have default values, those defaults will be used in place of the missing arguments.
`define ADD(name="INST", a=5, b) $display("%s a=%0d b=%0d sum=%0d", name, a, b, a + b);
module tb;
initial begin
// Text substitute a with 3 and b with 4
`ADD("ADDER", 3, 4)
// 'b' does not have a default argument and none is passed during macro call
`ADD( , 3, 1)
// First argument
`ADD(, , 5)
// Whitespace between `ADD and (
`ADD ("SPACE", 1, 2)
end
endmodule
xcelium> run ADDER a=3 b=4 sum=7 INST a=3 b=1 sum=4 INST a=5 b=5 sum=10 SPACE a=1 b=2 sum=3 xmsim: *W,RNQUIE: Simulation is complete.
SystemVerilog enhances Verilog’s `define
text substitution macro by permitting the inclusion of certain special characters in the macro text.
In Verilog, quotation marks (") can be used in a define macro, but the text within the quotation marks is treated as a literal string.
`define show_txn(addr, data) \
$display("addr=0x%0h data=0x%0h", addr, data);
module tb;
initial begin
`show_txn(8'hf0, 8'h1d)
end
endmodule
Note that addr and data within the string did not get replaced.
xcelium> run addr=0xf0 data=0x1d xmsim: *W,RNQUIE: Simulation is complete.
SystemVerilog `define
In SystemVerilog, you can enable argument substitution within a macro text string by placing a grave accent ( ` ) before the quotation marks that define the string.
// Note (`) before (")
`define show_txn(addr, data) \
$display(`"addr=0x%0h data=0x%0h`", addr, data);
module tb;
initial begin
`show_txn(8'hf0, 8'h1d)
end
endmodule
Now, addr and data within the string are also replaced.
xcelium> run 8'hf0=0xf0 8'h1d=0x1d xmsim: *W,RNQUIE: Simulation is complete.
Quotation marks embedded within a string should be escaped with \ , and extending the previous example to replace something within quotations inside a string, a grave accent should precede both \ and " .
`define show_txn(addr, data) \
$display("addr=0x%0h \"data\"=0x%0h", addr, data);
module tb;
initial begin
`show_txn(8'hf0, 8'h1d)
end
endmodule
Note that data itself is within quotes because of the preceding escape character \ .
xcelium> run addr=0xf0 "data"=0x1d xmsim: *W,RNQUIE: Simulation is complete.
Lets look at how to substitute addr and data like we did in the previous example, by adding a grave accent ` before the quotes as well as the escape character.
`define show_txn(addr, data) \
$display(`"addr=0x%0h `\`"data`\`"=0x%0h`", addr, data);
module tb;
initial begin
`show_txn(8'hf0, 8'h1d)
end
endmodule
Note that both addr and data have been replaced.
xcelium> run 8'hf0=0xf0 "8'h1d"=0x1d xmsim: *W,RNQUIE: Simulation is complete.
Concatenate Macros
Verilog does not allow the construction of an identifier by concatenating two or more text macros togther because there will always be a white space in the constructed identifier name.
In SystemVerilog, a double accent grave `` is used to concatenate two text macros.
`define MODULE tb
`define SIGNAL a
`define CONCAT(mod, sig) assign ``mod.``sig = 1;
module tb;
wire a;
`CONCAT(`MODULE, `SIGNAL)
initial begin
$strobe("a=0x%0h", a);
end
endmodule
xcelium> run a=0x1 xmsim: *W,RNQUIE: Simulation is complete.
Keywords can be used as arguments in a macro definition.
// Both arguments to the text macro are real Verilog keywords
`define PATH(module, wire) ``module.``wire