EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
目前在所有的cpu中,为了提高加法的计算速度。都采用了超前进位加法器。
\# g& }) Z# b. S6 p9 V; m6 l- }7 T+ ?" H, X9 b. ?
普通的加法器我们很好理解,通常的16位行波进位加法器RCA结构图如下。
, w1 R V+ F) H( L% ]& ] @1 e K
/ M9 V7 H; \5 ], z. Y3 g0 b4 R1 I可以想象最简单的加法计算就是每一位都进行一次全加器计算,然后产生一个进行c,下一个全加器在取得进位以后再进行他的位的计算,循环下去直到最后一位。这样的问题是进行一次32位的加法计算就需要至少串行的经过32个全加器,如果CPU的频率是3Ghz,那么一个时钟周期,大约333皮秒内,是无法完成一次简单的加法运算的。 那么超前进位加法器是如何做到高速计算的?
, ]: d0 V% [: z2 j: y可以想象肯定是把计算平行化了,而且是用数量来换了速度。+ m; L% N9 G+ }! g; g
但是具体是怎么做的呢?
" i( p) c1 I8 r0 L- n( L我们来一起分析下。
' h1 w) I# r0 v k# e7 O% m6 N. O: P: o! U1 x
首先考虑所有的加法情况。 |
1 D% o1 Y0 }# d" F0 V
% |+ l) V+ M! n
我们用这公式来描述所有2进制加法的进位的计算公式。
' \. o4 N- d" P) n Ci+1 = Xi Yi + Xi Ci + Yi Ci& ^/ k7 W0 C& H. l1 k2 c( n* h
6 M B5 g; r5 J. A5 R
这里C表示的是进位。
! c0 b1 \. Z3 Q& \举个例子来说就是第一位的进位C1,它是由第零位的X0*Y0+X0*C0+Y0*C0, 这里很明显C0是始终为0的。那么C1=X0*Y0) ~3 O% s6 ]. |0 V) t2 p
然后这个提取公因子公式就变成了' C( J7 V( A3 T4 N ~* \
Ci+1 = XiYi + Ci(Xi + Yi)
, C7 \+ J X2 B! e; F k$ u. P. Z" [% l) E% ?/ w
然后是不是发现,这样一来只有Ci是不确定的。, w# ?$ A! E- I' k* y
其它的Xi和Yi都是直接输入。+ Z( w2 z! }6 r2 D8 X; [* {
但是Ci其实呢通过循环inline(迭代)的一个替换,其实会变成类似
8 f8 A! K! e$ O. f" [9 g2 m Ci+1 = XiYi + (Xi + Yi)(Xi-1 Yi-1 + Ci-1(Xi-1 + Yi-1)); R$ A. H; k; Y) F* q, T( e
然后可以一直这样替换下去,直到C0这一层。或者是最右端的输入。! T" Z& }4 F" v4 p7 r% ^
一般的通常会把这几个变量成为G、P变量(Generate和Propagate)
' y/ [- U. @8 N/ x/ ~0 x Gi = XiYi
& F- q1 C4 O- t7 B. w Pi = Xi + Yi
* _6 F$ C. k% Q2 P; x4 s2 q5 @. M/ f3 U8 b" g2 D2 Z" @
' Q1 a; O4 G! u; N" o
这样理论上可以实现任何位数都在有限次内完成,但是这样的代价是位数越多需要的电路也就越多。' {$ `8 m7 d# s# Y
这里附上一张wiki中的图来说明。 |
这里第一步的时候,所有的4个全加器对每一位计算出自身的和Si、Gi和Pi。
( p# A( [5 w$ G5 |: t然后第二步,超前进位器计算出C1、C2、C3、C4,当然这里的C1、C2、C3、C4计算需要的逻辑门数量是逐步递增的。0 B$ I/ |( D( U+ l" ]) g
然后C1、C2、C3对S1、S2、S3进行进位,C4会传递给更上面的位。+ e/ F7 ]" F& X% s
基本就是这样了。
" {/ x$ L* M* y* c8 Y' X
- F1 |1 c9 \; g3 y$ G' t但是由于成本的问题一般都会把32位或者64位的切割成多个16位的超前进位来进行计算,能保证在一个时钟周期内完成基本就可以了。; i. J) ? M% S, i( j
取得一个成本和性能上的平衡。 | 4位超前进位加法器CLA的FPGA实现
2 q- O1 D& C2 G9 p# ^2 M' d9 G% K; O \' T- W) p I
module cla4_adder (a, b, cin, s, cout); //顶层模块
4 @0 f* z E1 Y8 a- }8 z. i5 d; Z9 E3 ~9 X/ E! Q9 M0 E
input [3:0] a, b;
5 _5 |* ]$ x1 [* d/ y input cin;
3 i B4 b+ Q4 ~4 a) o2 J4 m
2 r$ V' y3 v; D. ^$ t% q output [3:0] s;
9 H! }$ ~2 z2 Z5 K# i output cout;
1 u8 Z3 e! M# y+ |7 y) {% p; q, U9 i+ y, |( J7 g2 L8 R
wire gg, gp; // G" d9 i5 z* E
; M4 ?0 r+ g1 k( L0 c+ S. `- @
bitslice4 b0 (a[ 3: 0], b[ 3: 0], cin, s[ 3: 0], gp, gg);
( J1 ~6 D) t- M* y: S$ {( K
4 V% C/ C* H& O2 ^7 P7 T( c2 p assign cout = gg | (gp & cin);
! n+ {( Y: c6 x/ |- i+ e) m% a; ]/ |
7 a; N# Y) r" ?& mendmodule | 其调用的4个子模块如下。' j' o* D- z+ X/ }
以后不论位数怎么变,只会修改顶层调用的模块,以下4个子模块均不需变化。
2 ^' M8 ^+ T6 X( M2 a( |" K. W( y
/ c3 I0 ]( O6 P( U1 D+ A% @//求和并按输出a,b,cin分组
! b3 v h; _ x# Hmodule bitslice4 (a, b, cin, s, gp, gg);- q7 }) ]) N2 ?. e
/ q$ r* c! R& V/ A7 z! J
input [3:0] a,b;
; b) N0 N; q' N9 z$ i) ? input cin;
* a- H. x- t# J+ y output [3:0] s;
9 R" u0 Q. _5 f$ V9 { output gp,gg;
1 [3 I; \2 N2 J2 `6 C6 L
+ j5 _( P. X3 k4 N2 v wire [3:0] p,g,c;5 Y: r3 O- l3 ~3 G% H
6 @ o2 x# d9 G/ f* [& x pg4 i1 (a, b, p, g); O/ O! I, H2 h4 t' T$ |7 P
cla4 i2 (p, g, cin, c, gp, gg);7 d" R# `$ t x& l1 N! z4 y
sum4 i3 (a, b, c, s);8 h+ m4 ]4 b% ^: x7 j9 B$ g
+ k4 k# j* ~4 K5 `endmodule * P( I1 S& `* I3 O8 L3 v- @% y" m
0 a6 M, l7 f9 G) F0 e% }: L//计算传播值和产生值的PG模块$ I9 y. i; G" K% w
module pg4 (a, b, p, g);
- n( C H* W" M0 }. a7 F1 W3 X( }. S) {: u Z
input [3:0] a, b;
& a3 p4 w! t7 S: {( r$ {& R, G' T* @3 L( E8 S+ p& X
output [3:0] p, g;/ J# [7 y4 ^; |: @9 A
9 ~$ l( L- Q, A2 a
assign p = a | b;
) n# m( t2 J, J/ ^; S5 c: k assign g = a & b;
2 G$ W8 j0 [& q- w4 d$ N& |0 f4 f. O4 @1 E$ R5 o/ R( ?
endmodule ! t# V5 O: f+ ^3 ~/ e
; A5 j. P! g w$ M0 v/ \4 o5 D$ }' [
//计算sum值的sum模块( B: a \. e4 T( U. @
module sum4 (a, b, c, s);! a3 e, w7 K1 j" g) y7 O4 J- ~9 A
4 @& N! [ l0 u1 G9 g* e, A4 b input [3:0] a,b,c;
, \8 v) Q6 Y: N$ r) ~8 P
6 S: ^; A, N: i output [3:0] s;6 Q1 q q3 k9 X: K5 i' G/ K. ~' T
+ S f$ }9 t& v9 ? wire [3:0] t = a ^ b; 2 }6 Z1 R+ ~. R r2 \. j! P+ G+ e
& u! ~2 g; Q5 x, T' |3 H/ k+ d assign s = t ^ c;
$ j: k5 I5 N2 F& e+ |
, A% C: b8 e" Z9 o; c% }6 dendmodule $ O$ M5 g! z, J) J
% m: N& k* C+ i! \3 n* w, Z/ H
0 j# e8 P2 y4 S' U1 |3 F5 T' _. \. @- t/ V
//n-bit 超前进位模块* _ o4 ?; s- M
module cla4 (p, g, cin, c, gp, gg);
v8 I: ^. B5 ^8 P% e7 T2 G; T8 x
3 i0 C) c8 I" F+ r/ p+ N input [3:0] p,g; //输出的propagate bit 和generate bit) P! {% X6 Y5 x
input cin; //进位输入
) E A: c/ |! } output [3:0] c; //为每一位产生进位. H# B- n3 l5 F4 v9 V0 t
output gp, gg; //传播值和进位制4 v1 r/ f D" a+ F! l+ M+ W
4 V3 E" Q0 ?# U1 d+ J6 s8 V7 S
assign {c,gp,gg} = do_cla4 (p, g, cin);+ {# f# g3 w; `6 Q
, ?" \0 L$ b/ @" d# O' H( n; h+ y0 {// function [99:0] do_cla4; //该函数内将为每个位计算其进位值6 [) L/ I2 n1 X7 g' N
function [5:0] do_cla4; //该函数内将为每个位计算其进位值) Q. L$ L7 t6 w" m9 z5 e
input [3:0] p, g;
# o) W. J5 }' ?; t+ `* X input cin;
/ C! C0 ^. w+ u1 V6 \+ \( V' n0 T/ B8 c J |5 E
begin: label( T* z' i3 e {0 l
integer i;
' z. Z( h: \" s: J& i: E reg gp, gg;1 A! X2 H2 ] M: _( K4 d) j- B% M
reg [3:0] c;
+ o2 |; ?2 i. O- k$ H gp = p[0];& d6 U9 }9 r0 s( Q2 [, d
gg = g[0];
5 ~! S3 E9 K8 f Q8 D6 a" B c[0] = cin;7 ?9 l: h' a% p/ t6 |/ C, m5 x% b0 I
$ {. J1 n0 l5 Z0 A for (i=1;i<4;i=i+1)
" H: j5 h) _! w/ Z# } begin 2 L( M1 U% c; a& ]
//C0=G0+P0C_1
# b$ F% a! }7 H! i% X' { //C1=G1+P1C0=(G1+P1G0)+P1P0C_1
( u; w2 R' M, _# a- I7 V gp = gp & p;
% _1 u# Z4 d# [( ^+ W( @ gg = (gg & p) | g;
2 i5 J& L+ ?* ]6 u0 M" f c = (c[i-1] & p[i-1]) | g[i-1];8 g% w) |5 i: w& ]) b; n; g& L. I. i
end
/ y* U; y& Q8 D( ~ h do_cla4 = {c,gp,gg};
, d" w; i% W7 u end
4 ?, e- N# d) ^7 b endfunction( c. k' ?3 }- j7 @, ?5 P5 ~/ S
" w( e; X) [8 j6 r8 m
endmodule | 4位超前进位加法器CLA的FPGA实现架构图如下。 |
cla4_adder的架构图
编写cla4_adder的testbench。# x' @" n5 w) s* a; G
编写cla4_adder_tb.v代码如下。% [+ R+ n. A$ H! D& Z& J M3 l7 B
`timescale 1ns/1ps$ g: W3 K- j- n, n
5 V' [; H( T; ymodule cla4_adder_tb;
. e7 |; w* S. [- E, m% M
2 N0 ?" [9 e2 W5 J7 x9 i reg [3:0] a, b;" I: b" ]; y, T/ N6 P$ c: ?
reg cin;
+ }4 D8 U* u" @- ~9 ? 9 B9 L+ I+ t: v# p
wire [3:0] s;
: Y+ P: S1 Y' U3 A: w wire cout;
6 I1 u' d: n ]5 } ; @3 H6 s8 t7 g! l2 h& U
cla4_adder dut(.a(a), .b(b), .cin(cin), .s(s), .cout(cout));
9 }8 K' K6 \3 s' z* T! G
/ k5 L9 K( e1 v+ ~0 O integer i;! f1 Z- c+ U: [" [/ j4 |$ _* p
4 B' c$ |9 c% F7 B# N initial begin7 V6 [" g: b1 o, e7 u
a = 0; b = 0; cin = 0;' R& ]1 p$ P$ X( V# B
forever begin6 O* L% {( z: l9 d5 k( Z
for (i=0; i<16; i=i+1) begin
+ n) v4 n5 S' R #10 a = i; b = i; cin = 0;
4 R, {4 J5 V2 d# L* \# p, `7 p #10 a = i; b = i; cin = 1;
. [2 `: l' m& v1 v' r0 S$ H O end6 l5 z x6 G8 I7 f
end+ W+ ]' w* m, h2 I
end0 X" o. W7 Q) F4 X/ B4 F
6 o# P/ R% S9 H% A& J- m" l initial #1000 $stop; c& s. u L4 u% y& u
) z2 g, l _6 P L; H
endmodule 设置好仿真之后,cla4_adder仿真结果如下图。 |
5 l5 N _1 `& q% R# M
) E7 u# M! d. s1 U% m7 R |