格雷码在异步FIFO中的应用
格雷码在异步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中的应用相关推荐
- 3D 机器视觉 01 - 格雷码在3D视觉中的运用和码位选择原则
1投影图像的编码方法: 常用的一种编码方法就是基于时间的编码方法. 该方法是将一系列投影图案在不同的时刻投射到被测物体的表面,像素的编码由物体表面反射的一系列值构成,因此这种方法被称为时间多路编码方法 ...
- 【verilog】 异步FIFO设计(格雷码转换,跨时钟域)
功能图 空满判别 顶层 子模块 测试 功能图 空满判别 对FIFO的空满判断采用地址位扩展的方法 waddr=raddr,fifo为空 waddr[最高bit]≠raddr[最高bit],waddr[ ...
- 74ls390设计任意进制计数器_异步FIFO:设计原理及Verliog源码
1. 异步FIFO的概念 异步FIFO为读取与写入采用不同的时钟,使用异步FIFO用于在不同的时钟域传输数据,主要用于跨时钟域传输多bit数据. 2. 异步FIFO的设计难点 同步异步信号,避免亚 ...
- 02【Verilog实战】异步FIFO设计(附源码RTL/TB)
脚 本:makefile 工 具:vcs 和 verdi 文 章:1. 同步FIFO的设计和功能验证(附源码) 2. Verilog的亚稳态现象和跨时钟域处理方法 写在前面 这个专栏的内容记录 ...
- 异步fifo_异步FIFO设计
由于知乎编辑器对markdown支持性问题,本文为直接上传markdown文档,格式混乱且图像不全,格式完整版请移步个人博客 异步FIFO设计qiankun214.github.io 1.设计目标 ...
- verilog异步复位jk触发器_以不变应万变的异步FIFO面试宝典(二)
异步FIFO面试宝典(二) 上一期为童鞋们带来了FIFO工作的基本原理,本期将继续与各位童鞋探讨FIFO类面试相关问题.首先让我们回顾一下上一期的课后思考题: 如果读时钟域速度较快.写时钟域速度较慢( ...
- 异步fifo_数字IC校招基础知识点复习(五)——跨时钟域涉及part2(异步FIFO)
1.跨时钟域设计(CDC)-part 2 在上一篇中我们主要关注的是单比特的控制信号,而对于多比特信号的跨时钟域传输则需要一些其他的手段. 首先需要明确的是,一般不采用对多比特信号中的每个比特单独使用 ...
- 异步FIFO的原理以及可综合的Verilog代码
异步FIFO的原理以及可综合的Verilog代码 一.FIFO的定义 二.FIFO的应用场景 三.FIFO的分类 FIFO的参数 FIFO的设计难点 一.FIFO的定义 _ First In Firs ...
- 异步FIFO的verilog代码实现(包含将满和将空逻辑)
目录 异步FIFO的verilog代码实现(包含将满和将空逻辑) 异步FIFO简介 异步FIFO关键技术1 -- 读写信号跨时钟域同步 异步FIFO关键技术2 -- 读写地址的比较 异步FIFO关键技 ...
最新文章
- 3*3卷积+1*3卷积+3*1卷积=白给的精度提升
- 第十六届全国大学生智能车比赛掠影
- 如何调用AngularJS指令中定义的方法?
- 住宅按套内面积算,医院人脸识别黄牛,DNA碱基对可能会扩充,菜鸟发布供应链系统,猪瘟不影响食品安全,这就是今天的大新闻...
- 微服务pact测试框架_消费者驱动的Pact和Spring Boot测试
- Java 算法 打水问题
- -------------初识----------动态规划。--------------------------------------------
- Python求解啤酒问题(携程2016笔试题)
- bilibili解析接口_仿最新BiliBili客户端(已开源)
- 微信小程序资源汇总整理
- dell商务计算机主机闪烁黄灯,戴尔电脑开不了机 已经几天了 主机灯橙色 闪闪的...
- 那些让我印象深刻的bug--04
- UVM中uvm_sequencer的方法总结
- vue中如何实现列表的详情页获取及渲染
- 大家都在努力,你凭什么不努力
- docker搭建xui
- Rails 中 scope
- 红孩子:基于网络的渠道增值
- 对话本体创始人李俊——有关IEO、DApp、区块链游戏的一些冷思考
- 基于Web的校园跑腿管理系统的设计与实现