摘要:該文介紹了格雷碼的概念和使用格雷碼計數的原因并給出了多位格雷碼計數器的Verilog HDL的兩種描述方法。
關鍵詞:格雷碼;格雷碼計數器;Verilog;競爭—冒險
中圖分類號:TP311文獻標識碼:A文章編號:1009-3044(2009)33-9601-03
1 格雷碼
格雷碼(Gray Code)是由貝爾實驗室的Frank Gray在20世紀40年代提出的,用來在使用PCM(Pusle Code Modulation)方法傳送訊號時避免出錯,并于1953年3月17日取得美國專利。格雷碼屬于可靠性編碼,因為,雖然自然二進制碼可以直接由數/模轉換器轉換成模擬信號,但在某些情況,例如從十進制的3轉換為4時二進制碼的每一位都要變,能使數字電路產生很大的尖峰電流脈沖。而格雷碼則沒有這一缺點,它在相鄰位間轉換時,只有一位產生變化。它大大地減少了由一個狀態到下一個狀態時邏輯的混淆。但格雷碼是一種無權碼,每一位碼沒有確定的大小,不能直接進行比較大小和算術運算。
2 組合邏輯電路中的競爭—冒險現象
在組合邏輯電路的設計分析中,經常將高低電的變化看成理想化的。但在實驗中,當信號經過電路時,由于門電路傳輸延遲時間的不同,可能使電路輸出端出現尖峰脈沖的現象,這種尖峰脈沖將使負載產生誤動作,為此應當識別電路是否有競爭冒險現象,并采取措施加以解決。
1) 競爭冒險的產生
在沒有考慮信號通過導線和邏輯門的傳輸延遲時間的理想情況下,門電路的輸入與輸出為穩定狀態。但實際情況是信號通過導線和門電路時,都存在時間延遲;信號發生變化時也有一定的上升時間或下降時間。我們將門電路兩個輸入信號同時向相反的邏輯電平跳變(一個從1 變為0,另一個從0 變為1)的現象稱為競爭。由于競爭而在電路輸出端可能產生尖峰脈沖的現象就稱為競爭—冒險。這些尖峰信號又稱為“毛刺”。
2) 競爭冒險現象的影響
由于FPGA以及其它的CPLD器件內部的分布電容和電感對電路中的毛刺基本沒有什么過濾作用,因此這些毛刺信號就會被“保留”并傳遞到后一級,從而使得毛刺問題更加突出。可見,即使是在最簡單的邏輯運算中,如果出現多路信號同時跳變的情況,在通過內部走線之后,就可能會產生毛刺。而現在使用在數字電路設計以及數字信號處理中的信號往往是由時鐘控制的,多數據輸入的復雜運算系統,甚至每個數據都由相當多的位數組成。這時,每一級的毛刺都會對結果有嚴重的影響,如果是多級的設計,那么毛刺累加后甚至會影響整個設計的可靠性和精確性。
通過對格雷碼的特點分析可知,使用格雷碼計數(每次計數只有一位發生變化)可以消除組合邏輯電路中可能存在的競爭—冒險現象。下面主要講述了格雷碼計數器的實現。
3 多位格雷碼計數器的實現
在設計格雷碼計數器的時候可以使用狀態機,給每個碼設定一個狀態然后用時鐘來控制它在狀態間轉換,這樣就完成了我們需要的功能,但是若是狀態比較多,如n=6,這時就會有64個狀態,顯然再用狀態機非常不方便,當然理論上是可以的。所以我們需要的是一種通用的計數方式,本文給出了一種辦法就是設計一個二進制計數器binary counter,通過它來計數,然后利用binary -gray的轉換編碼就可以得到對應的格雷碼計數器, 另一辦法就是找出格雷碼計數的規律,給出了一個不需要用二進制計數器轉換的純格雷碼計數器的Verlilog描述。
本文根據我的實際需要,給出了以上兩種不同思路的帶同步清零端的10232進制(14位)格雷碼計數器的Verilog HDL 描述方法。并且這兩種方法都已經通過Quartus Ⅱ軟件實現了仿真,最后的仿真結果是一樣的。
1) 使用二進制計數器轉換的格雷碼計數器的Verilog描述:
module graycounter_14(clk,nclr, q);
inputclk,nclr;
output[13:0] q;
reg[13:0] q;
always @ (posedge clk or negedge nclr)
begin
if(!nclr)q <= 14'b0;
else q <= next(q);//求計數格雷碼
end
function[13:0] next;
input[13:0] incode;
reg[13:0] code;
integeri;
begin
code[13] = incode[13]; //當前格雷碼轉二進制碼
for(i=12;i>=0;i=i-1)
code[i] = code[i+1]^incode[i];
if(code == 14'b10_0111_1111_0111)code = 14'b0;//十進制10231
elsecode = code+1'b1;//二進制計數
next[13]=code[13]; //二進制計數后轉成格雷碼
for(i=12;i>=0;i=i-1)
next[i]=code[i]^code[i+1];
end
endfunction
endmodule
2) 純格雷碼計數器的Verilog描述:
module graycnt_14 (clk, nclr,q);
input clk, nclr;
output [13:0] q;
reg [13:0]q;
reg [13:0]next;
reg [13:0]temp;
integer k;
always @(posedge clk or negedge nclr)
begin
if (!nclr )q <= 14'b0;
elseif (q == 14'b11_0100_0000_1100)q <= 14'b0;//計數到340C(十進制10231)后,清零。
elseq <= next;
end
always @( q )
begin
temp[13] = q[13];
for( k=12; k>=0; k=k-1 ) temp[k] = q[k] ^ temp[k+1];
if( temp[0]==1'b0 )
begin
next[0] = ~q[0];next[13:1] = q[13:1];
end
else if( temp[1]==1'b0 )
begin
next[0] = q[0];next[1] = ~q[1];next[13:2] = q[13:2];
end
else if( temp[2]==1'b0 )
begin
next[1:0] = q[1:0];next[2] = ~q[2];next[13:3] = q[13:3];
end
else if( temp[3]==1'b0 )
begin
next[2:0] = q[2:0];next[3] = ~q[3];next[13:4] = q[13:4];
end
else if( temp[4]==1'b0 )
begin
next[3:0] = q[3:0];next[4] = ~q[4];next[13:5] = q[13:5];
end
else if( temp[5]==1'b0 )
begin
next[4:0] = q[4:0];next[5] = ~q[5];next[13:6] = q[13:6];
end
else if( temp[6]==1'b0 )
begin
next[5:0] = q[5:0];next[6] = ~q[6];next[13:7] = q[13:7];
end
else if( temp[7]==1'b0 )
begin
next[6:0] = q[6:0];next[7] = ~q[7];next[13:8] = q[13:8];
end
else if( temp[8]==1'b0 )
begin
next[7:0] = q[7:0];next[8] = ~q[8];next[13:9] = q[13:9];
end
else if( temp[9]==1'b0 )
begin
next[8:0] = q[8:0];next[9] = ~q[9];next[13:10] = q[13:10];
end
else if( temp[10]==1'b0 )
begin
next[9:0] = q[9:0];next[10] = ~q[10];next[13:11] = q[13:11];
end
else if( temp[11]==1'b0 )
begin
next[10:0] = q[10:0];next[11] = ~q[11];next[13:12] = q[13:12];
end
else if( temp[12]==1'b0 )
begin
next[11:0] = q[11:0];next[12] = ~q[12];next[13] = q[13];
end
else
begin
next[12:0] = q[12:0];next[13] = ~q[13];
end
end
endmodule
3) 用Altera Quartus Ⅱ4.2軟件仿真結果如下:
計數器開始部分如圖1所示。
計數到格雷碼340C(十進制10231)時,從零開始重新計數,如圖2所示。
圖1圖2
參考文獻:
[1] 劉秋云,王佳.Verilog HDL設計實踐與指導[M].北京:機械工業出版社,2005.
[2] 常曉明,李媛援. Verilog HDL工程實踐入門[M].北京:北京航空航天大學出版社,2005.