基本原理:

      1.读写指针的工作原理

  写指针:总是指向下一个将要被写入的单元,复位时,指向第1个单元(编号为0)。

  读指针:总是指向当前要被读出的数据,复位时,指向第1个单元(编号为0).

     2.FIFO的“空”/“满”检测

  FIFO设计的关键:产生可靠的FIFO读写指针和生成FIFO“空”/“满”状态标志。

  当读写指针相等时,表明FIFO为空,这种情况发生在复位操作时,或者当读指针读出FIFO中最后一个字后,追赶上了写指针时,如下图所示:

当读写指针再次相等时,表明FIFO为满,这种情况发生在,当写指针转了一圈,折回来(wrapped around)又追上了读指针,如下图:

为了区分到底是满状态还是空状态,可以采用以下方法:

  方法1:在指针中添加一个额外的位(extra bit),当写指针增加并越过最后一个FIFO地址时,就将写指针这个未用的MSB加1,其它位回零。对读指针也进行同样的操作。此时,对于深度为2n的FIFO,需要的读/写指针位宽为(n+1)位,如对于深度为8的FIFO,需要采用4bit的计数器,0000~1000、1001~1111,MSB作为折回标志位,而低3位作为地址指针。

  • 如果两个指针的MSB不同,说明写指针比读指针多折回了一次;如r_addr=0000,而w_addr = 1000,为满。
  • 如果两个指针的MSB相同,则说明两个指针折回的次数相等。其余位相等,说明FIFO为空;

      3.  二进制FIFO指针的考虑

  将一个二进制的计数值从一个时钟域同步到另一个时钟域的时候很容易出现问题,因为采用二进制计数器时所有位都可能同时变化,在同一个时钟沿同步多个信号的变化会产生亚稳态问题。而使用格雷码只有一位变化,因此在两个时钟域间同步多个位不会产生问题。所以需要一个二进制到gray码的转换电路,将地址值转换为相应的gray码,然后将该gray码同步到另一个时钟域进行对比,作为空满状态的检测。

使用gray码解决了一个问题,但同时也带来另一个问题,即在格雷码域如何判断空与满。

  对于“空”的判断依然依据二者完全相等(包括MSB);

  而对于“满”的判断,如下图,由于gray码除了MSB外,具有镜像对称的特点,当读指针指向7,写指针指向8时,除了MSB,其余位皆相同,不能说它为满。因此不能单纯的只检测最高位了,在gray码上判断为满必须同时满足以下3条:

  • wptr和同步过来的rptr的MSB不相等,因为wptr必须比rptr多折回一次。
  • wptr与rptr的次高位不相等,如上图位置7和位置15,转化为二进制对应的是0111和1111,MSB不同说明多折回一次,111相同代表同一位置。
  • 剩下的其余位完全相等。

    5.总体实现

以上内容参考http://www.cnblogs.com/BitArt/archive/2013/04/10/3010073.html,非原创。

源码在原来的基础上进行改编,如下:

 module Asyn_FIFO(data_out, full, empty, data_in, wen, wclk, wrst,ren, rclk, rrst);
parameter datasize = ;
parameter addrsize = ; input [datasize-:]data_in;
input wen,ren,wclk,rclk,wrst,rrst;
output [datasize-:]data_out;
output empty,full; reg empty,full;
wire [datasize-:]data_out; wire [addrsize-:]raddr,waddr; //
wire [addrsize:]rbinnext,wbinnext,rptrnext,wptrnext;
wire empty_val,full_val;
reg [addrsize:]rbin,wbin,rptr,wptr,rptr1,rptr2,wptr1,wptr2;
reg [addrsize-:]memory[:(addrsize<<)-]; //双口RAM
assign data_out=memory[raddr];
always @(posedge wclk)
begin if(wen&&!full) memory[waddr]<=data_in;end //同步wptr指针
always @(posedge rclk or negedge rrst)
begin if(!rrst) {rptr2,rptr1}<=;
else {rptr2,rptr1}<={rptr1,wptr};
end //同步rptr指针
always @(posedge wclk or negedge wrst)
begin if(!wrst) {wptr2,wptr1}<=;
else {wptr2,wptr1}<={wptr1,rptr};
end //产生raddr信号和empty信号
always @(posedge rclk or negedge rrst)
begin if(!rrst) {rbin,rptr}<=;
else {rbin,rptr}<={rbinnext,rptrnext};
end
assign raddr=rbin[addrsize-:];
assign rbinnext=rbin+(ren&&~empty);
assign rptrnext=(rbinnext>>)^rbinnext; //生成raddr
assign empty_val=(rptrnext==rptr2);
always @(posedge rclk or negedge rrst)
begin if(!rrst) empty<=;
else empty<=empty_val;
end //产生waddr信号和full信号
always @(posedge wclk or negedge wrst)
begin if(!wrst) {wbin,wptr}<=;
else {wbin,wptr}<={wbinnext,wptrnext};
end
assign waddr=wbin[addrsize-:];
assign wbinnext=wbin+(wen&&~full);
assign wptrnext=(wbinnext>>)^wbinnext; //生成waddr
assign full_val=(wptrnext=={~wptr2[addrsize:addrsize-],wptr2[addrsize-:]});
always @(posedge wclk or negedge wrst)
begin if(!rrst) full<=;
else full<=full_val;
end
endmodule

Verilog学习笔记简单功能实现(八)...............异步FIFO的更多相关文章

  1. Verilog学习笔记简单功能实现(八)...............同步FIFO

    Part 1,功能定义: 用16*8 RAM实现一个同步先进先出(FIFO)队列设计.由写使能端控制该数据流的写入FIFO,并由读使能控制FIFO中数据的读出.写入和读出的操作(高电平有效)由时钟的上 ...

  2. Verilog学习笔记简单功能实现(二)...............全加器

    先以一位全加器为例:Xi.Yi代表两个加数,Cin是地位进位信号,Cout是向高位的进位信号.列表有:   Xi     Yi    Cin Sum Cout 0 0 0 0 0 0 0 1 1 0 ...

  3. Verilog学习笔记简单功能实现(六)...............计数分频电路

    在分频器电路中最重要的概念有两个:1)奇分频/偶分频:2)占空比. A)其中最简单的就是二分频电路,占空比为50%,其Verilog程序为 module half_clk(clr,clk_in,clk ...

  4. Verilog学习笔记简单功能实现(五)...............序列检测设计

    这里采用夏宇闻教授第十五章的序列检测为例来学习; 从以上的状态转换图可以写出状态机的程序: module seqdet(x,out,clk,rst); input x,clk,rst; output ...

  5. Verilog学习笔记简单功能实现(三)...............同步有限状态机

    在Verilog中可以采用多种方法来描述有限状态机最常见的方法就是用always和case语句.如下图所示的状态转移图就表示了一个简单的有限状态机: 图中:图表示了一个四状态的状态机,输入为A和Res ...

  6. Verilog学习笔记简单功能实现(一)...............D触发器

    module D_flop(data,clk,clr,q,qb); input data,clk,clr; output q,qb; wire a,b,c,d,e,f,ndata,nclk; nand ...

  7. Verilog学习笔记简单功能实现(四)...............译码器和编码器

    这里以简单的3-8译码器和8-3编码器为例: module decoder3_8(a,out); :]a; :]out; 'b1<<a;/*把最低位的1左移in位(根据in口输入的值)并赋 ...

  8. Verilog学习笔记简单功能实现(七)...............接口设计(并行输入串行输出)

    利用状态机实现比较复杂的接口设计: 这是一个将并行数据转换为串行输出的变换器,利用双向总线输出.这是由EEPROM读写器的缩减得到的,首先对I2C总线特征介绍: I2C总线(inter integra ...

  9. IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试

    IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试 目的不是为了编写TSC2007驱动,是为了学习IIC驱动的编写,读一下TSC2007的ADC数据进行练习,, Linux主机驱动和外设驱 ...

随机推荐

  1. 将 PAGE_VERIFY 数据库选项设置为 CHECKSUM

    此规则检查 PAGE_VERIFY 数据库选项是否已设置为 CHECKSUM.为 PAGE_VERIFY 数据库选项启用 CHECKSUM 后,SQL Server 数据库引擎会在向磁盘中写入页面时计 ...

  2. 用MVVM做了一个保存网页的工具-上篇

    前言: 你是否有过收藏了别人博客或文章,当想用的时候却找不到?你是否有过收藏了别人博客或文章,却因为没有网络而打不开网页?OK,下面是我做的一个工具,有兴趣的同学们可以download 玩下,哈哈^. ...

  3. 有关PHP、HTML单引号、双引号转义以及转成HTML实体的那些事!

    一.单引号和双引号转义在PHP的数据存储过程中用得比较多,即往数据库里面存储数据时候需要注意转义单.双引号: 先说几个PHP函数: 1.addslashes — 使用反斜线引用(转义)字符串: 返回字 ...

  4. Datatables 在asp.net mvc中的使用

    前言 最近使用ABP(ASP.NET Boilerplate)做新项目,以前都是自己扩展一个HtmlHelper来完成同步/异步分页,但是有个地方一直不满意,排序太费劲. 以前接触过一点点的Datat ...

  5. HTML Inspector – 帮助你编写高质量的 HTML 代码

    HTML Inspector 是一款代码质量检测工具,帮助你编写更优秀的 HTML 代码.HTML Inspector 使用 JavaScript 编写,运行在浏览器中,是最好的 HTML 代码检测工 ...

  6. java中复制对象通过反射或序列化

    在使用缓存读取数据后修改发现缓存被修改.于是找了下复制对象的方法. 关于对象克隆 按我的理解,对象是包含引用+数据.通常变量复制都是将引用传递过去.比如: Person p1 = new Person ...

  7. 简单的Linq笔记

    最近带一个新人,被问到Linq的一点东西,回答他后,自己记录下,防止自己懵逼. Linq中查询一个表中指定的几个字段: var ts = t.FindAllItems().Where(P => ...

  8. Elasticsearch增删改查 之 —— Update更新

    更新操作,一般用这个的,应该不会很多吧!ES本身还是一个倾向于查询检索的框架,对于这种更新的操作,太过频繁总归是不好的. 不过阅读本篇后,你可以使用Script对所有的文档执行更新操作,也可以使用do ...

  9. Twitter Bootstrap深受开发者喜爱的11大理由

    Bootstrap,作为创新技术框架,使开发者.设计者更容易.更快捷.更出色地完成网站及应用的搭建工作.如果你还没有使用Twitter Bootstrap,建议你去了解一下.Bootstrap为开发者 ...

  10. 基于HTML5的Web SCADA工控移动应用

    在电力.油田燃气.供水管网等工业自动化领域Web SCADA的概念已经提出了多年,早先年的Web SCADA前端技术大部分还是基于Flex.Silverlight甚至Applet这样的重客户端方案,在 ...