当前位置:   article > 正文

【FIFO】Standard / FWFT FIFO设计实现(二)——异步时钟

fwft fifo

在这里插入图片描述

标准FIFO

   异步FIFO需要使用格雷码同步读写信号,可参考牛客异步FIFO例题,不同于牛客例题之处在于FIFO读空信号置位与FIFO最后一个有效数据输出在同一个周期,与Xilinx FIFO一致。核心代码如下:


    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_r = 'd0, wr_ptr_r = 'd0;
    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_gray_r = 'd0, wr_ptr_gray_r = 'd0;
    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_gray_cdc_r = 'd0, wr_ptr_gray_cdc_r = 'd0;
    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_gray_scdc_r = 'd0, wr_ptr_gray_scdc_r = 'd0;
    
    always_ff @(posedge m_clk) begin
        if (wr_en & ~wfull) begin
            wr_ptr_r <= wr_ptr_r + 1;
        end
    end 

    always_ff @(posedge s_clk) begin
        if (rd_en & ~rempty) begin
            rd_ptr_r <= rd_ptr_r + 1;
        end
    end

    always_ff @(posedge s_clk) begin 
        rd_ptr_gray_r[FIFO_DEPTH_WIDTH] <= rd_ptr_r[FIFO_DEPTH_WIDTH];
        for (integer i = 0; i < FIFO_DEPTH_WIDTH; i++) begin
            rd_ptr_gray_r[i] <= rd_ptr_r[i + 1] ^ rd_ptr_r[i];
        end
    end

    always_ff @(posedge m_clk) begin
        rd_ptr_gray_cdc_r <= rd_ptr_gray_scdc_r;
        rd_ptr_gray_scdc_r <= rd_ptr_gray_r;
    end

    always_ff @(posedge m_clk) begin
        wr_ptr_gray_r[FIFO_DEPTH_WIDTH] <= wr_ptr_r[FIFO_DEPTH_WIDTH];
        for (integer i = 0; i < FIFO_DEPTH_WIDTH; i++) begin
            wr_ptr_gray_r[i] <= wr_ptr_r[i + 1] ^ wr_ptr_r[i];
        end
    end

    always_ff @(posedge s_clk) begin
        wr_ptr_gray_cdc_r <= wr_ptr_gray_scdc_r;
        wr_ptr_gray_scdc_r <= wr_ptr_gray_r;
    end

    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_m_clk, wr_ptr_s_clk;
    
    assign wfull = (wr_ptr_r[FIFO_DEPTH_WIDTH] != rd_ptr_m_clk[FIFO_DEPTH_WIDTH]) && (wr_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0] == rd_ptr_m_clk[FIFO_DEPTH_WIDTH - 1 : 0]);
    assign rempty = rd_ptr_r == wr_ptr_s_clk;
    
    always_comb begin
        wr_ptr_s_clk[FIFO_DEPTH_WIDTH] = wr_ptr_gray_cdc_r[FIFO_DEPTH_WIDTH];
        for (integer i = FIFO_DEPTH_WIDTH - 1; i >= 0; i--) begin
            wr_ptr_s_clk[i] = wr_ptr_s_clk[i + 1] ^ wr_ptr_gray_cdc_r[i];
        end
    end

    always_comb begin
        rd_ptr_m_clk[FIFO_DEPTH_WIDTH] = rd_ptr_gray_cdc_r[FIFO_DEPTH_WIDTH];
        for (integer i = FIFO_DEPTH_WIDTH - 1; i >= 0; i--) begin
            rd_ptr_m_clk[i] = rd_ptr_m_clk[i + 1] ^ rd_ptr_gray_cdc_r[i];
        end
    end

    logic [TDATA_WIDTH - 1 : 0] ram[FIFO_DEPTH - 1 : 0];

    always_ff @(posedge m_clk) begin
        if (wr_en & ~wfull) begin
            ram[wr_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]] <= m_axis_tdata;
        end
    end

    always_ff @(posedge s_clk) begin
        if (rd_en & ~rempty) begin
            s_axis_tdata <= ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
        end
    end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

图片

FWFT FIFO简单实现

   基于标准异步FIFO,引入FWFT机制。一种简单做法即将ram输出改为组合逻辑输出,这种方式实现的FWFT延时最低。

    always_comb begin
        // if (rd_en & ~rempty) begin
            s_axis_tdata = ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
        // end
    end
  • 1
  • 2
  • 3
  • 4
  • 5

图片

FWFT FIFO优化

   然而,在FPGA中所有存储资源如(BRAM、URAM)均具有一个周期的读延时,在构造大容量fifo时,为了让综合工具将RAM综合为BRAM / URAM,更合适的做法为添加寄存器slice,这种方式会增加1个周期的延迟:

        initial rempty = 1'b1;
        
        assign wfull = sfifo_wfull;
        
        always @(posedge s_clk) begin
            if (~sfifo_rempty & (rempty | rd_en)) begin
                s_axis_tdata <= ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
            end
        end
        
        assign sfifo_rd_en = (rempty | rd_en);
        
        always @(posedge s_clk) begin
            if (~sfifo_rempty) begin
                rempty <= 1'b0;
            end else if (rd_en) begin
                rempty <= 1'b1;
            end
        end     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

图片

完整代码

完整工程代码可公众号回复ASYNC_FIFOs下载。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/539398
推荐阅读
相关标签
  

闽ICP备14008679号