1. 程式人生 > 實用技巧 >(未完成)華為Verilog HDL程式碼書寫規範筆記

(未完成)華為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