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

之所以稱此方法為遞歸,是因?yàn)閷?duì)于任意位的二進(jìn)制的格雷碼最終都將歸結(jié)于1位二進(jìn)制的格雷碼的求解。上圖就是根據(jù)已知的3bit二進(jìn)制的格雷碼,求4bit二進(jìn)制的格雷碼,此時(shí)的n為3,所以2^3=8,所以0-7 的格雷碼為0+3bit格雷,8-15的格雷碼為1+逆序3bit格雷碼。
方法二:向左異或法
1. 對(duì)n位二進(jìn)制或格雷碼的碼字,將數(shù)位從右到左,從0到n-1編碼。
2. 如果二進(jìn)制碼字的第i位和第i+1位相同,則對(duì)應(yīng)的格雷碼碼字的第i位為0,否則為1.
(當(dāng)i+1=n,二進(jìn)制碼字的第n位被認(rèn)為是0)
解釋說明:
就那四位二進(jìn)制數(shù)4'b0010舉例,二進(jìn)制第0位為0,第1位為1,異或結(jié)果為1,所以格雷碼的第0位為1;二進(jìn)制第1位為1,第2位為0,異或?yàn)?,所以格雷碼的第1位為1;二進(jìn)制第2位為0,第3位為0,異或?yàn)?,所以格雷碼的第2位為0;二進(jìn)制的第3位為0,二進(jìn)制沒有第4位,所以第4位默認(rèn)為0,異或?yàn)?,所以格雷碼第3位為0。。。結(jié)果4'b0010的格雷碼為0011。
verilog代碼實(shí)現(xiàn):
//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
測(cè)試代碼(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
仿真結(jié)果:

3.解碼實(shí)現(xiàn)
解碼的方法為編碼中法二的逆過程,我稱之為:向右異或法。
360百科:最左邊一位不變,從左邊第二位起,將每一位與左邊一位解碼后的值進(jìn)行異或。
值得注意的是:這里是同解碼后的值異或。
解碼代碼:
//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
測(cè)試代碼(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
仿真結(jié)果:
