一般性的指導原則
總的來說,RTL級的評判標准有許多,從時序、面積到功耗等等,都是非常重要的指標。但是這里只介紹一般性的指導原則。
1.面積和速度的平衡互換原則,這兩者的目標是對立統一的關系,相互制衡。
2.硬件原則:理解HDL語言的本質,注意與軟件設計區分。
3.系統原則:從整體上、全局上優化和把握設計從而提高設計質量,優化設計效果。
4.同步設計原則:要求設計的時序穩定,這也是高速RTL設計的通用標准。
面積與速度的平衡互換原則
面積指的是一個設計所消耗的資源量。
速度指的是設計再芯片穩定運行上達到的最高頻率。
通常,在兩者之間需要去分析哪一個為主要矛盾,從緩解主要矛盾入手解決問題。如果時序余量較大,則”用時間換面積“,如果面積余量較大,則”用面積換時間“。通常而言更小的面積意味着更少的器件,更大的時序余量意味着更高的頻率,都能增強系統的魯棒性。如果二者發生沖突,則采用速度優先的原則。
書上的示例較長,這里就省略不寫了。
合理地使用速度和面積的轉換,可以在滿足前提條件的情況下,進一步優化設計。
硬件原則
首先要注意,無論看上去多么相像,硬件描述語言同軟件語言是有着本質區別的!
評價一段HDL代碼的優劣是看他實現的電路的性能(面積和速度)兩個方面的,而不是看代碼是否簡短。需要對電路本身所代表的硬件有一個較好的理解,然后再用描述語言把它表達出來。
HDL語言同C語言的最顯著區別在於HDL語言存在”互聯“、”並發“、”時間“三個概念。
1.互聯:硬件語言中的線網類型描述的是器件之間的連接。
2.並發:高級語言天生是串行的,而硬件語言則天然是並行執行的。
3.時間:高級程序執行的時間依賴於其處理器性能,而硬件語言中通過描述的時間在仿真時模擬信號的時間關系。
進一步討論for循環的使用
在行為級描述測試激勵時,通常使用for循環來描述測試激勵,描述簡單,代碼清晰,而且仿真時回單獨為for循環開辟內存,加速仿真。
在RTL級描述時,則不建議使用for循環,在綜合時,for循環的內容只是被一個個展開分別實現罷了,很容易造成資源浪費。
系統原則
系統原則包含兩層含義:其一,目標器件本身可以看成一個系統,如何設計系統,分割功能模塊,這很重要,其二,模塊化設計方法。合理划分模塊,單獨優化各個模塊的效率,最后再融合到頂層中去。
同步設計原則和多時鍾處理
同步設計原則
同步設計原則是PLD和ASIC最重要的設計原則。
同步時序設計與異步時序設計
首先比較一下同步時序電路和異步時序電路:
1.異步電路:
核心是由組合邏輯構成的,同時鍾沒有關系,不依賴於觸發器驅動。容易產生毛刺,不利於電路的移植,不利於靜態時序分析和驗證設計時序功能。
2.同步電路
核心是通過各種各樣的觸發器來實現。主要信號和輸出信號都是由時鍾沿驅動觸發器完成的。因此,可以避免毛刺,同時有利於移植和時序分析。
同步時序設計
基本原則:要求使用時鍾邊沿驅動所有的操作。
對於所有的寄存器,都必須要滿足setup和hold的時間指標。
setup:在有效時鍾沿到達前,信號必須已經建立setup時間。
Hold :在有效時鍾沿到來之后,信號必須還要保持hold時間。
同步時序的延時:對於比較大的延時,通過一個計數器來模擬,對於比較小的延時,過一個觸發器打一拍然后就完成了時序同步。對於”#5 state <= next_state“這樣的行為級描述是用於仿真測試激勵的,在綜合時是不可能對電路本身產生影響的。
亞穩態
如果觸發器是setup和hold時間不滿足,就可能產生亞穩態。此時觸發器的輸出就是不確定的,同輸入沒有關系。
亞穩態最主要的危害在於破壞系統的穩定性,可能使得后續電路產生誤判,甚至把亞穩態傳播下去。
只要有異步元件,亞穩態就不可避免,設計時首先要減少亞穩態帶來的錯誤,其次應該讓電路對亞穩態不那么敏感。前者可以通過同步設計實現,后者通過使用兩級以上的寄存器實現。
注意,多級寄存器也不一定能完全避免錯誤,但是對於有些情況如聲音圖像的傳播,對錯誤並非那么敏感則無傷大雅,如果有精確需求則應該配合校驗碼,實現查錯糾錯。
異步時鍾域數據同步
異步時鍾域的數據同步問題主要分為兩類:同頻異相,異頻問題。
不推薦的處理方法
1.通過buffer等組合邏輯來調整采樣時間:首先組合邏輯就容易產生毛刺,其次很容易受到環境因素的影響。
2.同時使用時鍾上下沿來調整采樣時間:
首先如果是倍頻可以直接通過倍頻時鍾來實現。同時使用雙沿可能回帶來占空比、相位差等一系列指標的問題。
其次一般對於某一個時鍾,都只能保證一個時鍾沿的指標比較好,對於另一個沿則難以保證質量。
第三,即使特殊情況要使用時鍾雙沿,一般也不會在一個周期內同時使用雙沿,對於DDR(Double rate sych Dynamic RAM)等特殊電路通常對時鍾雙沿都有明確的要求,同普通類型的設計是截然不同的。
異步時鍾數據同步常用方法
1.同頻異相問題:
其一就是在信號后面加寄存器,但是如果出現亞穩態仍然不能保證就一定輸出正確。其二,采用DPRAM和FIFO把數據根據上級時鍾控制寫入,通過下級時鍾控制輸出,完成相位的調整。
2.異頻問題:
其實解決方法和上面的第二點是一致的,但是,在異頻問題中,需要注意,因為頻率不同,所以上下級的吞吐率是不一樣的,所以必須設置合理的緩沖池來完成緩沖,防止信息丟失。這其實也非常類似操作系統里的緩沖池。
代碼風格
注意,有的代碼風格是不依賴於設計目標、EDA工具等等外界因素的准則,但是有的代碼風格則是同這些相關。例如前面我們反復提到組合邏輯會產生毛刺,但是在ASIC設計中有時就會有意識的采用組合邏輯的設計。因此還是要隨機應變。
結構層次設計與模塊划分
結構層次化編碼
結構層次化是設計的一種基本思想,不僅僅在硬件,甚至軟件以及其他的許多行業的設計中也廣泛應用了這一思想。
需要注意:
1.結構不宜太深,否則綜合時面積過大,綜合工具會默認做扁平化處理
2.頂層設置不宜過於復雜,主要完成諸如輸入輸出,模塊調用與實例化,全局時鍾,三態總線,全局復位等等簡單的功能。
3.雙向的信號最好只在頂層出現。
4.子模塊之間最好不要有跨層次的接口。
5.合理考慮子模塊的功能、結構、時序等。
模塊划分的技巧
1.對每個同步時序設計的子模塊的輸出使用寄存器處理
2.將相關的邏輯或者可以復用的邏輯寫在一起
3.將不同優化目標的部分分開,時序的和面積的分開處理。
4.將時序寬松的分到同一個模塊
5.將存儲器件獨立划分
6.合理規划模塊的規模
組合邏輯設計的主要事項
always信號敏感表的注意事項
1.敏感表必須包含所有的輸入和判斷信號模塊;
2.不可能通過改變敏感表的內容來改變邏輯(在綜合時沒有寫入的相關變量綜合工具會自動加上),設計時應該注意邏輯的問題而非通過修改敏感表實現邏輯的變換。
組合邏輯環路
組合邏輯環路是設計的大忌。
在物理實現中,完成組合邏輯環路往往依靠器件本身的延時性能保證的,但是事實上這些性能會受到PVT(工藝,電壓,溫度)極大的影響,往往是難以保證的。
在存在反饋的環路上必須加上寄存器。
脈沖產生器
簡單的脈沖產生器往往依靠一系列的反向器和原信號相與產生,利用的是反相器本身器件的延時特性,是沒有辦法保證較為准確的脈沖持續時間的,應該用寄存器來實現。
鎖存器
鎖存器同前面提到的環路一樣是很容易出錯的電路。
避免鎖存器,就應該在組合邏輯中的if...else...一定要加else,case語句一定要加default,這樣才能比較好地避免鎖存器的出現。
時鍾設計的注意事項
對於一些PLD如FPGA等,通常是內嵌有時鍾的,這里主要是做一些比較。
組合邏輯產生的時鍾
首先為了避免組合邏輯產生的毛刺,依然需要在組合邏輯輸出加上寄存器。
其次,組合邏輯產生的時鍾質量比較低,skew和Jitter都比較大。
Ripple Counter
行波計數器,實際上就是把每一級寄存器的輸出加到下一級寄存器的時鍾端。但是這是一個異步時序電路,會產生很多奇怪的問題。
時鍾選擇
通常在通信系統中會產生不同數據速率的要求,因而要使用專門的CLOCK MUX進行切換,這些MUX通常新能都非常不錯,切換時的沖擊也很小。
門控時鍾
門控時鍾通常使用一個異步信號與時鍾信號相與然后接到寄存器的時鍾端,其優點在於能控制功耗,缺點在於通過了一個門會降低時鍾信號的質量。
時鍾同步使能端
大多數寄存器單元都包含這樣的使能端,但是需要注意,這里的使能端不能減少功耗,實際上是屏蔽了輸出,寄存器內部仍然在運作,因此仍然會產生功耗。
RTL代碼優化技巧
使用pipeline技術優化時序
即使用流水線的方法,雖然對於每一個操作本身並沒有縮短時間,但是增大了總體的吞吐率,同時保證了時序。一定程度上增大了頻率。
模塊復用與resource sharing
以一個補碼平方器為例:
module resource sharing(
input[7:0] data_in,
output[15:0] square);
wire[7:0] data_bar;
assign data_bar = ~data_in + 1;
assign square = (data_in[7])? data_bar*data_bar : data_in*data_in;
//以下是方案二
wire[7:0] temp_data;
assign temp_data = (data_in[7])? ~data_in+1 : data_in;
assign square = temp_data * temp_data;
endmodule
顯然,方案二比方案一節省了一個多路選擇器和一個乘法器,大大優化了電路的面積性能。
需要注意,有時綜合工具可以幫助我們優化,但是不要過於依賴工具,還是應該提高自己的代碼能力。
邏輯復制
邏輯復制旨在為例改善時序而增加面積。
最常用於調整扇出,因為扇出若很大必須加多級寄存器以增加其驅動能力,這樣會耽誤時序,所以可以進行邏輯復制,減少單個扇出,從而改善時序。
簡而言之就是用面積換時間。
香農擴展運算
香農擴展運算其實對應於這個公式:F(a, b, c) = aF(1, b, c) + ~aF(0, b, c)
實際上,香農擴展運算也是通過把一個輸入變為MUX的控制信號從而改善時序的。
這也是以空間換時間,是否使用需要綜合實際情況進行考慮。
主要內容和示例來源:《輕松稱為設計高手 Verilog HDL實用精解》;北京航空航天大學出版社;
推薦練習網站:https://hdlbits.01xz.net/wiki