格雷码在异步FIFO中的应用

2018年7月1日 22点44分

1.格雷码的介绍

在介绍格雷码之前,我们先说说自然二进制码,也就是我们经常说的二进制数。

我们用二进制数表示一个变化的数值,例如,用一个8位的二进制数表示热水壶的温度,温度是不断连续变化的,36°C、37°C、38°C……,那么温度每升高一度,二进制数就加1。这时候,二进制数有可能是多个位同时变化的:当温度由119°C变成120°C时,二进制数由01110111变化成01111000,有四个位发生变化;当二进制数由177°C变化成178°C时,二进制数由01111111变化成10000000,有8个位发生了变化。

也就是说,自然二进制数在表示一个连续变化的数值时,可能会有多个位同时发生变化,每个位翻转(变化)的频率是比较高的,这在某些应用场合,如在FPGA内部跨时钟域传输数据时,是十分不利的。

格雷码,由于具有循环特性和单步特性。
单步特性:当用它表示一个连续变化的数值时,仅有一个位会翻转,大大的降低了位翻转的频率,因而可以保证传输的稳定性,较少传输误码率。格雷码的单步特性是指,当格雷码表示的一个数值,连续变化时,格雷码只有一个位会变化。

例如,当十进制数由7变成8时,自然二进制数是由0111变成1000,格雷码是由0100变成1100。自然二进制数有4位发生翻转,格雷码只有一位发生翻转。

循环特性:格雷码的循环特性是指,当一个格雷码表示的数,由最大值变为最小值时,也只有一个位发生翻转。
例如,一个4位的格雷码,能表示的最大十进制数是15,能表示的最小十进制数是0,当十进制数由15变成0时,自然二进制数由1111变成0000,格雷码由1000变成0000。自然二进制数有4位翻转,格雷码只有1位翻转。

2.格雷码与自然二进制数的转换

二进制码->格雷码的算法:

从最右边一位起,依次将每一位与左边一位异或(XOR),作为对应格雷码该值最左边一位不变(相当于左边是0);

格雷码->二进制码的算法:

从左边第二位起,将每位与左边一位解码后的值异或,作为该位解码后的值左一位依然不变)。
Verilog实现
以下给出四位格雷码与二进制数、十进制数的对照表:

十进制数 二进制数 格雷码
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

3.格雷码在异步FIFO中的应用

在异步FIFO中,写操作和读操作工作在不同的时钟域,需要跨时钟域来传递FIFO的空满状态信息。一般是通过传递读写的地址来实现空满状态控制的。

写地址减去读地址(如果写地址小于读地址,则写地址先加上FIFO深度再减去读地址),即为FIFO中存放的数据个数,由此产生FIFO的空满判断。不管是读地址还是写地址,每次变化都是加1,溢出后从0开始重新累加。

当写地址跨越时钟域到达读操作一侧时,需要用读时钟去采样由写时钟产生的数据(即写地址)。由于是异步操作,有可能会出现竞争和冒险,采样过程不满足建立保持时间,导致亚稳态。写地址变化的位越多,出现亚稳态的位就越多,用读时钟采样时出错的概率越高。

同理,当读地址跨越时钟域到达写操作侧时,读地址变化的位越多,写时钟采样时出错的概率越高。因此,必须采用有效的编码,降低读写地址在连续变化时的位翻转率。采用格雷码就能有效的降低连续变化数值的位翻转率。

解决方法:可以在将地址跨越时钟域之前,先转换成格雷码,然后跨越时钟域。到达另一时钟域后,通过两级寄存器消除亚稳态,再将格雷码转换成二进制数。这样,每次地址变化,跨越时钟域时只有一位可能出错,可以大幅降低出错概率,提高FIFO运行的可靠性。

4.设计实例

对于使用格雷码实现异步FIFO的实例,可参阅:异步FIFO的实现 。

5.知识扩展

格雷码虽然也是用0和1表示,但它并不是二进制数,格雷码是一种变权码。每个位码没有固定的大小。在各种进制数的表示方法中,每一位有一个大,称之为权,一个数的大小不仅与它的数字(十进制为0~9,十六进制为0~,二进制为0和1)有关,还有数字的位置有关,数值放在权比较大位置,就比较大。如同样是使用数字0和1,十进制数1000就比0001要大。十进制的位权是以10为底的幂,二进制数的位权是以2为底的幂,十六进制数的权是以16为底的幂。幂的指数从右到左依次增加。例如,在自然二进数0100中,右边开始数第一个位码的大小(位权)是2的0次方,第二个位的大小是2的1次方,第三个位码的大小是2的2次方。而格雷码的每一个位具有固定的权(大小)。

另外,格雷码编码方式不是唯一的,本文介绍的是最常用的一种。


/*-----------------------------------------------------------------------
CONFIDENTIAL IN CONFIDENCE
This confidential and proprietary software may be only used as authorized
by a licensing agreement from zjl ().
In the event of publication, the following notice is applicable:
Copyright (C) 2013-20xx zjl Corporation
The entire notice above must be reproduced on all authorized copies.
Author              :       zjl
Technology blogs    :
Email Address       :       540113104@gmail.com
Filename            :       .v
Data                :       2018-07-20
Description         :       .
Modification History    :
Data            By          Version         Change Description
=========================================================================
04/06/18        zjl           1.0               Original
-----------------------------------------------------------------------*/
module Asyn_FIFO(data_out, full, empty, data_in, wen, wclk, wrst,ren, rclk, rrst);
parameter datasize = 8;
parameter addrsize = 4;input   [datasize-1:0]  data_in;
input                   wen;
input                   ren;
input                   wclk;
input                   rclk;
input                   wrst;
input                   rrst;output  [datasize-1:0]  data_out;
output                  empty;
output                  full;wire [datasize-1:0]     data_out;
reg                     empty;
reg                     full;wire                    empty_val,full_val;
wire [addrsize-1:0]     raddr,waddr;            //格雷码地址reg  [addrsize:0]       rbin,wbin;              //二进制地址
wire [addrsize:0]       rbinnext,wbinnext;reg  [addrsize:0]       rptr,wptr,rptr1,rptr2,wptr1,wptr2;//二进制转换为格雷码
wire [addrsize:0]       rptrnext,wptrnext;//rptrnext,wptrnext,二进制转化为格雷码,右移一位并与自己按位异或。reg  [datasize-1:0]     memory      [0:(1<<addrsize)-1];//双口RAM,mem中raddr地址处的数据输出data_out
assign data_out             =       memory[raddr];
//在wclk时钟驱动下,data_in数据写入mem
always @(posedge wclk)
beginif(wen&&!full)memory[waddr]       <=      data_in;
end//同步wptr指针
//使用移位寄存器来同步wptr,wptr->rptr1->rptr2
always @(posedge rclk or negedge rrst)
beginif(!rrst){rptr2,rptr1}       <=      0;else{rptr2,rptr1}       <=      {rptr1,wptr};
end//同步rptr指针,rptr->wptr1->wptr2
always @(posedge wclk or negedge wrst)
beginif(!wrst){wptr2,wptr1}       <=      0;else{wptr2,wptr1}       <=      {wptr1,rptr};
end//产生raddr信号和empty信号
always @(posedge rclk or negedge rrst)
beginif(!rrst){rbin,rptr}         <=      0;else{rbin,rptr}         <=      {rbinnext,rptrnext};
endassign raddr                =       rbin[addrsize-1:0];
assign rbinnext             =       rbin+(ren&&~empty);        //二进制读地址在“读允许&非空”条件下,加1
assign rptrnext             =       (rbinnext>>1)^rbinnext;  //二进制转化为格雷码,右移一位并与自己按位异或。生成raddr
assign empty_val=(rptrnext==rptr2);always @(posedge rclk or negedge rrst)
beginif(!rrst)empty               <=      1;elseempty               <=      empty_val;
end//产生waddr信号和full信号
//{wbin,wptr} = {写二进制地址,写格雷码地址}
always @(posedge wclk or negedge wrst)
beginif(!wrst){wbin,wptr}         <=      0;else{wbin,wptr}         <=      {wbinnext,wptrnext};
end
assign waddr        =       wbin[addrsize-1:0];
assign wbinnext     =       wbin+(wen&&~full);
assign wptrnext     =       (wbinnext>>1)^wbinnext;  //生成waddr
assign full_val     =       (wptrnext=={~wptr2[addrsize:addrsize-1],wptr2[addrsize-2:0]});
always @(posedge wclk or negedge wrst)
beginif(!rrst)full                <=      0;elsefull                <=      full_val;
end
endmodule

格雷码在异步FIFO中的应用相关推荐

  1. 3D 机器视觉 01 - 格雷码在3D视觉中的运用和码位选择原则

    1投影图像的编码方法: 常用的一种编码方法就是基于时间的编码方法. 该方法是将一系列投影图案在不同的时刻投射到被测物体的表面,像素的编码由物体表面反射的一系列值构成,因此这种方法被称为时间多路编码方法 ...

  2. 【verilog】 异步FIFO设计(格雷码转换,跨时钟域)

    功能图 空满判别 顶层 子模块 测试 功能图 空满判别 对FIFO的空满判断采用地址位扩展的方法 waddr=raddr,fifo为空 waddr[最高bit]≠raddr[最高bit],waddr[ ...

  3. 74ls390设计任意进制计数器_异步FIFO:设计原理及Verliog源码

    1.  异步FIFO的概念 异步FIFO为读取与写入采用不同的时钟,使用异步FIFO用于在不同的时钟域传输数据,主要用于跨时钟域传输多bit数据. 2.  异步FIFO的设计难点 同步异步信号,避免亚 ...

  4. 02【Verilog实战】异步FIFO设计(附源码RTL/TB)

    脚 本:makefile 工 具:vcs 和 verdi 文 章:1. 同步FIFO的设计和功能验证(附源码)     2. Verilog的亚稳态现象和跨时钟域处理方法 写在前面 这个专栏的内容记录 ...

  5. 异步fifo_异步FIFO设计

    由于知乎编辑器对markdown支持性问题,本文为直接上传markdown文档,格式混乱且图像不全,格式完整版请移步个人博客 异步FIFO设计​qiankun214.github.io 1.设计目标 ...

  6. verilog异步复位jk触发器_以不变应万变的异步FIFO面试宝典(二)

    异步FIFO面试宝典(二) 上一期为童鞋们带来了FIFO工作的基本原理,本期将继续与各位童鞋探讨FIFO类面试相关问题.首先让我们回顾一下上一期的课后思考题: 如果读时钟域速度较快.写时钟域速度较慢( ...

  7. 异步fifo_数字IC校招基础知识点复习(五)——跨时钟域涉及part2(异步FIFO)

    1.跨时钟域设计(CDC)-part 2 在上一篇中我们主要关注的是单比特的控制信号,而对于多比特信号的跨时钟域传输则需要一些其他的手段. 首先需要明确的是,一般不采用对多比特信号中的每个比特单独使用 ...

  8. 异步FIFO的原理以及可综合的Verilog代码

    异步FIFO的原理以及可综合的Verilog代码 一.FIFO的定义 二.FIFO的应用场景 三.FIFO的分类 FIFO的参数 FIFO的设计难点 一.FIFO的定义 _ First In Firs ...

  9. 异步FIFO的verilog代码实现(包含将满和将空逻辑)

    目录 异步FIFO的verilog代码实现(包含将满和将空逻辑) 异步FIFO简介 异步FIFO关键技术1 -- 读写信号跨时钟域同步 异步FIFO关键技术2 -- 读写地址的比较 异步FIFO关键技 ...

最新文章

  1. 3*3卷积+1*3卷积+3*1卷积=白给的精度提升
  2. 第十六届全国大学生智能车比赛掠影
  3. 如何调用AngularJS指令中定义的方法?
  4. 住宅按套内面积算,医院人脸识别黄牛,DNA碱基对可能会扩充,菜鸟发布供应链系统,猪瘟不影响食品安全,这就是今天的大新闻...
  5. 微服务pact测试框架_消费者驱动的Pact和Spring Boot测试
  6. Java 算法 打水问题
  7. -------------初识----------动态规划。--------------------------------------------
  8. Python求解啤酒问题(携程2016笔试题)
  9. bilibili解析接口_仿最新BiliBili客户端(已开源)
  10. 微信小程序资源汇总整理
  11. dell商务计算机主机闪烁黄灯,戴尔电脑开不了机 已经几天了 主机灯橙色 闪闪的...
  12. 那些让我印象深刻的bug--04
  13. UVM中uvm_sequencer的方法总结
  14. vue中如何实现列表的详情页获取及渲染
  15. 大家都在努力,你凭什么不努力
  16. docker搭建xui
  17. Rails 中 scope
  18. 红孩子:基于网络的渠道增值
  19. 对话本体创始人李俊——有关IEO、DApp、区块链游戏的一些冷思考
  20. 基于Web的校园跑腿管理系统的设计与实现

热门文章

  1. SM敏捷实践经验总结
  2. 九峰影业创始人_以终为始 逐梦青春——九峰实验学校2020届高三毕业典礼
  3. 方正高拍仪文件上传到服务器,高拍仪拍摄文件后如何进行文字识别?本地文件能否导入高拍仪进行识别?...
  4. 关于APIC的一些概念
  5. go timer和ticker使用方式
  6. 阿里云云服务器ECS选购指南及省钱法宝
  7. 怎样写标题才能获得流量,写标题的技巧
  8. JPG转换成PDF转换器使用说明
  9. 爬虫练习(3)-- 36Kr 站点正则和 ajax 混合
  10. 学生托管班_小学生托管班托管班价格是多少?如何收费?