FIFO 是FPGA设计中最有用的模块之一。FIFO 在模块之间提供简单的握手和同步机制,是设计人员将数据从一个模块传输到另一个模块的常用选择。

在这篇文章中,展示了一个简单的 RTL 同步 FIFO,可以直接在自己的设计中配置和使用它,该设计是完全可综合的。

为什么要自己设计FIFO

那么,为什么呢?网上有很多关于 FIFO 的 Verilog/VHDL 代码的资源,过去,我自己也使用过其中的一些。但令人沮丧的是,它们中的大多数都存在问题,尤其是在上溢出和下溢出条件下。所以想一劳永逸地解决这些问题。

FIFO 规格\性能

  • 同步,单时钟。

  • 基于寄存器的 FIFO,适用于中小型 FIFO。

  • Full、Empty、Almost-full、Almost-empty 标志。

  • 完全可配置的数据宽度、深度和标志。

  • 完全可综合的系统 Verilog 代码。

/*===============================================================================================================================Design       : Single-clock Synchronous FIFODescription  : Fully synthesisable, configurable Single-clock Synchronous FIFO based on registers.- Configurable Data width.- Configurable Depth.- Configurable Almost-full and Almost-empty signals.
===============================================================================================================================*/module my_fifo #(parameter DATA_W           = 4      ,        // Data widthparameter DEPTH            = 8      ,        // Depth of FIFO                   parameter UPP_TH           = 4      ,        // Upper threshold to generate Almost-fullparameter LOW_TH           = 2               // Lower threshold to generate Almost-empty)(input                   clk         ,        // Clockinput                   rstn        ,        // Active-low Synchronous Resetinput                   i_wren      ,        // Write Enableinput  [DATA_W - 1 : 0] i_wrdata    ,        // Write-dataoutput                  o_alm_full  ,        // Almost-full signaloutput                  o_full      ,        // Full signalinput                   i_rden      ,        // Read Enableoutput [DATA_W - 1 : 0] o_rddata    ,        // Read-dataoutput                  o_alm_empty ,        // Almost-empty signaloutput                  o_empty              // Empty signal);/*-------------------------------------------------------------------------------------------------------------------------------Internal Registers/Signals
-------------------------------------------------------------------------------------------------------------------------------*/logic [DATA_W - 1        : 0] data_rg [DEPTH] ;        // Data array
logic [$clog2(DEPTH) - 1 : 0] wrptr_rg        ;        // Write pointer
logic [$clog2(DEPTH) - 1 : 0] rdptr_rg        ;        // Read pointer
logic [$clog2(DEPTH)     : 0] dcount_rg       ;        // Data counterlogic                         wren_s          ;        // Write Enable signal generated iff FIFO is not full
logic                         rden_s          ;        // Read Enable signal generated iff FIFO is not empty
logic                         full_s          ;        // Full signal
logic                         empty_s         ;        // Empty signal/*-------------------------------------------------------------------------------------------------------------------------------Synchronous logic to write to and read from FIFO
-------------------------------------------------------------------------------------------------------------------------------*/
always @ (posedge clk) beginif (!rstn) begin     data_rg   <= '{default: '0} ;wrptr_rg  <= 0              ;rdptr_rg  <= 0              ;      dcount_rg <= 0              ;endelse beginready_rg <= 1'b1 ;/* FIFO write logic */            if (wren_s) begin                          data_rg [wrptr_rg] <= i_wrdata ;        // Data written to FIFOif (wrptr_rg == DEPTH - 1) beginwrptr_rg <= 0               ;        // Reset write pointer  endelse beginwrptr_rg <= wrptr_rg + 1    ;        // Increment write pointer            endend/* FIFO read logic */if (rden_s) begin         if (rdptr_rg == DEPTH - 1) beginrdptr_rg <= 0               ;        // Reset read pointerendelse beginrdptr_rg <= rdptr_rg + 1    ;        // Increment read pointer            endend/* FIFO data counter update logic */if (wren_s && !rden_s) begin               // Write operationdcount_rg <= dcount_rg + 1 ;end                    else if (!wren_s && rden_s) begin          // Read operationdcount_rg <= dcount_rg - 1 ;         endendend/*-------------------------------------------------------------------------------------------------------------------------------Continuous Assignments
-------------------------------------------------------------------------------------------------------------------------------*/// Full and Empty internal
assign full_s      = (dcount_rg == DEPTH) ? 1'b1 : 0 ;
assign empty_s     = (dcount_rg == 0    ) ? 1'b1 : 0 ;// Write and Read Enables internal
assign wren_s      = i_wren & !full_s                ;
assign rden_s      = i_rden & !empty_s               ;// Full and Empty to output
assign o_full      = full_s                          ;
assign o_empty     = empty_s                         ;// Almost-full and Almost Empty to output
assign o_alm_full  = (dcount_rg > UPP_TH) ? 1'b1 : 0 ;
assign o_alm_empty = (dcount_rg < LOW_TH) ? 1'b1 : 0 ;// Read-data to output
assign o_rddata    = data_rg [rdptr_rg]              ;   endmodule/*=============================================================================================================================*/

基于 RAM 的 FIFO

在上面的步骤中,我们看到了一个基于寄存器的同步FIFO。接下来,我们来看看基于 RAM 的 FIFO。该 FIFO 在 RAM 而不是寄存器上实现其数据阵列。这适用于在硬件上实现大型 FIFO ;特别是在 FPGA 上,FPGA 里有大量的Block RAM 可用。这将降低资源利用率,也可以获得更好的时序性能。

详细代码:

https://github.com/iammituraj/FIFOs

【手撕代码】同步 FIFO、LIFO/Stack相关推荐

  1. 数字IC手撕代码-同步FIFO

    前言: 本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析.代码及波形,所有代码均经过本人验证. 目录如下: 1.数字IC手撕代码-分频器(任意偶数分频) 2.数字IC手 ...

  2. 数字IC手撕代码---百题斩

    前言: 本篇导览目录,用来索引笔者写的其他手撕代码文章 本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析.代码及波形,所有代码均经过本人验证. 目录如下: 1.数字IC ...

  3. 数字IC笔面常考,跨时钟域神器。——异步FIFO(简介及手撕代码)

    异步FIFO 写在前面的话 异步FIFO相关知识点 FIFO简介 FIFO结构 应用场景(来源小梅哥 <FPGA 系统设计与验证实战指南> 章节4.4) 相关参数 异步FIFO 内部组成 ...

  4. 【数字IC手撕代码】Verilog奇数分频|题目|原理|设计|仿真(三分频,五分频,奇数分频及特殊占空比)

    芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区联合力荐!近500篇数字IC精品文章收录! [数字IC精品文章收录]学习路线·基础知识·总线·脚本语言·芯片求职· ...

  5. 【数字IC手撕代码】Verilog偶数分频|题目|原理|设计|仿真(二分频,四分频,六分频,八分频,偶数分频及特殊占空比)

    芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区联合力荐!近500篇数字IC精品文章收录! [数字IC精品文章收录]学习路线·基础知识·总线·脚本语言·芯片求职· ...

  6. 【数字IC手撕代码】Verilog固定优先级仲裁器|题目|原理|设计|仿真

    芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区联合力荐!近500篇数字IC精品文章收录! [数字IC精品文章收录]学习路线·基础知识·总线·脚本语言·芯片求职· ...

  7. 数字IC手撕代码-边沿检测(上升沿、下降沿、双边沿)

    前言: 本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析.代码及波形,所有代码均经过本人验证. 目录如下: 1.数字IC手撕代码-分频器(任意偶数分频) 2.数字IC手 ...

  8. 【数字IC手撕代码】Verilog自动售卖饮料机|题目|原理|设计|仿真

    芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区联合力荐!近500篇数字IC精品文章收录! [数字IC精品文章收录]学习路线·基础知识·总线·脚本语言·芯片求职· ...

  9. 【数字IC手撕代码】Verilog伪随机数生成器|线性反馈移位寄存器|题目|原理|设计|仿真

    芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区联合力荐!近500篇数字IC精品文章收录! [数字IC精品文章收录]学习路线·基础知识·总线·脚本语言·芯片求职· ...

  10. 【数字IC手撕代码】Verilog半整数分频|题目|原理|设计|仿真

    芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球 四社区联合力荐!近500篇数字IC精品文章收录! [数字IC精品文章收录]学习路线·基础知识·总线·脚本语言·芯片求职· ...

最新文章

  1. 【Qt】QImage、QPixmap、QBitmap和QPicture
  2. 网传BAT等大厂2020校招传统大厂白菜价!
  3. R语言使用compareGroups包绘制单因素分析表实战:基于survival包的colon数据集
  4. Qt 进程 QProcess
  5. 理解MySQL——索引与优化
  6. 战疫期,钉钉如何扛起暴增百倍的流量?【阿里云快速扩容新纪录】
  7. 【渝粤题库】国家开放大学2021春2724市场营销原理与实务题目
  8. poj 3748 位操作
  9. STM系列单片机中文参考手册下载方法
  10. 问题 G: 编写函数:数组的排序 (Append Code)
  11. C++左值与右值,移动与完美转发
  12. String,StringBuffer,StringBulilder之间的区别
  13. flutter显示图标_如何自动调整Flutter中的图标大小
  14. Android异常之SIGABRT
  15. 删除只读属性的文件夹及其子文件
  16. 占用80端口的几种情况及解决方法
  17. 一语成金,说透管理,点透人生!
  18. 健美运动员赛前脱水断碳_就金刚狼的问题,谈谈健美比赛前的控水脱水
  19. 智能门禁系统教程--人脸识别方案
  20. 矛盾集合体——static的相关用法介绍

热门文章

  1. 【Java知识点总结】Java语句简介及顺序结构
  2. 林萧谈如何进入BAT
  3. word恢复和粘贴按钮变灰色,不可用怎么办?
  4. ping命令——网卡选择
  5. 马云鹤:淡然行走,一路从容
  6. 广播报时的-滴-滴-嘟-声音频率
  7. Sql中CAST用法介绍
  8. WordPress自定义小工具
  9. warning: #550-D: variable “a“ was set but never use 解决方法
  10. 史上最简单安装windows11原版镜像方法