(未完成)華為Verilog HDL程式碼書寫規範筆記
1. 目的
本規範的目的是提高書寫程式碼的可讀性、可修改性、可重用性,優化程式碼綜合和模擬的結果,指導設計工程師使用VerilogHDL規範程式碼和優化電路,規範化可程式設計技術部的FPGA設計輸入,從而做到:① 邏輯功能正確,②可快速模擬,③ 綜合結果最優(如果是hardware model),④可讀性較好。
2.適用範圍
本規範涉及Verilog HDL編碼風格,編碼中應注意的問題,Testbench的編碼等。
本規範適用於Verilog model的任何一級(RTL,behavioral, gate_level),也適用於出於模擬、綜合或二者結合的目的而設計的模組。
3.Verilog 編碼風格
3.1命名習慣:
用有意義而有效的名字;
用連貫的縮寫;
用最右邊的字元下劃線表示低電平有效,高電平有效的訊號不得以下劃線表示,短暫的引擎訊號建議採用高有效;
大小寫原則:名字一般首字元大寫,其餘小寫(但parameter, integer 定義的數值名可全部用大寫),兩個詞之間要用下劃線連線。
全域性訊號名字中應包含訊號來源的一些資訊。
同一訊號在不同層次應保持一致性;
自己定義的常數、型別等用大寫標識;
避免使用保留字;
新增有意義的字尾,使訊號名更加明確;
一個module一個檔案,且檔名能與module名對應起來;
3.2 Modules
頂層模組應只是內部模組間的互連;
每一個模組應在開始處註明檔名、功能描述、引用模組、設計者、設計時間及版權資訊等。程式碼中的所有說明、註釋必須均為英文,例如:
/*********************************************************************\ Filename : fulladd.v Author : Verilog_gruop Description : Example of a one-bit full add. Revision : 2000/02/29 Company : Verilog_group \*********************************************************************/
不要對Input進行驅動, 在module 內不要存在沒有驅動的訊號,更不能在模組埠中出現沒有驅動的輸出訊號,避免在elaborate和compile時產生warning,干擾錯誤定位。
每行應限制在80個字元以內,以保持程式碼的清晰、美觀和層次感。
電路中呼叫的 module名用Uxx標示, Cell名用Vxx標識。向量大小表示要清晰,採用基於名字(name_based)的呼叫而非基於順序的(order_based)
用一個時鐘的上沿或下沿取樣訊號,不能一會兒用上沿,一會兒用下沿。如果既要用上沿又要用下沿,則應分成兩個模組設計。建議在頂層模組中對Clock做一非門,在層次模組中如果要用時鐘下沿就可以用非門產生的Posedge Clk_, 這樣的好處是在整個設計中採用同一種時鐘沿觸發,有利於綜合。
在模組中增加明瞭的英文註釋。對訊號、參量、引腳、模組、函式及程序等加以說明,便於閱讀與維護。
Module 名要用大寫標示,且應與檔名保持一致。
嚴格晶片級模組的劃分.只有頂層包括IO引腳(pads),中間層是時鐘產生模組、JTAG、晶片的核心(CORE),這樣便於對每個模組加以約束模擬,對時鐘也可以仔細模擬。
模組輸出暫存器化:對所有模組的輸出加以寄存(如圖1),使得輸出的驅動強度和輸入的延遲可以預測,從而使得模組的綜合過程更簡單。
- 輸出驅動的強度都等於平均的觸發器驅動強度
- 輸入延遲始終等於通過觸發器的路徑,近於相等
將關鍵路徑邏輯和非關鍵路徑邏輯放在不同模組:保證DC可以對關鍵路徑模組實現速度優化,而對非關鍵路徑模組實施面積優化。在同一模組DC無法實現不同的綜合策略。
將相關的組合邏輯放在同一模組: 有助於DC對其進行優化,因為DC通常不能越過模組的邊界來優化邏輯
ultraedit中的tab鍵設定為4個空格鍵;
輸入輸出的埠定義分行寫,一行定義一個輸入輸出,頂格對齊;
module頭中的括號內的輸入輸出的定義按輸入輸出分開,與括號對齊
module用到的變數統一在輸入輸出的定義之後,按wire和reg型分開定義,並對重要的訊號加註釋說明
module主體以//module begin作為起始標識
子模組的呼叫頂格對齊;子模組中的輸入輸出的埠訊號的名字儘量與呼叫的名字一致
if...else一一對應,若無else時,加一個空語句;
3.3 Net and Register
一個reg變數只能在一個always語句中賦值;
向量有效位順序的定義一般是從大數到小數;
對net和register型別的輸出要做宣告;
無用訊號不要引入module內部,避免在elaborate和compile時產生warningr型別的輸出要做宣告。
3.4 Expressions
用括號來表示執行的優先順序,儘管操作符本身有優先順序,但用括號來表示優先順序對讀者更清晰,更有意義;
用一個函式(function)來代替表示式的多次重複;
3.5 IF 語句
向量比較時,注意長度匹配;
每一個If 都應有一個else 和它相對應;硬體設計中,常要求條件為真時執行一種動作而條件為假時執行另一動作,即使認為條件為假不可能發生。沒有else可能會使綜合出的邏輯和RTL級的邏輯不同。
應注意If ..else if ...else if ...else 的優先順序;
3.6 case 語句
case語句通常綜合成一級多路複用器(圖的右邊部分),而if-then-else則綜合成優先編碼的串接的多個多路複用器,如圖的左邊部分。通常,使用case 語句要比if語句快,優先編碼器的結構僅在訊號的到達有先後時使用。條件賦值語句也能綜合成多路複用器,而case 語句模擬要比條件賦值語句快。
所有的Case 應該有一個default case ,允許空語句;
3.7 Writing functions
在function的最後給function賦值;
函式中避免使用全域性變數否則容易引起HDL行為級模擬和門級模擬的差異;
3.8 Assignment
Verilog 支援兩種賦值:過程賦值(procedural) 和連續賦值(continuous),也被稱為阻塞賦值與非阻塞賦值。過程賦值用於過程程式碼(initial, always, task or function)中給reg 和 integer變數賦值,而連續賦值一般給wire 變數賦值。
Always @(敏感表),敏感表要完整,如果不完整,將會引起模擬和綜合結果不一致;
Assign/deassign 僅用於模擬加速;
Force/release 僅用於debug;
避免使用Disable;
對任何reg賦值用非阻塞賦值代替阻塞賦值;
3.9 Combinatorial Vs Sequential Logic
如果一個事件持續幾個時鐘週期,設計時就用時序邏輯代替組合邏輯;
在simulation pattern 或 report file中,儘量不用內部訊號,如果要用就把它們引到埠,這樣做並不增加芯片面積。(???)
內部匯流排不要懸空。在default狀態,要把它上拉或下拉。
3.10 Macros