层次化设计
1、模块原型
外部的模块声明
SystemVerilog允许用户为被实例化的模块指定一个原型,这就简化了编译过程。原型的定义使用关键字extern,extern之后是模块及其端口是声明。
//使用Verilog-1995代码风格的原型
entern module counter(cnt,d,clock,resetN)
//使用Verilog-1995代码风格的原型
extern module counter#(paramter N=15)
(output logic[N:0] cnt,
input wire[N:0] d,
input wire clock,load,resetN);
模块的原型定义还有利于对设计存档。大型的设计可能有许多源文件。当一个文件包含了另一个模块的实例时,则需要在其他的文件中查找该例化模块的定义。而模块定义的原型可以与模块的实例列在同一个文件里。
外部模块声明的可见性
原型对起作用域来说是局部的
可以在设计的任何模块内使用extern module声明,但该声明只在其定义的范围可见。在任何模块或接口外部进行的extern module声明都将在$unit编译单元声明域中。不管模块在设计的那个层次,只要共享 $unit域都可以实例化这个全局可见的模块。
1.1原型与实际定义
原型与实际定义必须匹配
SystemVerilog要求extern module声明的端口列表必须与模块的实际定义严格匹配,包括端口顺序与端口位数。如果两种定义的端口列表不匹配,则会造成严重的错误。
1.2避免端口冗余声明
为了减少冗余代码,SystemVerilog提供了便捷的简写方式。如果模块有extern module声明,则在模块定义时不需要重复端口的声明。取而代之的是,在模块实际定义的端口列表位置上使用.*符号。软件工具会自动将 . *替换为extern module原型中定义的端口。这样避免了在外部模块原型和实际模块定义中两次定义同样的端口列表。
extern module counter#(paramter N=15)
(output logic[N:0] cnt,
input wire[N:0] d,
input wire clock,load,resetN);
module counter(.*)
always@(posedge clock,negedge resetN)
begin
if(!resetN) cnt <= 0;
else if(load) cnt <= d;
else cnt <= cnt + 1;
end
endmodule