目录
加法是基本的运算,在数字信号处理和数字通信的各种算法中被广泛应用。由于加法器使用频繁,所以其速度往往影响整个系统的运行速度。如果可实现快速的加法器的设计,则可以提高整个系统的运行速度。
以下介绍几种常见的加法器设计,提供 Verilog 设计并分析其优缺点。
这中加法器设计由多个 1 位全加器级联构成,依次从低位向高位传递,并输出最终的结果。
- 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
- 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
这种方式实现起来就比较简单,直接采用全加器的形式进行描述,让综合工具自动识别形成电路。
- 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
将八位宽的数值计算拆分成两个四位数据的同步计算,可以提高计算速度,甚至可以差分成三份计算,这种视情况而定。