相关文章
Verilog基础:表达式位宽的确定(位宽拓展)
Verilog基础:表达式符号的确定
Verilog基础:数据类型
Verilog基础:位宽拓展和有符号数运算的联系
Verilog基础:case、casex、casez语句
Verilog基础:casex和full_case、parallel_case的使用
Verilog基础:表达式中的整数常量(integer)
Verilog基础:task和function的使用(一)
Verilog基础:task和function的使用(二)
Verilog基础:标识符的层次名引用
1.向上向下层次名引用
在之前的文章中已经介绍了标识符的层次名引用Verilog基础:标识符的层次名引用,如前文所示,所有的完整层次名都是由Top模块开始的由“.”分隔的一系列标识符组成的。但有时候,模块或模块实例的名称足以标识模块及其在层次结构中的位置。较低级别的模块可以在层次结构中引用它上级模块中的项目。如果上级模块的名字,或模块实例的名字已知,则变量可以被引用。对于任务、函数、命名块和生成块,Verilog将在上级模块中查找名称,直到找到它或直到到达层次结构的根,而且只在更高的封闭模块中搜索模块的名称,而不是模块实例名。
下图是向上层次引用的语法。
向上的层次名引用也可以使用以下形式。
其中scope_name是模块实例名或生成块名。这种形式的名称应按下列方式解析:
a)在当前作用域中查找名为scope_name的作用域。如果未找到且当前作用域不是模块作用域,则在上层作用域中查找该名称,必要时重复查找,直到找到该名称或到达模块作用域。如果仍未找到,则继续执行步骤b)。否则,将此名称引用视为从找到该名称的作用域向下引用。
b)在父模块最外层的作用域中查找名为scope_name的作用域。如果发现,则从该范围解析项目名称。
c)重复步骤b),往上走直到顶层模块。
在实际操作中,笔者发现虽然从形式上看,这两种形式的层次名引用只能由“.”分隔的两部分构成,但它们依然可以像标识符的层次名引用一样,由“.”分隔的多个部分组成。
下面将会举例说明以上的内容。
例1
module Top;
reg x;
Middle middle_0();
initial fork:a
reg x;
join
endmodule
module Middle;
reg x;
Below below_0();
initial fork:b
reg x;
join
endmodule
module Below;
initial Middle.b.x = 0; //使用模块名引用上层模块的信号
//initial middle_0.b.x = 0; 使用实例名引用上层模块的信号
//initial Top.middle_0.b.x = 0; 完整层次名引用上层模块的信号
endmodule
第一种方法是使用模块名引用上层模块的信号,具体过程为,首先搜索本层次(Below模块)有无名字为Middle的层次,然后向上推进到Middle模块的最外层,此时仍然没有Middle层次(本模块名在本模块内不可见),最后搜索Top模块,发现例化了Middle模块,则可以确定x的位置。
第二种方法是使用实例名,与第一种方法类似,不同的是,此时的指向更为清晰,明确指定了是middle_0实例,而第一种方法使用模块名,指的是层次包括了信号使用处层次的实例。
第三种方法则是使用了之前的文章中提到的完整层次名引用,这其实也可以看做是和第一种方法,只不过这时会向上搜索直到Top模块,然后再逐步解析后面的middle_0、b和x。
例2
module Top;
reg x;
Middle middle_0();
initial fork:a
reg x;
join
endmodule
module Middle;
reg x;
Below below_0();
initial below_0.x = 0; //向下层引用
//initial Middle.below_0.x = 0; 首先向上搜索Middle直到在Top中找到Middle,然后向下解析
//initial Top.middle_0.below_0.x = 0; 完整层次引用,可以理解为向上搜索Top,直到顶层模块
endmodule
module Below;
reg x;
endmodule
第一种方法先在本层次(Middle模块最外层)搜索below_0,结果显示可以找到,below_0中也可找到x,所以这被解释为向下引用below_0中的信号。
后面两种方法和之前一致,其中第二种方法似乎有点奇怪,是一种不完整的层次引用,先向上查找,然后再向下解析below_0和x。
例3
module Top;
reg x;
Middle middle_0();
initial fork:a
reg x;
join
endmodule
module Middle;
reg x;
Below below_0();
fork: Middle
reg x;
//fork: Middle
//reg x; 无法被Middle.x搜索到
//join
join
endmodule
module Below;
//fork: Middle
//reg x; 如果有注释内容,则x在此处就会被解析到,而不会继续向上搜索了
//fork: b
initial Middle.x = 0;
//join
//join
endmodule
上例可以说明,本模块名在本模块中是不可见的,其中initial语句改变的是Middle命名块中x的值,而不是Middle模块中x的值。注意,在向上搜索引用的第一个结点名字的过程中,只会在上层模块的最外层搜索,注释中的x是无法被Middle.x搜索到的,需要使用Middle.Middle.x才能搜索到。