【不止IP】First In First Out,FIFO核的使用


一、Vivado FIFO IP核的使用方法和注意事項

1、fifo類型主要分兩種,即同步fifo和異步fifo。

當使用異步fifo時,尤其要注意一點,復位信號rst要和wr_clk保持同步,否則將無法對fifo進行有效復位,會出現寫不進數等不正常的情況。

所以當復位信號為異步信號,且與wr_clk不同源時,要用wr_clk拍兩下rst信號。

always @ (posedge wr_clk) begin
    rst_fifo0 <= aclr;
    rst_fifo1 <= rst_fifo0;
    rst_fifo2 <= rst_fifo1;
    rst_fifo3 <= rst_fifo2;
end

以下介紹的fifo使用方法主要適用於同步fifo。

2、fifo核的兩種讀出模式:standard fifo、first word fall through,它們的功能和操作上有一些區別。

(1)Standard FIFO(標准FIFO):

  在標准FIFO中,數據輸入(寫入)和數據輸出(讀取)是獨立的操作。寫入和讀取操作是異步進行的,即它們可以在任何時刻進行。
  在讀取操作之前,FIFO必須至少有一個完整的數據字來供讀取。否則,讀取操作將被阻塞直到有數據可用。
  標准FIFO可以支持數據的雙向傳輸,即數據可以同時從FIFO讀取和寫入。
  當選擇Standard模式的時候,在讀使能信號有效的下一個周期才能讀出第一個有效的數據。

(2)First Word Through (FWT) FIFO(首字通過FIFO):

  在FWT FIFO中,寫入操作和讀取操作之間存在一種特殊的關系。當第一個數據字從寫入端輸入FIFO時,它會立即通過FIFO進行讀取。
  在FWT FIFO中,讀取操作是優先於寫入操作的。當有數據可用時,讀取操作優先獲得數據,而不需要等待FIFO緩沖區填充完整。
  FWT FIFO也支持數據的雙向傳輸,即可以在讀取操作和寫入操作同時進行。
  當選擇FWT模式的時候,在讀使能信號有效的第一個周期就能能讀出第一個有效的數據; 這是因為在這種模式下,FIFO提前把數據已經准備到了數據輸出總線上,等待都使能有效就輸出到數據輸出端口(組合邏輯),但在這種模式下,valid信號將會在復位后就保持有效,這一點要特別注意;

總結起來,標准FIFO和首字通過FIFO之間的主要區別在於數據的讀取時機和操作的優先級。標准FIFO對讀取和寫入操作是異步的,而FWT FIFO在寫入第一個數據時即可立即讀取,讀取操作具有優先級。

2、在配置IP核時,一般不需要”Enable safety circuit“。

3、在配置IP核時,一般不需要設置all most full/all most empty,使用半空半滿的方式讀寫fifo。

 

 

二、FIFO的設計與開發技巧

1、FIFO的讀寫方式

正如前面提到的,一般不需要設置all most full/all most empty,使用半空半滿的方式讀寫fifo。除了這種方法之外,還有非空即讀的方式,乒乓FIFO(double buffer)的方式等。

(1)半空半滿讀寫

用fifo的計數器控制,寫半滿時開始讀,讀半空時開始寫,其它時間既讀又寫。

// 利用狀態機對fifo進行半空半滿的讀寫
module fifo_example;

// 三段式狀態機
always @(posedge clk100m) begin
    if(Rst == 1'b1)
        curr_state <= #TCQ_STA_IDLE;
    else
        curr_state <= #TCQ_next_state;
end

// Calculate the next state
always @ ( * ) begin
    case(curr_state)
        STA_IDLE:begin
            if (full == 1'b0) // fifo IP核的性質,初始化狀態full為1
                next_state <= STA_WRITING;
            else
                next_state <= STA_IDLE;
        end

        STA_WRITING:begin
            if (wr_data_count > 8'd200) // 已寫入200個數
                next_state <= STA_READING;
            else
                next_state <= STA_WRITING;
        end
        
        STA_READING:begin
            if (rd_data_count < 6'd20)  // 可讀取的數小於20
                next_state <= STA_WRITING;
            else
                next_state <= STA_READING;
        end

        default :begin
            next_state <= STA_IDLE;
        end
    endcase
end

// state output
always @(posedge clk100m) begin
    if (Rst == 1'b1) begin
        wr_en        <= #TCQ 1'b0;
        rd_en        <= #TCQ 1'b0;
        din          <= #TCQ 8'd0;
        din_r        <= #TCQ 8'd0;
    end
    else case (curr_state)
        STA_IDLE: begin
            wr_en        <= #TCQ 1'b0;
            rd_en        <= #TCQ 1'b0;
            din          <= #TCQ 8'd0;
            din_r        <= #TCQ 8'd0;
        end

        STA_WRITING:begin
            wr_en        <= #TCQ 1'b1;
            rd_en        <= #TCQ 1'b0;
            if (din == 8'd255)
                din      <= #TCQ 8'd0;
            else 
                din      <= #TCQ din + 8'd1;
            din_r        <= #TCQ din;
        end

        STA_READING:begin
            wr_en        <= #TCQ 1'b0;
            rd_en        <= #TCQ 1'b1;
        end
    endcase
end

endmodule //fifo_example

 (2)非空即讀,即當empty拉低后就讀出,如果只用一個異步時鍾FIFO也能實現這個效果,但有可能導致數據斷流,對於要保證fifo無縫銜接的設計,這種方法不可靠,所以推薦使用乒乓fifo的方式讀寫。需要乒乓fifo的場景如下:①異步fifo跨時鍾域;②效率第一,非空即讀;③要求不間斷寫(存),不間斷讀;④數據流的接口。

  要注意異步fifo的讀取速度要比寫入速度快,否則就要添加更多的fifo來進行乒乓操作。

 

2、fifo的empty信號和full信號

  對於fifo的empty信號,如果rden沒有賦值(紅色,懸空),那么empty信號在拉低后也會進入紅色,因為“不知道有沒有被讀出”。

  fifo的empty沒有正常拉低時(一般發生於仿真過程中),可能是因為復位信號太短,或者復位后間隔時間不夠長就寫入數據;適當延長復位時間和工作到來時間。

  初始化的fifo full信號是拉高的,寫入數據要等full拉低后。

 

3、fifo的特殊應用場景

  (1)以UDP轉SDRAM的場景為例,PHY芯片過來的時鍾、數據、有效信號等引腳灌入fifo進行隔離,把兩個時鍾域隔開,避免用該時鍾直接作為UDP模塊的時鍾,否則會因為該時鍾扇出太大,導致程序不穩定,例如改了兩行代碼程序就不能正常運行了。用fifo進行兩個時鍾域的隔離還有一個好處,無論前端時鍾有多快都無所謂,只當隔離fifo滿了以后再讀出新的時鍾,即“網速自適應”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM