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