在 Verilog 中,模块实例化是将一个模块作为组件使用在另一个模块中。这类似于在编程中调用一个函数或在硬件设计中使用一个子电路。通过实例化,可以将复杂的设计分解为更小的、可复用的模块。
模块实例化的基本语法
假设我们有两个模块:一个是已经定义好的 32 位加法器模块 add32
,另一个是顶层模块 top_module
,它实例化了 add32
模块。
add32
模块
module add32(
input wire [31:0] in1,
input wire [31:0] in2,
output wire [31:0] out
);
assign out = in1 + in2;
endmodule
顶层模块 top_module
module top_module(
input wire [31:0] a,
input wire [31:0] b,
output wire [31:0] sum
);
// 实例化 add32 模块
add32 u_add32 (
.in1(a), // 将顶层模块的输入 a 连接到子模块 add32 的 in1 端口
.in2(b), // 将顶层模块的输入 b 连接到子模块 add32 的 in2 端口
.out(sum) // 将子模块 add32 的输出 out 连接到顶层模块的输出 sum
);
endmodule
详细讲解
-
子模块定义
module add32( input wire [31:0] in1, input wire [31:0] in2, output wire [31:0] out ); assign out = in1 + in2; endmodule
这是一个简单的 32 位加法器模块,定义了两个输入端口
in1
和in2
,以及一个输出端口out
。它将输入端口的值相加,并将结果赋给输出端口。 -
顶层模块定义
module top_module( input wire [31:0] a, input wire [31:0] b, output wire [31:0] sum );
顶层模块
top_module
定义了三个端口:两个 32 位的输入端口a
和b
,以及一个 32 位的输出端口sum
。 -
实例化子模块
add32 u_add32 ( .in1(a), // 将顶层模块的输入 a 连接到子模块 add32 的 in1 端口 .in2(b), // 将顶层模块的输入 b 连接到子模块 add32 的 in2 端口 .out(sum) // 将子模块 add32 的输出 out 连接到顶层模块的输出 sum );
在顶层模块中,我们实例化了
add32
模块。实例化时,我们给这个实例取了一个名字u_add32
。通过端口映射,将顶层模块的端口a
、b
和sum
分别连接到子模块add32
的端口in1
、in2
和out
。
实例化的另一种写法
除了上面的端口名映射方式,我们还可以使用位置映射方式。这种方式在实例化时按顺序列出端口的连接。
module top_module(
input wire [31:0] a,
input wire [31:0] b,
output wire [31:0] sum
);
// 实例化 add32 模块,使用位置映射
add32 u_add32 (a, b, sum); // 依次将 a, b 和 sum 连接到子模块的 in1, in2 和 out
endmodule
使用位置映射时,要特别注意端口的顺序必须与子模块的端口定义顺序一致,否则可能会导致错误的连接。
总结
模块实例化是 Verilog 中将一个模块嵌入到另一个模块中的过程。它使得设计更具层次性和可复用性。通过端口映射,可以灵活地将顶层模块的信号连接到子模块的端口,从而实现复杂设计的模块化。