最近在看數電,看到了格雷碼,閻石那本書介紹轉換方法為:每一位的狀態變化都按一定的順序循環。不理解,然后在網上搜了下,蠻多人寫怎么轉換的。然后發現John的《數字設計原理與實踐》(原書第四版)中講了兩個方法特別實用。
1.什么是格雷碼?
對于做FPGA的來說,格雷碼一般是用來定義狀態機,有什么優勢,我前面寫的FSM中需注意事項一文中有提到。格雷碼的特點:相鄰的兩個數之間只有一位不同。這就是格雷碼存在的意義。
2.轉換方法
二進制轉為格雷碼方法有兩個:方法1比較適用于筆試,考試等;方法二適用于代碼編程,主要是為了做課程設計這類的。
方法一:遞歸法,我喊作:順序逆序遞歸法
1. 1位格雷碼有2個碼字:0和1
2. (n+1)位格雷碼中的前2^n(2的N次方)個字碼等于n位格雷碼的碼字,按順序書寫,加前綴0.
3. (n+1)位格雷碼中的后2^n(2的N次方)個字碼等于n位格雷碼的碼字,但按逆序書寫,加前綴1.
解釋說明:

之所以稱此方法為遞歸,是因為對于任意位的二進制的格雷碼最終都將歸結于1位二進制的格雷碼的求解。上圖就是根據已知的3bit二進制的格雷碼,求4bit二進制的格雷碼,此時的n為3,所以2^3=8,所以0-7 的格雷碼為0+3bit格雷,8-15的格雷碼為1+逆序3bit格雷碼。
方法二:向左異或法
1. 對n位二進制或格雷碼的碼字,將數位從右到左,從0到n-1編碼。
2. 如果二進制碼字的第i位和第i+1位相同,則對應的格雷碼碼字的第i位為0,否則為1.
(當i+1=n,二進制碼字的第n位被認為是0)
解釋說明:
就那四位二進制數4'b0010舉例,二進制第0位為0,第1位為1,異或結果為1,所以格雷碼的第0位為1;二進制第1位為1,第2位為0,異或為1,所以格雷碼的第1位為1;二進制第2位為0,第3位為0,異或為0,所以格雷碼的第2位為0;二進制的第3位為0,二進制沒有第4位,所以第4位默認為0,異或為0,所以格雷碼第3位為0。。。結果4'b0010的格雷碼為0011。
verilog代碼實現:
//pro : binary to gray
//data: 2014-04-23 kb129
//info: this is a pro exe that change the binary data to gray
module binary_gray(
binary,
gray
);
parameter n = 4;
input [n-1:0] binary;
output [n-1:0] gray;
reg [n-1:0] data_reg;
always@(binary)
begin
data_reg[0] = binary[0]^binary[1];
data_reg[1] = binary[1]^binary[2];
data_reg[2] = binary[2]^binary[3];
data_reg[3] = binary[3];
end
assign gray = data_reg;
endmodule
測試代碼(testbench):
`timescale 1ns / 1ps
//Module Name: gray_tb.v
module gray_tb;
reg [3:0] binary;
wire [3:0] gray;
initial
begin
binary = 0;
#5 binary =4'b0001;
#10 binary =4'b0010;
#15 binary =4'b0011;
#20 binary =4'b0100;
#25 binary =4'b0101;
#30 binary =4'b0110;
#35 binary =4'b0111;
#40 binary =4'b1000;
#45 binary =4'b1001;
#50 binary =4'b1010;
#55 binary =4'b1011;
#60 binary =4'b1100;
#65 binary =4'b1101;
#70 binary =4'b1110;
#75 binary =4'b1111;
#80 binary =4'b1111;
end
binary_gray u_binary_gray(
.binary(binary),
.gray(gray)
);
endmodule
仿真結果:

3.解碼實現
解碼的方法為編碼中法二的逆過程,我稱之為:向右異或法。
360百科:最左邊一位不變,從左邊第二位起,將每一位與左邊一位解碼后的值進行異或。
值得注意的是:這里是同解碼后的值異或。
解碼代碼:
//pro : gray to binary
//data: 2014-04-23 kb129
//info: this is a pro exe that change the gray data to binary
module binary_gray(
binary,
gray
);
parameter n = 4;
input [n-1:0] gray;
output [n-1:0] binary;
reg [n-1:0] data_reg;
always@(gray )
begin
data_reg[3] = gray[3];
data_reg[2] = gray[2]^data_reg[3];
data_reg[1] = gray[1]^data_reg[2];
data_reg[0] = gray[0]^data_reg[1];
end
assign binary = data_reg;
endmodule
測試代碼(testbench):
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
//Engineer: LYC
//Create Date: 2014.4.23
//Module Name: gray_tb.v
////////////////////////////////////////////////////////////////////////////////
module gray_tb;
reg [3:0] gray;
wire [3:0] binary;
initial
begin
gray = 0;
#5 gray =4'b0001;
#10 gray =4'b0011;
#15 gray =4'b0010;
#20 gray =4'b0110;
#25 gray =4'b0111;
#30 gray =4'b0101;
#35 gray =4'b0100;
#40 gray =4'b1100;
#45 gray =4'b1101;
#50 gray =4'b1111;
#55 gray =4'b1110;
#60 gray =4'b1010;
#65 gray =4'b1011;
#70 gray =4'b1001;
#75 gray =4'b1000;
#80 gray =4'b0000;
end
binary_gray u_binary_gray(
.binary(binary),
.gray(gray)
);
endmodule
仿真結果:
