一、什么是格雷码
格雷码,又叫循环二进制码或反射二进制码,格雷码是我们在工程中常会遇到的一种编码方式,它的基本的特点就是任意两个相邻的代码只有一位二进制数不同,这点在下面会详细讲解到。格雷码的基本特点就是任意两个相邻的代码只有一位二进制数不同,这点很重要。常用的二进制数与格雷码间的转换关系如下表:
二、二进制格雷码与自然二进制码的互换
1、二进制码转换成二进制格雷码
二进制码转换成二进制格雷码,其法则是保留二进制码的最高位作为格雷码的最高位,而次高位格雷码为二进制码的高位与次高位相异或,而格雷码其余各位与次高位的求法相类似。
verilog代码
`timescale 1ns / 1ns
module DecimaltoGray
#(parameter width=5
)
(
input wire clk,
input wire rst_n,
input wire decimal_load,
input wire [width-1:0] decimal,
output reg gray_finsh,
output reg [width-1:0] gray
);
parameter [2:0]idle=3'd0;
parameter [2:0]load_decimal=3'd1;
parameter [2:0]finsh_gray=3'd2;
reg [2:0] state;
reg [width-1:0]decimal_reg1;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)begin
decimal_reg1<='d0;
gray_finsh<=1'b0;
end
else if(decimal_load) begin
decimal_reg1<=decimal;
gray<={decimal[width-1],decimal[width-1:1]^decimal[width-2:0]};
gray_finsh<=1'b1;
end
else begin
gray_finsh<=1'b0;
decimal_reg1<=decimal_reg1;
end
end
endmodule
仿真代码
module graycode(
);
parameter width=5;
reg clk;
reg rst_n;
reg [width-1:0] decimal;
reg decimal_load;
wire gray_finsh;
wire [width-1:0] gray;
initial begin
clk<=1'b1;
rst_n<=1'b1;
#100
rst_n<=1'b0;
#100
rst_n<=1'b1;
#20
decimal_load<=1'b0;
decimal<=5'd1;
#20
decimal_load<=1'b0;
decimal<=5'd0;
#20
decimal_load<=1'b1;
decimal<=5'd1;
#20
decimal_load<=1'b0;
decimal<=5'd0;
#20
decimal_load<=1'b1;
decimal<=5'd2;
#20
decimal_load<=1'b0;
decimal<=5'd0;
#20
decimal_load<=1'b1;
decimal<=5'd3;
#20
decimal_load<=1'b0;
decimal<=5'd0;
#20
decimal_load<=1'b1;
decimal<=5'd4;
#20
decimal_load<=1'b0;
decimal<=5'd0;
#20
decimal_load<=1'b1;
decimal<=5'd5;
#20
decimal_load<=1'b0;
decimal<=5'd0;
#100
$finish;
end
always #10 clk=~clk;
DecimaltoGray
#(.width(width)
)
DecimaltoGray_inst(
.clk(clk),
.rst_n(rst_n),
.decimal_load(decimal_load),
.decimal(decimal),
.gray_finsh(gray_finsh),
.gray(gray)
);
endmodule
仿真波形,使用vivado
2、二进制格雷码转换成二进制码
二进制格雷码转换成二进制码,其法则是保留格雷码的最高位作为自然二进制码的最高位,而次高位自然二进制码为高位自然二进制码与次高位格雷码相异或,而自然二进制码的其余各位与次高位自然二进制码的求法相类似
verilog代码
`timescale 1ns / 1ps
module GraytoDecimal#(parameter width=5
)
(
input wire clk,
input wire rst_n,
input wire gray_load,
input wire [width-1:0] gray,
output reg decimal_finsh,
output reg [width-1:0] decimal
);
reg [7:0]cnt;
parameter [2:0]idle=3'd0;
parameter [2:0]load_decimal=3'd1;
parameter [2:0]ing_gray=3'd2;
parameter [2:0]finsh_gray=3'd3;
reg [2:0] state;
reg [width-1:0] gray_reg;
reg [width-1:0] decimal_reg;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)begin
gray_reg<='d0;
decimal_reg<='d0;
cnt<=8'd0;
state<=idle;
decimal_finsh<=1'b0;
end
else begin
case(state)
idle: begin
decimal_finsh<=1'b0;
if(gray_load)begin
gray_reg<=gray;
state<=load_decimal;
end
end
load_decimal:begin
cnt<=width-2;
state<=ing_gray;
decimal_reg[width-1]<=gray_reg[width-1];
end
ing_gray:begin
cnt<=cnt-1;
decimal_reg[cnt]<=decimal_reg[cnt+1]^gray_reg[cnt];
if(cnt==8'd0) begin
state<=finsh_gray;
end
end
finsh_gray:begin
decimal<=decimal_reg;
decimal_finsh<=1'b1;
state<=idle;
end
default:begin
state<=idle;
end
endcase
end
end
endmodule
仿真代码
`timescale 1ns / 1ns
module graycode(
);
parameter width=5;
reg clk;
reg rst_n;
reg [width-1:0] gray;
reg gray_load;
wire decimal_finsh;
wire [width-1:0] decimal;
initial begin
clk<=1'b1;
rst_n<=1'b1;
#100
rst_n<=1'b0;
#100
rst_n<=1'b1;
#20
gray_load<=1'b1;
gray<=5'd0;
#20
gray_load<=1'b0;
gray<=5'd0;
#200
gray_load<=1'b1;
gray<=5'd1;
#20
gray_load<=1'b0;
gray<=5'd1;
#200
gray_load<=1'b1;
gray<=5'd2;
#20
gray_load<=1'b0;
gray<=5'd2;
#200
gray_load<=1'b1;
gray<=5'd3;
#20
gray_load<=1'b0;
gray<=5'd3;
#200
gray_load<=1'b1;
gray<=5'd4;
#20
gray_load<=1'b0;
gray<=5'd4;
#200
gray_load<=1'b1;
gray<=5'd5;
#20
gray_load<=1'b0;
gray<=5'd5;
#500
$finish;
end
always #10 clk=~clk;
GraytoDecimal
#(.width(width)
)
GraytoDecimal_inst(
.clk(clk),
.rst_n(rst_n),
.gray_load(gray_load),
.gray(gray),
.decimal_finsh(decimal_finsh),
.decimal(decimal)
);
endmodule
vivado仿真波形
由于格雷码求二进制需要逐位计算,因此需要周期比较长,本代码使用了一个状态机进行改过程计算。