我的 FPGA 学习历程(06)—— 二进制转格雷码

格雷码是一种无权码,它的特点是相邻的两数之间只有一个位不同,像这样:

        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
时间: 2024-08-08 09:25:29

我的 FPGA 学习历程(06)—— 二进制转格雷码的相关文章

HDU HDU 5375 Gray code(二进制和格雷码)

Description: The reflected binary code, also known as Gray code after Frank Gray, is a binary numeral system where two successive values differ in only onebit (binary digit). The reflected binary code was originally designed to prevent spurious outpu

我的 FPGA 学习历程(02) —— 实验点亮 LED 灯

关于 Quartus 的操作可以使用 Quartus 自带的帮助,帮助中有全套的操作教程. 中文网络教程链接(链接至altera中文官网,点击观看) Quartus II 软件设计系列:基础 Quartus II 软件中的原理图设计 SignalTap II 嵌入式逻辑分析器 使用Nios II 处理器 系统控制台 Nios II 处理器开发软件:设计流程 Nios II 处理器开发软件:MMU和MPU 无论是英文帮助还是网络中文教程,他们的前提是你是有基础的,这些教程之会教给你我们的 quar

我的 FPGA 学习历程(01)—— FPGA 基础知识和 Quartus 的安装

高级的嵌入式市场主要分为以下三类:ARM.DSP 和 FPGA. 其中 ARM 是行业内的佼佼者,目前几乎所有的安卓智能手机都使用 ARM 授权的 CPU架构:而 DSP(数字信号处理器) 早年就被大面积的应用与电话.DVD.通讯基站等领域.DSP 与 ARM 的区别在于,ARM 是通用 CPU,DSP 则是专用 CPU.FPGA 则与他们不同,FPGA 的名称的由来是由于 FPGA 功能的成型是在实验室等通常工作环境下进行的:区别与专有集成电路 (ASIC)在晶圆工厂的制造,所以 FPGA 被

我的 FPGA 学习历程(10)—— 实验数码管驱动

根据黑金 AX301 手册,数码管位选信号命名为 SEL[5:0],其中 SEL[5] 对应最左边的数码管,而SEL[0] 对应最右边数码管:作为约定,在下面的描述中我们对应的称之为数码管 5 和数码管 0.数码管的段选信号被命名为 DIG[7:0]:DIG[7] 为小数点 DP,DIG[6] 为数码管 g 段,DIG[0] 为 a 段,其他类推即可. 由于数码管的段选信号是共用的,理论上是不可能同时显示六个不同字符的,但由于人眼的视觉残留现象,只要我们很快的依次显示每一个数字,就可以欺骗人眼达

我的 FPGA 学习历程(08)—— 多文件工程的建立

这篇的重点是讲解如何使用多文件工程.伴随着学习的深入,编写的代码量会变得越来越大,尤其是当工程中有相互调用的模块关系的时候,如果还使用一个文件描述整个工程,就会使得文件变得非常的长而且难以查阅. 这篇新建一个名为 add4 的工程,目标是设计一个由四个一位全加器构成的四位加法器.在 verilog 语法中可以直接使用 + 运算符来构建加法器,当然在实际工程中生成一个加法器既不需要这么多工作也不需要这么麻烦,但这篇存在的价值是作为多文件工程的练习. 一位全加器的代码如下: 在 Quaruts 工程

我的 FPGA 学习历程(14)—— PWM 脉冲宽度调制

PWM 是一种调节输出功率的技术(俗称调压),其原理在于改变输出方波的占空比,具体输出见下图: 输出信号为电压值,当负载为恒阻时,上图中的输出功率分别为 25%.50%.75%. 实现方法如下: 设置一个计数器,上图中的第一行就是个 4 位的计数器,每满 15 自动变为 0.那么可以得到输出频率等于时钟的 1/16. 当计数器的值小于某个值的时候输出 0,高于或者等于某个值的时候输出 1. 假设控制的是一个小灯为 1/8 功率输出,那么我们需要的值就是 13 (4'hD),当计数器小于等于 13

我的 FPGA 学习历程(09)—— 实验点亮单个数码管

数码管是一种常见的用于显示的电子器件,根据数码管大致可以分为共阴极和共阳极两种,下图所示的是一个共阳极的数码管的电路图(摘自金沙滩工作室的 51 开发板电路图),我的 AX301 开发板与这张图的情况类似,几乎所有的教科书上都会讲到数码管的原理,这里我就不再详述了. 由于多个数码管的段选信号(下图中的 DB0~DB7)是共用的,想要显示多个数字需要用到动态扫描,动态扫描电路需要使用时钟.冒然的使用时钟会使得初学者不知所措,所以在这篇基础的组合逻辑电路中只点亮单个数码管,这样就不必涉及到时钟了.时

我的 FPGA 学习历程(01)—— 数字逻辑入门

       大概是在13年的时候,弟弟给我看了一段 verilog 代码,并且跟我说这东西很有用,于是网上查了查资料,大神们是这样说的:在大学,你只能学到 51单片机,作为电子的入门基础,但是实际上嵌入式市场上用的大多是更为高端的芯片,主要分为三类:ARM.DSP.FPGA.        既然决定学下 FPGA,就一定要有一块开发板.淘宝上的板子有很多家,有黑金.特权.至芯科技等等好多家,最后选了黑金的一块学生版AX301.当时以为 FPGA 嘛,肯定要比 51 高级一些,板子上有个 VGA

我的 FPGA 学习历程(13)—— 电子钟项目

在秒表上一些其他模块就可以变成电子钟了,使用以下约定: 使用 KEY[0] 作为复位按键,复位后显示 00:00. 使用 KEY[1] 作为调整/暂停按键,暂停时电子钟调整的两个灯管保持 1Hz 的频率闪烁. 使用 KEY[2] 作为调整左移按钮,KEY[3] 作为调整右移. 具体看原理图,太大了分成四块: 代码如下: 代码大家应该大致看得懂了,这里就不多做讲解了,祝大家成功. 最后附上 tcl 脚本文件(根据黑金光盘提供修改):