“要養(yǎng)成良好的Verilog代碼風(fēng)格,要先有硬件電路框圖之后再寫(xiě)代碼的習(xí)慣,設(shè)計(jì)出良好的時(shí)序,這樣才能在FPGA開(kāi)發(fā)或者ASIC設(shè)計(jì)中起到事半功倍的效果,否則會(huì)事倍功半。”
01、代碼規(guī)范
一、概述
1、always/assign/reg/wire
2、文件名與module名要一致,一個(gè)文件一個(gè)module
3、統(tǒng)一的復(fù)位方式,異步復(fù)位上升沿有效(無(wú)論軟復(fù)位或硬復(fù)位)
4、盡量避免用低電平有效的信號(hào),盡量高電平有效
5、狀態(tài)機(jī)一定要采用三段式
6、端口聲明輸入輸出要分開(kāi),最好要有區(qū)分輸入輸出的標(biāo)示
7、條件分支要寫(xiě)全。Case及if else等
8、信號(hào)名不要過(guò)長(zhǎng),不要超過(guò)32個(gè)字母
9、所有寄存器都要復(fù)位且有初始值
10、不允許使用門(mén)控時(shí)鐘或門(mén)控的復(fù)位
11、組合邏輯阻塞賦值,時(shí)序邏輯非阻塞賦值
12、內(nèi)部信號(hào)避免出現(xiàn)三態(tài)
13、避免出現(xiàn)latch
14、多使用parameter,增加修改的便利性
15、連接同一端口的同一組信號(hào)盡量有公共的符號(hào)表示,如dav/sop/eop等
另外:
不允許將多個(gè)寄存器寫(xiě)到一個(gè)always里面;
要為每一個(gè)寄存器單獨(dú)寫(xiě)一個(gè)always,哪怕兩個(gè)信號(hào)很相關(guān);
要有寫(xiě)電路的意識(shí),不能是寫(xiě)軟件的風(fēng)格(代碼短);
按照橫向思維,每個(gè)信號(hào)都要仔細(xì)考慮,考慮全。
剛開(kāi)始時(shí)盡量避免同一個(gè)寄存器在多個(gè)模塊里面都賦值(Multi Driver);
代碼 - > 電路,寫(xiě)的時(shí)候一定明白什么樣的代碼產(chǎn)生什么樣的電路;
設(shè)計(jì)流程:
設(shè)計(jì)目標(biāo)分析 - > 功能模塊劃分 - > 確定關(guān)鍵電路時(shí)序和模塊間時(shí)序 - > 具體電路設(shè)計(jì)
設(shè)計(jì)電路尤其是數(shù)字電路,最關(guān)鍵的一環(huán)是:設(shè)計(jì)各模塊間的接口時(shí)序。這個(gè)工作必須在具體電路設(shè)計(jì)之前確定下來(lái)。
綜合的TOP_DOWN流程是對(duì)整個(gè)芯片加約束;而綜合的BOTTOM_UP流程是先把小模塊做綜合,然后把綜合好的模塊用一個(gè)頂層的模塊包進(jìn)去,再綜合一次。電路較大時(shí),用BOTTOM_UP流程。
時(shí)序是事先設(shè)計(jì)出來(lái)的,而不是事后測(cè)出來(lái)的,更不是湊出來(lái)的!
二、初學(xué)者注意的問(wèn)題
對(duì)初學(xué)者一定要反復(fù)提醒自己注意:
1、避免把寫(xiě)軟件的思想帶入到寫(xiě)硬件電路中,對(duì)于verilog代碼而言,常常是簡(jiǎn)單冗長(zhǎng)的代碼出來(lái)的電路反而高效;
2、寫(xiě)硬件電路代碼的時(shí)候頭腦中要有硬件結(jié)構(gòu),一定要弄明白什么樣的代碼能夠綜合出來(lái)什么樣的電路。
3、要養(yǎng)成簡(jiǎn)單高效的寫(xiě)代碼風(fēng)格,寫(xiě)電路設(shè)計(jì)的硬件代碼,關(guān)鍵的行為描述部分只允許用assing、always、if語(yǔ)句、case語(yǔ)句,其余的循環(huán)和函數(shù)之類(lèi)的代碼都不提倡使用。
一個(gè)典型的verilog模塊的組成包括module,端口聲明,輸入輸出定義,輸出屬性的聲明,主要代碼及endmodule。都有具體的格式要求,可查找資料查看詳細(xì)的具體格式。另外,module的前面還有一個(gè)timescale及include和宏定義,端口聲明之后還有一些參數(shù)定義等。
需要提示的規(guī)范的module寫(xiě)法是一個(gè).v文件里只寫(xiě)一個(gè)module。這里面最重要的是主要代碼部分,只需要掌握always、assign、wire、reg即可,assign語(yǔ)句后面盡量不要出現(xiàn)較為復(fù)雜的邏輯運(yùn)算,復(fù)雜的邏輯運(yùn)算需要修改成always的寫(xiě)法,以提高可讀性。
數(shù)據(jù)的寫(xiě)法要注意規(guī)范性,每種類(lèi)型的數(shù)據(jù)都要注明位寬及類(lèi)型。
在芯片設(shè)計(jì)中,memory類(lèi)型的數(shù)組變量一般用在深度小于64的寄存器堆定義中,對(duì)于FPGA中不涉及,都是用軟件自動(dòng)生成的RAM。不能對(duì)數(shù)組類(lèi)型的變量中單獨(dú)的幾個(gè)bit進(jìn)行操作,都是按照以“字”為單位進(jìn)行操作。
運(yùn)算符及表達(dá)式只需要注意區(qū)分單目和雙目的運(yùn)算符即可,簡(jiǎn)單來(lái)講,單目的一般是用來(lái)進(jìn)行計(jì)算的運(yùn)算符,常常用來(lái)進(jìn)行邏輯運(yùn)算,寫(xiě)在賦值語(yǔ)句里面;而雙目的運(yùn)算符常常用來(lái)進(jìn)行關(guān)系的判斷,常常用在if語(yǔ)句的判斷條件里面。需要注意的是,運(yùn)算符是有優(yōu)先級(jí)的,為了代碼規(guī)范性及正確性,常常需要添加括號(hào)和空格進(jìn)行隔離和區(qū)分。
對(duì)于語(yǔ)句而言,只允許用較為簡(jiǎn)單的assign賦值語(yǔ)句和always語(yǔ)句。在電路設(shè)計(jì)的可綜合代碼中,不提倡使用for、while等軟件常用循環(huán)語(yǔ)句。always模塊中敏感變量列表中有沿觸發(fā)邏輯的是時(shí)序邏輯模塊,綜合出來(lái)的電路帶有DFF,在賦值的時(shí)候要用非阻塞賦值;always模塊中敏感變量列表中沒(méi)有沿觸發(fā)邏輯的是組合邏輯模塊,綜合出來(lái)的電路都是組合電路門(mén)的連接,在賦值的時(shí)候要用阻塞語(yǔ)句賦值。
if語(yǔ)句是有優(yōu)先級(jí)的,同時(shí)滿(mǎn)足多個(gè)分支的情況下優(yōu)先執(zhí)行最前面的分支,case語(yǔ)句是沒(méi)有優(yōu)先級(jí)的,可以同時(shí)執(zhí)行多個(gè)滿(mǎn)足條件的分支。if語(yǔ)句嵌套最多不能超過(guò)兩級(jí),否則會(huì)影響綜合出來(lái)電路的性能。if語(yǔ)句要寫(xiě)全,一定要有else語(yǔ)句,并且組合邏輯中的else語(yǔ)句不能寫(xiě)自己等于自己,否則就會(huì)形成組合邏輯的反饋環(huán),對(duì)電路產(chǎn)生很大的隱患。另外,if語(yǔ)句的條件判斷語(yǔ)句不能過(guò)于冗長(zhǎng),如果條件判斷太復(fù)雜,也會(huì)影響電路的性能,最好把時(shí)序邏輯里面較為冗長(zhǎng)的判斷邏輯單獨(dú)拉出去寫(xiě)成組合邏輯,這樣就可以提高電路的性能。
經(jīng)常采用initial語(yǔ)句來(lái)寫(xiě)testbench.整個(gè)工程的宏定義可以寫(xiě)成一個(gè)文件,在每個(gè)文件的module前面include上,這樣便于修改。
對(duì)于門(mén)級(jí)電路的描述也很重要,這常常是寫(xiě)出關(guān)鍵路徑高效電路的一種最直接的方法。比如乘法器有很多種,如果用工具自動(dòng)產(chǎn)生的電路,經(jīng)常是不能滿(mǎn)足性能需求,這個(gè)時(shí)候可以自己采用門(mén)級(jí)的描述方式來(lái)寫(xiě)booth編碼的乘法器等來(lái)替換代碼中的一個(gè)乘號(hào),這樣才能提高電路的性能。
三、工程實(shí)例
一個(gè)FPGA工程應(yīng)該把電路設(shè)計(jì)代碼和仿真代碼分開(kāi)成hdl文件夾和sim文件夾兩個(gè)文件夾來(lái)存放,每個(gè)文件夾下都存放相應(yīng)的文件,這樣可以便于高效管理。詳細(xì)例子可以參考從opencores網(wǎng)站上下載的工程。基本都是按照這樣的思路來(lái)進(jìn)行的存儲(chǔ)。
四、代碼的review
代碼的review很重要,可以及早的發(fā)現(xiàn)問(wèn)題,避免在后續(xù)調(diào)試階段發(fā)現(xiàn)定位問(wèn)題耗費(fèi)更多的時(shí)間和精力。
02、基本技能
1、采沿
上升沿、下降沿。
適用于根據(jù)一些信號(hào)進(jìn)行計(jì)數(shù),比如多少個(gè)emac幀等,若根據(jù)某些信號(hào)來(lái)計(jì)數(shù),無(wú)法保證這些信號(hào)是否持續(xù)一個(gè)時(shí)鐘周期,所以需要進(jìn)行取沿的操作。采沿時(shí)打一拍后,適用assign語(yǔ)句產(chǎn)生。
上升沿采樣
下降沿采樣
上升沿和下降沿采樣
沿檢測(cè)代碼:
reg reg_ff1,reg_ff2; always@(posedge clk ) begin reg_ff1 <= reg_in; reg_ff2 <= reg_ff1; end
上升沿:if((reg_ff1) & (!reg_ff2 ) )
下降沿if(( ! reg_ff1) & (reg_ff2 ) )
雙沿:if(reg_ff1 != reg_ff2)
2、“打拍”同步。
不同時(shí)鐘域的信號(hào)進(jìn)行交互時(shí),需要進(jìn)行“打兩拍”的同步操作之后才能使用。主要是為了消除亞穩(wěn)態(tài)問(wèn)題。
具體代碼如下:
reg bdat1,bdat2; always@(posedge clkb ) begin bdat1 <= adat; bdat2 <= bdat1; end
3、同步復(fù)位與異步復(fù)位
(1)同步復(fù)位,綜合出來(lái)不帶復(fù)位端,代碼如下:
always @ (posedge clk) begin if (reset) q<= 1’b0 else q<= d; end
(2)異步復(fù)位,綜合出來(lái)帶復(fù)位端,代碼如下:
always @ (posedge clk or posedge reset) begin if (reset) q<= 1’b0 else q<= d; end
4、三段式狀態(tài)機(jī)
有限狀態(tài)機(jī)(FSM)的寫(xiě)法,時(shí)序邏輯和組合邏輯分成兩個(gè)模塊寫(xiě)。決不允許把輸出也寫(xiě)在里面。
時(shí)序部分:只能有當(dāng)前信號(hào)和下一狀態(tài);
組合部分:組合內(nèi)不能有輸出,即任何輸出都要經(jīng)過(guò)寄存器才能輸出;
module state4 (clock,reset,out); input reset, clock; output [1:0] out; parameter [1:0] stateA=2’b00; parameter [1:0] stateB=2’b01; parameter [1:0] stateC=2’b10; parameter [1:0] stateD=2’b11; reg [1:0] state, nextstate, out; //第一段,時(shí)序邏輯部分 always @ (posedge clock) begin if (reset ==1,0’b0) state <= stateA; else state <= nextstate; end //第二段,組合邏輯部分 always @ (state) begin case (state) stateA: nextstate = stateB; stateB: nextstate = stateC; stateC: nextstate = stateD; stateD: nextstate = stateA; endcase end //第三段,輸出信號(hào)賦值部分,可能有多個(gè)always always@(postdge clock or negedge reset) begin if (reset==1’b0) out <= 2’b0; else … end endmodule
5、“One-hot” 編碼
one-hot編碼方式只用一個(gè)bit來(lái)表示一個(gè)狀態(tài),這大大縮小了狀態(tài)譯碼的組合電路規(guī)模,使得路徑延時(shí)更小,因此狀態(tài)機(jī)的時(shí)鐘可以運(yùn)行在更高的頻率上。
特例:不妨想象該狀態(tài)機(jī)就是一個(gè)循環(huán)計(jì)數(shù)器,如果采用binary編碼,則該計(jì)數(shù)器存在明顯的組合電路;而如果采用one-hot編碼,該計(jì)數(shù)器的綜合結(jié)果就是一個(gè)移位寄存器序列,根本不存在任何組合門(mén)!
6、if條件判斷不能過(guò)于復(fù)雜,若比較復(fù)雜,最好重新定義一個(gè)信號(hào),用組合邏輯實(shí)現(xiàn)后再判斷,否則將影響性能。
7、乒乓操作。
乒乓操作最忌諱兩塊RAM的區(qū)分信號(hào)向無(wú)限遠(yuǎn)處傳播,導(dǎo)致跟很多模塊糾纏,最終造成乒乓不起來(lái)。 因此,乒乓操作的一些RAM區(qū)分信號(hào)最好限制在模塊的內(nèi)部,對(duì)外不可見(jiàn)。這樣才能準(zhǔn)確的進(jìn)行乒乓。
8、64Byte為存儲(chǔ)單元存儲(chǔ)問(wèn)題
根據(jù)EMAC幀的幀長(zhǎng)特點(diǎn),選擇64Byte作為以太網(wǎng)幀存儲(chǔ)的基本單元,在進(jìn)行流量等測(cè)試時(shí)測(cè)試幀長(zhǎng)對(duì)吞吐率的影響會(huì)降至最小。
所用知識(shí):C語(yǔ)言中隊(duì)列管理,鏈表等。
了解隊(duì)列管理模塊、內(nèi)存分配模塊的基本功能。
9、RAM讀出是否寄存問(wèn)題
整個(gè)設(shè)計(jì)中用到RAM的地方若采用工具生產(chǎn),最好要統(tǒng)一采用讀出后寄存一拍再輸出的RAM。
10、仿真環(huán)境-BFM模型
需要掌握以太網(wǎng)PHY模型、簡(jiǎn)單CPU模型(能夠處理中斷及配置寄存器功能)等簡(jiǎn)單行為模型的編寫(xiě)。此處不要求代碼規(guī)范。
11、看時(shí)序圖
會(huì)根據(jù)時(shí)序圖,尤其是一些總線關(guān)系,如地址、數(shù)據(jù)及讀寫(xiě)使能之間的相互關(guān)系,模擬出相應(yīng)的Master或者Slaver應(yīng)該滿(mǎn)足的關(guān)系。
一種典型的應(yīng)用是FPGA工具自動(dòng)生成的FIFO或者RAM的時(shí)序圖能夠看明白,另外,一些較為常見(jiàn)的總線時(shí)序應(yīng)牢記,如AMBA AHB總線。
12、了解腳本的含義
掌握簡(jiǎn)單的Tcl、Perl等語(yǔ)言的基本操作。如Modelism不用圖形界面,而用命令行方式操作。
13、掌握仿真環(huán)境產(chǎn)生的方式
會(huì)使用Verilog語(yǔ)言熟練對(duì)文本進(jìn)行操作。如從文件中讀出若干個(gè)以太網(wǎng)幀作為激勵(lì),輸出端的結(jié)果寫(xiě)成文件與正確結(jié)果文件進(jìn)行對(duì)比。
14、掌握多種文本編輯工具
Ultra-Edit、Notepad++、GVIM等。會(huì)使用列操作等進(jìn)行編輯,會(huì)使用BeyondCompare對(duì)文件夾或文件進(jìn)行比較。
15、掌握版本管理工具的使用方法
會(huì)使用SVN等簡(jiǎn)單的版本管理工具。會(huì)服務(wù)器端及客戶(hù)端的基本配置,會(huì)對(duì)代碼進(jìn)行更新、下載不同的版本、log信息上傳等。養(yǎng)成良好的代碼版本管理習(xí)慣。
16、掌握Debussy等工具的使用
能夠看懂簡(jiǎn)單的Debussy跟Modelsim仿真結(jié)合的腳本語(yǔ)言的含義。會(huì)對(duì)代碼中某些信號(hào)進(jìn)行跟蹤,會(huì)從波形定位到代碼進(jìn)行錯(cuò)誤的檢查等。
17、掌握nLint工具的使用
導(dǎo)入代碼到工具中,能夠自助設(shè)計(jì)規(guī)則對(duì)所寫(xiě)代碼進(jìn)行代碼規(guī)范檢查,并明白常見(jiàn)的多驅(qū)動(dòng)、賦值錯(cuò)誤、敏感變量不全等常見(jiàn)的錯(cuò)誤修改。
養(yǎng)成寫(xiě)好代碼就用nLint進(jìn)行檢查的良好習(xí)慣,尤其是對(duì)設(shè)計(jì)中原來(lái)以為要用到結(jié)果沒(méi)有用到的一些變量甚至邏輯代碼進(jìn)行刪除,避免最后造成資源的浪費(fèi)。
如自己感覺(jué)這些工具使用起來(lái)麻煩,則可以自己手動(dòng)寫(xiě)一個(gè)基于文本處理的代碼規(guī)范檢查腳本。
18、掌握SMART BITS等工具的使用
會(huì)以一定的速率產(chǎn)生自定義的以太網(wǎng)幀。能夠結(jié)合SMART BITS及FPGA板能夠完成回環(huán)實(shí)驗(yàn)。
掌握Wireshark等相應(yīng)功能常見(jiàn)軟件的使用方法,以便在沒(méi)有硬件設(shè)備的情況下也可進(jìn)行FPGA調(diào)試。
19、掌握Quartus/ISE等工具的使用
會(huì)對(duì)設(shè)計(jì)代碼進(jìn)行綜合、布局布線。
會(huì)生產(chǎn)或利用工具生產(chǎn)RAM、FIFO、PLL等IP。
會(huì)利用工具進(jìn)行管腳分配。
編輯:hfy
-
FPGA
+關(guān)注
關(guān)注
1643文章
21966瀏覽量
614130 -
asic
+關(guān)注
關(guān)注
34文章
1243瀏覽量
121989 -
Verilog
+關(guān)注
關(guān)注
29文章
1366瀏覽量
111828
發(fā)布評(píng)論請(qǐng)先 登錄
FPGA初學(xué)者系列——模塊書(shū)寫(xiě)&電路綜合

FPGA初學(xué)者該從哪里開(kāi)始學(xué)起呢?
Verilog HDL華為入門(mén)教程
Verilog HDL入門(mén)教程(華為絕密資料)
HDL初學(xué)者謹(jǐn)記:學(xué)習(xí)HDL前必知
Verilog HDL入門(mén)教程
verilog_經(jīng)驗(yàn)(適合初學(xué)者)
初學(xué)者學(xué)習(xí)Verilog HDL的步驟和經(jīng)驗(yàn)技巧

Verilog HDL入門(mén)教程

fpga開(kāi)發(fā)板推薦初學(xué)者
初學(xué)者必看的電源測(cè)試項(xiàng)目要點(diǎn)及教程
初學(xué)者必看的LABVIEW工程師編程經(jīng)驗(yàn)
FPGA初學(xué)者必讀文檔

評(píng)論