2. 在門與門之間請不要來回走動
門(寄存器)與門之間是什么?是組合邏輯電路。信號的傳遞就是不斷的打開一個門,然后進(jìn)入另外一個門,這樣一級一級的不斷傳遞,你才可以一直從起點走到終點。在有些時候也許你并沒有注意,你在到達(dá)另外一個門之前,你轉(zhuǎn)了一個圈又回來了。雖然這只是一個簡單的圈,但是這個動作會被無限循環(huán),因為這個動作沒有被時鐘限制。所以導(dǎo)致的后果可想而知了。舉一個最簡單的例子:
D = A + B + C;
Reg C = D + B;
A 和 B 都是輸入,而 C 是輸出,你會發(fā)現(xiàn)其實這個 C 偷偷的回去轉(zhuǎn)了一圈,而結(jié)果是使自己又多做了幾次循環(huán)。而最終結(jié)果是多少要看這段邏輯自身的延遲和你的時鐘頻率,對不起,誰都不可能預(yù)測結(jié)果。而且每次編譯的結(jié)果都會不同,因為編譯導(dǎo)致的電路延遲是隨機(jī)的。但是如果我們把 D 也用門關(guān)一下(寄存器),那么結(jié)果就會舒服了。
Reg D = A + B + C;
Reg C = D + B;
不妨在 QuartusII 里面嘗試這兩種電路。 工具會報告一個 combinational loop 的警告給你。也可以嘗試做一些仿真體會一下。
一號門 = A + B 二號門 = C + D.
三號門 = 一號門 + 二號門
四號門 = 三號門 + E
這樣通過一個三層門的結(jié)構(gòu)做一個五輸入的加法器,來達(dá)到最好的效果。
6 輸入查找表 (StratixII, CycloneII, 和其他那些比較新的器件)
在新的結(jié)構(gòu)中,我們可以使用 6 輸入的查找表,這樣,就可以用三個數(shù)加在一起 變成:
一號門 = A + B + C
二號門 = 一號門 + D + E
狀態(tài)機(jī)
狀態(tài)機(jī)是設(shè)計過程中的核心部分,所以我們需要特別的提一下寫狀態(tài)機(jī)的一些注意事項。為了實現(xiàn)利益最大化,建議在 FPGA 中使用 one hot 模式的狀態(tài)機(jī),而在 CPLD 中使用最少比特數(shù)的狀態(tài)機(jī)。在具體的設(shè)計中需要注意的是:
優(yōu)化目標(biāo):一個是全局的設(shè)置,告訴工具你這個設(shè)計的優(yōu)化偏向。當(dāng)時序優(yōu)化偏重要的時候,可以設(shè)置為 Speed。當(dāng)然這使以犧牲 area, power 為代價的。也可以對某個獨立模塊做局部設(shè)置,就是說在這個模塊中,優(yōu)化目標(biāo)是時序。
Design Space Explorer: 這個是一個實在沒辦法的辦法,但凡還有一線生路,最好不要用這個東西。他會自動的對你的設(shè)計根據(jù)一些設(shè)置,不斷的嘗試布局布線。比如使用不同的優(yōu)化方法,不同的算法,甚至不同的種子來做編譯,最后給你一個最符合約束要求的編譯結(jié)果。但是這樣的工作量有多大,大家可想而知了。如果你有比較多的時間,你可以試試把它扔在那里跑個幾天。
不求甚解之 NiosII
所有的系統(tǒng)都是由模塊組成的,或大或小的模塊,拼接成一個大積木。所以我們首先需要了解這些模塊 (IP)。關(guān)于怎么去了解一個 IP,其實是很重要的問題。NiosII CPU 作為一個比較大型的模塊,可以作為一個例子來講。一個關(guān)鍵詞是不求甚解。不求甚解的目的,并不是偷懶,而是更準(zhǔn)確,更有針對性,更快捷。IP 的作用就是為了完成一個特定的功能,所以我們并不需要知道它是如何實現(xiàn)的,事實上,由于很多的 IP 都是加密的代碼,所以也不可能知道具體的電路狀態(tài)。同時也不需要花很多的時間把文檔里面的每一行都了解清楚。作為工程師,大家的脾氣一般都是一種超強(qiáng)的好奇心和鉆研精神的集合。而往往會鉆進(jìn)牛角尖里面。而作為系統(tǒng)設(shè)計,是需要有一種粗曠型的大氣魄,不需要在細(xì)節(jié)上浪費時間。你會發(fā)現(xiàn)很多的細(xì)節(jié)是沒有意義的。并不是說我們不需要去研究細(xì)節(jié),細(xì)節(jié)是很重要的,但是細(xì)節(jié)需要在被用到的時候才去關(guān)注就好了。
作為一個 IP,最重要的,其實是接口。因為你最重要的是需要知道是怎么讓它工作起來,而不是它怎么工作的。所以在看文檔的時候,最主要看的就是接口信號,對所有的信號的作用有一個了解。NiosII 使用的是 Avalon MM 點對點接口,這其實是一個非常有趣的接口,因為它的交流更加短平快一些。它與普通的 PCI 接口不同的地方是,他可以支持同時多線控制。因為它沒有總線的概念,不會在總線被占據(jù)的時候,其他任何通訊都無法進(jìn)行。NiosII是在 SOPC builder 中被直接使用的,我們不需要知道具體有哪些信號,因為沒有非常需要,我們是看不到這些接口的。在 NiosII 中,我們有兩個 Master Avalon MM 接口,一個是Instruction Master Port, 這是 CPU 用來讀取指令的接口。CPU 通過這個端口從 Memory 上讀取指令。另一個是 Data master port, 很簡單,這是用來連接數(shù)據(jù)通道的。比如說你要讀取的數(shù)據(jù),你要存儲的數(shù)據(jù),都是走這個通道。這兩個端口可以連接同一個內(nèi)存,在這種時候需要特別小心,很有可能自己把自己的指令給改掉了。但是反過來思考一下,其實我們可以做什么?可以按照狀況改變軟件代碼。NiosII 中還有第三個端口,這是用來做 Debug 用的端口。還有其他的一些接口,比如 TCM 接口。我們需要知道這些接口的存在,但是不需要知道細(xì)節(jié),只有在用到的時候再去看相關(guān)的文檔就好了。
第二個需要關(guān)注的問題就是參數(shù)設(shè)置。這里面是有講究的。IP 是廠家做出來的通用模塊,不是為你而特制的,所以必然有一些是你不需要的方面。我們可以通過參數(shù)的修改,讓它盡量的接近我們的需求。有很多人在做設(shè)計的時候是有思維定勢的,而且這種定勢的頑固性很強(qiáng)。這很容易對環(huán)境產(chǎn)生一種叛逆思想。就是說除了他自己假想出來的做法,其他的一切都是不對的,或者說不好的。而這在使用 IP 的時候,會遭遇到意想不到的痛苦的。所以,盡量不要依靠假設(shè)來臆想了模塊的設(shè)置。而是盡量的適應(yīng)環(huán)境,來配置自己的設(shè)計。作為一個FPGA 的玩家,這種依照環(huán)境來改變的能力是必須的。
NiosII 的參數(shù)中首先是指令集或者說 CPU 復(fù)雜度的選擇,有三個選擇,根據(jù)不同的選擇,CPU 的能力會有不同,當(dāng)然使用的資源也是完全不一樣的 NiosII/E (經(jīng)濟(jì)型)能力最弱,當(dāng)然資源也最小(600-700 LE )
NiosII/S (中間型) 中庸配置,資源消耗是 1200-1400 LEzNiosII/F (快速型) 能力最強(qiáng)配置,資源消耗是 1400-1800LE
再了解一下 Jtag Debug 的模式選擇,一共有五個等級的選擇。和選擇 CPU 一樣,從簡單到復(fù)雜。一般來說選擇 Level2 也就夠用的。
自定義指令設(shè)置。這是最有價值的設(shè)置。別忘記了,我們是在 FPGA 的世界里。所以 CPU并不像在其他地方那樣的鐵板一塊。我們可以選擇使用自定義的指令。所謂自定義指令,并不是一個軟件宏或者函數(shù)。而是一塊硬件。當(dāng) CPU 調(diào)用到這個指令的時候,事實上它調(diào)用的就是這個硬件模塊,它被嵌入在 CPU 中。而這其實就是 NiosII 好玩的地方。
好了,現(xiàn)在我們要考慮的問題,就是使用。使用 CPU 的方法,當(dāng)然就是軟件編程。NiosII的軟件其實是非常簡單的。就是普通的 C,或者 C++,需要做的就是不斷的對端口的地址讀啊,寫啊,計算數(shù)據(jù),就好了。但也可能非常的復(fù)雜,因為你不僅需要了解軟件編程,你更需要了解你使用的那些硬件,那些外設(shè)模塊。NiosII 的編程很硬件的依賴性是很強(qiáng)的。針對比較大型的一些外設(shè),可以寫一些 HAL 程序。這是類似于驅(qū)動的一些指令。而軟件只需要調(diào)用這些 API 就可以了。大部分的 NiosII 程序是不需要使用操作系統(tǒng)的,作為一個嵌入式系統(tǒng)的控制核心,更多的是一些存儲式的讀寫,算法的計算的操作。除非你需要運行一些網(wǎng)絡(luò)協(xié)議啊,什么的。但其實我們可以用更加解構(gòu)的方式來看待一個操作系統(tǒng)。操作系統(tǒng)其實就是給我們提供了一大堆的操作指令而已。沒什么更特別的作用了。所以,思考一下吧。
大家知道我們這里說玩轉(zhuǎn) FPGA 的,每次我在 FPGA 里面提到了 DSP 的題目的時候,總是會有一些人打斷我說,兄弟啊,你大概走錯地方了。我們這里都是硬件工程師,或者可能有些寫 C 的,但是 DSP,那東西不會寫哦。那么好吧,我就跑到 DSP 那里去講,F(xiàn)PGA,然后就會有人問我,你們這個 FPGA 和 TI 的 DSP 比有什么區(qū)別呢?我暈。我想說的是,我這里的 DSP 是 Digital Signal Processing (數(shù)字信號處理),而不是 Digital Signal Processor (數(shù)字信號處理器)。
1. 多通道支持,在這個模塊組中,接口都異常的簡單,基本上就是這樣三個,V, D, C. V就是 Valid, D 就是 Data, C 就是 Channel。所以要告訴他的就是,是個數(shù)據(jù),是不是有效數(shù)據(jù),是那個通道上的有效數(shù)據(jù)。所以,無論你是多少通道的設(shè)計,無論你怎么修改你的通道數(shù)目,模型就還是這么個模型,都是一樣的。這樣可以使你的模型和你的算法框圖看上去幾乎是一樣的。
3. 系統(tǒng)層面的設(shè)計。這也是一個比較新鮮的東西。所有設(shè)計里面的寄存器都會被編入一個系統(tǒng)地址查找表,比如說 FIR 的系數(shù),一些控制寄存器都會有不同的地址。我們可以通過一個系統(tǒng)接口來對這些寄存器進(jìn)行操作。這樣使整個設(shè)計更具有系統(tǒng)化概念。在編譯的時候,同時非常高級的生成一個寄存器列表(網(wǎng)頁格式),包括寄存器名字,地址,初始值。所以可以見到,通過這個高級的模塊的增強(qiáng),使得算法方面的實現(xiàn)與設(shè)計變得更加容易。也可以很容易的實現(xiàn)非常復(fù)雜的系統(tǒng)。