数字设计---格雷码与二进制码
格雷码与二进制码
格雷码
格雷码是一种循环二进制码或者叫作反射二进制码。
格雷码的特点是从一个数变为相邻的一个数时,只有一个数据位发生跳变(或者说相邻的两个格雷码之间只有一位不同)。
从图上可以看出,相邻的二进制数会出现多位的变化(比如从15变到0就会有4位的变化),但对于格雷码来说,相邻的格雷码只有一位存在不同。
对于二进制数计数器来说,如果在跨时钟域的时候将计数器传到不同的时钟域,如果仅采用“打两拍的方法”,因为有多位数的变化,就可能会导致电路出现亚稳态或者出现毛刺。
由于格雷码的这种特点,采用格雷码就可以避免二进制编码计数组合电路中出现的亚稳态。格雷码常用于通信,FIFO 或者 RAM 地址寻址计数器中。
格雷码与BCD码的转换
BCD码转格雷码
对于\(n\)位的二进制数,可以通过下面的式子转换为格雷码
即格雷码的最高位与二进制数的最高位相同,后面格雷码的各位等于相应的二进制码的对应位与上一位的异或。
从上图可以看出二进制码转换为格雷码的具体流程
拿5位二进制数10110举例
\(gray[4] = bin[4] = 1\)
\(gray[3] = bin[3] \oplus bin[4] = 1\)
\(gray[2] = bin[2] \oplus bin[3] = 1\)
\(gray[1] = bin[1] \oplus bin[2] =0\)
\(gray[0] = bin[0] \oplus bin[1] =1\)
对于verilog来说,我们可以将二进制数与他右移一位的数按位相异或来求得gray码。
module bin_to_gray
#(parameter WIDTH = 4)
(
input [WIDTH-1:0] bin_in,
output [WIDTH-1:0] gray_out
);
//================================================================
// ------------------------- MAIN CODE --------------------------
//================================================================
assign gray_out = (bin_in >> 1) ^ bin_in; //右移一位再按位相异或
// gray_out[0] = (bin_in[1]) ^ bin_in[0]; //当然可以分着来,就是没上面那么简洁
// gray_out[1] = (bin_in[2]) ^ bin_in[1];
// gray_out[2] = (bin_in[3]) ^ bin_in[2];
// gray_out[3] = (bin_in[3]) ^ 0 ;
endmodule
格雷码转BCD码
对于\(n\)位的格雷码,可以采用下面的式子转换为二进制码
\(bin_{n-1} = gray_{n-1}\)
\(bin_{i}=gray_{i}\oplus bin_{i+1}\)
即二进制码的最高位与格雷码的最高位相同,剩余位可以通过将对应位的格雷码与上一位的二进制码相异或求得
还是拿上图的5位格雷码10110举例
\(bin[4] = gray[4]=1\)
\(bin[3]=gray[3] \oplus bin[4] = gray[3] \oplus gray[4] =1\)
\(bin[2] = gray[2] \oplus bin[3] = gray[2] \oplus gray[3] \oplus gray[4] = 0\)
\(bin[1] = gray[1] \oplus bin[2] = gray[1] \oplus gray[2] \oplus gray[3] \oplus gray[4] = 1\)
\(bin[0] = gray[0] \oplus bin[1] = gray[0] \oplus gray[1] \oplus gray[2] \oplus gray[3] \oplus gray[4] = 1\)
从上面的分析可以看出格雷码转换为二进制,对应位的二进制可以通过求对应位格雷码及以上所有位的异或求得。
对于verilog实现来说,可以通过将格雷码右移相应位数,再求所有位的异或来实现上面的效果(求对应位格雷码及以上所有位的异或)。
module gray_to_bin
#(parameter WIDTH = 4)
(
input [WIDTH-1:0] gray_in,
output reg [WIDTH-1:0] bin_out
);
//===================================================
// ------------------- MAIN CODE -------------------
//===================================================
integer i;
always @(*) begin
for(i=0;i<WIDTH;i=i+1)
bin_out[i] = ^(gray_in >> i);
end
endmodule
参考
(9条消息) 二进制与格雷码互相转换_耐心的小黑的博客-CSDN博客_二进制转格雷码
《硬件架构的艺术》