In Verilog, namespaces are a way to organize and manage identifiers (such as variables, types, tasks, and functions) to avoid naming conflicts and improve code modularity. There are multiple namespaces; two are classified as global, while the others are local. The global namespaces consist of definitions and text macros.

Global Namespace

The definitions namespace consolidates all module and primitive definitions. Once a name is assigned to a module or primitive, it cannot be reused to declare another module or primitive.


module A;
  // Statements
endmodule

// cannot use 'module A' because it is already declared in global namespace
module B;  
  // Statements
endmodule

The text macros names are global and utilized with a leading backtick (`) character, they are clearly distinct from names in other namespaces. Text macro names are defined in the order they appear in the input files that comprise the design unit. Any subsequent definitions of the same name will override previous definitions for the remainder of the input files.


// file1.v
`define   ADDR_WIDTH    32  

// file2.v
`define   ADDR_WIDTH    16   // Redefined to 16 when file2.v is compiled after file1.v

Local Namespace

The local namespaces include block, module, generate block, port, specify block, and attribute. Once a name is defined within any of these namespaces—block, module, port, generate block, or specify block—it cannot be redefined in that same namespace, regardless of whether it is the same or a different type.

Block Namespace

The block namespace is established by named blocks, functions, and tasks. It consolidates the definitions of named blocks, functions, tasks, parameters, named events, and variable type declarations. The variable type declarations include reg, integer, time, real, and realtime.


module example;
    reg signal;

    task myTask;
        reg signal;    // This 'signal' is local to myTask

      begin
        reg signal;    // This 'signal' is local to this begin-end block
      end
    endtask
endmodule

Module Namespace

The module namespace is established by the module and primitive constructs. It consolidates the definitions of functions, tasks, named blocks, module instances, generate blocks, parameters, named events, genvars, net type declarations, and variable type declarations.


module A;
  reg signal;    // 'signal' is local to module A
endmodule

module B;  
  reg signal;    // 'signal' is local to module B
endmodule

Generate Namespace

The generate block namespace is created by generate constructs. It consolidates the definitions of functions, tasks, named blocks, module instances, generate blocks, local parameters, named events, genvars, net type declarations, and variable type declarations.


    // 'i' genvar variable is visible only inside this 
    // generate block named "adder_instance"
    genvar i; 

    generate
        for (i = 0; i < N; i = i + 1) begin : adder_instance 
            half_adder HA (
                .a(A[i]),
                .b(B[i]),
                .sum(SUM[i]),
                .carry(CARRY[i])
            );
        end
    endgenerate

Specify Namespace

The specify block name space is introduced by the specify construct.


specify
  specparam  Thold = 5;     // Tdelay is visible only inside this specify block

  $hold(clk, d, Thold);           
endspecify