Verilog 模块基础:结构与语法
module 是实现特定功能的 Verilog 代码块。模块可嵌套在其他模块内,高层模块通过输入输出端口与低层模块通信。
语法
module 必须包含在 module 和 endmodule 关键字之间。模块名紧跟 module 关键字后,可选端口列表。注意:端口列表中声明的端口不能在模块体内重复声明。
module ([port_list]);
// Contents of the module
endmodule
// 模块可有空端口列表
module name;
// Contents of the module
endmodule
所有变量声明、数据流语句、函数/任务及下层模块实例(如有)必须定义在 module 和 endmodule 之间。同一文件可包含多个不同名称的模块,顺序任意。
示例
模块 dff 代表 D 触发器,有三个输入端口 d、clk、rstn 和一个输出端口 q。模块内容描述 D 触发器对不同输入组合的行为。此处输入 d 在时钟上升沿赋给输出 q,因为 rstn 是低电平有效复位。
// 模块 "dff" 有 3 个输入和 1 个输出端口
module dff (
input d,
input clk,
input rstn,
output reg q
);
// 模块内容
always @ (posedge clk) begin
if (!rstn) q <= 0;
else q <= d;
end
endmodule
硬件原理图
综合时该模块转换为以下数字电路。
注意: 你不能在模块外编写任何代码!
模块的用途
模块代表实现特定行为特征的设计单元,综合时转换为数字电路。任何输入组合均可施加于模块,产生相应输出。这允许同一 模块 被复用构建实现更复杂硬件的大模块。
例如,上述 DFF 可串联形成移位寄存器。
module shift_reg (
input d,
input clk,
input rstn,
output q
);
wire [2:0] q_net;
dff u0 (.d(d), .clk(clk), .rstn(rstn), .q(q_net[0]));
dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q(q_net[1]));
dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q(q_net[2]));
dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
endmodule
硬件原理图
注意 DFF 实例通过线网连接,正如 Verilog RTL 模块描述。
也可反向分解。考虑将简单 GPU 引擎分解为更小组件,每个作为实现特定功能的模块。下图 GPU 引擎可分为五个子块,每个执行特定功能。总线接口单元从外部获取数据,另一单元提取指令,后续单元处理前一单元提供的数据。
每个子块可表示为具有特定输入输出信号的 module,并可按需进一步细分。
什么是顶层模块?
顶层 模块是包含所有其他模块的模块。顶层模块不在任何其他模块中实例化。
例如,设计模块通常在顶层测试平台模块中实例化以便仿真提供激励。但测试平台不在任何其他模块中实例化,因为它封装了所有内容,故是 顶层模块。
设计顶层
下面设计代码顶层模块叫 design,因为它包含完成设计所需的所有子模块。子模块可有更深嵌套子模块(如 mod3 在 mod1 内,mod4 在 mod2 内)。无论如何,实例化 mod1 和 mod2 时所有这些都被包含在顶层模块中,使 design 完整,成为设计的顶层模块。
//---------------------------------
// Design code
//---------------------------------
module mod3 ( [port_list] );
reg c;
// Design code
endmodule
module mod4 ( [port_list] );
wire a;
// Design code
endmodule
module mod1 ( [port_list] );
// This module called "mod1" contains two instances
wire y;
mod3 mod_inst1 ( ... ); // First instance is of module called "mod3" with name "mod_inst1"
mod3 mod_inst2 ( ... ); // Second instance is also of module "mod3" with name "mod_inst2"
endmodule
module mod2 ( [port_list] );
// This module called "mod2" contains two instances
mod4 mod_inst1 ( ... ); // First instance is of module called "mod4" with name "mod_inst1"
mod4 mod_inst2 ( ... ); // Second instance is also of module "mod4" with name "mod_inst2"
endmodule
// Top-level module
module design ( [port_list]);
// From design perspective, this is the top-level module
wire _net;
mod1 mod_inst1 ( ... ); // since it contains all other modules and sub-modules
mod2 mod_inst2 ( ... );
endmodule
测试平台顶层
测试平台模块包含激励以检查设计功能,主要用于仿真工具的功能验证。因此设计在测试平台模块中实例化并命名为 d0。从仿真器角度,测试平台是顶层模块。
//-----------------------------------------------------------
// Testbench code
// From simulation perspective, this is the top-level module
// because 'design' is instantiated within this module
//-----------------------------------------------------------
module testbench;
design d0 ( [port_list_connections] );
// Rest of the testbench code
endmodule
层次化名称
模块可相互实例化形成层次结构,顶层模块称为 根。给定模块内每个下层模块实例必须有不同标识符名,因此访问信号无歧义。层次化名称由每层标识符列表用点 . 分隔构成。可通过层次路径在任何模块内访问任意信号。
// Take the example shown above in top level modules
design.mod_inst1 // Access to module instance mod_inst1
design.mod_inst1.y // Access signal "y" inside mod_inst1
design.mod_inst2.mod_inst2.a // Access signal "a" within mod4 module
testbench.d0._net; // Top level signal _net within design module accessed from testbench
Verilog