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;
#60gray =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
仿真结果: