2013-06-15 22:11:35
常用計數器的verilog實現(binary、gray、one-hot、LFSR、環形、扭環形)
代碼測試功能正確,時間有限,錯誤難免;如有錯誤,歡迎指正。
binary(二進制)計數器
很簡單,可根據需要完成同步或異步復位、置數、使能的功能。
在ISE的language template中有各種計數器,可進行參考。下面給出一個帶有同步復位、使能、置數端的計數器。
8bit二進制計數器的代碼:
1 module binary_counter( 2 rst_n, 3 clk, 4 en, 5 load, 6 cnt_load, 7 cnt 8 ); 9 10 parameter CNT_SIZE = 8; 11 12 input rst_n; 13 input clk; 14 input en; 15 input load; 16 input [CNT_SIZE - 1 : 0] cnt_load; 17 18 output [CNT_SIZE - 1 : 0] cnt; 19 reg [CNT_SIZE - 1 : 0] cnt; 20 21 //在ISE的language template中有各種計數器,可進行參考 22 //下面給出一個帶有同步復位、使能、置數端的計數器 23 24 always@(posedge clk) 25 if(!rst_n) 26 cnt <= 8'd0; 27 else if(en) 28 if(load) 29 cnt <= cnt_load; 30 else 31 cnt <= cnt + 1; 32 33 endmodule
gray(格雷碼)計數器
- 格雷碼的特點決定了它適用於數據傳輸,比如在異步時鍾域之間傳遞計數結果而用到的計數器。常見的異步FIFO空滿信號的信號就是用格雷碼進行比較的(因為格雷碼計數器計數時相鄰的數之間只有一個bit發生了變化,例如:000-001-011-010-110-111-101-100)
- 也常用在狀態機的狀態編碼
- 而由於格雷碼是一種變權碼,每一位碼沒有固定的大小,很難直接進行比較大小和算術運算,因此在實際的數據運算中並不使用格雷碼,如異步FIFO中讀寫地址仍然是使用二進制編碼。
與普通二進制碼之間的轉換
8bit格雷碼計數器的代碼:
1 module gray_counter( 2 rst_n, 3 clk, 4 bin_cnt, //輸出二進制,可用於同步時鍾域的計算、比較等 5 gray_cnt //輸出格雷碼,可用於異步傳輸 6 ); 7 8 parameter CNT_SIZE = 8; 9 10 input rst_n; 11 input clk; 12 13 output [CNT_SIZE - 1 : 0] bin_cnt; 14 output [CNT_SIZE - 1 : 0] gray_cnt; 15 16 reg [CNT_SIZE - 1 : 0] bin_cnt_tmp; 17 wire [CNT_SIZE - 1 : 0] gray_cnt_tmp; 18 19 reg [CNT_SIZE - 1 : 0] bin_cnt; 20 reg [CNT_SIZE - 1 : 0] gray_cnt; 21 22 //二進制轉換為格雷碼 23 assign gray_cnt_tmp = (bin_cnt_tmp>>1) ^ bin_cnt_tmp; 24 25 //二進制計數 26 always@(posedge clk) 27 if(!rst_n) 28 begin 29 bin_cnt_tmp <= 8'd0; 30 end 31 else 32 bin_cnt_tmp <= bin_cnt_tmp + 1; 33 34 //輸出打一拍 35 always@(posedge clk) 36 if(!rst_n) 37 begin 38 bin_cnt <= 8'd0; 39 gray_cnt <= 8'd0; 40 end 41 else 42 begin 43 bin_cnt <= bin_cnt_tmp; 44 gray_cnt <= gray_cnt_tmp; 45 end 46 47 endmodule
one-hot(獨熱碼)計數器
簡介
所謂的獨熱碼是指對任意給定的狀態,狀態向量中只有1位為1,其余位都是為0。n狀態的狀態機需要n個觸發器。這種狀態機的速度與狀態的數量無關,僅取決於到某特定狀態的轉移數量,速度很快。當狀態機的狀態增加時,如果使用二進制編碼,那么狀態機速度會明顯下降。而采用獨熱碼,雖然多用了觸發器,但由於狀態譯碼簡單,節省和簡化了組合邏輯電路。獨熱編碼還具有設計簡單、修改靈活、易於綜合和調試等優點。對於寄存器數量多、而門邏輯相對缺乏的FPGA器件,采用獨熱編碼可以有效提高電路的速度和可靠性,也有利於提高器件資源的利用率。獨熱編碼有很多無效狀態,應該確保狀態機一旦進入無效狀態時,可以立即跳轉到確定的已知狀態。通過獨熱碼可是實現簡單的有限狀態機。
只有一位為1,也就是下面的環形計數器產生的計數序列。如4bit one-hot計數器的計術序列即為:0001-0010-0100-1000循環。
這種計數器的優點是速度快,且每次只有兩個bit發生跳變,而且不需外加譯碼電路,可以直接以各個觸發器輸出端的1狀態表示計數。
主要缺點是沒有有效利用電路的狀態,對於nbit,有2^n-n個狀態沒有利用。
應用:在狀態機的狀態編碼時,經常用到;實際上,大多情況下這種計數器不被稱作計數器,而是狀態編碼的一種。
one-hot(獨熱碼)計數器與環形移位計數器相同,見下面環形計數器代碼。
基於移位寄存器的計數器
移位寄存器為何可用作計數器?
通過移位寄存器可以產生不同狀態,在時鍾下,電路狀態循環變化,用電路的不同狀態能夠表示輸入時鍾的數目,從而作為時鍾脈沖的計數器。但這種計數器有一個缺點,就是計數序列不是通常的遞增或遞減,常用作偽隨機數發生器。
主要包括LFSR計數器、環形計數器、扭環形計數器(又稱約翰遜計數器)三種。
三種都可歸結於由寄存器與一個反饋回路組成,只不過對於環形計數器,沒有反饋回路;對於扭環形計數器,反饋回路只是將最高位取反,作為最低位的輸入;而LFSR的反饋回路比較復雜,對於不同的位數,由不同的生成多項式指定。
LFSR(線性反饋移位寄存器,又稱為偽隨機序列發生器)
在通信領域lfsr 有着很廣泛的應用,比如說M序列,擾碼,信道編碼,密碼學這方面都有很廣泛的應用,而不僅僅用於計數器。
LFSR Applications (LFSR應用)
• Pattern Generators
• Counters
• Built-in Self-Test (BIST)
• Encryption
• Compression
• Checksums
• Pseudo-Random Bit Sequences (PRBS)
注意到 LFSR總是將 0狀態轉化成0狀態, 因此對於一個n級LFSR, 最多可輸出周期為2^(n− 1)的周期序列.
An address counter supplies sequential addresses, but there is no need for a conventional binary address sequence. Any repetitive pattern is
acceptable, and a linear feedback shift register counter is the most efficient.
(也就是說,地址計數器提供順序地址,但是沒必要是傳統的二進制地址序列,任何重復的序列都是可接受的,而LFSR計數器是最有效的)
Conventional binary counters use complex or wide fan-in logic to generate high end carry signals. A much simpler structure sacrifices the binary count sequence, but achieves very high speed with very simple logic, easily packing two bits into every CLB. Such Linear Feedback Shift-Register (LFSR) counters are also known as pseudo random sequence generators.
(傳統的二進制計數器用復雜的或大扇入邏輯產生進位信號,LFSR以犧牲二進制計數序列為代價,用相當簡單的結構與邏輯實現很高的速度,這種移位寄存器又稱為偽隨機序列發生器;LFSR計數器的計數序列就是偽隨機序列)
A possible disadvantage is that the count sequence is not the normal bina r y increment or decrement sequence.
(LFSR的缺點是計數序列不是通常的遞增或遞減)
LFSR計數器優缺點:
Comparison to other counter types Comparison to other counter types
PROS:
Requires ver y little log ic to imp lement(邏輯資源少)
Even long counters are very efficient(速度高)
Low gate count
Hi g h sp eed gp
Easy to test for faults - typically only need 2*n clocks(容易測試錯誤)
CONS:
Pr i m iti ve forms must b e i n iti a li zed to va lid s ta te(本原形式必須初始化為有效狀態)
Some applications require binary count sequences(某些場合需要二進制計數序列)
Not easy to predict count sequence (不易預測計數序列)
LFSR的產生需要一個生成多項式,生成多項式指定反饋邏輯中抽頭的有無。
LFSR不同長度的序列產生可根據下表得到(也就是生成多項式中的系數):
This table lists the appropriate taps for maximum-length LFSR counters of up to 168 bits. The basic description and the table for the first 40 bits was originally published in XCELL and reprinted on page 9-24 of the 1993 and 1994 Xilinx Data Books.
Responding to repeated requests, the list is here extended to 168 bits. This information is based on unpublished research done by Wayne Stahnke while he was at Fairchild Semiconductor in 1970.
References
P. Alfke, “Efficient Shift Registers, LFSR, Counters, and Long Pseudo-Random Sequence Generators,” XAPP 052, July 7,1996 (Version 1.1)
說明:
實際中,LFSR計數器的實現有兩大類:一對多與多對一。根據反饋回路是異或還是異或之后再經過一個非門,分為XOR與XNOR。
下面是多對一、XNOR的方式,此處的代碼僅僅是模擬LFSR計數器的工作,具體使用時需根據需要進行改進。
下面給出8bit LFSR計數器的verilog代碼。
根據上表,可知tap為8、6、5、4,因此,代碼如下:
1 module lfsr_counter(rst_n, 2 clk, 3 cnt 4 ); 5 6 parameter CNT_SIZE = 8; 7 8 input rst_n; 9 input clk; 10 11 output [CNT_SIZE - 1 : 0] cnt; 12 13 reg [CNT_SIZE - 1 : 0] cnt; 14 15 always@(posedge clk) 16 if(!rst_n) 17 cnt <= 8'b0000_0000; //初始值 18 else 19 begin 20 cnt[7:1] <= cnt[6:0]; //移位寄存 21 cnt[0] <= ~(^{cnt[7],cnt[5:3]}); //xnor 22 end 23 24 endmodule
環形計數器
也是基於移位寄存器的計數器,對於n個移位寄存器構成的計數器,只有n個有效狀態。
設置一個初始狀態,通過移位即可得到。
說明:
實際中,因為該計數器有2^n-n個無效狀態,因此存在自鎖的問題,這可以通過設計可以自啟動(自動從無效狀態轉移到有效狀態,進入有效循環)的電路來解決。自啟動的設計可通過修改狀態邏輯實現,本質是改變無效狀態的次態,使其為有效狀態。
下面的代碼僅僅是簡單的實現,模擬環形計數器的工作方式,並沒有過多的考慮自啟動的問題。
代碼:
1 module circle_counter(rst_n, 2 clk, 3 cnt 4 ); 5 6 parameter CNT_SIZE = 8; 7 8 input rst_n; 9 input clk; 10 11 output [CNT_SIZE - 1 : 0] cnt; 12 13 reg [CNT_SIZE - 1 : 0] cnt; 14 15 always@(posedge clk) 16 if(!rst_n) 17 cnt <= 8'b0000_0001; //初始值 18 else 19 //cnt <= cnt>>1; 20 cnt <= {cnt[0],cnt[CNT_SIZE - 1 : 1]}; //注意是循環移位,而非簡單的移位 21 22 endmodule
約翰遜(扭環形)計數器
也是基於移位寄存器的計數器,是對環形計數器的改進,對於n個移位寄存器構成的計數器,有2n個有效狀態。
說明:
與環形計數器類似,實際中,因為該計數器有2^n-2n個無效狀態,因此存在自鎖的問題,這可以通過設計可以自啟動(自動從無效狀態轉移到有效狀態,進入有效循環)的電路來解決。自啟動的設計可通過修改狀態邏輯實現,本質是改變無效狀態的次態,使其為有效狀態。
下面的代碼僅僅是簡單的實現,模擬環形計數器的工作方式,並沒有過多的考慮自啟動的問題。
設置一個初始狀態,將最高位取反,作為最低位的輸入,通過移位即可得到。
代碼:
1 module john_counter(rst_n, 2 clk, 3 cnt 4 ); 5 6 parameter CNT_SIZE = 8; 7 8 input rst_n; 9 input clk; 10 11 output [CNT_SIZE - 1 : 0] cnt; 12 13 reg [CNT_SIZE - 1 : 0] cnt; 14 15 always@(posedge clk) 16 if(!rst_n) 17 cnt <= 8'b0000_0000; //初始值 18 else 19 cnt <= {~cnt[0],cnt[CNT_SIZE - 1 : 1]}; //注意是循環移位,而非簡單的移位 20 21 endmodule