系列文章目錄:FPGA原理與結(jié)構(gòu)(0)——目錄與傳送門
一、CARRY概述
1、半加器與全加器
? ? ? ? 進(jìn)位鏈CARRY在FPGA中本質(zhì)上就是解決加減法進(jìn)位問題的元器件,在學(xué)習(xí)進(jìn)位鏈之前,我們需要對數(shù)字電路的加減法做一個簡單的回顧。
1.1半加器
? ? ? ? 在學(xué)習(xí)組合電路的時候,半加器作為一個非常經(jīng)典的電路設(shè)計是初學(xué)者避不開的一個話題。其本質(zhì)就是實現(xiàn)了不帶進(jìn)位輸入的二進(jìn)制加法運算,其真值表如下
a | b | carry | sum |
0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 |
1 | 0 | 0 | 1 |
1 | 1 | 1 | 0 |
????????根據(jù)真值表我們可以很容易得出:
????????????????????????????????????????????????????????????????carry = a & b ;
????????????????????????????????????????????????????????????????sum = a ^ b ;
????????對應(yīng)的電路結(jié)構(gòu)如下:????????
????????對應(yīng)真值表不同的輸入情況如下:
1.2全加器
????????有了半加器我們就解決了一位二進(jìn)制數(shù)的加法問題,但是這顯然還是不夠的,要想實現(xiàn)多位二進(jìn)制數(shù)的加法問題,我們就必須在現(xiàn)有電路的基礎(chǔ)上進(jìn)行改進(jìn),首先就是要引入進(jìn)位輸入。
? ? ? ? 和之前一樣,我們還是先給出真值表
A | B | Cin | Sum | Cout |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
? ? ? ? ?根據(jù)真值表給出邏輯式:
?????????????????????????????????????????????????Sum = A ^ B ^ Cin;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Cout = ( A & B ) | (( A ^ B ) & Cin);
? ? ? ? 這里再去搭電路就有點浪費時間了,我們用vivado的rtl分析來觀察電路結(jié)構(gòu)
module full_add2
(
input a, //加數(shù)
input b, //被加數(shù)
input cin, //進(jìn)位輸入
output sum, //結(jié)果輸出
output cout //進(jìn)位輸出
);
assign sum = a^b^cin;
assign cout = (a&b)|((a^b)&cin);
endmodule
?2、全加器的級聯(lián)
? ? ? ? 在有了半加器和全加器之后,我們就算是有了搭建多位二進(jìn)制加法器的基本元件,接下來的問題就是怎么完成全加器之間的級聯(lián)問題。
2.1行波進(jìn)位加法器(Carry Ripple Adder)
? ? ? ? 我們以搭建一個4位的加法器為例,這種加法器的設(shè)計思路非常的簡單,就是把上一個加法器的進(jìn)位連接到下一個加法器的進(jìn)位輸入端,具體的設(shè)計電路如下:
? ? ? ? ?用這樣的設(shè)計思路,我們可以實現(xiàn)任意位數(shù)的加法器。這里我們在第一位使用的是半加器,我們也可以把這個半加器換成全加器來實現(xiàn),只要保證第一位的Cin為0就行:
? ? ? ? ?我們來看以下行波進(jìn)位加法器是如何運行的,首先我們假設(shè)初始狀態(tài)下所有的位都是0
? ? ? ? 接下來我們來進(jìn)行一個運算:0111+0001 = 01000?,但是在經(jīng)過一個全加器(FA)的時延后,結(jié)果是00110
? ? ? ? 這當(dāng)然不意味著我們設(shè)計的加法器是錯誤的,只是因為想要得到正確的結(jié)果,我們還需要更多的時間:
? ? ? ? 可以看到在經(jīng)過4個FA的時延之后,我們得到了正確的答案,但是這顯然暴露出一個很大的問題,那就是行波進(jìn)位加法器需要很大的處理時間才能得到正確答案,而且我們很容易預(yù)見到,這個處理時間會隨著我們運算位數(shù)的增加而增加。因為高位的運算必須等待低位的運算完成, 這樣造成了整個加法器的延遲時間很長。?
2.2超前進(jìn)位加法器(Carry-Lookahead Adder,CLA)
? ? ? ? 很顯然我們之前討論的行波進(jìn)位加法器在效率和時延問題上有著很大的不足,那么有沒有更加高效的加法器設(shè)計呢?要設(shè)計出更高效的加法器,我們首先要明確,造成行波進(jìn)位加法器效率問題的根本原因在于它的高位運算必須等待低位的運算完成,這樣等于同一時間只有一個全加器能夠進(jìn)行有效運算,其本質(zhì)是在進(jìn)行一個串行的運算,那么我們很自然地想到能不能把這個串行的運算轉(zhuǎn)換成并行處理,也就是能否提前計算出“進(jìn)位輸出信號”?
????????我們可以用前一個全加器的參數(shù)來表示后面的進(jìn)位輸出(Cout),即:
????????由此來表示4個全加器的進(jìn)位輸出為:?
????????最終我們需要得到的是C4,經(jīng)過換算C4的這些參數(shù),全部已知!并不需要前一個全加器運算輸出,由此我們得到了提前計算進(jìn)位輸出的方法, 用這樣的方法實現(xiàn)了加法器就被稱為超前進(jìn)位加法器(Carry-Lookahead Adder,CLA)。
????????根據(jù)上面的優(yōu)化算法,我們重新繪制了CLA的布線方式
? ? ? ? 這樣設(shè)計出來的超前進(jìn)位加法器顯然在效率上更加有優(yōu)勢,但是也有著自己的問題,最明顯的就是設(shè)計起來的復(fù)雜度大大增加了,而且也是隨著運算位數(shù)的增加而顯著增加。?
二、FPGA中的進(jìn)位邏輯
1、概述? ? ? ??
????????說了一大堆加法器的前置知識,接下來進(jìn)入我們的整體,F(xiàn)PGA中的進(jìn)位鏈,進(jìn)位鏈的使用其實是非常廣泛的(或者說所有有資格在FPGA單獨成為一個器件的元件應(yīng)用都很廣泛),舉個簡單的例子,大家對于計數(shù)器應(yīng)該并不陌生,那既然都有計數(shù)器了,就必然已經(jīng)用到了進(jìn)位鏈。我們知道CLB在FPGA中最為豐富,在7系列的FPGA中,一個CLB中有兩個Slice,一個Slice中包含4個LUT6、3個數(shù)據(jù)選擇器MUX、1個獨立進(jìn)位鏈(Carry4,Ultrascale是Carry8)和8個觸發(fā)器。這里我們來談?wù)揅arry4。在CLB中,除了函數(shù)發(fā)生器之外,還提供了專用的快速超前進(jìn)位邏輯,以slice中執(zhí)行快速算術(shù)加法和減法。 7系列FPGA CLB具有兩個獨立的進(jìn)位鏈,如下圖所示,?進(jìn)位鏈可級聯(lián)以形成更寬的加/減邏輯。
????????
?2、端口介紹
????????
CI:? ? ? ? 上一個CARRY4的進(jìn)位輸出,位寬為1,可以級聯(lián)形成更大規(guī)模的運算邏輯
CYINT: 進(jìn)位的初始化值,位寬為1,0為加法,1為減法
DI:? ? ? ? 數(shù)據(jù)的輸入(兩個加數(shù)的任意一個),位寬為4;
S:? ? ? ? ?兩個加數(shù)的異或,位寬為4;
O:? ? ? ? ?加法/減法結(jié)果輸出,位寬為4,它們連接到slice AMUX / BMUX / CMUX / DMUX輸出;
CO:? ? ? 進(jìn)位輸出,位寬為4,這里的進(jìn)位是每一位的進(jìn)位,比如CO[0]就表示最低位的加法進(jìn)位,這樣就可以實現(xiàn)小于4bit的加減法。
3、CARRY4內(nèi)部結(jié)構(gòu)
? ? ? ? ?僅僅看端口含義顯然不足以幫助我們理解CARRY4的具體工作原理,接下來我們來看CARRY4的內(nèi)部結(jié)構(gòu)。
? ? ? ? 從圖中我們可以觀察到,其實CARRY4是由相同的4個單元構(gòu)成的,如下圖中紅色部分標(biāo)注的就是其中的一個基本單元:
這個單元我們本質(zhì)上可以理解成一個全加器:
CIN = 進(jìn)位輸入(當(dāng)它在最低位時,置0做加法,置1做減法)
S0 = A0 ^ B0 (這里和全加器中的S有些區(qū)別),它來自LUTA的O6
O0 = S0 ^ CIN =?A0 ^ B0 ^ CIN(這里的O才是全加器的S),它來自LUTA的O5或外面外部輸入AX
DI0 = A0 或者 B0 (這里指的是兩個加數(shù)中的任意一個,它的作用要配合S0)
AX 是預(yù)置數(shù),這里我們不過多關(guān)注。
這里面還包含一個MUX邏輯,這里的邏輯是:S = 0,輸出為左側(cè)輸入,S = 1,輸出為右側(cè)輸入。
我們知道產(chǎn)生進(jìn)位的條件在A B以及 CIN中有兩個或兩個以上的1。
(1)當(dāng)S=0時,有兩種情況,即兩個加數(shù)都為0和兩個加數(shù)都為1。此時,MUX選擇DI作為數(shù)據(jù)輸入,CO的結(jié)果由DI決定。因為S0=0時,DI為0等價于A0,B0,CO0都為0。DI為1等價于A,B,CO都為1。
(2)當(dāng)S=1時,即A與B中有1個為1。此時,MUX選擇CIN作為數(shù)據(jù)輸入,CO的結(jié)果由CIN決定。因為S=1時,A與B中只有1個1,還缺1個1才能進(jìn)位,進(jìn)位所需的那個1就看低位來的進(jìn)位CIN是不是1了。
這樣從結(jié)構(gòu)上來看,和我們之前談到過的超前進(jìn)位加法器就很像了。
三、實例測試
? ? ? ? 我們以一個8位的加法運算為例
module carry4(
input [7:0] a,
input [7:0] b,
output[7:0] o
);
assign o=a+b;
endmodule
綜合后的結(jié)果如下:
? ? ? ? 可以看到由于是8位的加法運算,所以這里用到了兩個CARRY4 。
????????有關(guān)進(jìn)位鏈的內(nèi)容就大概說到這里,再補(bǔ)充兩點。
? ? ? ? (1)進(jìn)位鏈級聯(lián)數(shù)有限制,它取決于當(dāng)前列SLICE的個數(shù),而且不能跨邏輯區(qū)域。邏輯區(qū)域里進(jìn)位鏈最大級數(shù)等于綠框中的SLICE的高度(如果是多位全加器的位寬就是SLICE的高度x4,因為1個SLICE里有4個級聯(lián)的全加器)。
? ? ? ? (2)進(jìn)位鏈級聯(lián)數(shù)越多,造成的路徑延遲就會越大,這樣會讓時序十分的緊張。所以在使用進(jìn)位鏈時要綜合考慮級聯(lián)數(shù)與整個系統(tǒng)速率的關(guān)系。例如在設(shè)計位寬較大的計數(shù)器,可以選擇用DSP替換,也可以選擇將位寬分隔。(如32位計數(shù)器,可將它分成高16位,與低16位,低16位計數(shù)到16'hffff,高16位計數(shù)才+1)?
四、參考資料
306 - 加法器的優(yōu)化——超前進(jìn)位加法器(Carry-Lookahead Adder,CLA)文章來源:http://www.zghlxwxcb.cn/news/detail-739649.html
FPGA從入門到精通(5) - 進(jìn)位鏈文章來源地址http://www.zghlxwxcb.cn/news/detail-739649.html
到了這里,關(guān)于FPGA原理與結(jié)構(gòu)(7)——進(jìn)位鏈CARRY的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!