寫代碼是給別人和多年后的自己看的。 關(guān)于Verilog代碼設(shè)計(jì)的一些風(fēng)格和方法之前也寫過一些Verilog有什么奇技淫巧?
模塊化設(shè)計(jì)
把所有的代碼都寫到一個(gè)模塊里,也不是一個(gè)好的風(fēng)格。 積累自己的小IP,在芯片設(shè)計(jì)階段,就將功能模塊劃分仔細(xì),劃分清楚,可復(fù)用的功能做成一個(gè)可參數(shù)化IP。搭建起你的數(shù)字積木。
對齊
把編輯器設(shè)置成tap自動(dòng)替換成2/4個(gè)空格。 用空格對齊代碼,提高代碼觀賞性。
//case0 input clk; input rst_n; inout in; output [6:0] out; //case1 input clk ; input rst_n ; inout in ; output [6:0] out ;連分號也要對齊的對齊狂魔,大可不必,徒增功耗。 關(guān)于提高Verilog代碼編寫效率的Gvim插件本訂閱號之前也分享過,I/O端口按如上所示風(fēng)格編寫好后,直接可以生成端口列表。直接寫assign和always塊語句,也可以直接生成定義。省去手動(dòng)定義的麻煩。
括號
用括號將表達(dá)式的條件括起來,讓層次關(guān)系更清晰,一些情況不括起來功能上也沒有問題,但是會(huì)引起閱讀者的歧義和可讀性差。善用括號,避免閱讀歧義和工具理解歧義。
assign flag = cnt == 2'd1 && (mode != 2'd1 && (|v_shift) || cnt2 < 8'd15); assign flag = (cnt == 2'd1) && ((mode != 2'd1) && (|v_shift) || (cnt2 < 8'd15));
能少寫則少寫
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
out <= 0;
end
else if(en)begin
out <= in;
end
else begin
out <= out;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
out <= 0;
else if(en)
out <= in;
end
只有單行語句可以省略去begin-end,一個(gè)always塊只對一個(gè)變量操作。else分支如果是保持的話,可以省略。還有begin的位置...,能少寫一行算一行。 注意,在組合邏輯中else分支不寫會(huì)產(chǎn)生鎖存器,寫成了保持就是組合邏輯環(huán),這一點(diǎn)要和時(shí)序邏輯分開。時(shí)序邏輯中else分支不寫代表保持。
always @(*)begin
case(in[1:0])
2'd0 : data[1:0] = 2'd0;
2'd1 : data[1:0] = 2'd1;
2'd2 : data[1:0] = 2'd2;
default : data[1:0] = 2'd3;
endcase
end
case語句也一樣,不寫default分支會(huì)產(chǎn)生鎖存器,如果case中的所有情況都達(dá)到,就可以不用寫default分支,但在ASIC設(shè)計(jì)中可能工具會(huì)報(bào)lint,所以這樣的寫法是最完美的。
FSM
狀態(tài)機(jī)采用三段式
小Tips,在寫狀態(tài)機(jī)時(shí),將第二段需要保持狀態(tài)循環(huán)的狀態(tài)寫法,寫成這樣的寫法,可以省去很多else的分支。 萬物基于狀態(tài)機(jī)——狀態(tài)機(jī)大法好
assign語句慎用
assign語句+三目運(yùn)算符/與或門邏輯慎用
assign data_out[5:0] = data_vld0 ? data0[5:0] :
data_vld1 ? data1[5:0] :
data_vld2 ? data2[5:0] :
data_vld3 ? data3[5:0] : 6'b0;
assign data_out[5:0] = ({6{data_vld0}} & data0[5:0])
| ({6{data_vld1}} & data1[5:0])
| ({6{data_vld2}} & data2[5:0])
| ({6{data_vld0}} & data3[5:0]);
這兩種寫法一個(gè)帶有優(yōu)先級另一個(gè)不帶優(yōu)先級,本身沒什么問題。不過覆蓋率的expression中會(huì)將這個(gè)表達(dá)式中的所有條件滿足與否列出來。 其實(shí)很多情況是不可能出現(xiàn)的,比如這幾個(gè)vld同時(shí)1,data為0的情況組合,但是這就需要designer一個(gè)個(gè)去waive掉,然后寫出原因,選擇的語句少了還好,但是如果非常多,waive起來工作量還是很大的,徒增功耗。 這樣的問題可在開發(fā)階段就避免。
always @(*)begin
if(data_vld0)
data_out[5:0] = data0[5:0];
else if(data_vld1)
data_out[5:0] = data1[5:0];
else if(data_vld2)
data_out[5:0] = data2[5:0];
else if(data_vld3)
data_out[5:0] = data3[5:0];
else
data_out[5:0] = 6'd0;
end
寫成這樣,所有條件跑到就可以了。并行的語句用case。用與門和或門做的表達(dá)可能會(huì)省一些cell,但是比起后來waive時(shí)漫長的體力活,省這一毛兩毛的干啥。 看過一本書上的寫法,將所有的組合邏輯都用assign做,把D觸發(fā)器都做成IP,直接需要打拍的時(shí)候再調(diào)用。這樣的思想很好,準(zhǔn)確的將組合邏輯和時(shí)序邏輯分開,從代碼到電路。 作者提到另一個(gè)原因是由于if-else和case不能傳播不定態(tài),有的EDA工具有X態(tài)傳播選項(xiàng),可以強(qiáng)行傳播,一般也需要license,但并不是所有的EDA工具都有這個(gè)功能。 但是我個(gè)人(淺薄的)認(rèn)為這樣的風(fēng)格不適合所有人。比如上面提到的覆蓋率問題,還有代碼的可讀性問題,assign式的寫法可讀性會(huì)變差。 直接在聲明wire時(shí)就給變量賦值這樣的寫法,連spyglass都過不了。還是先聲明再用吧。 關(guān)于工具的license問題,看看公司怎么給解決。
乘法器分時(shí)復(fù)用
一個(gè)設(shè)計(jì)要考慮PPA最優(yōu),就要考慮乘法器的數(shù)量多少以及復(fù)用能不能最大化,追求最好的設(shè)計(jì)是整個(gè)數(shù)據(jù)通路中乘法器空閑不下來。 乘法器調(diào)用方法,一般是在乘法器的輸入保證寄存器輸入,結(jié)果輸出到各個(gè)復(fù)用模塊時(shí)打一拍再使用。可以做成在進(jìn)行完乘法運(yùn)算后,就打拍,這樣消耗的寄存器會(huì)少很多。畫個(gè)圖意思一下(單bit)。
修改前
修改后
修改完后的寄存器省了很多,但是乘法器的輸出寄存器負(fù)載會(huì)變大,不過后端綜合時(shí)約束了max_fan_out工具會(huì)自動(dòng)插buffer和復(fù)制寄存器,經(jīng)過實(shí)測還是會(huì)節(jié)省很多面積,把一些優(yōu)化工作可以交給工具去做,了解它,信任它,使用它。
數(shù)據(jù)位寬寫全
assign dout = din;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
dout[255:0] <= 'd0;
else
dout[255:0] <= din;
end
寫成這樣
assign dout[3:0] = din[3:0];
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
dout[255:0] <= 256'd0;
else
dout[255:0] <= din;
end
寫代碼時(shí)將數(shù)據(jù)位寬寫全,方便編輯器插件自動(dòng)生成定義,而且寫上位寬再后續(xù)閱讀代碼時(shí)能一眼看變量的位寬,提高閱讀效率。 寄存器賦初始值 'd0 'h0等等,功能應(yīng)該沒有問題,這樣寫工具會(huì)默認(rèn)是最大32bit??lint檢查工具可能會(huì)報(bào)出來,最后還是得修改,不如一次到位。
良好的代碼風(fēng)格
寫了這么多,總結(jié)一起,其實(shí)關(guān)于代碼風(fēng)格的問題,通過多看書,多看一些代碼風(fēng)格的寫法,很多書上都有關(guān)于一些常見的風(fēng)格闡述,多寫代碼多積累,最后形成自己的代碼風(fēng)格習(xí)慣,另外一般公司都會(huì)有代碼規(guī)范的文檔,到時(shí)候參加工作以后,一定要記得多讀幾遍。
審核編輯:湯梓紅
-
Verilog
+關(guān)注
關(guān)注
30文章
1374瀏覽量
114520 -
代碼
+關(guān)注
關(guān)注
30文章
4967瀏覽量
73956 -
編輯器
+關(guān)注
關(guān)注
1文章
828瀏覽量
32895
原文標(biāo)題:什么樣的Verilog代碼風(fēng)格是好的風(fēng)格?
文章出處:【微信號:IP與SoC設(shè)計(jì),微信公眾號:IP與SoC設(shè)計(jì)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
FPGA實(shí)戰(zhàn)演練邏輯篇39:代碼風(fēng)格與書寫規(guī)范
FPGA實(shí)戰(zhàn)演練邏輯篇41:代碼風(fēng)格
勇敢的芯伴你玩轉(zhuǎn)Altera FPGA連載35:Verilog代碼風(fēng)格概述
Linux內(nèi)核編碼風(fēng)格(編程代碼風(fēng)格推薦)
什么是良好的Verilog代碼風(fēng)格?
Altera代碼風(fēng)格講義--作者:駿龍小馬
山東分公司的風(fēng)格山東分公司的風(fēng)格山東分公司的風(fēng)格山東分公司的風(fēng)格
你想iPhone變成什么樣,iPhone 4中框風(fēng)格最完美
Linux內(nèi)核的首選代碼風(fēng)格應(yīng)該如何設(shè)置
Verilog HIDL的RTL設(shè)計(jì)風(fēng)格指南資源下載
關(guān)于Linux的內(nèi)核代碼風(fēng)格
C語言代碼風(fēng)格
Verilog編碼風(fēng)格的建議
淺談Verilog HDL代碼編寫風(fēng)格
什么樣的Verilog代碼風(fēng)格是好的風(fēng)格?
評論