前言:在这篇文章中FPGA 设计时序篇 —— 跨时钟域问题及解决方法提到格雷码在跨时钟域的应用,本篇作为对该篇文章的补充,详细介绍格雷码的编解码原理及语法实现。
一、格雷码简介
格雷码,即 Gray code。由于自然二进制码在相邻数据之间可能存在多个bit的变化,比如8和7对应的4bit二进制码分别为:1000,0111,当寄存器的输出在这两个数据简跳转的时候,寄存器的每一位都会发生变化,从而造成不稳定态。
为了解决上面的问题,出现了格雷码编码规则。在格雷码中,所有相邻两数据的二进制表示中只有一位不同。下表为 4bit 自然二进制码,格雷码对应关系。
十进制 | 二进制 | 格雷码 |
---|---|---|
0 | 0000 | 0000 |
1 | 0001 | 0001 |
2 | 0010 | 0011 |
3 | 0011 | 0010 |
4 | 0100 | 0110 |
5 | 0101 | 0111 |
6 | 0110 | 0101 |
7 | 0111 | 0100 |
8 | 1000 | 1100 |
9 | 1001 | 1101 |
10 | 1010 | 1111 |
11 | 1011 | 1110 |
12 | 1100 | 1010 |
13 | 1101 | 1011 |
14 | 1110 | 1001 |
15 | 1111 | 1000 |
二、格雷码编、解码方法
1.编码:将自然二进制码转化为格雷码。方法是从自然二进制码的最低位起,将每一bit位 与 左边bit位进行异或运算,最高位不变,公式如下:
2.解码:将格雷码转化为自然二进制码。方法是从格雷码的左边第二位起,将每一bit位 与 左边解码后的bit位进行异或运算,最高位不变,公式如下:
三、格雷码语法实现
原理方法如上述,但怎样才能在语法中快速实现呢?
1.首先看编码,实际也就是将自然二进制码A向右移一位变成B(右移后高位补0),再将A与B进行以异或运算,而异或运算在FPGA中是最基本的运算,非常容易实现。
接下来分析一下:右移后最高位是否能实现算法。前面提到,编码时最高位保持不变,B的最高位现在为0,当A的最高位为0时,0与0异或的结果为0,满足最高位保持不变;当A的最高位为1时,1与0异或的结果为1,满足最高位保持不变。
奈斯!
代码如下:
module Bin2Gray
#( parameter DataWidth = 4
)
( input [DataWidth-1:0] iBinary,
output [DataWidth-1:0] oGraycode
);
assign oGraycode = (iBinary >> 1) ^ iBinary;
endmodule
2.接着看解码
module Bin2Gray
#( parameter DataWidth = 8
)
( input [DataWidth-1:0] iGraycode,
output [DataWidth-1:0] oBinary
);
assign oBinary = { iGraycode[7],
^iGraycode[7:6],
^iGraycode[7:5],
^iGraycode[7:4],
^iGraycode[7:3],
^iGraycode[7:2],
^iGraycode[7:1],
^iGraycode[7:0],
};
endmodule
这里牵涉到一元约简运算,需要注意下。