1 module fifo1 #(parameter DSIZE = 8,
  2                     parameter ASIZE = 4)        //用格雷码的局限性:循环计数深度必须是2的n次幂,否则就失去了每次只变化一位的特性
  3                 (wclk,wrstn,wdata,wfull,winc,rclk,rrstn,rdata,rempty,rinc);
  4         input                         wclk,wrstn,winc;
  5         input    [DSIZE - 1:0]    wdata;
  6         output                    wfull;
  7
  8         input                        rclk,rrstn,rinc;
  9         output [DSIZE - 1:0] rdata;
 10         output                    rempty;
 11
 12         reg                        wfull,rempty;                    //空满输出
 13         reg    [ASIZE:0]        rbin,wbin;                        //读写二进制地址
 14         reg    [ASIZE:0]        wptr,rq1_wptr,rq2_wptr,        //读写指针打两拍CDC同步
 15                                     rptr,wq1_rptr,wq2_rptr;
 16         wire    [ASIZE:0]        rbinnext,wbinnext,            //读写指针递增
 17                                     rgraynext,wgraynext;            //读写指针递增对应的格雷码
 18         wire    [ASIZE - 1:0]    waddr,raddr;                    //实际读写mem的地址
 19
 20         reg    [DSIZE - 1:0]    mem [0:(1<<ASIZE) - 1];    //左移一位表示乘2
 21
 22
 23 //---------------------双口RAM存储器 数据读写-----------------------------
 24 assign rdata = mem[raddr];            //读
 25 always@(posedge wclk) begin        //写
 26     if(winc && !wfull) begin
 27         mem[waddr] <= wdata;
 28     end
 29 end
 30
 31 //---------------------将读指针CDC到写时钟域------------------------------
 32 always@(posedge wclk or negedge wrstn) begin
 33     if(!wrstn) begin
 34         wq2_rptr <= 5'd0;
 35         wq1_rptr <= 5'd0;
 36     end
 37     else begin
 38         wq1_rptr <= rptr;
 39         wq2_rptr <= wq1_rptr;
 40     end
 41 end
 42
 43 //---------------------将写指针CDC到读时钟--------------------------------
 44 always@(posedge rclk or negedge rrstn) begin
 45     if(!rrstn) begin
 46         rq2_wptr <= 5'd0;
 47         rq1_wptr <= 5'd0;
 48     end
 49     else begin
 50         rq1_wptr <= wptr;
 51         rq2_wptr <= rq1_wptr;
 52     end
 53 end
 54
 55
 56 //读相关指针的产生
 57 always@(posedge rclk or negedge rrstn) begin
 58     if(!rrstn) begin
 59         rptr <= 5'd0;
 60         rbin <= 5'd0;
 61     end
 62     else begin
 63         rptr <= rgraynext;
 64         rbin <= rbinnext;
 65     end
 66 end
 67 //写相关的指针
 68 always@(posedge wclk or negedge wrstn) begin
 69     if(!wrstn) begin
 70         wbin <= 5'd0;
 71         wptr <= 5'd0;
 72     end
 73     else begin
 74         wbin <= wbinnext;
 75         wptr <= wgraynext;
 76     end
 77 end
 78
 79 //addr截取与格雷码化指针
 80 assign raddr = rbin[ASIZE - 1:0];                //mem的读地址
 81 assign rbinnext = rbin + (rinc & ~rempty);    //mem的下一个读地址
 82 assign rgraynext = (rbinnext>>1) ^ rbinnext; //mem的读地址对应的格雷码
 83
 84 assign waddr = wbin[ASIZE - 1:0];
 85 assign wbinnext = wbin + (winc & !wfull);
 86 assign wgraynext = (wbinnext>>1) ^ wbinnext;
 87
 88 //---------------------rempty产生------------------------------
 89 //FIFO empty when the next rptr == synchronized wptr or on the reset
 90 always@(posedge rclk or negedge rrstn) begin
 91     if(!rclk) begin
 92         rempty <= 1'b1;
 93     else begin
 94         rempty <= (rgraynext == rq2_wptr);
 95     end
 96 end
 97
 98 //---------------------wfull产生------------------------------
 99 //FIFO full when CDC过来的格雷码(采样值)的最高位+次高位和bin转换过来的格雷码(理论值)均不同,剩下低位都相同
100 always@(posedge wclk or negedge wrstn) begin
101     if(!wrstn) begin
102         wfull <= 0;
103     end
104     else begin
105         wfull <= (wgraynext == {~wq2_rptr[ASIZE,ASIZE-1],wq2_rptr[ASIZE-2:0]});
106     end
107 end
108
109 endmodule
110 /*Clifford E. Cummings的文章中提到的STYLE #1,构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指
111 针转换为二进制指针)。当指针的二进制码中最高位不一致而其它N位都 相等时,FIFO为满(在Clifford E. Cummings的文章中以
112 格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。当指针完全相等时,
113 FIFO为空。
114 这种方法思路非常明了,为了比较不同时钟产生的指针,需要把不同时钟域的信号同步到本时钟域中来,而使用Gray码的目的就是使这个
115 异步同步化的过程发生亚稳态的机率最小。
116 */ 

很好的讲解:

https://www.cnblogs.com/aslmer/p/6114216.html#4067080

https://blog.csdn.net/wyj_2016/article/details/78469272

https://blog.csdn.net/IamSarah/article/details/76085635

https://blog.csdn.net/IamSarah/article/details/76093802

https://blog.csdn.net/tnaig/article/details/81503259

转载于:https://www.cnblogs.com/ucas-ime/p/10254811.html

学习笔记二:异步FIFO相关推荐

  1. IC学习笔记3——异步FIFO

    IC学习笔记3--异步FIFO 异步FIFO的工作内容与同步FIFO类似,但是异步FIFO的控制并不像同步FIFO那么简单,因为异步FIFO工作在不同的时钟域,这将会带来一些问题,比如空满检测?是否还 ...

  2. 深度强化学习笔记(二)——Q-learning学习与二维寻路demo实现

    深度强化学习笔记(二)--Q-learning学习与二维寻路demo实现 文章目录 深度强化学习笔记(二)--Q-learning学习与二维寻路demo实现 前言 理论 什么是Q-Learning 算 ...

  3. SwiftUI学习笔记之异步数据请求

    SwiftUI学习笔记之异步数据请求 方法一 方法描述: 结合使用 ObservableObject @Published @ObservedObject ObservableObject 定义自己的 ...

  4. Netty学习笔记二网络编程

    Netty学习笔记二 二. 网络编程 1. 阻塞模式 阻塞主要表现为: 连接时阻塞 读取数据时阻塞 缺点: 阻塞单线程在没有连接时会阻塞等待连接的到达,连接到了以后,要进行读取数据,如果没有数据,还要 ...

  5. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7851 ...

  6. [转载]dorado学习笔记(二)

    原文地址:dorado学习笔记(二)作者:傻掛 ·isFirst, isLast在什么情况下使用?在遍历dataset的时候会用到 ·dorado执行的顺序,首先由jsp发送请求,调用相关的ViewM ...

  7. PyTorch学习笔记(二)——回归

    PyTorch学习笔记(二)--回归 本文主要是用PyTorch来实现一个简单的回归任务. 编辑器:spyder 1.引入相应的包及生成伪数据 import torch import torch.nn ...

  8. tensorflow学习笔记二——建立一个简单的神经网络拟合二次函数

    tensorflow学习笔记二--建立一个简单的神经网络 2016-09-23 16:04 2973人阅读 评论(2) 收藏 举报  分类: tensorflow(4)  目录(?)[+] 本笔记目的 ...

  9. Scapy学习笔记二

    Scapy学习笔记二 Scapy Sniffer的用法: http://blog.csdn.net/qwertyupoiuytr/article/details/54670489 Scapy Snif ...

  10. Ethernet/IP 学习笔记二

    Ethernet/IP 学习笔记二 原文链接:http://wiki.mbalib.com/wiki/Ethernet/IP 1.通信模式 不同于源/目的通信模式,EtherNet/IP 采用生产/消 ...

最新文章

  1. for 循环迭代变量
  2. 山寨SaaS--管理软件夜未眠(五)
  3. I/O设备的编址方式(统一编址,独立编址)
  4. dhcp服务器没有响应怎么解决,dhcp服务器没有响应
  5. 腾讯专利仅次谷歌;​苹果或将 iPhone 订单转给和硕;​Uber 接受比特币支付 | 极客头条...
  6. mysql计算经纬度亮点之间的距离
  7. Go基础-变量的定义
  8. 四种超实用的超级记忆法-数字定桩法,借助语句定桩法,标题定桩法,记忆宫殿法
  9. ov5640摄像头使用心得
  10. 雅猴的脚印——2019年下半年
  11. pandas面板(Panel)
  12. 【Verilog基础】数字电路-逻辑式化简公式(附吸收律推导过程)
  13. Class-Balanced Loss Based on Effective Number of Samples - 1 - 论文学习
  14. 工业循环水浅层砂过滤器(励进浅层介质过滤器)介绍及现场案例图
  15. 内存动态分配与释放,malloc和new区别
  16. Codeforces——791A Bear and Big Brother
  17. Johnson法则简要证明
  18. 用CNN实现全景图像语义分割!
  19. 08001-命名通道提供程序:无法打开与SQL Server的连接[53] 08001-命名管道提供程序:无法打开与SQL Server的连接[1326] 数据库连接不上提示08001
  20. 《学术小白的学习之路 07》自然语言处理之 LDA主题模型 01

热门文章

  1. 每日一题(16)—— 声明和定义的区别
  2. vk_down 每次下翻丙行 c++_笔记本接口不够用?不妨试试这款Type-C拓展坞,给你7个接口用...
  3. 最新车载导航端口检测工具_高德地图这个功能 把微信都没做好的车载社交解决了?...
  4. python复制sheet_python excel sheet复制
  5. 一张倾斜图片进行矫正 c++_专业性文章:10分钟矫正骨盆前倾
  6. oracle 锁表如何解决_Java高并发解决什么方式
  7. CoderHub接口文档
  8. Chapter3-2_Speech Separation(TasNet)
  9. LeetCode 1689. 十-二进制数的最少数目(脑筋急转弯)
  10. LeetCode 1244. 力扣排行榜(map+multiset)