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