一、格雷码的特点
格雷码是一种循环二进制码或者叫作反射二进制码。格雷码的特点是从一个数变为相邻的一个数时,只有一个数据位发生跳变,由于这种特点,就可以避免二进制编码计数组合电路中出现的亚稳态。格雷码常用于通信,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