記得Long long time ago,特權同學寫過一篇簡短的博文《M4K使用率》,文章中提到了Cyclone器件的內嵌存儲塊M4K的配置問題。文中提到了這個M4K塊除了存儲大小是有限的4Kbit,它的可配置的Port數量也是有限的,通常為最大36個可用port。 當時只是簡單的提到有這么回事,提醒使用者注意,也沒有具體的談到如何解決或者確切的說應該是避免這樣的狀況出現。因此,本文將結合特權同學近期在使用FPGA時,配置片內存儲器遇到的一些片內資源無法得到充分利用的問題,更深入的探討如何在既有的基礎上優化我們的配置,也就是標題所言,我們的目標是“榨干FPGA的片上存儲資源”。 關于如何在綜合或布局布線后查看FPGA的片上存儲資源的使用情況,就Quartus II軟件,這里要先教大家幾招,讓大家在系統設計完后對自己的存儲資源情況做到明明白白、心中有數,這對將來的產品維護、升級乃至完全推到重來都是有助益的。很好,想必您已經等不及了,那么就ReadyàGo! 在一個工程完全編譯后,Quartus II會彈出一個全新的Compilation Report,首先映入設計者眼簾的是Flow Summary頁面。當然設計者也可以如圖1所示,直接找到菜單欄點擊ProcessingàCompilation Report選項查看。 ![]() 再看Flow Summary頁面,如圖2所示,其他選項這里不說了,就看Total memory bits后圈出來的部分:103,264/165,888(62%)。這里意思也很明白,特權使用的器件EP2C8Q208C8的片內存儲器總大小是 165,888bit,而在該工程中使用了103,264bit,使用率是62%。 ![]() OK,那么我們再來看看詳細的存儲資源都用在哪里了。如圖3所示,點開編譯報告的Analysis&SynthesisàRAM Summary。 ![]() 同時在頁面右側就彈出如圖4所示的詳細的存儲資源分配情況。在這個頁面的報告中,我們只能簡單的看到存儲資源的詳細使用位置、存儲資源類型(即是使用了專用的片內存儲資源還是用邏輯資源構造的,顯然用邏輯資源是很浪費甚至說不現實的)、存儲器類型(即RAM/ROM/FIFO等)、存儲器的位寬和深度信息以及存儲量大小,還有就是是否有初始化文件映射。 ![]() 因為是綜合報告的一部分,所以不針對特定的器件給出一些信息,如這里我們可能還會關心文章開頭就提到的M4K塊使用數量甚至是我們所例化的存儲器具體都使用了哪些M4K塊。不用擔心,咱的這點好奇心開發商還是能夠滿足的。下面我們就接著打開編譯報告里的FitteràResource SectionàRAM Summary選項(方法同圖3)。我們可以看到如圖5所示的,哦,很抱歉由于頁寬有限,所以name一欄沒有完全顯示,Location一欄也只是“小荷才露尖尖角”,但是不要緊,只要你領會精神。先說這個Location一欄,它就是前面提到設計者可能關心的具體的M4K塊都是哪些,而M4Ks一欄就是使用的M4K塊的數量,其他選項類同,讀者可以自己分析。看到這些,估計已經是一目了然了,設計者對自己例化的每一個片內存儲器的具體的使用情況都應該有所了解。 ![]() 但是,估計細心的讀者會問,我知道了我所例化的每個存儲器的M4K塊使用數量,那么我怎么知道是否超出了器件所有的數量,難道非要等到編譯出 error才行嗎?或者自己在這個頁面掐指算算再找來handbook比對一下嗎?非也,其實用戶只要點開FitteràResource SectionàResource Usage Summary,如圖6所示,里面羅列了非常詳細的FPGA所有片上資源的使用情況,圈出來的部分也是這里我們需要重點關注的地方。M4Ks里指明器件的 36個M4K塊使用了26個,占用率72%;而Total block memory bits和前面綜合報告里是一樣的,嚴格的說,這個數據應該算是片內存儲資源的絕對使用情況;最后說Total block memory implementation bits選項,它是最終實現到FPGA器件上的片上資源占用情況(注意這里只能是占用而非使用,漢語文字真是博大精深,也許有些時候兩個詞怎么用都差不多,但是這里特權同學想區分這個概念,所以刻意要提醒大家注意,因為,它還涉及本文的主題,哈哈,不好意思,有點班門弄斧了),它的占用率和M4Ks是一致的,并且必須是一致的。 ![]() 那么好,“工欲善其事,必先利其器”,我們利完器,就來說正事。特權同學提出一個概念,就是FPGA片上資源的利用率,他的公式為:(Total block memory bits/Total block memory implementation bits),對于該設計就是(62% / 72%) = 86.11%,應該說是個不錯的數據(呵呵,悄悄的告訴你,這個實例可是被特權同學優化過了)。 說完這些概念,我們可以真刀真槍的玩一玩了,理論永遠只是理論,要提高必須靠實踐。其實可以把這個工程打回原形,退回優化前的情況。由于篇幅關系,這里只討論它優化過程中的一個最顯著的例子。 在這個工程中,有一連串的8bit數據流,第1個數據要和第1280個數據做一些處理。因此,最簡單的想法就是例化一個1280*8bit的移位寄存器。并且這個移位寄存器在第一個移入的數據移出時,要和此時要正要移入的數據做一些處理。但是,在配置移位寄存器的時候遇到了一些麻煩,如圖8所示,移位寄存器的深度一般是用配置的taps數量乘以distance值(建議對移位寄存器配置的相關知識還不熟悉的朋友參考特權同學的另一篇博文《Cyclone M4K移位寄存器使用》)。而這里distance值最大只能配置為256,需要1280個寄存器,并且只用一個taps的想法破滅了,于是思考了下:發現256*5/128*10/64*20都是可行的辦法。 ![]() 剛開始配置的時候沒有太多考慮,就選擇了64*20的方案,即配置taps = 24(因為taps值只能為可選的1/2/3/4/5/6/7/8/12/16/24/32/48/64/96/128,這里配置為24個taps,而使用的時候取taps輸出的bit159-152,實際綜合的時候其實會把4個不用的taps優化掉),distance = 64。 如圖8所示。如果你夠細心,你應該發現了左下角的Resource Usage是6 M4K。 ![]() 然后就著這樣的配置,在編譯后可以使用前面提到的方法查看一下存儲器資源的使用情況。因為我們重點要算FPGA片上資源的利用率,所以還是查看 FitteràResource SectionàResource Usage Summary這個報告吧。如圖9所示,這個報告中的Total block memory bits和之前沒有變,都是62%,而M4Ks占用多了2個,相應的M4Ks占用率和Total block memory implementation bits占用率增加到了78%。計算一下,(62% / 78%) = 79.5%,下降了近7個百分點。也許這個參數說明不了問題,但是在資源緊張的時候,這個問題就是最撓人的問題。 ![]() 再提特權同學發現問題后,如何處置優化提高了這里的利用率(實際上,如果真用EP2C8Q完成這個工程,也不是非得做這個優化的工作,只不過最終的設計是要實現在向下兼容的EP2C5Q上,所以,就誕生了這篇文章的故事……)?很簡單,前面其實都已經給了大家暗示,移位寄存器的存儲資源利用率不高不是因為本身存儲量大(只有1280*8bit=10Kbit,需要3個M4K足夠),而是因為生成的taps占用的port過多,前面配置24個taps就占用了6個M4K塊,那么如果配置成12個taps,distance值為128會怎樣呢?6個taps,distance值為256會怎樣呢?答案馬上揭曉,如圖10所示。其實兩者都是占用了3個M4K。這里做的變化就是最終優化成功的玄機。 ![]() 如圖11所示,其實這個工程最終實現到EP2C5Q上是沒有問題的,但是如果沒有類似移位寄存器例子中的一些優化,存儲器資源還是很緊張的。 ![]() 說到這里,雖然已經洋洋灑灑圖文并茂好長一篇文章了。但是,還是很想再提一些和FPGA片上存儲資源相關的問題。關于Cyclone/Cyclone II的M4K到Cyclone III的M9K,可能還有一些M512,將來不知道會不會有什么M32K/M128K/M1M云云的概念出來。但是就特權同學對目前器件使用的一點經驗上來看,這個MXX的塊存儲量越大,雖然總的存儲量也會越來越大(不能否定它能夠滿足片內大存儲量應用的需求),但是相應的在工程需要的很多小存儲應用中對存儲塊的利用率也會越來越低。因為,對于用戶例化的任何一個存儲器,如果使用M4K塊實現一個8bit的512B/256B/128B/64B甚至哪怕只有1B的應用,其實他們都需要占用1個M4K塊。打一個更形象更極端的例子,我的設計中需要兩個1*8bit的FIFO(當然實際應用中沒有人這么傻,^o^),那么例化完編譯后,我的M4K資源別占用了2個,這就是問題。這也是制約著極大多數的應用中,特權同學提到的FPGA片內存儲資源利用率無法100%的原因。其實,這也是最近特權同學的另一個項目中搭建的NIOS2平臺,如圖12所示,各種簡單的外設都分別要占用一點片內存儲器(沒有充分的利用M9K的資源),直接導致整個利用率很低的原因。針對與這種情況,不知道器件廠商是否有所考慮,也許對他們而言,也是處在一種魚和熊掌不可兼得的矛盾之中。 ![]() |