【華為】verilog語言編寫規(guī)范(二)
時間:2025-11-09 22:02:03
手機看文章
掃描二維碼
隨時隨地手機看文章
5.1.3 Net and Register
- 一個reg變量只能在一個always語句中賦值 。
- 向量有效位順序的定義一般是從大數(shù)到小數(shù)。
盡管定義有效位的順序很自由, 但如果采用毫無規(guī)則的定義勢必會給作者和讀代碼的人帶來困惑, 如Data[-4 :0] ,則LSB[0][-1][-2][-3][-4]MSB ,或 Data[0 :4] ,則LSB[4][3][2][1][0]MSB, 這兩種情況的定義都不太好 ,推薦 Data[4 :0] 這種格式的定義。
- 對net和register類型的輸出要做聲明 (在PORT中)。如果一個信號名沒做聲明 Verilog將假定它為一位寬的wire變量。
- 線網(wǎng)的多種類型 。寄存器的類型。
5.1.4 Expressions
- 用括號來表示執(zhí)行的優(yōu)先級。盡管操作符本身有優(yōu)先順序, 但用括號來表示優(yōu)先級對讀者更清晰, 更有意義。
If ((alpha < beta) && (gamma >= delta)).... 比下面的表達(dá)更合意 。 If (alpha < beta && gamma >= delta)...
- 用一個函數(shù)(function)來代替表達(dá)式的多次重復(fù)
5.1.5 IF 語句
- 向量比較時 比較的向量要相等。
Reg Abc [7:0]; Reg Bca [3:0]; ...... If (Abc = = {4’b0, Bca})begin ....... If (Abc = = 8’b0) begin
-
每一個If 都應(yīng)有一個else 和它相對應(yīng)。
always @(Cond) begin if (Cond) DataOut <= DataIn; End // Else以上語句DataOut會綜合成鎖存器.
- 應(yīng)注意If ..else if ...else if ...else 的優(yōu)先級
- 如果變量在If-else 或case 語句中做非完全賦值, 則應(yīng)給變量一個缺省值 ,即,
V1 = 2’b00; V2 = 2’b00; V3 = 2’b00; If (a = = b) begin V1 = 2’b01; //V3 is not assigned V2 = 2’b10; End Else if (a = = c) begin V2 = 2’b10; //V1 is not assigned V3 = 2’b11; End Else ;;
5.1.6 case 語句
case語句通常綜合成一級多路復(fù)用器 (圖的右邊部分), 而if-then-else則綜合成優(yōu)先編碼的串接的多個多路復(fù)用器, 如圖的左邊部分。通常 ,使用case 語句要比if語句快 ,優(yōu)先編碼器的結(jié)構(gòu)僅在信號的到達(dá)有先后時使用。條件賦值語句也能綜合成多路復(fù)用器, 而case 語句仿真要比條件賦值語句快。
5.1.7 Writing functions
在function的最后給function賦值.Function CompareVectors; // (Vector1, Vector2, Length) Input [199:0] Vector1, Vector2; Input [31:0] Length; //local variables Integer i; Reg Equal; Begin i = 0; Equal = 1; While ((iIf (Vector 2[i] !== 1’bx) begin If (Vector1[i] !== Vector2[i]) Equal = 0; Else ; End i = i + 1; End CompareVectors = Equal; End Endfunction //compareVectors
- 函數(shù)中避免使用全局變量 否則容易引起HDL行為級仿真和門級仿真的差異 如
function ByteCompare input [15:0] Vector1 input [15:0] Vector2 input [7:0] Length begin if (ByteSel) // compare the upper byte else // compare the lower byte end endfunction // ByteCompare
中使用了全局變量ByteSel, 可能無意在別處修改了 ,導(dǎo)致錯誤結(jié)果。最好直接在端口加以定義 。注意 函數(shù)與任務(wù)的調(diào)用均為靜態(tài)調(diào)用。
5.1.8 Assignment
- Verilog 支持兩種賦值 :過程賦值(procedural) 和連續(xù)賦值(continuous)。過程賦值用于過程代碼 initial, always, task or function)中給reg 和 integer變量 time\realtimereal賦值, 而連續(xù)賦值一般給wire 變量賦值。
Always @(敏感表 敏感表要完整 如果不完整 將會引起仿真和綜合結(jié)果不一致 always @(d or Clr) if (Clr) q = 1'b0; else if (e) q = d;以上語句在行為級仿真時e的變化將不會使仿真器進入該進程,導(dǎo)致仿真結(jié)果錯誤
- Assign/deassign 僅用于仿真加速 僅對寄存器有用 。
- Force/release 僅用于debug 對寄存器和線網(wǎng)均有用 。
- 避免使用Disable。
- 對任何reg賦值用非阻塞賦值代替阻塞賦值 reg 的非阻塞賦值要加單位延遲 ,但異步復(fù)位可加可不加 。
Always @(posedge Clk or negedge Rst_) Begin If (!Rst_) // prioritize the “if conditions” in if statement Begin Rega <= 0; //non_blocking assignment Regb <= 0; End Else if (Soft_rst_all) Begin Rega <= #u_dly 0; //add unit delay Regb <= #u_dly 0; End Else if (Load_init) Begin Rega <= #u_dly init_rega; Regb <= #u_dly init_regb; End Else Begin Rega <= #u_dly Rega << 1; Regb <= #u_dly St_1; End End // end Rega, Regb assignment.
5.1.9 Combinatorial Vs Sequential Logic
如果一個事件持續(xù)幾個時鐘周期 設(shè)計時就用時序邏輯代替組合邏輯 。如Wire Ct_24_e4; //it ccarries info. Last over several clock cycles Assign Ct_24_e4 = (count8bit[7:0] >= 8’h24) & (count8bit[7:0] <= 8’he4);那么這種設(shè)計將綜合出兩個8 比特的加法器 而且會產(chǎn)生毛刺 對于這樣的電路 要采用時序設(shè)計 代碼如下
Reg Ct_24_e4; Always @(poseddge Clk or negedge Rst_) Begin If (!Rst_) Ct_24_e4 <= 1’b0; Else if (count8bit[7:0] = = 8’he4) Ct_24_e4 <= #u_dly 1’b0; Else if (count8bit[7:0] = = 8’h23) Ct_24_e4 <= #u_dly 1’b1; Esle ; //內(nèi)部總線不要懸空 在default狀態(tài) 要把它上拉或下拉. Wire OE_default; Assign OE_default = !(oe1 | oe2 | oe3); Assign bus[31:0] = oe1 ? Data1[31:0] : oe2 ? Data2[31:0] : oe3 ? Data3[31:0] : oe_default ? 32’h0000_0000 : 32’hzzzz_zzzz;
5.1.10Macros
- 為了保持代碼的可讀性 常用 “ `define ” 做常數(shù)聲明。
- 把“define”放在一個獨立的文件中 參數(shù) parameter 必須在一個模塊中定義 不要傳替參數(shù)到模塊 仿真測試向量例外 “define”可以在任何地方定義 要把所有的“define”定義在一個文件中 在編譯原代碼時首先要把這個文件讀入 如果希望宏的作用域僅在一個模塊中 就用參數(shù)來代替。
5.1.11Comments
- 對更新的內(nèi)容更新要做注釋。
- 在語法塊的結(jié)尾做標(biāo)記。
//style 1 If (~OE_ && (state != PENDING)) begin .... End // if enable = = ture and ready //style 2 --- identical lables on begin and end If (~OE_ && (state != PENDING)) begin //drive data .... End //drive data // Comment endwith the name of the Function Calcparity //Data, ParityErr .... Endfunction // Calcparity
- 每一個模塊都應(yīng)在模塊開始處做模塊級的注釋 參考前面標(biāo)準(zhǔn)模塊頭 。
- 在模塊端口列表中出現(xiàn)的端口信號 都應(yīng)做簡要的功能描述。
5.1.12 FSM
-
VerilogHDL狀態(tài)機的狀態(tài)分配 VerilogHDL描述狀態(tài)機時必須由parameter分配好狀態(tài),這與VHDL不同 VHDL狀態(tài)機狀態(tài)可以在綜合時分配產(chǎn)生。
- 組合邏輯和時序邏輯分開用不同的進程。組合邏輯包括狀態(tài)譯碼和輸出 時序邏輯則是狀態(tài)寄存器的切換。
- 必須包括對所有狀態(tài)都處理 不能出現(xiàn)無法處理的狀態(tài) 使?fàn)顟B(tài)機失控 。
- Mealy機的狀態(tài)和輸入有關(guān),而Moore機的狀態(tài)轉(zhuǎn)換和輸入無關(guān)。
... reg CurrentState, NextState, Out1; Parameter S0=0,S1=1; always @(posedge Clk or negedge Rst_) // state vector flip-flops (sequential) if (!Reset) CurrentState = S0; else CurrentState <= #u_dly NextState; always @(In1 or In2 or CurrentState) // output and state vector decode (combinational) case (CurrentState) S0: begin NextState <= #u_dly S1; Out1 <= #u_dly 1'b0; end S1: if (In1) begin NextState <= #u_dly S0; Out1 <= #u_dly In2; end else begin NextState <= #u_dly S1; Out1 <= #u_dly !In2; end endcase endmodule





