5.2 代碼編寫中容易出現(xiàn)的問題
for (i=0;i<4;i=i+1) begin Sig1 = Sig2; DataOut[i] = DataIn[i]; end
for-loop中第一條語句始終不變,浪費(fèi)運(yùn)算時(shí)間.
z = (cond) ? (a + b) : (c + d);
必須使用兩個(gè)加法器; 而等效的條件if-then-else語句則可以資源共享 如
if (Cond) z = a + b; else z = c + d;
只要加法器的輸入端復(fù)用,就可以實(shí)現(xiàn)加法器的共享,使用一個(gè)加法器實(shí)現(xiàn)。
module COUNT (AndBits, Clk, Rst); Output Andbits; Input Clk, Rst; Reg AndBits; //internal reg Reg [2:0] Count; always @(posedge Clk) begin begin if (Rst) Count <= #u_dly 0; else Count <= #u_dly Count + 1; End //end if AndBits <= #u_dly & Count; End //end always endmodule
在進(jìn)程里的變量都綜合成觸發(fā)器了,有4個(gè);
module COUNT (AndBits, Clk, Rst); Output AndBits; Input Clk, Rst; Reg AndBits; //internal reg Reg [2:0] Count; always @(posedge Clk) begin //synchronous if (Rst) Count <= #u_dly 0; else Count <= #u_dly Count + 1; End //end always always @(Count) begin //asynchronous AndBits = & Count; End //end always Endmodule //end COUNT
組合邏輯單開,只有3個(gè)觸發(fā)器.
module COUNT (Z, Enable, Clk, Rst); Output [2:0] Z; Input Rst, Enable, Clk; reg [2:0] Z; always @(posedge Clk) begin if (Rst) begin Z <= #u_dly 1'b0; end else if (Enable == 1'b1) begin If (Z == 3'd7) begin Z <= #u_dly 1'b0; End else begin Z <= #u_dly Z + 1'b1; end End Else ; End //end always Endmodule //end COUNT
是同步邏輯,而下例則使用了組合邏輯作時(shí)鐘,以及異步復(fù)位.實(shí)際的運(yùn)用中要加以避免.
module COUNT (Z, Enable, Clk, Rst); Output [2:0] Z; Input Rst, Enable, Clk; Reg [2:0] Z; //internal wire wire GATED_Clk = Clk & Enable; always @(posedge GATED_Clk or posedge Rst) begin if (Rst) begin Z <= #u_dly 1'b0; end else begin if (Z == 3'd7) begin Z <= #u_dly 1'b0; end else begin Z <= #u_dly Z + 1'b1; end End //end if End //end always Endmodule //end module
c = a &b; 等效于 c[3:0] = a[3:0] & b[3:0]; 等效于 c[3] = a[3] & b[3]; c[2] = a[2] & b[2]; c[1] = a[1] & b[1]; c[0] = a[0] & b[0]; 等效于 for ( i=0; i<=3; i = i + 1) c[i] = a[i] & b[i];可以選擇簡(jiǎn)潔的寫法.
always @(Cond) begin if (Cond) DataOut <= DataIn end
使用門控時(shí)鐘(Gated clock)不利于移植 ,可能引起毛刺, 帶來時(shí)序問題 ,同時(shí)對(duì)掃描鏈的形成帶來問題。門控鐘在低功耗設(shè)計(jì)中要用到 ,但通常不要在模塊級(jí)代碼中使用 ??梢越柚赑ower compiler來生成 ,或者在頂層產(chǎn)生。
在設(shè)計(jì)中最好使用同步設(shè)計(jì)。如果要使用內(nèi)部時(shí)鐘 ,可以考慮使用多個(gè)時(shí)鐘。因?yàn)槭褂脙?nèi)部時(shí)鐘的電路要加到掃描鏈中比較麻煩,降低了可測(cè)性, 也不利于使用約束條件來綜合。
模塊中所有的寄存器最好同時(shí)復(fù)位。如果要使用內(nèi)部復(fù)位, 最好將其相關(guān)邏輯放在單獨(dú)的模塊中, 這樣可以提高可閱讀性。
將這些信號(hào)的產(chǎn)生放在頂層的一個(gè)獨(dú)立模塊, 這樣所有的子模塊分別使用單一的時(shí)鐘和復(fù)位信號(hào)。一般情況下內(nèi)部門控時(shí)鐘可以用同步置數(shù)替代。
/* *\ Filename ﹕ Author ﹕ Description ﹕ Called by ﹕ Revision History ﹕mm/dd/yy Revision 1.0 Email ﹕ M@sz.huawei.com.cn Company ﹕ Huawei Technology .Inc Copyright(c) 1999, Huawei Technology Inc, All right reserved \* */ Module module_name( Output_ports, //comment ; port description Input_ports, //comment ; port description Io_ports, //comment ; port descripttion Clk_port, //comment ; port description Rst_port //comment ; port description ); //port declarations Output [31:;0] Dataout; Input [31:0] Datain; Inout Bi_dir_signal; Input input1, Input2; //interrnal wire/reg declarations Wire [31:0] internal_data; Reg output_enable; //module instantiations , Self-build module Module_name1 Uinstance_name1(...); Module_name2 Uinstance_name2(...); // TSC4000 cell DTC12 V1 (.Clk(Clk), .CLRZ(Clr), .D(Data), .Q(Qout)); //continuous assignment Assign Data_out = out_enable ? Internal_data : 32’hz; //always block Always @(input2) Begin ... End //function and task definitions Functiom [function_type] function_name; Declarations_of_inputs; [declarations_of_local_variables]; Begin Behavirol_statement; Function_name = function_express; End Endfunction //end function_name Endmodule //end module_name
下面是一個(gè)格雷碼的測(cè)試模塊, module TB_GRAY; reg Clock; reg Reset; wire [7:0] Qout; integer fout; //輸出文件指針 parameter CYC = 20; GRAY DUT(.Clock(Clock),.Reset(Reset),.Qout(Qout)); initial begin Clock = 1'b0; Reset =1'b1; #(5*CYC) Reset = 1'b0; #(5*CYC) Reset = 1'b1; #(5000*CYC) $fclose(fout); $finish; end initial begin $shm_open("GRAY.shm"); $shm_probe("AS"); fout=$fopen("gray.dat"); end always #CYC Clock = ~ Clock; //輸出數(shù)據(jù)到文件gray.dat always @(posedge Clock) begin $fwrite(fout,"%d %b\n",Qout,Qout); end endmodule
在testbench中避免使用絕對(duì)的時(shí)間,如#20,#15或#(CYC+15)等,應(yīng)該在文件前面使用parameter定義一些常量,使得時(shí)間的定義象#(CYC+OFF0)的形式,便于修改。
觀測(cè)結(jié)果可以輸出到波形文件GRAY.shm ,或數(shù)據(jù)文件gray.dat 。生成波形文件可以用simwave觀測(cè)結(jié)果 ,比較直觀。而生成數(shù)據(jù)文件則既可以快速定位 ,也可以通過編寫的小程序工具對(duì)它進(jìn)行進(jìn)一步的處理。
對(duì)大的設(shè)計(jì)的頂層仿真 ,一般不要對(duì)所有信號(hào)跟蹤, 波形文件會(huì)很大, 仿真時(shí)間延長,可以有選擇的觀測(cè)一些信號(hào)。