一、格雷碼的特點
格雷碼是一種循環二進制碼或者叫作反射二進制碼。格雷碼的特點是從一個數變為相鄰的一個數時,只有一個數據位發生跳變,由於這種特點,就可以避免二進制編碼計數組合電路中出現的亞穩態。格雷碼常用於通信,FIFO或者RAM地址尋址計數器中。經常作為跨市終於處理的一種方法。切記在做跨時鍾處理的時候要成對的出現。
二、二進制碼轉換為格雷碼的方法
十進制 |
二進制 |
格雷碼 |
十進制 |
二進制 |
格雷碼 |
0 |
0000 |
0000 |
8 |
1000 |
1100 |
1 |
0001 |
0001 |
9 |
1001 |
1101 |
2 |
0010 |
0011 |
10 |
1010 |
1111 |
3 |
0011 |
0010 |
11 |
1011 |
1110 |
4 |
0100 |
0110 |
12 |
1100 |
1010 |
5 |
0101 |
0111 |
13 |
1101 |
1011 |
6 |
0110 |
0101 |
14 |
1110 |
1001 |
7 |
0111 |
0100 |
15 |
1111 |
1000 |
從自然的二進制碼到GRAY碼,就是GRAY的編碼。具體方法是從二進制的最低位起(最右邊的位數),依次起與左邊的一位數進行異或運算,作為對應格雷碼該位的值。而最高位保持不變。如下圖所示:根據圖示可以寫出的代碼:
1 g[n] = b[n];//最高位不變 2 g[i] = b[i] xor b[i+1];//其中g,b 分別對應n位的格雷碼和二進制碼。 其實根據以上圖示以及,表格中的對比,可以發現規律: 就是二進制碼右移一位后與自身異或。所以可以描述數為:
assign gray = binary ^ binary(binary>>1);
三、格雷碼轉換為二進制碼
具體的方法就是:從格雷碼左邊第二位(次高位),將每一位與其左邊一位解碼后的值進行異或,作為當前格雷碼的值,而最左邊一位(最高位)的解碼結果就是它本身。如下圖所示:
轉換成邏輯代碼就是:
b[n] = g[n] ;//最高位,保持不變 b[n] = g[i] xor b[i+1];//b和G都是n位的二進制碼和格雷碼。
轉換成Verilog 語言實現:
1 // ********************************************************************************* 2 // Project Name : 3 // weixin : li15226499835 4 // Website : https://www.cnblogs.com/lgy-gdeu/ 5 // Create Time : 2020// 6 // File Name : .v 7 // Module Name : 8 // Abstract : 9 // editor : sublime text 3 10 // ********************************************************************************* 11 // Modification History: 12 // Date By Version Change Description 13 // ----------------------------------------------------------------------- 14 // 2020// Liguoyong 1.0 Original 15 // 16 // ********************************************************************************* 17 `timescale 1ns/1ns 18 module gray2bin #( 19 parameter N= 6 20 )( 21 //system signals 22 input wire [N-1:0] gray , 23 output wire [N-1:0] bin 24 25 ); 26 //============================================================================= 27 //**************************** Main Code ******************************* 28 //============================================================================= 29 assign bin[N-1] = gray[N-1];//最高位不發生改變 30 generate 31 genvar i; 32 for (i = N-2; i >=0; i = i - 1) 33 begin:gray_2_bin 34 assign bin[i] = bin[i+1] ^ gray[i]; 35 end 36 endgenerate 37 endmodule
在上述,實現中使用了generate for語句,現在改用平常的for語句,來實現。平常的For語句一定要出現在always 塊中。
1 module gray_to_binary #(parameter N = 4 2 ) 3 ( 4 input [N-1:0] gray_value, 5 output [N-1:0] binary_value 6 ); 7 reg [N-1:0] binary_value; 8 integer i; 9 10 always@(*)begin 11 binary_value[N-1] = gray_value[N-1]; 12 for(i=0; i<=N-2; i=i+1)begin:U1 13 binary_value[i] = binary_value[i+1]^gray_value[i]; 14 end 15 end 16 endmodule
四、格雷碼計數原理
格雷碼計數器,采用三個模塊進行設計,格雷碼轉二進制、加法器、二進制轉格雷碼。格雷碼轉二進制將格雷碼轉換為二進制,並將值輸出用於加法器進行加法運算,然后將加法運算結果通過二進制轉格雷碼轉換為格雷碼,最后將格雷碼進行輸出,同時將結果輸出到格雷碼轉二進制作為輸入,形成一個計數功能。
1 module gray_counter #( 2 parameter data_width = 4 3 ) 4 ( 5 input wire clk, 6 input wire reset_n, 7 output wire [data_width-1:0] gray_out 8 ); 9 10 //格雷碼轉二進制 11 12 wire [data_width-1:0] bin_out; 13 14 gray_to_bin gray_to_bin_1( 15 16 .gray_in (gray_wire), 17 .bin_out (bin_out) 18 ); 19 20 //二進制加一 21 22 wire [data_width-1:0] bin_add_wire; 23 assign bin_add_wire = bin_out + 1'b1; 24 25 //二進制轉格雷碼 26 27 wire [data_width-1:0] gray_wire; 28 29 reg [data_width-1:0] gray_out; 30 31 bin_to_gray bin_to_gray_1( 32 33 .bin_in (bin_add_wire), 34 35 .gray_out (gray_wire) 36 37 ); 38 39 40 41 always @(posedge clk or negedge reset_n)begin 42 if(reset_n == 1'b0)begin 43 gray_out <= {data_width{1'b0}}; 44 end 45 else begin 46 gray_out <= gray_wire; 47 end 48 end 49 50 endmodule