异步FIFO的原理以及可综合的Verilog代码

  • 一、FIFO的定义
  • 二、FIFO的应用场景
  • 三、FIFO的分类
  • FIFO的参数
  • FIFO的设计难点

一、FIFO的定义

_ First In First Out 【FIFO】先进先出的缓存器,它与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,并顺序读出先写入的数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器可以根据地址对读取或写入某个指定的地址位上的数据信息。

二、FIFO的应用场景

— 数据缓存
比如当数据发送侧写入数据后,接收侧不能实时的对数据进行读取就可以对数据暂存到FIFO内,当接收侧准备完毕后,就可以顺序读取FIFO内相应的数据。

— 位宽转换
比如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。

— 速率匹配\异步处理
当数据的读写时钟相互异步,不一致时,而这种情况在集成芯片内对这种跨时钟域处理数据的情况非常多,而异步FIFO是一个可以很好解决这个问题的方案。

三、FIFO的分类

根据FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。

  • 同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。
  • 异步FIFO是指读写时钟不一致,读写时钟是互相独立的。

FIFO的参数

  • FIFO的位宽:表示一次性读取数据位的宽度(N),与通常所表示的32位、64位单片机含义是一样的。
  • 读时针:读数据时所采用的时钟,在时钟上升沿进行从FIFO内读取读指针所对应地址的数据。
  • 写时钟:写数据时所采用的时钟,在时钟上升沿时将数据写入写指针所对应地址的FIFO内存内。
  • FIFO的深度(Deep):表示的FIFO可以存取多少个N位数据。如果FIFO的位宽为N=8bit,FIFO的深度为Deep=16,就表示此FIFO可以存储16个8位的数据。也就是说此FIFO的内存大小为8*16bit。
  • 读指针:指向下一个要读的数据地址,读完后地址指针自动加一。
  • 写指针:指向下一个要写的数据地址,写完后地址指针自动加一。
  • 空标致(empty):如果将读、写指针类似成两个人在圆形操场内跑圈,如果读写指针跑的圈数一样(写指针没有领先读指针一圈的情况下),当读指针追上了写指针,表示FIFO内没有数据了,已经被读指针全部读出并送出数据, FIFO就会发出空标致信号,禁止再进行读数据操作。(可以想像成写指针一直领先读指针,因为只有先在FIFO内写入数据,才能进行相应的读数据操作
  • 满标致:表示FIFO已经将最后一个8位内存写入数据,也就是写指针已经超过读指针一圈,并追上了读指针,此时FIFO会发出满标致信号,禁止再进行写操作。

FIFO的设计难点

  • 空满信号的判断:对于一个FIFO的设计其难点在于对其空、满状态的准确判断。当进行读操作时,根据FIFO发出的空信号,不至于产生在FIFO已空状态下,进行读操作,造成读空情况的发生; 当进行写操作时,根据FIFO发出的满信号,不至于产生在FIFO已满的状态下,进行写入数据的操作,造成数据溢出的情况发生。所以对FIFO进行正确的空、满状态判断是进行FIFO设计的重点及难点。
Binary Gray
0_000 0_000
0_001 0_001
0_010 0_011
0_011 0_010
0_100 0_110
0_101 0_111
0_110 0_101
0_111 0_100
1_000 1_100
1_001 1_101
1_010 1_111
1_011 1_110
1_100 1_010
1_101 1_011
1_110 1_001
1_111 1_000
  • 在同步FIFO中,读写时钟为同一时钟,在实际硬件电路设计中,用的到比较少,而且空满判断比较简单,这里不做介绍。而异步FIFO芯片以及FPGA硬件电路设计中是一种常用的数据缓存方式。异步在产生满信号时,需要将读时钟域内的读指针同步到写时钟域内。如果采用Binary(二进制)做为地址指针,那么相邻位码元之间变化会有多个Bit位发生变化(例如:1到2,二进制0_001变为0_010有两bit位发生变化),如上表所示:(为二进制与格雷码变化对应表),每一时钟地址指针发生多bit位变化,会大大增加亚稳态发生的概率,且增大功耗。而格雷码是相邻两个码元之间只有一Bit位发生变化,而在芯片IC设计及FPGA设计异步FIFO中通常采用格雷码做为指针地址,这样大大降低亚稳态情况的发生。
    在实际设计中通常采用N+1位格雷码做为地址指针,在读写时钟进行指针同步,以产生空满信号。用N位二进制地址进行对FIFO内数据进行读写。如果感兴趣的可以深入看一下Clifford E的文章,看完之后会对异步FIFO有深入的理解。相应文章链接如下。
    超经典的异步 FIFO文章讲解,如果你读懂了异步你肯定懂了
    对于Verilog的讲解一定要看程序 ,不然不会明白 了,大家有什么想知道的,不明白的可以评论说明,大家一直学习。
  • 采用Gray2的形式的代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date:    22:30:20 08/04/2020
// Design Name:
// Module Name:    async_fifo
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module async_fifo #(parameter DATASIZE = 8,parameter ADDRSIZE = 4//parameter DEEP  = 32)
(
input  wire                 wclk,
input  wire                 rclk,
input  wire                 wrst_n,
input  wire                 rrst_n,
input  wire                 din_vld,
input  wire [DATASIZE-1:0]  din_data,
output reg                  rempty,
output reg                  ral_empty,output wire                   dout_vld,
output reg                  wfull,
output reg                  wal_full,
output wire [DATASIZE-1:0] dout_data);
wire    [ADDRSIZE-1:0]      waddr           ;
wire    [ADDRSIZE-1:0]      raddr           ;
reg [ADDRSIZE  :0]      waddr_bin   ;
reg [ADDRSIZE  :0]      raddr_bin   ;
wire                    wfull_val   ;
wire                            rempty_val  ;
reg   [ADDRSIZE  :0]     rptr           ;
reg   [ADDRSIZE  :0]        wq1_rptr        ;
reg   [ADDRSIZE  :0]        wq2_rptr        ;reg    [ADDRSIZE  :0]     wptr         ;
reg     [ADDRSIZE  :0]      rq1_wptr        ;
reg [ADDRSIZE  :0]      rq2_wptr        ;wire   [ADDRSIZE  :0]     rgray_next   ;
wire    [ADDRSIZE  :0]     wgray_next   ;wire   [ADDRSIZE  :0]      wbin_next       ;
wire    [ADDRSIZE  :0]      rbin_next       ;localparam DEPTH = 1 << ADDRSIZE;
reg   [DATASIZE-1 :0] ram [0: DEPTH - 1];//write and read data from ram
assign dout_data = ram[raddr];always @(posedge wclk)if(din_vld && !wfull) ram[waddr] <= din_data;//radr_gary syco to write clk
always @(posedge wclk or negedge wrst_n)
begin
if(!wrst_n)
beginwq1_rptr <= 0;wq2_rptr <= 0;
end
else
beginwq1_rptr <= rptr;wq2_rptr <= wq1_rptr;
end
end//wadr_gray syco to read clk
always @(posedge rclk or negedge rrst_n)
begin
if(!rrst_n)
beginrq1_wptr <= 0;rq2_wptr <= 0;
end
else
beginrq1_wptr <= wptr;rq2_wptr <= rq1_wptr;
end
end//generating empty
assign rempty_val = (rgray_next == rq2_wptr);
always @(posedge rclk or negedge rrst_n)if(!rrst_n) rempty <= 1'b1;else           rempty <= rempty_val;//generating  full
//assign wfull_val = ((wgnext[DATASIZE : DATASIZE-1] != wq2_rptr[DATASIZE : DATASIZE-1]) &&
//                       (wgnext[DATASIZE-2 : 0]     == wq2_rptr[DATASIZE-2 : 0]));
assign wfull_val = (wgray_next == {~wq2_rptr[ADDRSIZE : ADDRSIZE-1],wq2_rptr[ADDRSIZE-2 : 0]});
always @(posedge wclk or negedge wrst_n)if(!wrst_n) wfull <= 1'b0;else            wfull <= wfull_val;//read point
always @(posedge rclk or negedge rrst_n)
beginif(!rrst_n) beginraddr_bin <= 0;rptr      <= 0;endelse beginraddr_bin <= rbin_next;rptr      <= rgray_next;end
endassign raddr = raddr_bin[ADDRSIZE-1 : 0];assign rbin_next  = raddr_bin + (din_vld && ~rempty);
assign rgray_next = (rbin_next>>1) ^ rbin_next; //write point
always @(posedge wclk or negedge wrst_n)
beginif(!wrst_n)    beginwaddr_bin <= 0;wptr      <= 0;endelse beginwaddr_bin <= wbin_next;wptr      <= wgray_next;end
endassign waddr     = waddr_bin[ADDRSIZE-1 : 0]            ;assign wbin_next  = waddr_bin + (din_vld && ~wfull) ;
//bin to gray
assign wgray_next = (wbin_next >>1 ) ^ wbin_next      ;endmodule

异步FIFO的原理以及可综合的Verilog代码相关推荐

  1. 异步FIFO设计原理及Verliog源代码

    1.什么是FIFO? FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据 ...

  2. FPGA基础知识极简教程(4)从FIFO设计讲起之异步FIFO篇

    博文目录 写在前面 正文 同步FIFO回顾 $clog2()系统函数使用 综合属性控制资源使用 异步FIFO设计 FIFO用途回顾 异步FIFO原理回顾 异步FIFO设计 异步FIFO仿真 参考资料 ...

  3. FPGA逻辑设计回顾(6)多比特信号的CDC处理方式之异步FIFO

    文章目录 前言 异步FIFO的概念 异步FIFO为什么可以解决CDC问题? 异步FIFO的RTL实现 参考资料 前言 异步FIFO是处理多比特信号跨时钟域的最常用方法,简单来说,异步FIFO是双口RA ...

  4. verilog异步复位jk触发器_以不变应万变的异步FIFO面试宝典(二)

    异步FIFO面试宝典(二) 上一期为童鞋们带来了FIFO工作的基本原理,本期将继续与各位童鞋探讨FIFO类面试相关问题.首先让我们回顾一下上一期的课后思考题: 如果读时钟域速度较快.写时钟域速度较慢( ...

  5. 异步fifo设计及验证verilog代码

    论文参考:The Design and Verification of a Synchronous First-In First-Out 博客参考:[原创]异步FIFO设计原理详解 (含RTL代码和T ...

  6. 74ls390设计任意进制计数器_异步FIFO:设计原理及Verliog源码

    1.  异步FIFO的概念 异步FIFO为读取与写入采用不同的时钟,使用异步FIFO用于在不同的时钟域传输数据,主要用于跨时钟域传输多bit数据. 2.  异步FIFO的设计难点 同步异步信号,避免亚 ...

  7. 异步fifo的空满判断原理

    异步FIFO通过比较读写地址进行满空判断,但是读写地址属于不同的时钟域,所以在比较之前需要先将读写地址进行同步处理,将写地址同步到读时钟域再和读地址比较进行FIFO空状态判断(同步后的写地址一定是小于 ...

  8. Asynchronous FIFO with gray code(异步FIFO verilog设计理念)

    代码来自asic world 和paper" Simulation and Synthesis Techniques for Asynchronous FIFO Design",文 ...

  9. 异步FIFO的FPGA实现

    本文大部分内容来自Clifford E. Cummings的<Simulation and Synthesis Techniques for Asynchronous FIFO Design&g ...

最新文章

  1. Spring Cloud/Dubbo 应用无缝迁移到 Serverless 架构
  2. 用servlet校验密码2
  3. stm32编码器正反转计数程序_如何高效的扩展定时/计数器?
  4. UWP 自然灾害App在刷新数据后卡死的解决方案
  5. SQL Server系统表sysobjects介绍
  6. 通过自学可以搭建量化交易模型吗?
  7. Stellar Phoenix Office Repair(Office修复工具)v6.2绿色版
  8. XShell免费版的安装配置教程以及使用教程(超级详细、保姆级)
  9. 骨科手术ICD编码主要缺陷与原因分析
  10. 标准数独游戏-深搜解法
  11. 北大MBA夫妇不满现有教育系统 携女隐居终南山
  12. 【UE4】联网游戏开发的正确姿势
  13. 以太坊ETH源码分析(1):地址生成过程
  14. 前端主流面试官必问超详细面试题(整理完以秃头)持续更新中
  15. fwrite和fread函数的用法小结
  16. 服务器网口修改为百兆,服务器千兆网口能否设置为百兆
  17. 蓝屏死机!Windows 7用户千万别装这个补丁
  18. 典型大数据架构有哪些?我该怎么选择?
  19. 鼠标DPI和液晶显示器分辨率的关系
  20. Codeforces Round #470 D Perfect Security

热门文章

  1. 选好核心交换机六个关键指标有哪些?
  2. 如何有效提升工作效率?其实就是这四点
  3. easyexcel实现导出
  4. 【以太坊】什么是雷电网络 Raiden network
  5. git: Couldn‘t find remote ref
  6. Apache Curator客户端的使用
  7. 汽车销量数据库(分车型、分品牌月度销量数据 2005-2021)
  8. 在Sublime Text 2中将默认语法设置为不同的文件类型
  9. 购物商城html源码asp,购物商城 html
  10. Mt7628调试简记