EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
目前在所有的cpu中,为了提高加法的计算速度。都采用了超前进位加法器。# l% t. ~( h/ r- a& Q/ Q4 Q( L/ Y
+ g# o- t" e0 @普通的加法器我们很好理解,通常的16位行波进位加法器RCA结构图如下。
$ v9 t/ N' G b- H
v3 z8 A: }* _& b2 Q/ ?
可以想象最简单的加法计算就是每一位都进行一次全加器计算,然后产生一个进行c,下一个全加器在取得进位以后再进行他的位的计算,循环下去直到最后一位。这样的问题是进行一次32位的加法计算就需要至少串行的经过32个全加器,如果CPU的频率是3Ghz,那么一个时钟周期,大约333皮秒内,是无法完成一次简单的加法运算的。 那么超前进位加法器是如何做到高速计算的?
8 _) Q$ s: q! M可以想象肯定是把计算平行化了,而且是用数量来换了速度。
9 l$ ]* o6 b" D但是具体是怎么做的呢?
" q; @5 W+ q# [, M2 K% E( v" p我们来一起分析下。' c3 W9 e: ~2 s2 a5 j- t
# X" } q8 S3 M0 X首先考虑所有的加法情况。 |
' S" P3 M- P6 \+ U7 w* F0 l. i/ a; U. P7 f
我们用这公式来描述所有2进制加法的进位的计算公式。
' S' r; k# }# n+ ^ Ci+1 = Xi Yi + Xi Ci + Yi Ci
1 ^+ n) g. y/ @9 W$ Q6 @/ ]1 }' {) a' D! r5 D8 `
这里C表示的是进位。5 F( z4 Z5 A" Q T" u8 k
举个例子来说就是第一位的进位C1,它是由第零位的X0*Y0+X0*C0+Y0*C0, 这里很明显C0是始终为0的。那么C1=X0*Y01 W @( |1 S9 I. D
然后这个提取公因子公式就变成了
. t$ N6 Q/ u7 z. _ Ci+1 = XiYi + Ci(Xi + Yi)
6 d7 D2 y; c" Q# x( m- O' B) p% x+ j. c# L) p3 b
然后是不是发现,这样一来只有Ci是不确定的。
- B- I* F2 I; ~其它的Xi和Yi都是直接输入。 X7 l( J2 {8 @2 E
但是Ci其实呢通过循环inline(迭代)的一个替换,其实会变成类似' s v- Y- V6 A- j$ W/ }
Ci+1 = XiYi + (Xi + Yi)(Xi-1 Yi-1 + Ci-1(Xi-1 + Yi-1))
8 c- v' L) E2 R3 W然后可以一直这样替换下去,直到C0这一层。或者是最右端的输入。! e& |) H8 p9 k, i5 O
一般的通常会把这几个变量成为G、P变量(Generate和Propagate)5 ^; _0 ^) Z1 G$ ^1 N
Gi = XiYi $ E* g3 Q1 V' P ?: u5 h
Pi = Xi + Yi
+ N; |/ m0 V u9 j! ~* }; h
5 N. |! t3 k b0 N4 n9 v! p5 C4 s! {
$ O5 n. Q4 R: l- Q9 P- U* W& d8 i这样理论上可以实现任何位数都在有限次内完成,但是这样的代价是位数越多需要的电路也就越多。
- A0 i3 P5 M# b$ N C这里附上一张wiki中的图来说明。
|
这里第一步的时候,所有的4个全加器对每一位计算出自身的和Si、Gi和Pi。# b1 w% h& n! Y$ N% }
然后第二步,超前进位器计算出C1、C2、C3、C4,当然这里的C1、C2、C3、C4计算需要的逻辑门数量是逐步递增的。+ W5 w. `) \" O4 s
然后C1、C2、C3对S1、S2、S3进行进位,C4会传递给更上面的位。
+ F9 R7 K/ ^* V/ d ]基本就是这样了。
$ R; K" N6 F+ j% o3 q: p" O- P* |& |$ @# `( h0 J
但是由于成本的问题一般都会把32位或者64位的切割成多个16位的超前进位来进行计算,能保证在一个时钟周期内完成基本就可以了。
/ z( h, M. w& C取得一个成本和性能上的平衡。 | 4位超前进位加法器CLA的FPGA实现
* T! T. E- T! H0 z: [+ H0 `
4 _- N8 h8 y: t. L( _( n) [module cla4_adder (a, b, cin, s, cout); //顶层模块
3 ~3 W2 e4 B1 y0 B* y# K8 K7 _+ h
0 ]! |+ q6 a6 F9 A0 S9 `1 y input [3:0] a, b; E% [6 S. K9 P8 S+ f1 Y
input cin;
. v' ] X ]2 b4 X5 j; Q' J , F3 W3 G$ H, x( j' l
output [3:0] s;
+ d2 V8 ]) W) A y2 g output cout;
- G5 }# L# k: d1 W* f% d7 e T" Z# m6 c
wire gg, gp; //3 g3 O6 h+ ~$ I/ ~) V
4 z. s1 H# ?% ]: e' e! I' H bitslice4 b0 (a[ 3: 0], b[ 3: 0], cin, s[ 3: 0], gp, gg);
: r8 ^% {7 ^* W
9 u3 Q& C+ F7 u* ^8 j# d assign cout = gg | (gp & cin);
* c Z# C8 N5 m2 M: a1 U0 J5 f1 B$ M$ c. j$ q" }. o& ?! g
endmodule | 其调用的4个子模块如下。
6 P" P1 Z2 ^: e+ @+ P$ s& T以后不论位数怎么变,只会修改顶层调用的模块,以下4个子模块均不需变化。
1 M* {* |* {- t2 h1 _) a5 B0 k7 W4 H& l
//求和并按输出a,b,cin分组
' g; Q, x" U2 J+ Wmodule bitslice4 (a, b, cin, s, gp, gg);
/ H* g. O2 _- ~% u9 I0 o# ^9 j7 I: j) f7 x) \( E
input [3:0] a,b;
( T- c, P% l2 G: I" g input cin;
: h4 z3 ]6 i4 o$ `) i! n. O: e output [3:0] s;
0 ?% T I3 v7 S# N+ h# D F, y output gp,gg;& _5 H/ O b( `% b7 ~
# W/ v( C6 Q7 O! [) S) F wire [3:0] p,g,c;. D$ {( R3 L0 O5 w: p8 }4 `# t# O
2 {( N) b* V6 `/ _8 i( X2 P
pg4 i1 (a, b, p, g);
( U, M- Q1 l6 @, W6 L cla4 i2 (p, g, cin, c, gp, gg);
, L0 }3 s: v8 D& X4 { sum4 i3 (a, b, c, s);
+ ?# n0 p7 A2 K5 E
- U- P) e0 n* Z# \( z* Z$ Z3 V% gendmodule 5 t2 |0 w, R1 p- W
& i4 d& v2 {8 r# x//计算传播值和产生值的PG模块* I1 Q5 s3 w9 A) ^
module pg4 (a, b, p, g);+ j: X# s9 C. A$ o# R2 x5 D2 ^
1 ]+ x b, i: o2 m5 w' h
input [3:0] a, b;$ R% H2 r0 v+ O( h
3 W, ^$ x0 J; N7 t* {' x
output [3:0] p, g;
* Z$ C& C/ x6 _/ w- I
6 b; H" u8 n! T7 n assign p = a | b;
/ m8 N2 ~: H) q: U1 u assign g = a & b;
$ M( K- N6 [# q( n, c
* D s3 C9 ~- }5 j g0 C; u* [+ Xendmodule
+ o1 D( h, J* g% q' t2 A- f- |7 d5 D
# M, i+ ]& i+ E' ]& M; y0 c; a, [//计算sum值的sum模块 E- g6 V2 u3 d# u6 ]4 O! W
module sum4 (a, b, c, s);
# [- E2 O4 ^" j, v+ C" Z2 a2 O0 N/ i* O( P7 d! D% r
input [3:0] a,b,c;( o4 F- w8 [8 {9 j) A( ^: S+ R
' J: f2 M. q7 d3 r. N$ ?
output [3:0] s;
" r0 O8 j: r( X6 j3 @& [2 j9 r % X j2 C" a, e) g/ P
wire [3:0] t = a ^ b; / v3 o: `% H4 ^5 x; k
v" p7 S# \% k1 k! J
assign s = t ^ c;6 J; s4 I. K" ~8 S
4 R6 j6 }" @* K# ?( Zendmodule
1 Q1 U$ h7 H j, h: z: [# _9 _1 ~3 g" w6 }6 A1 Y
$ x) N3 l0 Z+ J" a6 ]: ~: I3 e
8 W2 O" m& e3 ~( b//n-bit 超前进位模块5 p/ t [/ M# i V8 T
module cla4 (p, g, cin, c, gp, gg);
4 Y0 ]$ ]' m4 s' N# ?9 `
$ @, U" q, K, s D input [3:0] p,g; //输出的propagate bit 和generate bit
$ L- i* c( j4 L$ j H2 q input cin; //进位输入8 G% u# N; W: U7 K! j I
output [3:0] c; //为每一位产生进位8 L' |8 B/ ]4 `$ J) ~
output gp, gg; //传播值和进位制4 _) h/ @* ~- @8 H+ B3 D3 ?
; q) p( s! b) d, ? assign {c,gp,gg} = do_cla4 (p, g, cin);- E5 O) w$ ^+ I$ L& K( g# u
6 ?3 ?) c- J& s) U. L! u
// function [99:0] do_cla4; //该函数内将为每个位计算其进位值& x& F9 j k( @$ a$ R5 H0 `
function [5:0] do_cla4; //该函数内将为每个位计算其进位值5 s K M* S& r" G
input [3:0] p, g;
5 Z: ~ c' S" T3 n6 D; O7 j input cin;3 T0 i# D' m( r) k) t
! {7 i1 Z2 P" p& n begin: label; k% e3 n! h E; A
integer i;, C5 n. B6 t% S% ]& H
reg gp, gg;
7 V7 S% s# N( F0 [0 E reg [3:0] c;
- K6 E3 X6 N9 Q8 S+ s( x7 i' N gp = p[0];9 i- k) E$ Y8 ^2 H7 b% q( d
gg = g[0];( {* }0 q- W1 \+ d n9 J3 U
c[0] = cin;# L; V) H8 ^) j
4 C- H) X1 B0 Z for (i=1;i<4;i=i+1)
* o( m9 [. E4 Q$ Q) B6 O: I+ D begin ' t3 t6 ~" n* r6 J$ u/ O
//C0=G0+P0C_1* Z+ r# l$ f- u! g2 L( E- C3 j) q
//C1=G1+P1C0=(G1+P1G0)+P1P0C_1. F, O! O1 x4 O5 ?2 O- k' {
gp = gp & p;
P/ c: j0 N7 c8 x2 j9 J gg = (gg & p) | g;
- X/ \; `- Y3 g% d' {- ^" [ c = (c[i-1] & p[i-1]) | g[i-1];
5 t) g' D3 z l end( P4 q0 k1 T: V! K1 R5 N
do_cla4 = {c,gp,gg};7 _9 V4 G* F2 \; Y X/ E
end! v7 }0 L* z$ d* n
endfunction
' L, u* H' j* x6 A; ^2 p
o0 w) H. L" tendmodule | 4位超前进位加法器CLA的FPGA实现架构图如下。 |
cla4_adder的架构图
编写cla4_adder的testbench。; q1 L0 j9 w* A9 \) `
编写cla4_adder_tb.v代码如下。
% y5 C6 d) z: c. a, ?9 r`timescale 1ns/1ps
8 M7 z) k% t1 Q: |: h- u* M- m. o
* y+ m* s9 M1 s' H( L" nmodule cla4_adder_tb;
. b S; `. V9 ^2 k
' D" M; i6 P% e- l reg [3:0] a, b;& a2 V; k/ z9 W$ w9 P+ F& M0 \
reg cin;
: r1 X- r/ ]. y/ L& a, Z3 B
' z0 K/ A$ w+ r, _2 g8 ?! z4 l wire [3:0] s;
# p. a( h/ z* k wire cout;7 n" \4 r( M7 M8 k3 w
: A/ A( r( E) y. m' ? cla4_adder dut(.a(a), .b(b), .cin(cin), .s(s), .cout(cout));
$ I/ L, S0 I- T$ ?; w ( Y6 P- L5 I* b, N5 ^
integer i;
6 P& \7 o4 p' |, ^: l- T" h6 s! L1 Y8 A' U/ Z/ Q
initial begin
8 E8 Z* h9 C1 J) o k2 Q( U a = 0; b = 0; cin = 0;! Q9 G7 H& z0 j5 N2 h* F
forever begin8 a7 a0 P6 W- E9 n% r9 u
for (i=0; i<16; i=i+1) begin
4 n% u; D: _# a4 `) O #10 a = i; b = i; cin = 0;
5 }% |% D0 c$ M #10 a = i; b = i; cin = 1;
1 P& R, ^# o/ y1 h7 N end
7 B7 _! x! W! P, j4 [/ X/ h' ` |, w end
; q) m" M( ?. f$ _ end
, ?3 M, ^" @, b0 t8 y y. t, O1 s2 }
initial #1000 $stop;0 W4 o( N$ I- T, Z: b& j" M: I! F
+ E, `2 n/ O2 A
endmodule 设置好仿真之后,cla4_adder仿真结果如下图。 |
( }) B! d. t6 S' e6 {9 x3 G
' S' L1 `. Q7 {( N! F
|