1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Verilog实现的格雷码与二进制码的互相转换

Verilog实现的格雷码与二进制码的互相转换

时间:2018-12-12 12:28:33

相关推荐

Verilog实现的格雷码与二进制码的互相转换

1、什么是格雷码

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

下表给出了4bit自然二进制码、4bit典型格雷码(无特殊说明,典型格雷码即格雷码)与4bit十进制整数的对照:

可以看到,上表中格雷码的每次变化位数只有一位,这就有效的避免了在CDC情况(跨时钟域情况)下亚稳态问题发生的概率。比如当数字从 7 变为 8 时,4 位二进制数都发生跳变,如果直接使用异步时钟采样这些数字信号,这就很可能会发生亚稳态或者数据采样错误。而采用格雷码,就可以避免 4 位二进 制数都同时发生跳变,导致出现的亚稳态,就算出现亚稳态,最多也就一位出现错误。

但是由于格雷码是一种变权码,每一位码没有固定的大小,所以很难直接进行比较大小和算术运算。

2、二进制转格雷码

二进制码转化为格雷码原理如下:

二进制的最高位作为格雷码的最高位,次高位的格雷码为二进制的高位和次高位相异或得到,其他位与次高位类似。转化过程如下图:

假如是4bit的二进制数据转成格雷码则是:

gray[3] = 0^ bin[3];----gray[3] = bin[3] 异或0等于自身gray[2] = bin[3] ^ bin[2];gray[1] = bin[2] ^ bin[1];gray[0] = bin[1] ^ bin[0];

根据上面的式子不难推到出一般公式:gray = (bin >> 1) ^ bin。根据公式很容易写出二进制码转换为格雷码的Verilog代码:

//二进制转格雷码module bin2gray#(parameterdata_width = 'd4//数据位宽)(input[data_width - 1 : 0]bin, //二进制output[data_width - 1 : 0]gray//格雷码); assign gray = (bin >> 1) ^ bin;endmodule

3、格雷码转二进制

格雷码转化为二进制码原理如下:

使用格雷码的最高位作为二进制的最高位,二进制次高位产生过程是使用二进制的高位和次高位格雷码相异或得到,其他位的值与次高位产生过程类似。转化过程如下图:

假如是4bit的格雷码转成二进制则是:

bin[3] = gray[3] ;bin[2] = gray[2] ^ bin[3];bin[1] = gray[1] ^ bin[2];bin[0] = gray[0] ^ bin[1];

可以看到,最高位不需要转换,从次高位开始使用二进制的高位和次高位格雷码相异或,那么可以使用generate--for来构建重复赋值语,具体代码如下:

//格雷码转二进制module gray2bin#(parameterdata_width = 'd4//数据位宽)(input[data_width - 1 : 0]gray, //格雷码output [data_width - 1 : 0]bin //二进制); assign bin[data_width - 1] = gray[data_width - 1];//最高位直接相等//从次高位到0,二进制的高位和次高位格雷码相异或genvar i;generatefor(i = 0; i <= data_width-2; i = i + 1) begin: gray//需要有名字assign bin[i] = bin[i + 1] ^ gray[i];endendgenerateendmodule

4、测试

构建一个测试脚本对两个模块进行测试:生成0-15的4bit二进制数据,通过bin2gray转换成格雷码,观察格雷码输出;将转换后的格雷码输出通过gray2bin再转换成2进制码,然后对比三组数据是否符合转换规则。

`timescale 1ns/1ns//时间单位/精度//------------<模块及端口声明>----------------------------------------module gray_code();parameterdata_width = 'd4;//数据位宽reg [data_width - 1 : 0]bin_in;//生成的二进制码wire[data_width - 1 : 0]gray;//转换后的格雷码wire [data_width - 1 : 0]bin_out;//转换后的二进制码//------------<例化被测试模块>----------------------------------------bin2gray#(.data_width(data_width))bin2gray_inst(.bin(bin_in), .gray(gray)); gray2bin#(.data_width(data_width))gray2bin_inst(.bin(bin_out), .gray(gray));//------------<设置初始测试条件>----------------------------------------initial beginbin_in = 4'd0;forever#20 bin_in = bin_in + 1;//每隔20ns累加1end//打印输出initial$monitor("bin_in:%b,gray:%b,bin_out:%b",bin_in,gray,bin_out);endmodule

仿真结果如下:

可以看到两次转换的结果都是正确的,接下来看一下命令窗口打印的输出:

可以看到这个转换结果与第一章的对照表是一致的。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。