Module shift8(八位移位寄存器)
这个练习是module_shift的延伸。模块端口不再是单一的引脚,我们现在有了以矢量作为端口的模块,你将把线矢量连接到这些模块上,而不是普通的线。与Verilog中的其他地方一样,端口的向量长度不必与连接它的电线匹配,但这将导致向量的零填充或结构。本练习不使用向量长度不匹配的连接。
您会得到一个模块my_dff8,它有两个输入和一个输出(它实现了一组8d触发器)。实例化其中三个,然后将它们链在一起,生成一个长度为3的8位宽移位寄存器。此外,创建一个4对1多路复用器(未提供),根据sel[1:0]选择输出什么:输入d的值,在第一个、第二个或第三个d触发器之后。(本质上,sel选择输入延迟的周期,从0到3个时钟周期。)
提供给你的模块是:module my_dff8 ( input clk, input [7:0] d, output [7:0] q );
没有提供复用器。一种可能的编写方法是在always块中使用case语句。
Module Declaration
module top_module ( input clk, input [7:0] d, input [1:0] sel, 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,q2,q3; my_dff8 (clk,d, q1 ); my_dff8 (clk,q1, q2 ); my_dff8 (clk,q2, q3 ); always@(*)begin case(sel) 0: q = d; 1: q = q1; 2: q = q2; 3: q = q3; endcase end endmodule
加法器模块1
您将得到一个模块add16,它执行一个16位的添加操作。实例化其中两个以创建一个32位加法器。一个add16模块计算相加结果的低16位,而第二个add16模块在收到第一个加法器的进位后计算结果的高16位。您的32位加法器不需要处理进位(假设0)或进位(忽略),但内部模块需要正确工作。(换句话说,add16模块执行16位a + b + cin,而您的模块执行32位a + b)。
如图所示将这些模块连接在一起:module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
Module Declaration
module top_module( input [31:0] a, input [31:0] b, output [31:0] sum );
答案(按名字连接比较常用,所以这里只给出按名字的结果):
module top_module( input [31:0] a, input [31:0] b, output [31:0] sum ); wire cout_to_cin; add16 u_add16_l( .a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(cout_to_cin)); add16 u_add16_h( .a(a[31:16]), .b(b[31:16]), .cin(cout_to_cin), .sum(sum[31:16]), .cout()); endmodule
加法器模块2
在本练习中,您将创建一个具有两个层次结构的电路。您的top_module将实例化add16的两个副本(提供的),每个副本将实例化add1的16个副本(您必须编写add1)。因此,必须编写两个模块:top_module和add1。
与module_add类似,您将得到一个执行16位添加的模块add16。您必须实例化其中两个以创建一个32位加法器。一个add16模块计算添加结果的低16位,而第二个add16模块计算结果的高16位。您的32位加法器不需要处理进位(假设0)或进位(忽略)。
按照下图将add16模块连接在一起。提供的模块add16有以下声明:module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
在每个add16中,将实例化16个完整的加法器(模块add1,未提供)以实际执行添加。你必须编写完整的加法器模块,声明如下:module add1 ( input a, input b, input cin, output sum, output cout );
综上所述,本设计主要分为三个模块:
- top_module -你的顶级模块。
- add16 -16位加法器模块。
- add1 - 1位全加法器模块。
Module Declaration
module top_module ( input [31:0] a, input [31:0] b, output [31:0] sum );
答案:
module top_module ( input [31:0] a, input [31:0] b, output [31:0] sum );// wire cout_to_cin; add16 u_add16_l( .a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(cout_to_cin)); add16 u_add16_h( .a(a[31:16]), .b(b[31:16]), .cin(cout_to_cin), .sum(sum[31:16]), .cout()); endmodule module add1( input a, input b, input cin, output sum, output cout ); assign sum = a ^ b ^ cin; assign cout = a&b | a&cin | b&cin; // Full adder module here endmodule
进位选择加法器
纹波进位加法器的一个缺点(前面的练习)是,加法器计算进位的延迟(在最坏的情况下,从进位算起)相当缓慢,第二级加法器直到第一级加法器完成后才能开始计算其进位。这使得加法器变慢。一个改进是进位选择加法器,如下所示。第一级加法器和之前一样,但是我们复制了第二级加法器,一个假设进位为0,一个假设进位为1,然后使用快速的2比1多路复用器来选择哪个结果恰好是正确的。
在本练习中,提供了与前一个练习相同的add16模块,该模块对两个16位数字进行进位运算,并生成一个进位和16位和。您必须实例化其中三个以使用您自己的16位2- 1多路复用器来构建进位选择加法器。
如下图所示将这些模块连接在一起。提供的模块add16有以下声明:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
Module Declaration
module top_module( input [31:0] a, input [31:0] b, output [31:0] sum );
答案:
module top_module( input [31:0] a, input [31:0] b, output [31:0] sum ); wire cout_to_cin; wire [15:0]sum_0; wire [15:0]sum_1; add16 u_add16_1( .a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(cout_to_cin)); add16 u_add16_2( .a(a[31:16]), .b(b[31:16]), .cin(0), .sum(sum_0), .cout()); add16 u_add16_3( .a(a[31:16]), .b(b[31:16]), .cin(1), .sum(sum_1), .cout()); always@(*)begin case(cout_to_cin) 0: sum[31:16]= sum_0; 1: sum[31:16]= sum_1; endcase end endmodule
加减法器
加-减法器可以由加法器建立,可以选择对一个输入取反,这相当于将输入取反,然后加1。最终得到的电路可以进行两种运算:(a + b + 0)和(a + ~b + 1)。
构建下面的加减器。
你提供了一个16位加法器模块,你需要实例化两次:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
当sub为1时,使用一个32位宽的异或门来反置b输入。(这也可以看作是b[31:0] xor与子复制32次。看到复制操作符)。也连接子输入到加法器的进位。
Module Declaration
module top_module( input [31:0] a, input [31:0] b, input sub, output [31:0] sum );
答案:
module top_module( input [31:0] a, input [31:0] b, input sub, output [31:0] sum ); wire cout_to_cin; wire [31:0] b1 ={32{sub}}^b; add16 u_add16_1( .a(a[15:0]), .b(b1[15:0]), .cin(sub), .sum(sum[15:0]), .cout(cout_to_cin)); add16 u_add16_2( .a(a[31:16]), .b(b1[31:16]), .cin(cout_to_cin), .sum(sum[31:16]), .cout()); endmodule