Vivado中調用FIFO


  FIFO(First In First Out),即先進先出。FPGA 或者 ASIC 中使用到的 FIFO 一般指的是對數據的存儲具有先進先出特性的一個緩存器,常被用於數據的緩存或者高速異步數據的交互。它與普通存儲器的區別是沒有外部讀寫地址線,這樣使用起來相對簡單,但缺點就是只能順序寫入數據,順序的讀出數據,其數據地址由內部讀寫指針自動加 1 完成,不能像普通存儲器那樣可以由地址線決定讀取或寫入某個指定的地址。

  FIFO 從讀寫時鍾上來分有兩類結構:單時鍾 FIFO(同步 FIFO)和雙時鍾 FIFO(異步 FIFO)。單時鍾 FIFO 具有一個時鍾(讀寫共用一個時鍾)輸入,因此所有輸入信號的讀取都是在這個時鍾的上升沿進行的,所有輸出信號的變化也是在這個時鍾信號的上升沿的控制下進行的,即單時鍾 FIFO 的所有輸入輸出信號都是同步這個時鍾信號的。而在雙時鍾 FIFO 結構中,寫端口和讀端口分別有獨立的時鍾,所有與寫相關的信號都是同步於寫時鍾 wr_clk 的,所有與讀相關的信號都是同步於讀時鍾 rd_clk 的。下面圖是雙時鍾 FIFO 的整體框圖和內部實現的框圖,有單獨的模塊對讀寫時鍾域進行同步處理。

 

  本文示范一個單時鍾FIFO,數據位寬為8位,數據深度為256,在Vivodo中產生一個FIFO IP核:

 

  將IP核例化到頂層模塊中,並在頂層模塊中完成寫入、讀出的控制(不另外編寫寫入、讀出模塊)。

 
 
           

例化FIFO:

 
           
wire                                    full                       ;//例化FIFO
wire                                    empty                      ;
reg                                     wr_en                      ;
reg                                     rd_en                      ;
reg                    [   7:0]         din                        ;
reg                    [   1:0]         wr_state                   ;
reg                    [   1:0]         rd_state                   ;
    fifo u_fifo(
    .clk                               (clk                       ),
    .srst                              (srst                      ),
    .din                               (din                       ),
    .wr_en                             (wr_en                     ),
    .rd_en                             (rd_en                     ),
    .dout                              (dout                      ),
    .full                              (full                      ),
    .empty                             (empty                     )
);
  寫入控制:
always @(posedge clk ) begin                         //寫數據
  if(srst)begin
    wr_en<=0;
    din<=0;
    wr_state<=0;
  end
  else begin
    case (wr_state)
      0:
      begin
        if(empty)begin
          wr_en<=1;
          wr_state<=1;
        end
        else
          wr_state<=0;
      end
      1:
      begin
        if(full)begin
          wr_en<=0;
          wr_state<=0;
          din<=0;
        end
        else begin
          wr_en<=1;
          din<=din+1'b1;
        end
      end
      default:wr_state<=0;
    endcase
  end
end
讀出控制:
always @(posedge clk ) begin                         //讀數據
  if(srst)begin
    rd_en<=0;
    rd_state<=0;
  end
  else begin
    case (rd_state)
      0:
        if(full)begin
          rd_en<=1;
          rd_state<=1;
        end
        else begin
          rd_en<=0;
          rd_state<=0;
        end
      1:
        if(empty)begin
          rd_en<=0;
          rd_state<=0;
        end
        else begin
          rd_state<=1;
        end
      default: rd_state<=0;
    endcase
  end
end
 
testbench:
`timescale 1ns / 1ps
module fifo_tb();
reg clk;
reg srst;
wire [7:0]dout;
fifo_test u_fifo_test(
  .clk  (clk  ),
  .srst (srst ),
  .dout (dout )
);
initial clk=1;
always#10 clk=!clk;
initial begin
    srst=1;
    #201;
    srst=0;
    #200000;
    $stop;
end
endmodule
 

 

仿真結果:

 

   時鍾高電平復位,可以發現,當empty脈沖信號出現時,wr_en拉高,開始往FIFO中寫入數據;寫滿之后,full信號脈沖拉高,wr_en拉低,rd_en拉高,開始讀出數據,直至數據全部讀出,empty脈沖信號再次出現,這樣就是一個寫讀周期。


免責聲明!

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



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