module fifo1 #(parameter DSIZE = ,
parameter ASIZE = ) //用格雷码的局限性:循环计数深度必须是2的n次幂,否则就失去了每次只变化一位的特性
(wclk,wrstn,wdata,wfull,winc,rclk,rrstn,rdata,rempty,rinc);
input wclk,wrstn,winc;
input [DSIZE - :] wdata;
output wfull; input rclk,rrstn,rinc;
output [DSIZE - :] rdata;
output rempty; reg wfull,rempty; //空满输出
reg [ASIZE:] rbin,wbin; //读写二进制地址
reg [ASIZE:] wptr,rq1_wptr,rq2_wptr, //读写指针打两拍CDC同步
rptr,wq1_rptr,wq2_rptr;
wire [ASIZE:] rbinnext,wbinnext, //读写指针递增
rgraynext,wgraynext; //读写指针递增对应的格雷码
wire [ASIZE - :] waddr,raddr; //实际读写mem的地址 reg [DSIZE - :] mem [:(<<ASIZE) - ]; //左移一位表示乘2 //---------------------双口RAM存储器 数据读写-----------------------------
assign rdata = mem[raddr]; //读
always@(posedge wclk) begin //写
if(winc && !wfull) begin
mem[waddr] <= wdata;
end
end //---------------------将读指针CDC到写时钟域------------------------------
always@(posedge wclk or negedge wrstn) begin
if(!wrstn) begin
wq2_rptr <= 'd0;
wq1_rptr <= 'd0;
end
else begin
wq1_rptr <= rptr;
wq2_rptr <= wq1_rptr;
end
end //---------------------将写指针CDC到读时钟--------------------------------
always@(posedge rclk or negedge rrstn) begin
if(!rrstn) begin
rq2_wptr <= 'd0;
rq1_wptr <= 'd0;
end
else begin
rq1_wptr <= wptr;
rq2_wptr <= rq1_wptr;
end
end //读相关指针的产生
always@(posedge rclk or negedge rrstn) begin
if(!rrstn) begin
rptr <= 'd0;
rbin <= 'd0;
end
else begin
rptr <= rgraynext;
rbin <= rbinnext;
end
end
//写相关的指针
always@(posedge wclk or negedge wrstn) begin
if(!wrstn) begin
wbin <= 'd0;
wptr <= 'd0;
end
else begin
wbin <= wbinnext;
wptr <= wgraynext;
end
end //addr截取与格雷码化指针
assign raddr = rbin[ASIZE - :]; //mem的读地址
assign rbinnext = rbin + (rinc & ~rempty); //mem的下一个读地址
assign rgraynext = (rbinnext>>) ^ rbinnext; //mem的读地址对应的格雷码 assign waddr = wbin[ASIZE - :];
assign wbinnext = wbin + (winc & !wfull);
assign wgraynext = (wbinnext>>) ^ wbinnext; //---------------------rempty产生------------------------------
//FIFO empty when the next rptr == synchronized wptr or on the reset
always@(posedge rclk or negedge rrstn) begin
if(!rclk) begin
rempty <= 'b1;
else begin
rempty <= (rgraynext == rq2_wptr);
end
end //---------------------wfull产生------------------------------
//FIFO full when CDC过来的格雷码(采样值)的最高位+次高位和bin转换过来的格雷码(理论值)均不同,剩下低位都相同
always@(posedge wclk or negedge wrstn) begin
if(!wrstn) begin
wfull <= ;
end
else begin
wfull <= (wgraynext == {~wq2_rptr[ASIZE,ASIZE-],wq2_rptr[ASIZE-:]});
end
end endmodule
/*Clifford E. Cummings的文章中提到的STYLE #1,构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指
针转换为二进制指针)。当指针的二进制码中最高位不一致而其它N位都 相等时,FIFO为满(在Clifford E. Cummings的文章中以
格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。当指针完全相等时,
FIFO为空。
这种方法思路非常明了,为了比较不同时钟产生的指针,需要把不同时钟域的信号同步到本时钟域中来,而使用Gray码的目的就是使这个
异步同步化的过程发生亚稳态的机率最小。
*/

很好的讲解:

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

学习笔记二:异步FIFO的更多相关文章

  1. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  2. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  3. 微信小程序学习笔记二 数据绑定 + 事件绑定

    微信小程序学习笔记二 1. 小程序特点概述 没有DOM 组件化开发: 具备特定功能效果的代码集合 体积小, 单个压缩包体积不能大于2M, 否则无法上线 小程序的四个重要的文件 *js *.wxml - ...

  4. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  5. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  6. java之jvm学习笔记二(类装载器的体系结构)

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

  7. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

  8. 《SQL必知必会》学习笔记二)

    <SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语 ...

  9. NumPy学习笔记 二

    NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...

  10. Learning ROS for Robotics Programming Second Edition学习笔记(二) indigo tools

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

随机推荐

  1. jquery 中 $.map 用法

    $.map(data,function(item,index){return XXX}) 遍历data数组中的每个元素,并按照return中的计算方式 形成一个新的元素,放入返回的数组中 var b ...

  2. JavaScript的事件对象_实现拖拽

    实现拖拽一个元素 拖拽的流程: 当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown 当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove 当鼠标松开时,被拖拽元素固定在当前位置 onm ...

  3. xss实现获取内网ip

    前提得浏览器支持webRTC,测试的时候google浏览器测试成功,火狐浏览器不支持webRTC, 再在xss平台直接复制如下js代码: function form_ip(ip,port){ var ...

  4. AOP各种的实现

    1 AOP各种的实现 AOP就是面向切面编程,我们可以从几个层面来实现AOP. 在编译器修改源代码,在运行期字节码加载前修改字节码或字节码加载后动态创建代理类的字节码,以下是各种实现机制的比较. 类别 ...

  5. 关于tomcat无法启动问题详解

    通常情况tomcat无法启动,有这么几个原因?(1)代码有问题; (2)tomcat有问题; (3)端口被占; (4)动态web项目为3.0: (5)java环境运行内存不足; 这是比较常见的问题.解 ...

  6. ThinkPHP里面用原生SQL

    public function rewardlog(){ $adminNav = C('ADMIN_NAV'); $adminNav[1]['class'] = 'cur'; $this->as ...

  7. [整理记录备忘] Docker相关

    docker安装 linux上安装Docker(非常简单的安装方法) https://blog.csdn.net/qq_36892341/article/details/73918672 修改dock ...

  8. winrar 弹窗处理

    https://www.rarlab.com/ 1.下载英文版 2.把下面这段code文本复制到一个新建的记事本txt文档中,然后另存为rarreg.key文件,注意后缀名.txt改为.key才行. ...

  9. Linux系统调用原理

    操作系统通过系统调用为运行于其上的进程提供服务. 当用户态进程发起一个系统调用, CPU 将切换到 内核态 并开始执行一个 内核函数 . 内核函数负责响应应用程序的要求,例如操作文件.进行网络通讯或者 ...

  10. mina 通讯框架

    Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务.虚拟机管道通信服务等),M ...