2.3Modules:Hierachy
2.3.1Modules
问题陈述:
下图显示了一个带有子模块的非常简单的电路。在本练习中,创建一个module实例mod_a,然后将模块的三个引脚(in1、in2和out)连接到顶层模块的三个端口(电线a、b和out)。该模块mod_a是为您提供的——您必须实例化它。
连接模块时,只有模块上的端口很重要。您不需要知道模块内的代码。模块的代码mod_a如下所示:
module mod_a ( input in1, input in2, output out );
// Module body
endmodule
Verilog代码:
module top_module ( input a, input b, output out );
mod_a(a,
b,
out);
endmodule
2.3.2Connecting ports by position
问题陈述:
您将获得一个名为的模块,该模块mod_a按顺序具有 2 个输出和 4 个输入。您必须按位置将 6 个端口按顺序连接到顶层模块的端口out1、out2、a、b、c和d。
您将获得以下模块:
module mod_a ( output, output, input, input, input, input );
Verilog代码:
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a(out1,out2,a,b,c,d);
endmodule
2.3.3Connecting ports by name
问题陈述:
您将获得一个名为的模块,该模块mod_a按某种顺序具有 2 个输出和 4 个输入。您必须按名称将 6 个端口连接到顶级模块的端口:
Port in mod_a | Port in top_module |
---|---|
output out1 | out1 |
output out2 | out2 |
input in1 | a |
input in2 | b |
input in3 | c |
input in4 | d |
您将获得下面的模块:
module mod_a ( output out1, output out2, input in1, input in2, input in3, input in4)
Verilog代码:
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a(.out1(out1),
.out2(out2),
.in1(a),
.in2(b),
.in3(c),
.in4(d));
endmodule
2.3.4Three modules
问题陈述:
您将获得一个my_dff具有两个输入和一个输出的模块(实现 D 触发器)。实例化其中的三个,然后将它们链接在一起以制作长度为 3 的移位寄存器。clk端口需要连接到所有实例。
提供给您的模块是: module my_dff ( input clk, input d, output q );
在这里插入代码片
请注意,要建立内部连接,您需要声明一些连线。命名你的连线和模块实例时要小心:名称必须是唯一的
Verilog代码:
module top_module ( input clk, input d, output q );
wire w1,w2;
my_dff one(clk,d,w1);
my_dff two(clk,w1,w2);
my_dff three(clk,w2,q);
endmodule
2.3.5Medules and vector
问题陈述:
您将获得一个my_dff8具有两个输入和一个输出的模块(实现一组 8 个 D 触发器)。实例化其中的三个,然后将它们链接在一起,形成一个长度为 3 的 8 位宽移位寄存器。此外,创建一个 4 对 1 多路复用器(未提供),它根据以下内容选择输出sel[1:0]: 输入处的值d、在第一个、第二个或第三个 D 触发器之后。(本质上,sel选择延迟输入的周期数,从零到三个时钟周期。)
提供给您的模块是: module my_dff8 ( input clk, input [7:0] d, output [7:0] q );
未提供多路复用器。一种可能的写法是在一个always块内,里面有一个case语句。
Verilog代码:
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0]w1,w2,w3;
my_dff8 one(clk,d,w1);
my_dff8 two(clk,w1,w2);
my_dff8 three(clk,w2,w3);
always@(*)
begin
case(sel)
2'd0:q=d;
2'd1:q=w1;
2'd2:q=w2;
2'd3:q=w3;
endcase
end
endmodule
每日总结:
1.将信号连接到模块端口
将电线连接到端口有两种常用的方法:按位置或按名称。
1)按位置
按位置将电线连接到端口的语法应该很熟悉,因为它使用类似 C 的语法。实例化模块时,端口根据模块的声明从左到右连接。例如:
mod_a instance1 ( wa, wb, wc );
这将实例化一个类型的模块mod_a并为其提供实例名称“instance1”,然后将信号wa(在新模块之外)连接到新模块的第一个端口 ( in1)、wb第二个端口 ( in2) 和wc第三个端口 ( out)。这种语法的一个缺点是,如果模块的端口列表发生更改,则还需要找到并更改模块的所有实例以匹配新模块。
2)按名字
按名称将信号连接到模块的端口可以使电线保持正确连接,即使端口列表发生更改。然而,这种语法更加冗长。
mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );
上面的行实例化了一个mod_a名为“instance2”类型的模块,然后将信号wa(模块外部)连接到名为in1的端口、 名为的wb端口和名为in2的端口。请注意这里的端口顺序是如何无关的,因为无论其在子模块端口列表中的位置如何,都能使用正确的名称进行连接。还要注意此语法中端口名称之前的句点。