一个简单的RTL同步FIFO设计

fifo 是fpga设计中最有用的模块之一。fifo 在模块之间提供简单的握手和同步机制,是设计人员将数据从一个模块传输到另一个模块的常用选择。
在这篇文章中,展示了一个简单的 rtl 同步 fifo,可以直接在自己的设计中配置和使用它,该设计是完全可综合的。
为什么要自己设计fifo
那么,为什么呢?网上有很多关于 fifo 的 verilog/vhdl 代码的资源,过去,我自己也使用过其中的一些。但令人沮丧的是,它们中的大多数都存在问题,尤其是在上溢出和下溢出条件下。所以想一劳永逸地解决这些问题。
fifo 规格性能
同步,单时钟。
基于寄存器的 fifo,适用于中小型 fifo。
full、empty、almost-full、almost-empty 标志。
完全可配置的数据宽度、深度和标志。
完全可综合的系统 verilog 代码。
/*===============================================================================================================================   design       : single-clock synchronous fifo   description  : 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 width                   parameter depth            = 8      ,        // depth of fifo                                      parameter upp_th           = 4      ,        // upper threshold to generate almost-full                   parameter low_th           = 2               // lower threshold to generate almost-empty                )                (                   input                   clk         ,        // clock                   input                   rstn        ,        // active-low synchronous reset                                      input                   i_wren      ,        // write enable                   input  [data_w - 1 : 0] i_wrdata    ,        // write-data                   output                  o_alm_full  ,        // almost-full signal                   output                  o_full      ,        // full signal                   input                   i_rden      ,        // read enable                   output [data_w - 1 : 0] o_rddata    ,        // read-data                   output                  o_alm_empty ,        // almost-empty signal                   output                  o_empty              // empty signal                );/*-------------------------------------------------------------------------------------------------------------------------------   internal registers/signals-------------------------------------------------------------------------------------------------------------------------------*/logic [data_w - 1        : 0] data_rg [depth] ;        // data arraylogic [$clog2(depth) - 1 : 0] wrptr_rg        ;        // write pointerlogic [$clog2(depth) - 1 : 0] rdptr_rg        ;        // read pointerlogic [$clog2(depth)     : 0] dcount_rg       ;        // data counter      logic                         wren_s          ;        // write enable signal generated iff fifo is not fulllogic                         rden_s          ;        // read enable signal generated iff fifo is not emptylogic                         full_s          ;        // full signallogic                         empty_s         ;        // empty signal/*-------------------------------------------------------------------------------------------------------------------------------   synchronous logic to write to and read from fifo-------------------------------------------------------------------------------------------------------------------------------*/always @ (posedge clk) begin   if (!rstn) begin                     data_rg   <= '{default: '0} ;      wrptr_rg  <= 0              ;      rdptr_rg  <= 0              ;            dcount_rg <= 0              ;   end   else begin      ready_rg <= 1'b1 ;            /* fifo write logic */                  if (wren_s) begin                                            data_rg [wrptr_rg] <= i_wrdata ;        // data written to fifo         if (wrptr_rg == depth - 1) begin            wrptr_rg <= 0               ;        // reset write pointer           end         else begin            wrptr_rg <= wrptr_rg + 1    ;        // increment write pointer                     end      end      /* fifo read logic */      if (rden_s) begin                  if (rdptr_rg == depth - 1) begin            rdptr_rg <= 0               ;        // reset read pointer         end         else begin            rdptr_rg <= rdptr_rg + 1    ;        // increment read pointer                     end      end      /* fifo data counter update logic */      if (wren_s && !rden_s) begin               // write operation         dcount_rg <= dcount_rg + 1 ;      end                          else if (!wren_s && rden_s) begin          // read operation         dcount_rg  upp_th) ? 1'b1 : 0 ;assign o_alm_empty = (dcount_rg < low_th) ? 1'b1 : 0 ;// read-data to outputassign o_rddata    = data_rg [rdptr_rg]              ;   endmodule/*=============================================================================================================================*/  
基于 ram 的 fifo
在上面的步骤中,我们看到了一个基于寄存器的同步fifo。接下来,我们来看看基于 ram 的 fifo。该 fifo 在 ram 而不是寄存器上实现其数据阵列。这适用于在硬件上实现大型 fifo ;特别是在 fpga 上,fpga 里有大量的block ram 可用。这将降低资源利用率,也可以获得更好的时序性能。


谷歌将在更新中提高智能手表Wear OS的电池续航时间
自干扰消除在无线电中的作用是什么?
优化DC-DC转换器的控制和调制方法
英飞凌推出两款全新XENSIV™气压传感器
如何高效实现矩阵乘?CUDA初学者的角度入门
一个简单的RTL同步FIFO设计
HUD季度报告:DLP强势崛起,有人黯然离开
汽车智能化浪潮中对驾驶员辅助系统兴趣度最高
大数据的学习中你需要掌握的十二大技术
减少PCB地面反弹的设计注意事项
使用氮化镓(GaN)提高电源(PSU)能效
电子电路中源器件的区别
双电源自动切换电路图大全(TDA2030/功率放大/双电源供电的五款电路)
场效应管使用注意事项及检测技巧
电动汽车充电时开空调对电池有影响吗
探索“绿色计算”前沿技术,清华AIR、英特尔联合发力
变频家电——效率和节能的典范
超大电池+高颜值:魅蓝note3,比华为便宜3000元啊!
用一个仅有14条I/O腿的FPGA最小系统模块实现几种仪器的功能
黑客频繁攻击新冠疫苗冷链企业,是利益还是阴谋?