跳转到主要内容
--## 电子创新网图库均出自电子创新网,版权归属电子创新网,欢迎其他网站、自媒体使用,使用时请注明“图片来自电子创新网图库”,不过本图库图片仅限于网络文章使用,不得用于其他用途,否则我们保留追诉侵权的权利。 ##--

本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
judy 提交于

本文转载自:OpenFPGA微信公众号

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 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 counter

    logic 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) 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 = dcount_rg - 1 ;
    end

    end

    end

    /*-------------------------------------------------------------------------------------------------------------------------------
    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

    精彩推荐

    2026英伟达GTC大会专题

    CES 2026(国际消费类电子产品展览会)专题

    第四届南渡江智慧医疗与康复产业高峰论坛

    第十五届松山湖中国IC创新高峰论坛

    第四届滴水湖中国RISC-V产业论坛

    Recent comments

    • 1873774516_516738
    • 2460440665_516737
    • 1457585548_516736
    • 780289498_516735
    • 2283262460_516734