Verilog HDL描述中的每个标识符应具有唯一的分层路径名。模块的层次结构和项目的定义(如模块内的任务和命名块)应定义这些名称。名称的层次结构可以被视为树结构,其中每个模块实例、生成块实例、任务、函数或命名的begin-end 或者 fork-join块在树的特定分支中定义一个新的层次结构或范围。
设计说明包含一个或多个顶层模块(见12.1.1)。每个这样的模块构成了名称层次结构的顶部。此根或这些并行根模块构成设计描述或描述中的一个或多个层次结构。在任何模块内,每个模块实例(包括阵列实例)、生成块实例、任务定义、函数定义以及命名的begin-end 或者 fork-join块都应定义层次结构的新分支。
命名块内以及任务和功能内的命名块应创建新分支。未命名的生成块是例外。它们创建仅在块内以及块实例化的任何层次结构内可见的分支。未命名生成块的讨论见12.4.3。分层名称树中的每个节点应是与标识符相关的单独范围。特定标识符在任何范围内最多只能声明一次。关于范围规则的讨论,请参见12.7;关于命名空间的讨论,参见4.11。
通过串联模块名称、模块实例名称、生成块、任务、函数或包含它的命名块,任何命Verilog对象或分层名称引用都可以以其完整形式唯一引用。应使用句点字符分隔层次结构中的每个名称,但嵌入层次结构名称引用中的转义标识符除外,转义标识符后面是由空格和句点字符组成的分隔符。任何对象的完整路径名应从顶级(根)模块开始。此路径名可以在层次结构中的任何级别或并行层次结构中使用。路径名中的第一个节点名也可以是层次结构的顶部,该层次结构从使用路径的级别开始(这允许并允许向下引用项)。自动任务和函数中声明的对象是例外,不能通过层次结构名称引用访问。在未命名的生成块中声明的对象也是例外。它们只能由块内以及块实例化的任何层次结构中的层次结构名称引用。
层次路径名中引用实例数组或循环生成块的名称后面可以紧跟方括号中的常量表达式。此表达式选择数组的特定实例,因此称为实例选择。表达式的计算结果应为数组的合法索引值之一。如果数组名称不是层次结构名称中的最后一个路径元素,则需要实例选择表达式。分层路径名的语法在语法12-6中给出。
escaped_identifier ::= (From A.9.3)
\ {Any_ASCII_character_except_white_space} white_space
hierarchical_identifier ::=
{ identifier [ [ constant_expression ] ] . } identifier
identifier ::=
simple_identifier
| escaped_identifier
simple_identifier ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_$ ] }
white_space ::= (From A.9.4)
space | tab | newline | eof
Syntax 12-6—Syntax for hierarchical path names
例如:
示例1-本示例中的代码定义了模块实例和命名块的层次结构。
module mod (in);
input in;
always @(posedge in) begin : keep
reg hold;
hold = in;
end
endmodule
module cct (stim1, stim2);
input stim1, stim2;
// instantiate mod
mod amod(stim1), bmod(stim2);
endmodule
module wave;
reg stim1, stim2;
cct a(stim1, stim2); // instantiate cct
initial begin :wave1
#100 fork :innerwave
reg hold;
join
#150 begin
stim1 = 0;
end
end
endmodule
图12-1说明了Verilog代码中隐含的层次结构。
Figure 12-1—Hierarchy in a model
图12-2是代码中定义的所有对象名称的分层形式列表。
wave wave.a.bmod
wave.stim1 wave.a.bmod.in
wave.stim2 wave.a.bmod.keep
wave.a wave.a.bmod.keep.hold
wave.a.stim1 wave.wave1
wave.a.stim2 wave.wave1.innerwave
wave.a.amod wave.wave1.innerwave.hold
wave.a.amod.in
wave.a.amod.keep wave.a.amod.keep.hold
层次化名称引用允许从分层结构中的任何级别自由访问任何对象。如果项目的唯一分层路径名已知,则可以从描述中的任何位置对其值进行采样或更改。
示例2—下一个示例显示了一对命名块如何引用彼此内部声明的项。
begin
fork :mod_1
reg x;
mod_2.x = 1;
join
fork :mod_2
reg x;
mod_1.x = 0;
join
end
12.6 Upwards name referencing(向上名称引用)
模块或模块实例的名称足以识别模块及其在层次结构中的位置。较低级别的模块可以引用层次结构中位于其上方的模块中的项。如果知道更高级别模块的名称或其实例名称,则可以引用变量。对于任务、函数、命名块和生成块,Verilog应在封闭模块中查找名称,直到找到名称或到达层次结构的根。它只能在更高的封闭模块中搜索名称,而不是实例。
语法12-7给出了向上引用的语法。
upward_name_reference ::=
module_identifier.item_name
item_name ::=
function_identifier
| block_identifier
| net_identifier
| parameter_identifier
| port_identifier
| task_identifier
| variable_identifier
Syntax 12-7—Syntax for upward name referencing
向上的名称引用也可以使用以下形式的名称进行:
scope_name.item_name
其中scope_name是模块实例名称或生成块名称。这种形式的名称应按如下方式解析:
a) 在当前作用域中查找名为scope_name的作用域。如果找不到,并且当前作用域不是模块作用域,请在封闭作用域中查找该名称,根据需要重复,直到找到该名称或到达模块作用域。如果仍未找到,则继续执行步骤b)。否则,该名称引用应视为名称所在范围的向下引用。
b) 在父模块的最外层作用域中查找名为scope_name的作用域。如果找到,则应从该范围中解析项目名称。
c) 重复步骤b),向上进入层次结构。
对于defparam语句左侧的分层名称,这些规则有一个例外。详见12.8。
例如:在本例中,有四个模块,a、b、c和d。每个模块包含一个整数i。模型层次结构这一部分中的最高级别模块是a和d。模块b有两个副本,因为模块a和d实例化了b。有四个c.i副本,因为b的两个副本中的每一个都实例化了c两次。
module a;
integer i;
b a_b1();
endmodule
module b;
integer i;
c b_c1(), b_c2();
initial
#10 b_c1.i = 2; // a.a_b1.b_c1.i, d.d_b1.b_c1.i
endmodule
module c;
integer i;
initial begin
i = 1;
b.i = 1;
end
endmodule
module d;
integer i;
b d_b1();
initial begin // full path name references each copy of i
a.i = 1; d.i = 5;
a.a_b1.i = 2; d.d_b1.i = 6;
a.a_b1.b_c1.i = 3; d.d_b1.b_c1.i = 7;
a.a_b1.b_c2.i = 4; d.d_b1.b_c2.i = 8;
end
endmodule