FIFO、RAM的工程实践

作者:饿狼传说 来源:FPGA的现今未

在FPGA的设计中,不可避免的会用到FIFO和RAM这2个基本单元,它们也是FPGA项目的核心基础,前面作者有关于这2个基本单元的详细介绍(FIFO的应用RAM的应用),这里作者就近几年使用FIFO和RAM的工程实践做个总结。

作为FPGA的初学阶段,都做过一个题,就是写一个同步FIFO,本意只是让初学者更好的理解FIFO的功能,一般当时写的,也不会真正的用于项目。

在早期,使用FIFO和RAM的时候,一般都是直接例化供应商的IP core,因为简单可靠,在仿真的时候编译下基本库,跑工程的时候添加下网表文件就搞定了。但是缺点也很明显,功能不方便扩展,不同位宽和深度的FIFO和RAM,需要重新例化,生成的文件也比较多,在工程里管理的IP core非常的多,比较乱。

随着项目的需要和团队经验的积累,就开始自己写FIFO和RAM,一般可以配置的参数会比较多,比如深度、宽度、供应商、整包计数等等。这个好处是不言而喻的,这些FIFO和RAM都是统一管理,参数可配置,定制化的开发非常适合自己和团队。但是对经验要求比较高,别看FIFO功能简单,但是做到稳定可靠,并不是一个简单的事情,各种使用场景都要考虑清楚。

还有一种方式就是采用源语封装,早期的源语封装也是一件比较复杂的事情,信号非常的多,也没有很好的文档支撑,一般用这种方式的少(当然不排除有大牛采用这种方式)。近几年,xilinx推出了XPM,个人理解就是对源语比较高层点的封装,作者这几年一直用这种方法,非常不错,该方式集成了上述2种方案的优点,同时又规避了缺点,比如,位宽、深度、类型等等都参数化,基本功能在源语中已经写好,接口信号和功能有专门的文档说明。工程管理上就是一个RTL代码,没有任何的IP core,用户界面也非常友好。intel也有类似的源语,使用相对也方便了。个人在使用的时候,可以根据项目特点,再做一层封装,如下所示:

module syn_fifo #(
    parameter                               FIFO_MEMORY_TYPE    = "block"           ,
    parameter                               ECC_MODE            = "no_ecc"          ,
    parameter                               READ_MODE           = "fwft"            ,
    parameter                               FIFO_READ_LATENCY   = 0                 ,
    parameter                               FIFO_WIDTH          = 32                ,
    parameter                               FIFO_DEPTH          = 512               ,
    parameter                               PKT_CNT_WIDTH       = $clog2(FIFO_DEPTH),
    parameter                               PROG_EMPTY_THRESH   = 32                ,
    parameter                               PROG_FULL_THRESH    = 480               )   
    (
    input                                   clk_sys                                 ,
    input                                   rst                                     ,
    input                                   wen                                     ,
    input   [FIFO_WIDTH-1:0]                din                                     ,
    input                                   din_cnt_en                              ,
    output                                  afull                                   ,
    input                                   ren                                     ,
    output  [FIFO_WIDTH-1:0]                dout                                    ,
    input                                   dout_cnt_en                             ,
    output                                  empty                                   ,
    output     [PKT_CNT_WIDTH:0]            pkt_cnt                                 ,
    output reg [3:0]                        fifo_err                                );

那究竟什么样的方式适合自己或者团队呢?对于初创型公司,人员少,项目复杂度不高,经验也不是很丰富的情况下,直接采用例化IP core的方式,简单省事,除此以外,都可以考虑利用上面的方案三,即源语的方式,根据项目和团队特点,做一层封装后,再统一使用。

在FIFO和RAM的工程实践中,如果你有更好的方案,欢迎后台留言讨论。

最新文章

最新文章