加法是基本的运算,在数字信号处理和数字通信的各种算法中被广泛应用。由于加法器使用频繁,所以其速度往往影响整个系统的运行速度。如果可实现快速的加法器的设计,则可以提高整个系统的运行速度。
以下介绍几种常见的加法器设计,提供 Verilog 设计并分析其优缺点。
这中加法器设计由多个 1 位全加器级联构成,依次从低位向高位传递,并输出最终的结果。
Verilog 实现
module add_1 (
input [3:0] a,
input [3:0] b,
input cin,
output [3:0] sum,
output cout;
);
add_full add_full_1(
.a(a),
.b(b),
.cin(cin),
.sum(sum),
.cout(cin)
);
add_full add_full_1(
.a(a[0]),
.b(b[0]),
.cin(cin),
.sum(sum[0]),
.cout(cin1)
);
add_full add_full_2(
.a(a[1]),
.b(b[1]),
.cin(cin1),
.sum(sum[1]),
.cout(cin2)
);
add_full add_full_3(
.a(a[2]),
.b(b[2]),
.cin(cin2),
.sum(sum[2]),
.cout(cin3)
);
add_full add_full_4(
.a(a[3]),
.b(b[3]),
.cin(cin3),
.sum(sum[3]),
.cout(cin4)
);
module add_full(
input a,
input b,
input cin,
output reg sum,
output reg cout
);
always @(*) begin
{cout,sum} = a + b + cin;
end
endmodule
endmodule
行波进位加法器设计优缺点
在上一种加法器的设计,最大的缺点就是位宽比较大的计算延时过大,要想提高运行速度就必须解决位宽带来的延时影响,超前进位加法器便可以有效解决以上的弊端。
对于全加器,一位全加器的本位值和进位输出可表示为:
sum = a ^ b ^ cin
cout = (a*b) + (a*cin) + (b*cin) = ab + (a+b)*cin
可知当 a 和 b 都为 1 时,进位输出cout为 1,而当其一为 1 时,进位输出 cout 为进位输入 cin。
这样令 G = a * b,P = a + b,则有 cout = a*b + (a+b)*cin = G + P*cin
由此就可以得到各个位的进位输出呈如下结果:
进一步推算:
sum = A ^ B ^ Cin = (A*B) ^ (A + B) ^ Cin = G ^ P ^ Cin
Verilog 实现
module add_u(
input [3:0] a,
input [3:0] b,
input cin,
output [3:0] sum,
output cout
);
wire [3:0] G;
wire [3:0] P;
wire [3:0] C;
//第0位
assign G[0] = a[0] & b[0];
assign P[0] = a[0] | b[0];
assign C[0] = cin;
assign sum[0] = G[0] ^ P[0] ^ C[0];
//第1位
assign G[1] = a[1] & b[1];
assign P[1] = a[1] | b[1];
assign C[1] = cin;
assign sum[1] = G[1] ^ P[1] ^ C[1];
//第2位
assign G[2] = a[2] & b[2];
assign P[2] = a[2] | b[2];
assign C[2] = cin;
assign sum[2] = G[2] ^ P[2] ^ C[2];
//第3位
assign G[3] = a[3] & b[3];
assign P[3] = a[3] | b[3];
assign C[3] = cin;
assign sum[3] = G[3] ^ P[3] ^ C[3];
//输出最终进位值
assign cout = C[3];
endmodule
这种方式实现起来就比较简单,直接采用全加器的形式进行描述,让综合工具自动识别形成电路。
Verilog 实现
module add(
input [3:0] a,
input [3:0] b.
input cin,
output [3:0] sum,
output cout
);
assign {cout,sum} = a + b + cin;
endmodule
流水线加法器
在系统工作时为了尽可能的提高系统运行速度,保证数据的快速传输,流水线的设计是一种常见的设计方法。但是,如果在某些复杂逻辑功能的完成需要较长的延时,就会使系统难以运行在高的频率上。这种情况下,可使用流水线技术,即在长延时的逻辑功能块中插入触发器,使复杂的逻辑操作分步完成,减小每一部分的延时,从而使系统的运行频率得以提高。但是流水线的弊端在于增加了寄存器逻辑,进而消耗了更多的芯片内部资源。相当于用资源换速率,在资源允许的前提下,适当加入流水线的操作,可以显著提高系统的运行频率。
利用流水线的方法设计加法器可以显著提高系统的运行速度,以一个两级流水线的设计方法计算两个 8 位宽的数据相加。
module add(
input clk,
input [7:0] a,
input [7:0] b,
input cin,
output reg [7:0] sum,
output reg cout
);
reg [3:0] a_reg;
reg [3:0] b_reg;
reg [3:0] sum1;
reg cout1;
//计算低四位
always @(posedge clk) begin
{cout1,sum1} = a[3:0] + b[3:0] + cin;
a_reg = a[7:4];
b_reg = b[7:4];
end
//计算高四位
always @(posedge clk) begin
{cout1,sum[7:4]} = a_reg + b_reg + cout1;
sum[3:0] = sum1;
end
endmodule
将八位宽的数值计算拆分成两个四位数据的同步计算,可以提高计算速度,甚至可以差分成三份计算,这种视情况而定。