实验任务书
基础实验包:add_16
其实实现64位加法器,我们的思路是:先实现一位加法器,然后实现4位加法器,由4个4位加法器实现一个16位加法器,然后由4个16位加法器实现一个64位加法器。本节实验我采用的是串行进位,当然还有更多的更优化的加法器,例如波形进位等。这里我们暂且不考虑效率。
其实总结起来实现过程,就是——得寸进尺
实现最底层的 4 位加法器(门电路构成)
最底层的其实还不是4位加法器,而是1位加法器,也就是下图:
这张图本身说明的是4位加法器,其中的红色部分就是单独的一个一位加法器。

一位加法器的原理非常简单,输入端有 A B Cin,输出端有S 和Cout。
它的逻辑式为:
S = (A ^ B) ^ Cin ;
Cout = ((A ^ B) . Cin) + (A . B) ;
Ps:“.”是与、“+”是或。
使用verilog语言写出:
// 根据加法器实验结构图写出下面的基本逻辑门 assign out[0] = a[0]^b[0]^cin; // 电路图中的S assign temp[0] = (a[0]&b[0])|((a[0]^b[0])&cin); // 电路图中的Cout
根据下图,复制出4个一位加法器,再将其连接起来:

module add_4(a, b, cin, out, cout);
input [3:0] a;
input [3:0] b;
input cin; // 前一位进位
output [3:0] out;
output cout; // 进位
wire [3:0] temp;
// 根据加法器实验结构图写出下面的基本逻辑门
assign out[0] = a[0]^b[0]^cin; // 电路图中的S
assign temp[0] = (a[0]&b[0])|((a[0]^b[0])&cin); // 电路图中的Cout
assign out[1] = a[1]^b[1]^temp[0];
assign temp[1] = (a[1]&b[1])|((a[1]^b[1])&temp[0]);
assign out[2] = a[2]^b[2]^temp[1];
assign temp[2] = (a[2]&b[2])|((a[2]^b[2])&temp[1]);
assign out[3] = a[3]^b[3]^temp[2];
assign temp[3] = (a[3]&b[3])|((a[3]^b[3])&temp[2]);
assign cout = temp[3];
endmodule
现在,已经实现了四位加法器。
由 4 个 4 位加法器串联,构成中层 16 位加法器
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2017/10/17 09:52:05
// Design Name:
// Module Name: add_16
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module add_4(a, b, cin, out, cout);
input [3:0] a;
input [3:0] b;
input cin; // 前一位进位
output [3:0] out;
output cout; // 进位
wire [3:0] temp;
// 根据加法器实验结构图写出下面的基本逻辑门
assign out[0] = a[0]^b[0]^cin; // 电路图中的S
assign temp[0] = (a[0]&b[0])|((a[0]^b[0])&cin); // 电路图中的Cout
assign out[1] = a[1]^b[1]^temp[0];
assign temp[1] = (a[1]&b[1])|((a[1]^b[1])&temp[0]);
assign out[2] = a[2]^b[2]^temp[1];
assign temp[2] = (a[2]&b[2])|((a[2]^b[2])&temp[1]);
assign out[3] = a[3]^b[3]^temp[2];
assign temp[3] = (a[3]&b[3])|((a[3]^b[3])&temp[2]);
assign cout = temp[3];
endmodule
module add_16(a, b, cin, out, cout, tmp);
input [15:0] a;
input [15:0] b;
input cin;
output [15:0] out;
output cout;
output [3:0] tmp;
wire [3:0] temp1;
add_4 u1_add_4(
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.out(out[3:0]),
.cout(temp1[0])
);
add_4 u2_add_4(
.a(a[7:4]),
.b(b[7:4]),
.cin(temp1[0]),
.out(out[7:4]),
.cout(temp1[1])
);
add_4 u3_add_4(
.a(a[11:8]),
.b(b[11:8]),
.cin(temp1[1]),
.out(out[11:8]),
.cout(temp1[2])
);
add_4 u4_add_4(
.a(a[15:12]),
.b(b[15:12]),
.cin(temp1[2]),
.out(out[15:12]),
.cout(temp1[3])
);
assign cout = temp1[3];
assign tmp = temp1;
endmodule
扩展方式与之前一样,采用串行进位,只要把对应的线写好就OK。
因为实验包已经提供了testbeach文件,我们直接仿真即可:
经过计算器验证,没有任何问题,计算结果正确。

由 4 个 16 位加法器串联,构成上层 64 位加法器
参考文献:
https://www.runoob.com/w3cnote/verilog-expression.html
https://images.app.goo.gl/UPpoGDEoepcnPZF86