格雷码是一种无权码,它的特点是相邻的两数之间只有一个位不同,像这样:
000-->001-->011-->010-->110-->111-->101-->100
而二进制码是这样的:
000-->001-->010-->011-->100-->101-->110-->111
显然格雷码的顺序显然不是唯一的,而且格雷码十分不便于阅读,但它有它的优点;对比使用二进制编码的逻辑电路,如果要从 011 变为100,这种存在多个二进制位并行变化的情况;由于电路本身的物理结构限制,变化总是有先后的,而且会产生一些中间状态:111,110;由于中间状态并不在预想之中,中间状态可能会引发一些错误。
常用的编码方式还有独热码 (one-hot),热独码如下:
0000_0001, 0000_0010, 0000_0100, 0000_1000, 0001_0000, 0010_0000, 0100_0000, 1000_0000
相对于其他编码,使用独热码的电路需要更多的触发器,但这种电路结构简单而且速度更快。
书中讲到一种格雷码转化的算法
如果要把二进制串 b[i] (i=n-1, n-2, ..., 1, 0) 转换为格雷码串 g[i] (i=n-1, n-2, ..., 1, 0)
方法如下:
1. 保留最高位 g[i] = b[i] (i = n-1)
2. 其余各位 g[i] = b[i+1] ^ b[i] (i = n-2, n-3, ..., 1, 0)
以 3 位二进制串为例 则 n = 3, i = 2
二进制串的值为 000, 001, 010, 011, 100, 101, 110, 111
b[2] = 0, 0, 0, 0, 1, 1, 1, 1
b[1] = 0, 0, 1, 1, 0, 0, 1, 1
b[0] = 0, 1, 0, 1, 0, 1, 0, 1
根据书上的算法,格雷码串最高位的值
g[2] = 0, 0, 0, 0, 1, 1, 1, 1
这步发生后 0XX, 0XX, 0XX, 0XX, 1XX, 1XX, 1XX, 1XX
异或步骤
当 b[i+1] = 0, b[i] = 0 时, g[i] = 0^0; g[i] = 0;
当 b[i+1] = 0, b[i] = 1 时, g[i] = 0^1; g[i] = 1;
当 b[i+1] = 1, b[i] = 0 时, g[i] = 1^0; g[i] = 1;
当 b[i+1] = 1, b[i] = 1 时, g[i] = 1^1; g[i] = 0;
也就是说,当 b[i]与前一个数不同时, g[i] = 1;
因此得到 g[1] 的值
g[1] = 0, 0, 1, 1, 1, 1, 0, 0
格雷码变为 00X, 00X, 01X, 01X, 11X, 11X, 10X, 10X
同样得到 g[0] 的值
g[0] = 0, 1, 1, 0, 0, 1, 1, 0
最后得到g[2] = 0, 0, 0, 0, 1, 1, 1, 1
g[1] = 0, 0, 1, 1, 1, 1, 0, 0
g[0] = 0, 1, 1, 0, 0, 1, 1, 0
格雷码串: 000, 001, 011, 010, 110, 111, 101, 100
算法总是很容易被检验的,但证明它就非常困难了,书中有意略去算法的原理,对于算法东西初学者只要会用就可以了。
这里有一个通用的格雷码转化器,可以把 N 位的二进制码转化为相应的特定格式的格雷码,代码如下,各位可以试试。
module bin2gray ( input wire b[N-1:0], output reg g[N:0] ); //****************************// parmater N = 3; //这里设为 3 位的格雷码转化器 //****************************// assign g[N-1] = b[N-1]; assign g[N-2:0] = b[N-2:1] ^ b[N-3:0]; //***************************// endmodule