fifo學習(3)
3.fifo IP核的使用
(1)最簡單的ip核,不設定復位訊號,採用公共時鐘;公共時鐘FIFO寫入讀取的位寬比只能是1:1
module fifo_ip(clk,din,wr_en,rd_en,dout,full,empty); input clk; input [7:0] din;//位寬為8位,深度為16 input wr_en; input rd_en; output [7:0] dout; output full; output empty; fifo_8_16 f0 ( .clk(clk), // input wire clk .din(din), // input wire [7 : 0] din .wr_en(wr_en), // input wire wr_en .rd_en(rd_en), // input wire rd_en .dout(dout), // output wire [7 : 0] dout .full(full), // output wire full .empty(empty) // output wire empty ); endmodule //tb module tb_fifo_ip; reg clk; reg [7:0] din; reg wr_en,rd_en; wire [7:0] dout; wire full,empty; initial begin clk=1'b0; din=8'h01; wr_en=1'b1; rd_en=1'b0; #400 wr_en=1'b0; rd_en=1'b1; #300 wr_en=1'b1; rd_en=1'b0; #200 wr_en=1'b0; rd_en=1'b1; end always #10 clk = ~clk; always #20 din = din + 1'b1; fifo_ip t1(.clk(clk), .din(din), .wr_en(wr_en), .rd_en(rd_en), .dout(dout), .full(full), .empty(empty)); endmodule
在第16個週期,fifo處於滿狀態,full置1;
但是,第一次讀取只讀取到了15,此時又開始寫入資料,寫入的第一個資料為36,故下一次讀取從16開始,第二個讀取的資料為36;可以說明在full或者empty拉高時,無論是寫入還是讀取使能都不會影響fifo中儲存的資料!
(2)設定同步復位訊號,採用公共時鐘
module fifo_ip0(clk,srst,din,wr_en,rd_en,dout,full,empty); input clk; input srst; input [7:0] din; input wr_en; input rd_en; output [7:0] dout; output full; output empty; reg [7:0] din1; always @(posedge clk) begin if(srst) din1 <= 8'd0; else din1 <= din; end fifo_8_16_srst f1 ( .clk(clk), // input wire clk .srst(srst), // input wire srst復位訊號為高電平有效 .din(din1), // input wire [7 : 0] din .wr_en(wr_en), // input wire wr_en .rd_en(rd_en), // input wire rd_en .dout(dout), // output wire [7 : 0] dout .full(full), // output wire full .empty(empty) // output wire empty ); module tb_fifo_ip0; reg clk,srst; reg [7:0] din; reg wr_en,rd_en; wire [7:0] dout; wire full,empty; initial begin clk=1'b0; srst=1'b1; din=8'h01; wr_en=1'b1;//寫 rd_en=1'b0; #40 srst=1'b0; #400 wr_en=1'b0;//讀 rd_en=1'b1; #300 srst=1'b1; wr_en=1'b1;//寫 rd_en=1'b0; #500 srst=1'b0; wr_en=1'b0;//讀 rd_en=1'b1; #200 wr_en=1'b1;//寫 rd_en=1'b0; end always #10 clk = ~clk; always #20 din = din + 1'b1; fifo_ip0 t2(.clk(clk), .srst(srst), .din(din), .wr_en(wr_en), .rd_en(rd_en), .dout(dout), .full(full), .empty(empty)); endmodule
srst訊號有效時,在下一個上升沿來臨時empty拉高,上圖中在srst訊號無效時開始寫入,寫入的資料為0,3,4....17;
srst有效期間,不管是寫入還是讀取狀態,fifo的輸入輸出都是0;上圖可見在din1為63時進行讀取操作,所讀出的數為0,且empty為1;
繼續寫入,寫到87時,full拉高;
(3)帶輸出標誌位valid和almost full、almost empty
almost_full總是比full提前一個週期拉高,它拉高表明還可以進行一次寫入操作;同時在srst有效的情況下,almost_empty和empty同時拉高;
almost_empty和empty在fifo為空時是同時為1的;valid訊號在讀使能有效的第1個上升沿拉高,在寫入的第1個上升沿到來時置零;
(4)FWFT首字預現fifo
在srst有效時,valid置零;在寫使能有效的第3個上升沿到來時拉高,在讀使能有效之前且empty不為零就已經處於拉高狀態;
寫使能只存在2個週期,寫入了0和3;valid在90ns拉高,在empty拉高的同時,valid置零;可以說明,在FWFT fifo中valid不能作為資料的輸出標誌位!!
(5)加入輸出快取暫存器,增加一級延時
在讀訊號的時鐘第2個上升沿到來時才開始讀出資料,同時valid拉高;
(6)FWFT+輸出快取暫存器
對FWFT模式的FIFO,加入暫存器對輸出並沒有增加1個週期的延時,但是對full和almost_full訊號有延時,實際上是FWFT模式相對於標準模式分別增加了兩個讀深度和寫深度;