流水線設(shè)計
基本概念
流水線處理源自現(xiàn)代工業(yè)生產(chǎn)裝配線上的流水作業(yè),是指將待處理的任務(wù)分解為相對獨立的、可以順序執(zhí)行的而又相互關(guān)聯(lián)的一個個子任務(wù)。流水線處理是高速設(shè)計中的一個常用設(shè)計手段,如果某個設(shè)計的處理流程分為若干步驟,并且整個數(shù)據(jù)處理是“單流向”的,即沒有反饋或者迭代運算,前一個步驟的輸出是下一個步驟的輸入,那么可以考慮采用流水線設(shè)計方法來提高系統(tǒng)頻率。流水線設(shè)計結(jié)構(gòu)如圖所示。
其基本結(jié)構(gòu)是將適當(dāng)劃分的n個操作步驟單流向串聯(lián)起來。流水線操作的最大特點是數(shù)據(jù)流在各個步驟的處理從時間上看是連續(xù)的順序操作,與此同時各個步驟又是同時并行的在運作。
在處理器架構(gòu)上,一個單核處理器只能一次處理一個任務(wù),是順序的執(zhí)行,如要實現(xiàn)并行操作需要多個處理器來執(zhí)行。
FPGA中典型的流水線設(shè)計
流水線處理采用面積換取速度的思想,可以大大提高電路的工作頻率,尤其對于圖像處理任務(wù)中的二維卷積運算、FIR及FFT濾波器等,采用流水線設(shè)計可以保證一個時鐘輸出一個像素,相對于全并行處理電路占用資源又不會太多。對于大部分的圖像處理任務(wù)而言,處理過程基本上也是一個“串行”的處理思路。因此,流水線設(shè)計無疑是最好的設(shè)計方式。如下圖所示是一個典型的圖像處理任務(wù)流程圖。
并行陣列
在并行陣列型電路中,多組并行排列的子電路同時接收整體數(shù)據(jù)的多個部分進(jìn)行并行計算。并行陣列型電路中的子電路本身可以是簡單的組合電路,也可以是復(fù)雜的時序電路例如上面提到的流水線型電路。如果受邏輯資源限制,無法同時處理全部數(shù)據(jù),那么也可以依次處理部分?jǐn)?shù)據(jù)直到完成全部數(shù)據(jù)的處理。
和流水線共享電路的思路不同,并行陣列電路對于每個處理數(shù)據(jù)都生成一個處理電路,這無疑更大地提高了電路的處理速度,但是也帶來了更大的資源消耗,是用面積換取速度原則的又一體現(xiàn)。如果系統(tǒng)設(shè)計對資源消耗相對不敏感,但是又需要較快的處理速度時,那么我們會選擇并行結(jié)構(gòu)來完成。
并行陣列的一個典型應(yīng)用是多通道像素同時進(jìn)行處理,對一個串行輸入的RGB通道或是YCbCr通道的視頻流,首先做一個串并轉(zhuǎn)換,接著復(fù)制處理邏輯對三個通道同時做處理。這樣理論上可以得到3倍的速度提升。
計算技術(shù)
計算技術(shù)也是圖像處理的核心技術(shù)之一。在軟件算法設(shè)計和調(diào)試完成之后,需要將軟件的算法映射到FPGA中去,由于軟件和硬件的設(shè)計差異性,相當(dāng)一部分算法在映射前需要通過等效轉(zhuǎn)換,近似計算等硬件計算技術(shù)來轉(zhuǎn)換成硬件易于實現(xiàn)的方式,從而達(dá)到邏輯資源消耗和時序,以及誤差與消耗的平衡。本節(jié)將介紹幾種常用的硬件計算技術(shù)。
算法轉(zhuǎn)換
在乘法和除法運算中,經(jīng)常會遇到乘數(shù)、被乘數(shù)或分子與分母是常數(shù)的情況。直接調(diào)用乘法器或除法器當(dāng)然可以解決這個問題,但是這會消耗一定的DSP運算單元,而DSP單元往往是FPGA里面比較少的資源。對于定常數(shù),可以通過一定的轉(zhuǎn)換將其轉(zhuǎn)換為移位和加法運算,從而減少乘法器和除法器的使用。下面列舉幾個常用的例子。
乘法運算的實現(xiàn):
dout =? din × 255
轉(zhuǎn)換后:
dout =? din ×(256-1)=(din<<8)-din
除法運算的實現(xiàn):
在這里擴展了10bit的位寬,這個位寬約大,精度約高,但也會消耗相對更多的資源,實際應(yīng)用中根據(jù)精度需求進(jìn)行選擇。
近似計算
與算法轉(zhuǎn)換不同的是,算法轉(zhuǎn)換是不會帶來任何原理的誤差,而近似則會帶來一定的計算誤差。通常情況下,在誤差允許的范圍內(nèi),采用近似計算帶來的明顯優(yōu)勢是計算復(fù)雜度的降低及資源消耗的降低。在FPGA中常見的近似計算是截斷。
截斷就是用位數(shù)較少的近似值來代替位數(shù)較多或無限位數(shù)的數(shù)時,要有一定的取舍法則。在數(shù)值計算中,為了適應(yīng)各種不同的情況,須采用不同的截取方法。
經(jīng)常使用的截斷方法就是四舍五入。實際上,對于FPGA來講,處理的都是二進(jìn)制數(shù)據(jù)。因此,在小數(shù)位的第一位的值是0還是1決定了是否對結(jié)果進(jìn)行進(jìn)位。
同樣,以除法的例子為例:
將位寬擴展10bit后,再進(jìn)行近似運算,近似運算直接去掉了小數(shù)部分,引入的誤差僅為0.04/210。如果din是圖像中的一個像素,其最大值為256,誤差僅為0.01,該近似運算幾乎不影響圖像像素。相對無損失的運算轉(zhuǎn)換,大大減輕了運算量。
增量更新
增量更新是指在進(jìn)行更新操作時,只更新需要改變的地方,不需要更新或者已經(jīng)更新過的地方則不會重復(fù)更新,增量更新與完全更新相對。增量更新在流水線處理中,特別是二維卷積處理中特別有用。這是由于在兩個連續(xù)的卷積窗口中有大量的相同元素。
假定要計算連續(xù)5個數(shù)據(jù)流的和,在上一個時刻,這5個待計算的數(shù)值是a0,a1,a2,a3,a4, ?在本時刻待計算的數(shù)值是a1,a2,a3,a4,a5。中間有4個值是相同元素。如此如果每次計算都將5個數(shù)重新相加,就有點浪費資源。正確的做法是加上一個新值,再減去一個最老的值。
對應(yīng)的增量計算方法如下圖所示,當(dāng)然5個數(shù)值求和,可以擴展到10個數(shù)值求和,但增量運算的運算量不變:
浮點計算
大部分運算可以通過擴位和近似的方式轉(zhuǎn)換為定點運算。但有些算法在設(shè)計在設(shè)計的過程中就涉及大量的浮點運算,在轉(zhuǎn)換為定點運算時比較麻煩,會帶來龐大的工作量。此外,在某些應(yīng)用中,定點算法是不可行的,動態(tài)范圍要求使用浮點算法的一個常見的例子是矩陣求逆運算。本節(jié)將介紹如何使用FPGA來實現(xiàn)浮點運算以便減少移植的工作量。
浮點數(shù)的定義
浮點數(shù)(float)是屬于有理數(shù)中某特定子集的數(shù)的數(shù)字表示,在計算機中用以近似表示任意某個實數(shù)。具體來說,這個實數(shù)由一個整數(shù)或定點數(shù)(即尾數(shù))乘以某個基數(shù)(計算機中通常是2)的整數(shù)次冪得到,這種表示方法類似于基數(shù)為10的科學(xué)記數(shù)法。
IEEE二進(jìn)制浮點數(shù)算術(shù)標(biāo)準(zhǔn)(IEEE 754)是20世紀(jì)80年代以來最廣泛使用的浮點數(shù)運算標(biāo)準(zhǔn),為許多CPU與浮點運算器所采用。這個標(biāo)準(zhǔn)定義了表示浮點數(shù)的格式(包括負(fù)零-0)與反常值(denormal number)),一些特殊數(shù)值(無窮(Inf)與非數(shù)值(NaN)),以及這些數(shù)值的“浮點數(shù)運算符”;它也指明了四種數(shù)值舍入規(guī)則和五種例外狀況(包括例外發(fā)生的時機與處理方式)。
IEEE 754規(guī)定了四種表示浮點數(shù)值的方式:單精確度(32位)、雙精確度(64位)、延伸單精確度(43比特以上,很少使用)與延伸雙精確度(79比特以上,通常以80位實現(xiàn))。只有32位模式有強制要求,其他都是選擇性的。大部分編程語言都有提供IEEE浮點數(shù)格式與算術(shù),但有些將其列為非必需的。例如,IEEE 754在問世之前就有的C語言,現(xiàn)在有包括IEEE算術(shù),但不算作強制要求(C語言的float通常是指IEEE單精確度,而double是指雙精確度)。
1)單精度浮點數(shù)
單精度浮點數(shù)用32位二進(jìn)制表示,其中最高位Bit[31],MSB為符號位,即sign域。Bit[30:23]為exponent域,這8位數(shù)據(jù)表示指數(shù);最低的23位Bit[22:0]為fraction域,用于表示浮點數(shù)的小數(shù)部分。
2)雙精度浮點數(shù)
單精度浮點數(shù)用64位二進(jìn)制表示,其中最高位Bit[63],MSB為符號位,即sign域。Bit[62:52]為exponent域,這11位數(shù)據(jù)表示指數(shù);最低的52位Bit[51:0]為fraction域,用于表示浮點數(shù)的小數(shù)部分
用FPGA實現(xiàn)浮點運算
乘法:對于乘法運算、位數(shù)相乘及指數(shù)相加,若位數(shù)結(jié)果大于2,則需要重新規(guī)范化,將其右移一位并且增加指數(shù)。由于乘積的位數(shù)可能會比表示位多,因此,需要進(jìn)行舍位處理。兩個指數(shù)的和包括兩個偏移量,因此必須減掉一個。輸出值的符號位是輸入符號位的異或。需要附加的邏輯來檢測下溢出、上移除及處理其他的錯誤情況,例如,處理無窮大和非數(shù)。
除法:除法與懲罰類似,只是尾數(shù)相除,指數(shù)相減并且在重新規(guī)范化時可能包含左移。
加法和減法:實現(xiàn)要更加復(fù)雜。與原碼表示相同,實際操作的執(zhí)行取決于輸入的符號。指數(shù)必須相同,因為數(shù)必須要對齊。根據(jù)指數(shù)位的差值,將較小的指數(shù)右移相應(yīng)的位數(shù)。
浮點操作相對于定點操作無疑要消耗更多的資源,這不是因為浮點操作有多復(fù)雜,而是因為處理異常時需要很多邏輯,尤其是在需要符合IEEE標(biāo)準(zhǔn)時。大部分FPGA在進(jìn)行浮點運算時,為符合IEEE 754標(biāo)準(zhǔn),每次運算都需要去歸一化和歸一化步驟,導(dǎo)致了極大的性能瓶頸。因為這些歸一化和去歸一化步驟一般通過FPGA中的大規(guī)模桶形移位寄存器實現(xiàn),需要大量的邏輯和布線資源。通常一個單精度浮點加法器需要500個查找表(LUT),單精度浮點要占用30%的LUT,指數(shù)和自然對數(shù)等更復(fù)雜的數(shù)學(xué)函數(shù)需要大約1000個LUT。因此,隨著DSP算法越來越復(fù)雜,F(xiàn)PGA性能會明顯劣化,對占用80%~90%邏輯資源的FPGA會造成嚴(yán)重的布線擁塞,阻礙FPGA的快速互連,最終會影響時序收斂。
存儲器映射
一般情況下,我們希望當(dāng)數(shù)據(jù)流過FPGA時,F(xiàn)PGA盡可能多地處理數(shù)據(jù),并且減少FPGA和外部設(shè)備之間的數(shù)據(jù)傳輸,采用流水線處理架構(gòu)則可以很好地減少對存儲器的頻繁讀寫。然而在某些情況下,一個圖像處理算法需要像素之間的行列同步或是幀同步,這個時候就必須要緩存部分圖像或者是整幅圖像。
在軟件處理中,這個緩存通常情況下是放在內(nèi)存中,需要的時候從內(nèi)存進(jìn)行讀取。在FPGA中,可以選擇將緩存放在FPGA內(nèi)部或者外部。
幀緩存
對于幀緩存,通常情況下會將其放在片外進(jìn)行讀寫。對于幀緩存,在成本不夠敏感的情況下,最好使用靜態(tài)存儲器(SRAM),尤其是用于需要頻繁和隨機地訪問這些幀緩存的地方。
靜態(tài)存儲器:相對于動態(tài)存儲器來說,通常情況下讀寫接口時序相對簡單,讀寫速度要快,并且功耗相對較低。但是,由于靜態(tài)存儲器每一位要使用6個晶體管,而動態(tài)存儲器每位只使用一個晶體管,因此靜態(tài)存儲器的價格要貴得多。這也限制了它在成本敏感場合的應(yīng)用。
一個幀緩存控制電路要包括讀地址發(fā)生器、寫地址發(fā)生器及讀寫控制時序。一般情況下,這個寫地址即為輸入幀數(shù)據(jù)流ImageDin的行列地址,而讀地址為輸出流Frame_buffer的行列地址。以SRAM為基礎(chǔ)的幀緩存電路如圖所示。
動態(tài)存儲器:如果系統(tǒng)對于讀取速度沒有嚴(yán)格要求的緩存應(yīng)用,那么動態(tài)存儲器無疑是更好的選擇。雖然動態(tài)存儲器存取速度較慢,從主機提供地址到數(shù)據(jù)輸出可能需要若干個時鐘,但是當(dāng)動態(tài)存儲器工作在突發(fā)模式時,也可以提供較大的帶寬,這對于圖像處理這樣的大數(shù)據(jù)應(yīng)用場合非常有用。
動態(tài)存儲器的接口設(shè)計相對比較復(fù)雜,這是由于動態(tài)存儲器必須要間隔一段時間對其進(jìn)行刷新來保持當(dāng)前的存儲器內(nèi)容。此外,與靜態(tài)存儲器不同,動態(tài)存儲器的行列地址通常是分開的。因此對動態(tài)存儲器的尋址工作需要分別進(jìn)行行列尋址工作。通常情況下,我們會直接采用FPGA廠家提供的IP核來實現(xiàn)外部的存儲器驅(qū)動,這樣可以大大提高開發(fā)的效率。
行緩存
行緩存通常情況下會放在片內(nèi)。每一個行緩存有效地將輸入延遲了一行。用階數(shù)為圖像寬度的移位寄存器是可以方便地實現(xiàn)這種延遲。
移位寄存器:首先,移位寄存器是由一連串的移位寄存器來實現(xiàn)的,每個位都適用一個寄存器,而每個邏輯單元都只有一個寄存器,因此,采用移位寄存器的方式將會占用大量的邏輯資源,特別是在圖像寬度比較大的時候,用內(nèi)部資源來實現(xiàn)行緩存往往是不明智的選擇。
片上RAM:設(shè)計行緩存時,通常會選擇利用FPGA片內(nèi)的RAM塊來實現(xiàn)。采用RAM作為行緩存,就需要設(shè)計寫入和讀出地址產(chǎn)生電路。寫入地址就是輸入圖像行的列地址,讀出地址就是輸出圖像行的列地址。若采用FIFO作為行緩存,則順序?qū)懭肱c讀出即可。
行緩存的理想工作狀態(tài):流狀態(tài)是行緩存的理想工作狀態(tài),也就是除了緩存裝載和卸載,緩存內(nèi)部的數(shù)據(jù)流入和流出是平衡的,這樣才不至于破壞系統(tǒng)的流水線。輸入圖像數(shù)據(jù)的到來時刻是由上一級時序所控制,輸出圖像的數(shù)據(jù)流則與行緩存息息相關(guān)。
考慮一個3×3的窗口濾波器——每個輸出結(jié)果是窗口內(nèi)九個像素值的一個函數(shù)。如果沒有高速緩存,每個窗口位置必須讀九個像素(對流處理來說是每個時鐘周期),并且當(dāng)窗口掃描整個圖像時,每個像素需要讀取九次。在連續(xù)的時鐘周期內(nèi)需要使用水平相鄰的像素,因此可以用寄存器緩存和延遲像素。這就能將每個時鐘周期讀取的像素數(shù)量減少到三個。行緩沖緩存了之前行中的像素值,避免了對這些行中像素的再次讀取。一個3×3的濾波器占據(jù)了三行:一個當(dāng)前行和兩個之前行,在當(dāng)前行中讀取新數(shù)據(jù),因此需要兩個行緩沖來緩存之前兩行的像素值。
異步緩存
異步緩存主要應(yīng)用在跨時鐘的場合。對于一些設(shè)計,在不同的部分使用不同的時鐘是不可避免的。這個問題主要出現(xiàn)在視頻輸入、視頻輸出及與外部的異步接口等場合。
一般來說,外部的視頻輸入數(shù)據(jù)流都會附帶一個視頻流的參考時鐘,而這個時鐘與本地邏輯時鐘是異步的。同時,處理完的視頻流要進(jìn)行顯示,顯示驅(qū)動電路的時鐘與本地系統(tǒng)時鐘往往也是不同的。系統(tǒng)與外部的一些異步接口,例如異步存儲器等,都是跨時鐘域的場合。
異步時鐘帶來的一個問題就是有效的讀寫速率不一致。一般情況下,這種場合是讀取速度要小于寫入速度。解決異步時鐘的一個方法就是建立異步緩存器,用一個異步FIFO即可實現(xiàn)。使用FIFO需要注意的問題就是溢出問題,需要使FIFO的讀寫匹配,在FIFO裝滿之前,需要把FIFO讀走。
FIFO的讀寫時序比較簡單,內(nèi)部結(jié)構(gòu)圖如圖所示。
對于異步時鐘域,用異步FIFO作異步緩存,還能有效解決壓穩(wěn)態(tài)的問題。尤其是對于不同頻不同相位的異步時鐘域,只能用異步緩存來進(jìn)行同步,這是由于需要緩存來進(jìn)行帶寬匹配,在這里FIFO是一個不錯的選擇。
亞穩(wěn)態(tài)問題:
亞穩(wěn)態(tài)狀態(tài)下,對于任何噪聲諸如環(huán)境,只要系統(tǒng)中有異步元件,亞穩(wěn)態(tài)就是無法避免的。亞穩(wěn)態(tài)主要發(fā)生在異步信號檢測、跨時鐘域信號傳輸及復(fù)位電路等常用設(shè)計中。對于壓穩(wěn)態(tài),一般的處理方法是三拍處理,使用三級寄存器同步后,亞穩(wěn)態(tài)出現(xiàn)的給概率基本為0。
在一些對系統(tǒng)穩(wěn)定性要求更高的場合(例如軍工領(lǐng)域),可能還會要求更多拍處理,以便進(jìn)一步提高系統(tǒng)穩(wěn)定性。但這種同步方式僅僅適用于同頻的異步時鐘域或?qū)τ谏倭垮e誤不敏感的功能單元。對于異步時鐘域根可靠的方式還是使用兩組異步時鐘來進(jìn)行異步緩存。
編輯:黃飛
?
評論
查看更多