二进制与格雷码之间的转换的Verilog实现(更多一点的讨论)

 

目录

前言

二进制码转换为格雷码的方法

格雷码转换为二进制码的过程

更多一点讨论之generate for

更多一点讨论之for

最后对格雷码的介绍


前言

以前的博客也有写这方面的内容,只是没有显式的命名,导致查找复习的时候并不能立即找到,这里单独成立一篇,记录与此,方便你我他。

这篇博客来自于FPGA之道,其中提到了格雷码;

和格雷码相关的其他问题也贴出来吧:关于格雷码和独热码消耗资源情况;

二进制码转换为格雷码的方法

从自然二进制码到格雷码

该过程也称为格雷码的编码,方法是从二进制码的最右边一位(最低位)起,依次将每一位与左边一位进行异或运算,作为对应格雷码该位的值,而最左边一位(最高位)不变。 对应公式如下:

g[n] = b[n],

g[i] = b[i] xor b[i+1] (i∈N,n-1≥i≥0);

其中g、b分别对应n位的格雷码和二进制码。

例如,将自然二进制码“10110”转换为格雷码,可以形象的用下图表示其转换过程:

  二进制与格雷码之间的转换的Verilog实现(更多一点的讨论)_第1张图片

简单说来,就是对二进制码右移移位,与其本身相异或即可。

根据以上说法,用Verilog描述为:

assign gray_value = binary_value ^ (binary_value>>1);

格雷码转换为二进制码的过程

该过程也称为格雷码的解码,方法是从格雷码左边第二位(次高位)起,将每一位与其左边一位解码后的值异或,作为该位解码后的值,而最左边一位(最高位)的解码结果就是它本身。对应公式如下:

         b[n] = g[n],

         b[i] = g[i] xor b[i+1] (i∈N, n-1≥i≥0)。 

         其中g、b分别对应n位的格雷码和二进制码。

         例如,将格雷码“11101”转换为自然二进制码,可以形象的用下图表示其转换过程:

二进制与格雷码之间的转换的Verilog实现(更多一点的讨论)_第2张图片

我的理解是先根据格雷码的最高位,得到二进制的最高位,然后,用二进制码的最高位与格雷码的次高位相异或,得到二进制的次高位,依次类推。

根据理解写出对应的Verilog设计:

module gray2bin #(
	parameter N = 4
)(
	input [N-1:0] gray,
	output [N-1:0] bin

    );
	
	assign bin[N-1] = gray[N-1];
	
	genvar i;
	generate
	for(i = N-2; i >= 0; i = i - 1) begin: gray_2_bin
		assign bin[i] = bin[i + 1] ^ gray[i];
	end
	endgenerate
	
	
endmodule

这是其对应的RTL原理图:

二进制与格雷码之间的转换的Verilog实现(更多一点的讨论)_第3张图片

上图中粗的绿线代表总线,画的比较清晰了,但是呢?

如果我们自己手工画,应该是?

二进制与格雷码之间的转换的Verilog实现(更多一点的讨论)_第4张图片

上图不考虑任何延迟。

更多一点讨论之generate for

上述代码用到了generate for,在其内部是将assign语句展开,这里验证下:

换一种写法,就是for中的i不从N-2开始,从0开始到N-2,如果二者的RTL电路一致,则可代表generate for是将内部循环语句,展开来实现:

 module gray2bin #(
	parameter N = 4
)(
	input [N-1:0] gray,
	output [N-1:0] bin

    );
	
	assign bin[N-1] = gray[N-1];
	
	genvar i;
	generate
	/* for(i = N-2; i >= 0; i = i - 1) begin: gray_2_bin
		assign bin[i] = bin[i + 1] ^ gray[i];
	end */
	for(i = 0; i <= N-2; i = i + 1) begin: be
		assign bin[i] = bin[i + 1] ^ gray[i];
	end
	endgenerate
	
	
endmodule 

二进制与格雷码之间的转换的Verilog实现(更多一点的讨论)_第5张图片

可见,RTL原理图一致;

更多一点讨论之for

那用for语句实现上述电路会是怎么样呢?

module gray_to_binary #(parameter N = 4)(
input [N-1:0] gray_value,
output [N-1:0] binary_value
);
reg [N-1:0] binary_value;
integer i;

always@(*)begin
binary_value[N-1] = gray_value[N-1];
for(i=0; i<=N-2; i=i+1)begin:U1
binary_value[i] = binary_value[i+1]^gray_value[i];
end 
end
endmodule

RTL原理图:

二进制与格雷码之间的转换的Verilog实现(更多一点的讨论)_第6张图片

可见,同样可以实现同样的功能。

简单的电路,我就不进行行为仿真了。


最后对格雷码的介绍

在FPGA之道这本书上,对格雷码的一点描述作为结尾:

格雷码,英文全称:Gray code。由于自然二进制码在相邻数据之间可能存在多个bit的变化,例如自然数7和8对应的4bits自然二进制码分别“0111”、“1000”,因此当寄存器的输出从7变到8时,寄存器的每一位都会发生变化,从而造成不稳定态,并且会使得数字电路产生很大的尖峰电流脉冲。而格雷码则没有这一缺点,因为格雷码是一种数字排序系统,其中的所有相邻整数在它们的二进制表示中仅有一位不同。例如下表给出了4bits自然二进制码、格雷码与十进制整数的对照表:    

十进制数

自然二进制编码

格雷码

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发生了变化,所以它有效的避免了寄存器由一个数值到下一个数值时的不稳定态。并且由于格雷码中最大数与最小数之间也仅1个bit不同,因此通常又被称作循环二进制码或者反射二进制码。

         不过格雷码也有一个缺点,那就是相比于自然二进制码来说,它是一种无权码(而自然二进制码实际上是“8421”码,因此很难直接进行比较和数学运算,所以一般都需要将采集到的以格雷码为表示形式的数据先转换成自然二进制码,然后再参与运算。

而二者之间的转换,上面也说了。

 

参考书籍:FPGA之道

你可能感兴趣的:(#)