Starting with a backtick,`certain identifiers are Verilog system compiler directives.

Compiler directives provide great convenience for writing, compiling, and debugging Verilog code.

The following introduces all 8 compiler directives, among which the first 4 are more frequently used.

`define, `undef

During the compilation stage,`defineit is used for text replacement, similar to #define in C language.#define。

Once`definethe directive is compiled, it will be valid throughout the entire compilation process. For example, if defined in one file:

`define    DATA_DW     32

then DATA_DW can also be used directly in another file.

`define    S     $stop;   
//用`S来代替系统函数$stop; (包括分号)
`define    WORD_DEF   reg [31:0]       
//可以用`WORD_DEF来声明32bit寄存器变量

`undefIt is used to cancel a previous macro definition, for example:

`define    DATA_DW     32
……
reg  [DATA_DW-1:0]    data_in   ;
……
`undef DATA_DW

`ifdef, `ifndef, `elsif, `else, `endif

These are conditional compilation directives. For example, in the example below, if MCU51 is defined, the first type of parameter description is used; if MCU is not defined but WINDOW is defined, the second type of parameter description is used; if neither of the two is defined, the third type of parameter description is used.

`ifdef       MCU51
    parameter DATA_DW = 8   ;
`elsif       WINDOW
    parameter DATA_DW = 64  ;
`else
    parameter DATA_DW = 32  ;
`endif

`elsif, `elseThe compiler directive, with respect to the`ifdefdirective, is optional; that is, it can consist of only`ifdefand`endifto form a conditional compilation directive block.

Of course, you can also use`ifndefto set up conditional compilation, meaning that if the relevant macro is not defined, the relevant statements will be executed.

In the following example, if WINDOW is defined, the second type of parameter description is used. If WINDOW is not defined, the first type of parameter description is used.

Example

`ifndef     WINDOW
    parameter DATA_DW = 32 ;  
 `else
    parameter DATA_DW = 64 ;
 `endif

`include

Using`includeone Verilog file can be embedded into another Verilog file at compile time, which functions similarly to the #include structure in C language. This directive is usually used to include global or common header files in the design file.

The file path can be either a relative path or an absolute path.

`include         "../../param.v"
`include         "header.v"

`timescale

In Verilog models, delays have specific unit-time expressions and use the`timescalecompiler directive to associate the time unit with the actual time.

This directive is used to define the units and precision of delays and simulation. The format is as follows:

`timescale      time_unit / time_precision

time_unit represents the time unit, and time_precision represents the time precision. Both are composed of a number and a unit: s (seconds), ms (milliseconds), us (microseconds), ns (nanoseconds), ps (picoseconds), and fs (femtoseconds). The time precision can be the same as the time unit, but the time precision value cannot exceed the time unit value. For example, in the following example, output Z will delay 5.21ns before outputting the result of A&B.

Example

`timescale 1ns/100ps    //Time unit is 1ns, precision is 100ps, legal
//`timescale 100ps/1ns //invalid
module AndFunc(Z, A, B);
    output Z;
    input A, B ;
    assign #5.207 Z = A & B
endmodule

During compilation, the`timescaledirective affects the delay values in all subsequent modules, until another`timescaledirective or the`resetalldirective is encountered.

Since there is no default`timescale, if not specified`timescale, Verilog modules will inherit the previously compiled module's`timescaleparameter. This may lead to design errors.

If multiple modules in a design all have`timescale, the simulator always positions itself at the smallest delay precision among all modules, and all delays are correspondingly converted to the smallest delay precision. The delay unit is not affected. For example:

Example

`timescale 10ns/1ns      
module test;
    reg        A, B ;
    wire       OUTZ ;
 
    initial begin
        A     = 1;
        B     = 0;
        # 1.28    B = 1;
        # 3.1     A = 0;
    end
 
    AndFunc        u_and(OUTZ, A, B) ;
endmodule

In module AndFunc, 5.207 corresponds to 5.21ns.

In module test, 1.28 corresponds to 13ns, and 3.1 corresponds to 31ns.

However, when simulating test, since the minimum precision in AndFunc is 100ps, the delay precision in test will be readjusted. 13ns will correspond to 130*100ps, and 31ns will correspond to 310*100ps. During simulation, the delay precision will also use 100ps. The size of the simulation time unit has no effect.

If there are parallel submodules, the `timescale directives among submodules do not affect each other.

For example, instantiate another submodule OrFunc in module test. When simulating test, the #5.207 delay in OrFunc still corresponds to 52ns.

Example

//Submodule:
`timescale 10ns/1ns      //Time unit is 1ns, precision is 100ps, legal
module OrFunc(Z, A, B);
    output Z;
    input A, B ;
    assign #5.207 Z = A | B
endmodule
 
//Top-level module:
`timescale 10ns/1ns      
module test;
    reg        A, B ;
    wire       OUTZ ;
    wire       OUTX ;
 
    initial begin
        A     = 1;
        B     = 0;
        # 1.28    B = 1;
        # 3.1     A = 0;
    end
 
    AndFunc        u_and(OUTZ, A, B) ;
    OrFunc         u_and(OUTX, A, B) ;
 
endmodule

In this example, when simulating test, the #5.207 delay in OrFunc still corresponds to 52ns.

`timescaleThe time precision setting will affect the simulation time. The smaller the time precision, the more memory is occupied during simulation, and the longer the actual simulation time used. Therefore, if not necessary, try to set the time precision as large as possible.

`default_nettype

This directive is used to specify implicit net variables as net types, that is, to define undeclared wires as net types.

`default_nettype wand 

The default net defined in this example is the wire-AND type. Therefore, if any wire in any module after this directive is not declared, the net is assumed to be of the wire-AND type.

`default_nettype none

After this example is defined, wire-type variables will no longer be automatically generated.

For example, the first writing style below will not report an Error during compilation, while the second writing style will fail to compile.

Example

//Z1 is used without definition; the system defaults Z1 to a wire-type variable, with a Warning but no Error
module test_and(
        input      A,
        input      B,
        output     Z);
    assign Z1 = A & B ;  
endmodule

Example

//Z1 is used without definition; due to the existence of the compiler directive, the system will report an Error, thereby detecting the writing error
`default_nettype none
module test_and(
        input      A,
        input      B,
        output     Z);
    assign Z1 = A & B ;  
endmodule

`resetall

This compiler directive resets all compiler directives to their default values.

`resetallIt can make the default connection type a net type.

When`resetallWhen added at the end of a module, the current`timescaleis cancelled to prevent further propagation, ensuring only that the current`timescaleis locally valid, avoiding erroneous inheritance of `timescale.

`celldefine, `endcelldefine

These two program directives are used to mark modules as cell modules; they contain the module definitions. For example, some AND, OR, NOT gates, some PLL cells, PAD models, and some Analog IP, etc.

Example

`celldefine
module (
    input      clk,
    input      rst,
    output     clk_pll,
    output     flag);
        ……
endmodule
`endcelldefine

`unconnected_drive, `nounconnected_drive

In module instantiation, any unconnected input ports appearing between these two compiler directives are in a forward-biased circuit state or in a reverse-biased circuit state.

`unconnected_drive pull1
. . .
 / *在这两个程序指令间的所有未连接的输入端口为正偏电路状态(连接到高电平) * /
`nounconnected_drive
`unconnected_drive pull0
. . .
 / *在这两个程序指令间的所有未连接的输入端口为反偏电路状态(连接到低电平) * /
`nounconnected_drive