搜索
bottom↓
回复: 26

手把手教你写异步FIFO

[复制链接]

出0入0汤圆

发表于 2014-7-25 13:54:31 | 显示全部楼层 |阅读模式
本帖最后由 cxhy 于 2014-7-25 14:01 编辑

         最近在上海实习,BOSS让我做一个异步FIFO。研究一阵子之后以后,代码已经逐渐完成。现在把设计思路一点一点写出来,当我把所有的代码调试完成以后,一定会开源的。
发这个帖子的主要目的纯粹是为了帮(shui)助(dian)新(mo)人(yuan)。楼主毕竟刚学FPGA不过半年左右,自己水平有限,只能分享一点自己的经验。如果有理解不到位的地方,请诸位一定要指出来。我一(fan)定(zheng)虚(lian)心(pi)学(hen)习(hou)。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
废话不说了,先从什么是FIFO说起吧。所谓的FIFO,就是first_in_first_out,即先入先出的数据缓存器。而一个FIFO的载体就是一块RAM,但是和普通的RAM又不太一样。主要的区别在于:FIFO没有内部地址线,它只能按顺序的读数据,按顺序写数据。数据的地址由内部指针自动加一可以得到。这样做的理由在于:当数据需要在两个不同的时钟域下面传输的时候,读写速率并不匹配,直接读写会造成数据的丢失。而且对于双方来说数据是直接读取,并不需要对地址进行额外的操作。所以在这种情况下,解决时钟不匹配的问题,FIFO就是一个很好的解决方案。

然后就是整个模块的接口,在顶层模块中,有复位信号(reset)  输入时钟信号(输入input_clk) 输出时钟信号(output_clk输出,对你没有看错,这个输出时钟信号对于fifo模块来说就是一个输入信号,因为fifo必须对输出时钟信号进行匹配)输入数据(输入信号input_data)输出信号(输出信号output_data)以及对外输出的空标志位(empty)和满标志位(full)

再说一下整体结构,,,,,看图


一个RAM,一个写指针模块,一个读指针模块,最后一个比较模块。
写指针模块作用是控制写入数据的数据指针,并且接收来自比较模块的满信号决定是否继续把写地址指针+1。
读指针模块作用是控制读出数据的数据指针,并且接收来自比较模块的空信号决定是否继续把读地址指针+1。
比较模块比较输入到RAM内部的读指针和写指针的大小,再判断是空还是满以决定反馈到顶层的模块,进而决定两个指针的变化情况。
RAM就是RAM了,,,


未完,待续.........

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入10汤圆

发表于 2014-7-25 14:54:34 | 显示全部楼层
收藏先,跟着学习

出0入0汤圆

 楼主| 发表于 2014-7-25 16:09:43 | 显示全部楼层
在详细介绍每一个模块之前,我先来说一下什么是亚稳态。亚稳态是一种在异步时钟域里面非常容易遇到的问题,而且亚稳态是无法被消除的,只能尽可能的减少亚稳态的持续时间,与可能存在亚稳态的端口数目。当在两个不同的时钟域下的时候,由于两个数据采集到的沿并未对齐。所谓只有在使用格雷码的情况下可以最小化亚稳态的影响

出0入0汤圆

 楼主| 发表于 2014-7-25 16:15:21 | 显示全部楼层
本帖最后由 cxhy 于 2014-7-25 16:18 编辑

首先说一说读指针模块,分为三个部分1.格雷码转换  2.如果接收到空使能信号,则读指针停止计数(不变) 3.否则连续加1

rgnext <= (rbnext >> 1)^rbnext     //格雷码转换
rbnext = (empty == 1'b0) ? (rbnext = rbnext + 1) : (rbnext);

出0入0汤圆

 楼主| 发表于 2014-7-25 16:21:42 | 显示全部楼层
其次是写指针模块,写指针控制略微麻烦一点,分为以下几步。1.判满,判断满标志位是否为满。 2.只要不为满,则持续计数 3.否则停止计数 4.转换为格雷码作为写地址的格雷码输出。写法大致和上面是类似的

出0入0汤圆

 楼主| 发表于 2014-7-25 17:06:56 | 显示全部楼层
接着就是判断位 。接收来自以上两个模块的指针并作判断状态为满还是空,进而发出不同的标志位。这一部分就比较复杂了。

这里我才用的是网上流传的方向标志位判断法。通过这个direction,告诉fifo里面数据的朝向,进而判断当读写指针相等时刻系统处于空还是满。方向的满空标志位计算基于这个标志所指向的方向,如果指向为满,则当两指针相等时候,fifo为满,当指向空的时候,当量指针相同时,fifo为空。在这里,我们可以选择75%和25%作为门限,这样做的话不需要比较每一位,只需要比较前两位就可以判断direction了。

公式如下:先有两个标志位,set和clr,以及标志位dir
assign dirset = (w_ptr[ADDR_WIDTH-1] ^ r_ptr[ADDR_WIDTH-2]) & (~(w_ptr[ADDR_WIDTH-2] ^ r_ptr[ADDR_WIDTH-1]));
assign dirclr = (~(w_ptr[ADDR_WIDTH-1] ^ r_ptr[ADDR_WIDTH-2])) & (w_ptr[ADDR_WIDTH-2] ^ r_ptr[ADDR_WIDTH-1]);

最后
assign direction = ~((~(dirset | direction)) | dirclr | (~rst_n));


真值表如下
w_ptr[ADDR_WIDTH-1]      w_ptr[ADDR_WIDTH-2]
r_ptr[ADDR_WIDTH-1]       r_ptr[ADDR_WIDTH-1]

00          01          11          10
00          00          00          00

00          01          11          10
01          01          01          01

00          01          11          10
11          11          11          11         

00          01          11          10
10          10          10          10         

而所对应的set变量和clr变量如下
set  0          0          0          1
clr   0          1          0          0

set  1          0          0          0
clr   0          0          1          0

set  0          1          0          0
clr   0          0          0          1

set  0          0          1          0
clr   1          0          0          0

这时候,如果dir变量处于0时:

其对应的真值表为
0          0          0          1
1          0          0          0
0          1          0          0
0          0          1          0

当dir为1时,对应的真值表为

1          0          1          1
1          1          0          1
1          1          1          0
0          1          1          1

所以可以看到,dir在一系列的变化中有着很强的方向性
只要使判空变量与dir进行and操作即可获得一个可靠的判断。

出0入0汤圆

 楼主| 发表于 2014-7-25 17:09:50 | 显示全部楼层
本帖最后由 cxhy 于 2014-7-25 17:27 编辑

最后上一份参考文档,说的比我详细多了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-7-25 20:05:59 | 显示全部楼层
好的,认真学习中

出0入0汤圆

 楼主| 发表于 2014-7-26 20:35:11 | 显示全部楼层
算了,下次还是发博客吧

出0入0汤圆

发表于 2014-7-26 20:53:08 来自手机 | 显示全部楼层
为什么不直接用 fifo dc 的 ip

出0入0汤圆

 楼主| 发表于 2014-7-27 14:12:38 | 显示全部楼层
linjpxt 发表于 2014-7-26 20:53
为什么不直接用 fifo dc 的 ip

定制的fifo不能自由修改RAM的大小啊。如果编译过了的代码,工程量很大的话,编译要很久,但是如果用参数化设计,把大小设置为常量,就可以直接修改工程文件而不用重新编译来获得更大的RAM

出0入0汤圆

发表于 2014-7-27 15:01:16 | 显示全部楼层
cxhy 发表于 2014-7-27 14:12
定制的fifo不能自由修改RAM的大小啊。如果编译过了的代码,工程量很大的话,编译要很久,但是如果用参数 ...

可以的啊,用的是m9k或m18k,一最多能有100来k到几百k,取决fpga的容量,应该是够用的

出0入0汤圆

 楼主| 发表于 2014-7-27 16:45:36 | 显示全部楼层
linjpxt 发表于 2014-7-27 15:01
可以的啊,用的是m9k或m18k,一最多能有100来k到几百k,取决fpga的容量,应该是够用的 ...

可能我没有表达清楚,我的意思是,在定制一个FIFO的IP之后,就无法对这个IP的容量进行修改了,尤其是编译之后更加麻烦,但是如果在设计FIFO中使用参数化设计,可以避免修改FIFO的大小而重新编译工程的繁琐。不知道我这一次说清楚没有

出0入0汤圆

发表于 2014-7-27 18:34:38 | 显示全部楼层
其实也就是这个概念可以通用到各类MCU里?

出0入0汤圆

 楼主| 发表于 2014-7-28 09:42:32 | 显示全部楼层
baoya1 发表于 2014-7-27 18:34
其实也就是这个概念可以通用到各类MCU里?

当然                           

出0入0汤圆

发表于 2014-7-29 22:43:17 | 显示全部楼层
嗯。。。。。。。。

出0入0汤圆

发表于 2014-7-29 23:07:25 | 显示全部楼层
越详细越好啊!

出0入0汤圆

发表于 2014-7-30 23:54:56 | 显示全部楼层
cxhy 发表于 2014-7-25 16:15
首先说一说读指针模块,分为三个部分1.格雷码转换  2.如果接收到空使能信号,则读指针停止计数(不变) 3. ...

LZ普及一下格雷码的转换吧,不明白啊!

出0入0汤圆

发表于 2014-7-31 13:28:24 | 显示全部楼层
不错啊,先mark下

出0入0汤圆

发表于 2014-7-31 13:44:54 | 显示全部楼层
这个感觉很不错,有助于大家学习

出0入0汤圆

 楼主| 发表于 2014-8-1 00:30:03 | 显示全部楼层
hy2515131 发表于 2014-7-30 23:54
LZ普及一下格雷码的转换吧,不明白啊!

移位再异或。没了

出0入0汤圆

发表于 2014-8-2 09:17:37 | 显示全部楼层
cxhy 发表于 2014-7-25 16:15
首先说一说读指针模块,分为三个部分1.格雷码转换  2.如果接收到空使能信号,则读指针停止计数(不变) 3. ...

rgnext rbnext 定义是?

出0入0汤圆

 楼主| 发表于 2014-8-2 20:51:58 | 显示全部楼层
hy2515131 发表于 2014-8-2 09:17
rgnext rbnext 定义是?

g代表的是格雷码,b代表的是二进制。

出0入0汤圆

发表于 2014-8-3 13:34:00 | 显示全部楼层
cxhy 发表于 2014-8-2 20:51
g代表的是格雷码,b代表的是二进制。

格雷码和二进制转换啊

出0入0汤圆

发表于 2014-8-8 14:57:38 | 显示全部楼层
很认真的,写得很详细

出0入0汤圆

 楼主| 发表于 2014-8-8 16:37:17 | 显示全部楼层
刚才花了100莫元,先挣一点回来

出0入0汤圆

发表于 2014-8-8 17:05:12 | 显示全部楼层
不错啊,先mark下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 03:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表