Logo

Compiler Directives in Verilog

22 Sep 2021
5 mins

Complier directives are common in any programming language which is based on compilers. These directives, as the name suggests, direct how the compiler will compile the code. In Verilog, there are various compiler directives to set the timescale of simulation, control the compiler flow. Compiler directives start with the ` (backquote) symbol. Compiler Directives, once declared, stays effective until another directive overrides the directive. Thus, if a directive is declared in one file, it is effective in other files also.
Different directives available in Verilog are:

  • `define
  • `include
  • `ifdef
  • `ifndef
  • `elseif
  • `else
  • `timescale
  • `undef
  • `resetall
  • `defaultnettype

Let us see different directives in detail.

Include directive

Include directive is used when a module defined in a file needs to be included in another file. This compiler directive will copy all the codes written in the mentioned file and include them in the present file during compile time, making all the code from another file accessible in the file.
Syntax: `include “file_name”

`define

This directive is used to declare a Macro or to define a custom data type. Macros are code that can be used to perform some tasks. It is different from function or task as it can be defined outside the modules and thus be used globally. Also, macros do not have any construct like that of function and task.
Syntax: `define name code

Example

This example shows how a define directive can be used to define a custom data type. A nibble is a 4-bit data which is defined using `define directive.

`define nibble reg[3:0]

module define_demo;
    `nibble a;
    initial begin
        a = 4'b1010;
        $display("a = %b", a);
    end
endmodule
Output
# a = 1010

`undef

This directive is used to remove any defined macros.

Example

This code will show an error as nibble is undefined using `undef directive. Thus, nibble cannot be used after the highlighted line.

module undefine_demo;
    `undef nibble
    `nibble a;
    initial begin
        a = 4'b1010;
        $display("a = %b", a);
    end
endmodule

`ifdef

This directive is like an if-else statement but is evaluated during the compile time. If a macro has been defined, it will compile the statements present after the directive. `ifdef directive is always followed by an `endif directive which marks the end of condition code. Thus, any code written inside `ifdef and `endif directive will be compiled only when a particular macro is defined.
Syntax: `ifdef macro_name <code> `endif

The macros can either be defined using `define directive or be passed as a parameter with the compile command using the +define option.

`ifndef

This directive is just the opposite of the `ifdef directive. This directive will compile the underlying code only when the macro is not defined. Generally, this is used when we want to compile some code only once. So, if a macro is not defined, it can compile some code and then define the exact macros. Now the same code will not be recompiled.
Syntax: `ifndef macro_name <code> `endif

`elseif

This directive is used with the `ifdef or `ifndef directive to give added options, just as in the case of if-else-if statements.

`else

This directive is used to define a default case, i.e., if none of the directives evaluates to true, then the statement present in this directive is compiled. It is not necessary to include an `else directive with `ifdef or `ifndef directives.

`timescale

This directive is used to define the time scale of the simulation. Choosing a correct timescale is very crucial for a simulation. The time scale is divided into two parts: time unit and time precision. Time unit maps one simulation unit to a real time unit. For example, if the time unit is selected as 1µs, then #1 will mean a delay of 1µs. Time precision shows the precision of the time scale. It can be equal to or less than the time unit specified. For example, if time precision is selected to be 100ns, then #1.2 would mean a time delay of 1.2µs. If precision is also set to 1µs, then #1.2 will mean a time delay of 1µs. As there is the precision is also in µs.

Example

In the below example, it must be noted that the $realtime function's output is related to the time precision we provide. Precision in the example is 100ns, and as 1µs = 10 * 100ns, thus the output of the $realtime function is 10.

`timescale 1us/100ns

module timescale_demo;
    reg a = 1'b0;
    initial begin
        #1.4
        a = 1'b1;
        $display("Simulation at %0t x 100ns", $realtime);

        #1.42
        a = 1'b0;
        $display("Simulation at %0t x 100ns", $realtime);

        #1.46
        a = 1'b1;
        $display("Simulation at %0t x 100ns", $realtime);
    end
endmodule
Output
# Simulation at 14 x 100ns
# Simulation at 28 x 100ns
# Simulation at 43 x 100ns