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