加法器是数字系统最基础的计算单元,用来产生两个数的和,加法器是以二进制作运算。负数可用二的补数来表示,减法器也是加法器,乘法器可以由加法器和移位器实现。加法器和乘法器由于会频繁使用,因此加法器的速度也影响着整个系统的计算速度。对加法器的设计也一直在更新迭代,反观数字IC初学者,往往只是了解个全加器和半加器,而对一些经典的加法器类型和实现方式却很少了解。
并行加法器就是利用多个全加器实现两个操作数各位同时相加。并行加法器中全加器的个数与操作数的位数相同,常用的并行加法器有行波进位加法器、超前进位加法器、进位选择加法器等。容易实现、运算速度快,但是耗用资源多,当位宽较宽时,耗用的资源会非常大。
Verilog代码:
// Verdion: v1.0
// Description: 8位并行加法器
// -----------------------------------------------------------------------------
module parallel_adder (
input [7:0] din_a , // data in a
input [7:0] din_b , // data in b
input cin , // carry in
output wire [7:0] sum , // summation of a ,b
output wire cout // carry out
);
assign {cout,sum} = din_a + din_b + cin ;
endmodule
这里使用的是数据流描述方式,只用了一条语句,不能控制综合的具体电路。
这里可以看出,相同的设计,在不同综合工具中综合出的电路结构是不同的,感兴趣的同学可以学习综合相关的知识点。后续也会把DC综合的教程笔记分享出来,这个可以在笔面前再了解,大部分同学都很难接触到流片相关的软件,在学校稍微熟悉就好。
超前进位加法器是由全加器发展而来,目的是提高运算速度。当加法器级数提高时,高位的进位信号需要从低级逐级传递,为了缩短这个时间,我们可以从低级的输入信号确定一个组合逻辑电路,唯一确定一个高位的进位信号,从而提高运行速度。超前进位加法器也称为快速进位加法器,目的就是缩短进位信号生成的时间。
Verilog代码:
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 [email protected]
// File : Carry_Look_ahead_adder.v
// Create : 2022-11-19 16:15:31
// Revise : 2022-11-19 16:15:31
// Editor : 0078
// Verdion: v1.0
// Description: 8bit 超前进位加法器
// -----------------------------------------------------------------------------
module Carry_Look_ahead_adder (
input [7:0] din_a , // data in a
input [7:0] din_b , // data in b
input cin , // carry in
output wire cout , // carry out
output wire [7:0] sum // summation of a ,b
);
wire [7:0] G ;
wire [7:0] P ;
wire [7:0] C ;
assign G[0] = din_a[0] & din_b[0] ; //bit 0
assign P[0] = din_a[0] | din_b[0] ;
assign C[0] = cin ;
assign sum[0] = G[0] ^ P[0] ^ C[0] ;
assign G[1] = din_a[1] & din_b[1] ; //bit 1
assign P[1] = din_a[1] | din_b[1] ;
assign C[1] = G[0] | (P[0] & cin) ;
assign sum[1] = G[1] ^ P[1] ^ C[1] ;
assign G[2] = din_a[2] & din_b[2] ; //bit 2
assign P[2] = din_a[2] | din_b[2] ;
assign C[2] = G[1] | (P[1] & C[1]) ;
assign sum[2] = G[2] ^ P[2] ^ C[2] ;
assign G[3] = din_a[3] & din_b[3] ; //bit 3
assign P[3] = din_a[3] | din_b[3] ;
assign C[3] = G[2] | (P[2] & C[2]) ;
assign sum[3] = G[3] ^ P[3] ^ C[3] ;
assign G[4] = din_a[4] & din_b[4] ; //bit 4
assign P[4] = din_a[4] | din_b[4] ;
assign C[4] = G[3] | (P[3] & C[3]) ;
assign sum[4] = G[4] ^ P[4] ^ C[4] ;
assign G[5] = din_a[5] & din_b[5] ; //bit 5
assign P[5] = din_a[5] | din_b[5] ;
assign C[5] = G[4] | (P[4] & C[4]) ;
assign sum[5] = G[5] ^ P[5] ^ C[5] ;
assign G[6] = din_a[6] & din_b[6] ; //bit 6
assign P[6] = din_a[6] | din_b[6] ;
assign C[6] = G[5] | (P[5] & C[5]) ;
assign sum[6] = G[6] ^ P[6] ^ C[6] ;
assign G[7] = din_a[7] & din_b[7] ; //bit 7
assign P[7] = din_a[7] | din_b[7] ;
assign C[7] = G[6] | (P[6] & C[6]) ;
assign sum[7] = G[7] ^ P[7] ^ C[7] ;
assign cout = G[7] | (P[7] & C[7]) ;
endmodule
Quartus Post mapping图
使用的资源明显要高于普通的并行加法器。
流水线设计可以有效提高工作频率,核心就是面积换速度。
Verilog代码:
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT90S [email protected]
// File : Pipeline_adder.v
// Create : 2022-11-21 15:40:45
// Revise : 2022-11-21 15:40:45
// Editor : 0078
// Verdion: v1.0
// Description: 8bit 流水线加法器
// -----------------------------------------------------------------------------
module Pipeline_adder (
input [7:0] din_a , // data in a
input [7:0] din_b , // data in b
input cin , // Carry in
input clk , // Clock
output reg [7:0] sum , // Sum
output reg cout // Carry out
);
reg [7:0] a_t ;
reg [7:0] b_t ;
//carry in & out
reg ci_t ;
reg p1co ;
reg p2co ;
reg p3co ;
reg [5:0] p1a ;
reg [5:0] p1b ;
reg [1:0] p1s ;
reg [3:0] p2a ;
reg [3:0] p2b ;
reg [3:0] p2s ;
reg [1:0] p3a ;
reg [1:0] p3b ;
reg [5:0] p3s ;
always@(posedge clk) begin
a_t <= din_a ;
b_t <= din_b ;
ci_t <= cin ;
end
always@(posedge clk ) begin
{p1co,p1s} <= a_t[1:0] + b_t[1:0] + ci_t ;
p1a <= a_t[7:2] ;
p1b <= b_t[7:2] ;
end
always@(posedge clk ) begin
{p2co,p2s} <= p1a[1:0] + p1b[1:0] + p1co + p1s ;
p2a <= p1a[5:2] ;
p2b <= p1b[5:2] ;
end
always@(posedge clk ) begin
{p3co,p3s} <= p2a[1:0] + p2b[1:0] + p2co + p2s ;
p3a <= p1a[3:2] ;
p3b <= p1b[3:2] ;
end
always@(posedge clk ) begin
{cout,sum} <= p3a[1:0] + p3b[1:0] + p3co + p3s ;
end
endmodule
Quartus RTL图
用到了四个2bit加法器以及中间数据缓存。
Quartus Post mapping图
这个资源的使用就更多,更大的面积换取更高的运行速度。
级联加法器的结构简单,但N位级联加法器的延时是一位全加器的N倍,延时主要是由于进位信号级联造成的,避免在高性能要求的设计中采用该结构。
Verilog代码:
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT90S [email protected]
// File : Cascade_adder.v
// Create : 2023-03-20 10:51:14
// Revise : 2023-03-20 10:51:14
// Editor : 0078
// Verdion: v1.0
// Description: 8bit 级联加法器
// -----------------------------------------------------------------------------
module Cascade_adder(
input [7:0] a , //data in a
input [7:0] b , //data in b
input cin , //carry in
output wire cout , //carry out
output wire [7:0] sum //sum
);
//signal
wire cin1 ;
wire cin2 ;
wire cin3 ;
wire cin4 ;
wire cin5 ;
wire cin6 ;
wire cin7 ;
// inst cascade desc
full_add1 f0(
.a (a[0] ),
.b (b[0] ),
.cin (cin ),
.cout (cin1 ),
.sum (sum[0] )
);
full_add1 f1(
.a (a[1] ),
.b (b[1] ),
.cin (cin1 ),
.cout (cin2 ),
.sum (sum[1] )
);
full_add1 f2(
.a (a[2] ),
.b (b[2] ),
.cin (cin2 ),
.cout (cin3 ),
.sum (sum[2] )
);
full_add1 f3(
.a (a[3] ),
.b (b[3] ),
.cin (cin3 ),
.cout (cin4 ),
.sum (sum[3] )
);
full_add1 f4(
.a (a[4] ),
.b (b[4] ),
.cin (cin4 ),
.cout (cin5 ),
.sum (sum[4] )
);
full_add1 f5(
.a (a[5] ),
.b (b[5] ),
.cin (cin5 ),
.cout (cin6 ),
.sum (sum[5] )
);
full_add1 f6(
.a (a[6] ),
.b (b[6] ),
.cin (cin6 ),
.cout (cin7 ),
.sum (sum[6] )
);
full_add1 f7(
.a (a[7] ),
.b (b[7] ),
.cin (cin7 ),
.cout (cout ),
.sum (sum[7] )
);
endmodule
其中,8bit级联加法器需要使用8个单bit的全加器。其描述如下:
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT90S [email protected]
// File : fuu_add1.v
// Create : 2023-03-20 11:06:52
// Revise : 2023-03-20 11:06:52
// Editor : 0078
// Verdion: v1.0
// Description: 1bit full adder
// -----------------------------------------------------------------------------
module full_add1 (
input a , // data in a
input b , // data in b
input cin , // carry in
output sum , // sum
output cout // carry out
);
//signal
wire s1 ;
wire m1 ;
wire m2 ;
wire m3 ;
and (m1,a,b ),
(m2,b,cin ),
(m3,a,cin );
xor (s1,a,b ),
(sum,s1,cin );
or (cout,m1,m2,m3);
endmodule
Quartus RTL图
用到了8个加法器。
单bit全加器。
Quartus Post mapping图