Verilog 編寫規范


    在學習Python時,作者有一句話對我影響很大。作者希望我們在學習編寫程序的時候注意一些業內約定的規范。在內行人眼中,你的編寫格式,就已經暴露了你的程度。學習verilog也是一樣的道理,一段好的verilog代碼,在完成設計要求的前提下,還需要條理清晰,有對應的注解,對非作者而言應該是友好的。因為對數字IC設計也處於初級階段,前期所寫的基本是在搜集資料的基礎上,添加一部分個人的理解,希望通過自己的不斷學習,沉淀出自己獨到的見解。

    對於Verilog編寫規范,網上的資料比較散,其中較好的我覺得是2001版華為的編寫規范。下面簡稱規范(https://wenku.baidu.com/view/bbad6339fe00bed5b9f3f90f76c66137ee064fc8.html)百度文庫

    我將在次規范的基礎上加入一些補充:

1.低電平有效信號,信號后加‘_n’。

2.模塊名小寫。

3.module例化名用U_xx_x表示(多次例化用次序號0.1.2...)。

4.使用降序排列定義向量有效位順序,最低位為0。

5.采用小寫字母定義reg,wire和input/output/inout。

6.采用大寫字母定義參數,參數名小於20個字母。

7.時鍾信號應前綴‘clk’,復位信號應前綴‘rst’。

8.三態輸出寄存器信號應后綴‘_z’。

9.代碼中不能使用VHDL保留字,更不能使用Verilog保留字。 ps:具體有哪些保留字可以百度搜索,這里不列舉。

10.輸出信號必須被寄存(只對頂層模塊)。ps:在查閱的各種資料中,都有提及這一點。

11.三態邏輯可以在頂層模塊中使用,子模塊中避免使用三態。

12.沒有未連接的端口。

13.到其他模塊的接口信號,按如下順序定義端口信號:輸入,(雙向),輸出。

14.建議使用coregen生成乘法電路。

15.采用基於名字的調用,而非基於順序的調用。

16.不要書寫空的模塊,即用一個模塊至少要有一個輸入和一個輸出。

17.時鍾事件的表達要用‘negedge<clk_name>’ 或 'posedge<clk_name>'的形式。

18.異步復位,高電平用‘if(<rst_name> == 1'b1)’,低電平有效用‘if(<rst_name> == 1'b0)’。 ps:if 內的判斷條件位寬為1。

19.if語句不能嵌套太多。

20.建議不使用include語句。

21.建議每個模塊加timescale。

22.代碼中給出必要的注釋。

23.每個文件有一個文件頭。ps:我的理解是每個文件最開頭應用注釋好,所寫模塊的名字、功能、版本、時間等。

24.每個文件只包含一個模塊。

25.模塊名與文件名保持一致。

26.同步時序邏輯的always block中有且只有一個時鍾信號,並且在同一個沿動作(如上升沿)。

27.同步時序邏輯的module中,在時鍾信號的同一個沿動作。

28.采用同步設計,避免使用異步邏輯(全局信號復位除外)。

29.一般不要將時鍾信號作為數據的信號輸入。

30.不要在時鍾路徑上添加任何的buffer。

31.不要門控時鍾。ps:

32.在頂層模塊中,時鍾信號必須可見。

33.不要采用向量的方式定義一組時鍾信號。

34.不要在模塊內部生成時鍾信號,使用DLL/PLL產生的時鍾信號。

35.建議使用單一的全局同步復位電路或者單一的全部異步復位電路。

36.不要在復位路徑上添加任何的buffer,也不要使用任何門控復位信號。ps:復位路徑上添加buffer,會使得復位信號到觸發器復位接收端口產生延遲,skew的產生,可能無法滿足復位恢復時間,從而導致亞穩態的產生。 門控會使得復位信號產生毛刺,增加亞穩態發生的可能性。

37.不使用PLI函數。

38.不使用事件變量。

39.不使用系統函數。

40.建議不使用任務。

41.不使用用戶自定義單元(UDP)。

42.不使用===,!==等不可綜合運算符。

ps: 補充Verilog不可綜合語句。

initial(只在testbench中使用)、events(在同步testbench時更有用)、real time、assign和deassign(reg型無法綜合,但是wire型可以)、fork join、primitives(只支持門級原語綜合)、table、敏感列表中同時帶有posedge和negedge(如always@(posedge clk or negedge clk)begin end 這個無法綜合)、同一個reg被多個always塊驅動、延時 #time ,比如a = #5 b ,此處仿真時候是可以的,但是在綜合時會自動忽略掉#time,相當於a = b、X或Z(未知態和高阻態),在條件表達式中不要使用它們,確保可以綜合。

43.不使用disable語句。

44.建議不使用forever,repeat,while循環語句。

45.避免產生latch(除CPU接口)。 ps:在if語句或者case語句中的所有條件分支中都有對變量有明確的賦值,不然會綜合出latch。

46.組合邏輯語句塊敏感列表中敏感變量必須和該模塊中使用的相一致,不能多也不能少。

47.在一個always語句中,有且僅有一個事件列表。

48.在時序always塊的敏感事件列表中,必須都是沿觸發事件,不允許出現電平觸發事件。

49.數據位寬要相匹配。

50.不使用real,time,realtime類型。

51.建議不使用integer類型。

52.位移變量必須是一個常數。

53.避免使用異步反饋電路。

54.時序邏輯語句塊中統一使用非阻塞型賦值。

55.組合邏輯語句塊使用阻塞型賦值。 ps:對於54 55需要了解一下阻塞和非阻塞的區別。 非阻塞賦值語句,右端表達式計算完並不會立刻傳遞給左端,而是等待下一個事件觸發前一刻再傳遞給左端,且它們是並行的。就是說,在所有的右端表達式在時鍾有效沿到來之時開始計算,等到下一個時鍾有效沿到來之前一刻,將值同時賦值給了左端。可以想象出它對時鍾沿觸發描述的恰到好處,所以用在時序邏輯中。 阻塞賦值語句,在每個右端表達式計算完之后,立刻傳遞給左端,並且后面的式子只能在前面完成后,方可運行。所以說是一個串行過程,而組合邏輯恰恰需要這樣的一個表達方式。

56.非阻塞賦值語句不加單位延時,尤其是對於寄存器類型的變量賦值時。

57.整型常量基數格式中不能有‘?’。

58.字符串中不能包含有控制字符(如CTRL鏈)。

59.禁止使用空的時序電路塊以及非法的always結構。

60.不要在連續賦值語句中引入驅動強度和延時。

61.不要為net,n_input,n_output,enable_gate型變量定義驅動強度,電荷保持強度以及延時。

62.禁止使用trireg(具有電荷保持特性的連接)NET型定義。

63.禁止使用tri0,tri1,triand和trior型連接。

64.在RTL級代碼中不能包含有initial結構,也不能對任何信號進行初始化賦值,應該采用復位的方式進行初始化。

65.不要在過程語句中使用assign,deassign,force,release等語句。

66.不要使用wait語句。

67.不要使用fork join語句塊。

68.不要為驅動類型為supply0和supply1型的連線(net)賦值。

69.設計中不使用macro_module。

70不要在RTL代碼中實例門級單元,尤其是下列單元:CMOS開關,RCMOS開關,NMOS開關,PMOS開關,RNOMS開關,RPMOS開關,trans雙向開關,rtrans雙向開關,tranif0,tranif1,rtranif0,rtranif1,pull_gate。

71.不要使用specify模塊。

    這些規則中有一些我還沒有弄清楚,等到更多的實際應用中出現的時候,應該會有一種恍然大悟的感覺,實踐才是檢驗真理的唯一標准。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM