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
Output
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)    
    
    // name is left empty, so its default ("INST") is used instead; a and b are both explicitly passed
    `ADD( , 3, 1)
    
    // First argument
    `ADD(, , 5)
    
    // Whitespace between `ADD and (
    `ADD ("SPACE", 1, 2)
  end  
endmodule
Output
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.

Output
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.

Output
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 \.

Output
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.

Output
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
Output
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
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5
Cron Job Starts