下列提供的代码答案不唯一!
目录
2、Connecting ports by position
1、Modules
下图显示了一个非常简单的电路及其子模块。在这个练习中,创建模块mod_a的一个实例,然后将模块的三个引脚(in1、in2和out)连接到top_module的三个端口(连接a、b和out)。
只要使用的所有模块都属于同一个项目(这样编译器就知道在哪里找到模块),就可以通过在模块内部实例化一个模块来创建模块的层次结构。一个模块的代码不能在另一个模块的主体中编写(不同模块的代码不是嵌套的)。
有两种常用的方法将wire连接到端口,按位置或按名称连接。
按位置将导线连接到端口的语法应该很熟悉,因为它使用了类似c的语法。当实例化一个模块时,端口根据模块的声明从左到右连接。例如:
mod_a instance1 (wa, wb, wc);
这将实例化一个mod_a类型的模块,并给它一个实例名“instance1”,然后将信号wa(在新模块外部)连接到新模块的第一个端口(in1), wb连接到第二个端口(in2), wc连接到第三个端口(out)。该语法的一个缺点是,如果模块的端口列表发生变化,则需要找到并修改模块的所有实例,以匹配新模块。按名称将wire连接到模块的端口,即使端口列表发生变化,连接线也可以保持正确连接。但是,这种语法更加冗长。
mod_a instance2(.out(wc), .in1(wa), .in2(wb));
上面的代码实例化了一个名为“instance2”的mod_a类型的模块,然后将信号wa(在模块外部)连接到名为in1的端口,将wb连接到名为in2的端口,将wc连接到名为out的端口。注意,这里端口的排序是如何无关紧要的,因为连接将连接到正确的名称,而不管它在子模块的端口列表中的位置。

代码:
module top_module ( input a, input b, output out );
mod_a(
.in1(a),
.in2(b),
.out(out)
);
endmodule
2、Connecting ports by position
这个问题类似于上述。一个名为mod_a的模块,它有2个输出和4个输入。必须按位置顺序将6个端口连接到顶级模块的端口out1、out2、a、b、c和d。
按下列模板::
mod_a ( output, output, input, input, input, input );

代码:
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a(out1, out2, a, b, c, d);
endmodule
3、Connecting ports by name
一个名为mod_a的模块,它有2个输出和4个输入,按某种顺序。必须按名称将这6个端口连接到top_module的端口。

按下列模板:
mod_a ( output out1, output out2, input in1, input in2, input in3, input in4);

代码:
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
4、Three modules
提供一个模块my_dff,它有两个输入和一个输出(相当于一个D触发器)。将它们链接在一起,形成长度为3的移位寄存器。

代码:
module top_module ( input clk, input d, output q );
wire q_1;
wire q_2;
my_dff u_my_dff_1(
.clk(clk),
.d(d),
.q(q_1)
);
my_dff u_my_dff_2(
.clk(clk),
.d(q_1),
.q(q_2)
);
my_dff u_my_dff_3(
.clk(clk),
.d(q_2),
.q(q)
);
endmodule
5、Modules and vectors
模块端口不再是单一的引脚,我们现在有了以向量作为端口的模块。
一个模块my_dff8,它有两个输入和一个输出(实现了一组8个D触发器)。将三个链接在一起,形成一个长度为3的8位宽移位寄存器。另外,创建一个4选1的多路器,根据sel[1:0]选择输出内容:输入d处的值,在第一个、第二个或第三个d触发器之后。
按下列模板:
my_dff8 ( input clk, input [7:0] d, output [7:0] q );

代码:
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0] q1;
wire [7:0] q2;
wire [7:0] q3;
my_dff8 u_my_dff8_1(
.clk(clk),
.d(d),
.q(q1)
);
my_dff8 u_my_dff8_2(
.clk(clk),
.d(q1),
.q(q2)
);
my_dff8 u_my_dff8_3(
.clk(clk),
.d(q2),
.q(q3)
);
always@(*)
begin
case(sel)
2'b00 : q = d;
2'b01 : q = q1;
2'b10 : q = q2;
2'b11 : q = q3;
endcase
end
endmodule
6、Adder1
一个模块add16,它执行16位加法。实例化其中两个来创建一个32位加法器。一个add16模块计算相加结果的下16位,而第二个add16模块在接收到第一个加法器的执行结果后,计算结果的上16位。32位加法器不需要处理输入或输出,但是内部模块需要处理才能正确运行。(换句话说,add16模块执行16位a + b + cin,而该模块执行32位a + b)。
按下列模板:
add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
如下图所示将模块连接在一起。

代码:
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cout_lo;
wire [15:0] sum_lo;
wire [15:0] sum_hi;
wire cout;
wire cin_lo;
add16 add16_lo(
.a({a[15:0]}),
.b({b[15:0]}),
.cin(cin_lo),
.sum(sum_lo),
.cout(cout_lo)
);
add16 add16_hi(
.a({a[31:16]}),
.b({b[31:16]}),
.cin(cout_lo),
.sum(sum_hi),
.cout(cout)
);
assign sum = {sum_hi, sum_lo};
endmodule
7、Adder2
在这个练习中,将创建一个具有两层层次结构的电路。top_module将实例化add16的两个副本(提供),每个副本将实例化add1的16个副本(必须编写)。因此,必须编写两个模块:top_module和add1。提供一个模块add16,它执行16位加法您必须实例化其中两个来创建一个32位加法器。一个add16模块计算加法结果的下16位,而第二个add16模块计算加法结果的上16位。
综上所述,本次设计共有三个模块:
top_module——顶层模块
add16——一个16位加法器模块
add1——1位完全加法器模块
按下列模板:
add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
add1 ( input a, input b, input cin, output sum, output cout );

代码:
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire cin_lo ;
wire cout_lo;
wire cout;
wire [15:0] sum_lo;
wire [15:0] sum_hi;
add16 add16_lo(
.a({a[15:0]}),
.b({b[15:0]}),
.cin(cin_lo),
.sum(sum_lo),
.cout(cout_lo)
);
add16 add16_hi(
.a({a[31:16]}),
.b({b[31:16]}),
.cin(cout_lo),
.sum(sum_hi),
.cout(cout)
);
assign sum={sum_hi,sum_lo};
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
// Full adder module here
assign sum = a ^ b ^ cin;
assign cout = (a ^ b) & cin | a & b;
endmodule
8、Carry-select adder
前面进位加法器的有一个缺点,是加法器计算进位的延迟在最坏的情况下是相当慢的,在第一阶段加法器完成之前,第二阶段加法器不能开始计算它的进位。这使得加法器变慢。改进之一是进位选择加法器,如下图所示。第一阶段加法器与之前相同,但我们复制了第二阶段加法器,一个假设进位=0,一个假设进位=1,然后使用快速2选1多路选择器来选择哪个结果是正确的。
在本练习中,提供与上一个模块add16,该模块将两个带进位的16位数字相加,并生成一个带进位的16位和。
按下列模板:
add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );

代码:
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cin1=0;
wire cin2=1;
wire [15:0] sum1,sum2,sum3,sum4;
wire cout1,cout2,cout3;
add16 add16_1(
.a({a[15:0]}),
.b({b[15:0]}),
.cin(cin1),
.sum(sum1),
.cout(cout1)
);
add16 add16_2(
.a({a[31:16]}),
.b({b[31:16]}),
.cin(cin1),
.sum(sum2),
.cout(cout2)
);
add16 add16_3(
.a({a[31:16]}),
.b({b[31:16]}),
.cin(cin2),
.sum(sum3),
.cout(cout3)
);
always@(a or b)
begin
if(cout1==0) sum4=sum2;
else sum4 = sum3;
end
assign sum = {sum4,sum1};
/*
//也可以这样
always@(a or b)begin
if(cout1 == 0)
sum = {sum2, sum1};
else
sum = {sum3, sum1};
end
*/
endmodule
9、Adder-subtractor
加-减法器可以由加法器构建,可选地对其中一个输入取反,这相当于将输入取反,然后加1。最终的结果是一个可以进行(a + b + 0)和(a + ~b + 1)两种操作的电路。如果想要更详细的电路工作原理的解释,请参阅维基百科。
构建下图的加-减法器。 按下列模板:
add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
当sub为1时,使用32位宽的异或门来反转b输入。

代码:
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire cout1, cout2;
wire [15:0] b_lo;
wire [15:0] b_hi;
wire [15:0] sum_lo;
wire [15:0] sum_hi;
always@(a or b or sub)begin
if(sub == 0)begin
b_lo = b[15:0];
b_hi = b[31:16];
end
else begin
//取反,程序到这说明sub=1,16位宽都为1与其进行异或运行,0变1,1变0,从而达到取反的效果
b_lo = {16{sub}} ^ b[15:0];
b_hi = {16{sub}} ^ b[31:16];
end
end
add16 u_add16_1(
.a(a[15:0]),
.b(b_lo),
.cin(sub),
.sum(sum_lo),
.cout(cout1)
);
add16 u_add16_2(
.a(a[31:16]),
.b(b_hi),
.cin(cout1),
.sum(sum_hi),
.cout(cout2)
);
assign sum = {sum_hi, sum_lo};
endmodule
本文详细介绍了VHDL和Verilog在数字电路设计中的模块连接方法,包括按位置和按名称连接端口,以及多层次模块实例化。通过实例展示了如何创建32位加法器、移位寄存器、进位选择加法器和加减法器。同时,探讨了加法器的优化,如进位选择加法器减少延迟的设计思想。
184

被折叠的 条评论
为什么被折叠?



