介紹
無論何時,在復雜的 FPGA 設計過程中,都不可避免地需要在模塊之間發送數據,實現這一點的常用的是 FIFO。
FIFO
寫入:當寫入 FIFO 時,需要確保不要寫入太多數據以致 FIFO 溢出。為了幫助解決這個問題,FIFO 通常有一個完整的計數標志,有時還可以使用一個watermark端口。
watermark:本質上告訴 FIFO 中的項目何時超過一定數量,這時候應該放慢速度或不放入數據。但如果想發送特定數量的數據,將需要添加額外的步驟在狀態機中管理“above watermark”的情況。在狀態機上工作時,可能需要添加狀態和寄存器來管理邊緣情況(空滿情況)。
full flag:比較棘手的信號,因為 full flag 可能會在輸入數據的同一時鐘變高。如果有流水線設計,則需要在檢測到“full”狀態時緩沖這些數據。
count:計數可以大致了解可以進入 FIFO 的數據量。計數的更新比watermark和full flag慢,并且會給你一個保守的 FIFO 內的空間計數。我很想經常使用它,但我發現我需要在狀態機中添加一些狀態來管理它。
Reading:從 FIFO 讀取通常不會那么糟糕,只要在空標志不置位時不讀取即可。
Double Buffer
我師傅讓我考慮使用雙端口block-ram 作為雙緩沖器。就像 FIFO 一樣,類似具有如下行為的讀取器和寫入器:
寫入器:將數據寫入block-ram,然后使用跨時鐘域技術將數據的大小和狀態發送給讀取器。
讀取器:讀取寫入器放入 RAM 的已知數據量。
這種方法的好處在于,寫入器知道它可以寫入多少空間,而讀取器知道它可以讀取多少數據。這非常適合流水線設計。另一個方面是寫入器可以在讀取器讀取數據時開始處理block-ram 的后半部分。不過,這種方法并不是自由操作。以下是現在需要由寫入器和讀取器管理的一些事情:
寫入器
ram中有多少空間(或ram的一半)
開始/結束地址指針
寫入了多少數據
讀取器
有多少數據可供讀取
開始/結束地址指針
我喜歡這種雙緩沖區給我的數據量的預知。這允許我編寫內核,將已知數量的數據從雙緩沖區的輸出轉儲到另一個位置,如音頻或視頻緩沖區。不幸的是,每個使用雙緩沖器的模塊都必須設計為能夠處理上述所有問題以及更多的跨時鐘域標志。
如果不需要擔心 FIFO(滿/空)的邊緣情況,這將是最容易使用的機制。下面將這兩種機制結合起來可能是最佳方案。
Ping Pong FIFO
Ping Pong FIFO 本質上是一個上面描述的雙緩沖區,包裹起來看起來像一個 FIFO。所有地址指針和跨時鐘域通信都包含在一個簡單的模塊中。模塊如下所示:
modulePPFIFO #(parameterDATA_WIDTH=8, ADDRESS_WIDTH=4 )( //universalinput inputreset, //writeside inputwrite_clock, outputreg[1:0]write_ready, input[1:0]write_activate, output[23:0]write_fifo_size, inputwrite_strobe, input[DATA_WIDTH-1:0]write_data, outputstarved, //readside inputread_clock, inputread_strobe, outputregread_ready, inputread_activate, outputreg[23:0]read_count, output[DATA_WIDTH-1:0]read_data, outputinactive );
有單獨的寫入端和讀取端時鐘,選通用于寫入和讀取數據。不過也有一些新的信號:
write_ready:這與雙緩沖區有關,需要管理緩沖區的兩側。這2 bit信號告訴雙緩沖區的哪一側已準備好。
0:緩沖區的下半部分準備好
1:上半部分準備好
write_activate:用戶告訴 Ping Pong FIFO 它想要擁有緩沖區的一側
write_fifo_size:表示用戶可以寫入 Ping Pong FIFO(PPFIFO) 的字數。
注意:不需要在完成之前填充寫入端,PPFIFO 將跟蹤寫入的元素數量并將此信息發送到讀取端,作為將遞增數字模式寫入 PPFIFO 的簡單模塊示例
/*Module:ppfifo_source * *Description:PopulateaPingPongFIFOwithanincrementingnumberpattern */ moduleppfifo_source#( parameterDATA_WIDTH=8 )( inputclk, inputrst, inputi_enable, //PingPongFIFOInterface input[1:0]i_wr_rdy, outputreg[1:0]o_wr_act, input[23:0]i_wr_size, outputrego_wr_stb, outputreg[DATA_WIDTH-1:0]o_wr_data ); //LocalParameters //Registers/Wires reg[23:0]r_count; //Submodules //AsynchronousLogic //SynchronousLogic always@(posedgeclk)begin //De-assertStrobes o_wr_stb<=?0; ??if?(rst)?begin ????o_wr_act????????<=??0; ????o_wr_stb????????<=??0; ????o_wr_data???????<=??0; ????r_count?????????<=??0; ??end ??else?begin ????if?(i_enable)?begin ??????if?((i_wr_rdy?>0)&&(o_wr_act==0))begin r_count<=??0; ????????if?(i_wr_rdy[0])?begin ??????????//Channel?0?is?open ??????????o_wr_act[0]??<=??1; ????????end ????????else?begin ??????????//Channel?1?is?open ??????????o_wr_act[1]??<=??1; ????????end ??????end ??????else?if?(o_wr_act?>0)begin if(r_count
正如所看到的,通過添加一個額外的寄存器來跟蹤添加到 PPFIFO 的數據量,不必擔心full flags、water marks 或者counts。
閱讀方面更容易。PPFIFO 知道首先寫入哪個緩沖區,因此用戶只需要觀察一個read_ready標志,然后使用read_activate告訴它我們有控制權。以下是從 PPFIFO 讀取數據的示例:
這里有更具體的細節:
用戶監視“read_ready”位:當“read_ready”信號為 1 時,ppfifo 為用戶準備好一個數據塊。
用戶使用“read_activate”信號激活該塊并使用“read_strobe”讀取 NEXT 數據
“read_count”是緩沖區中數據元素的總數。
用戶必須在將“read_activate”設置為低之前讀取所有數據
/*Module:ppfifo_sink * *Description:WheneverdataisavailablewithintheFIFOactivateitandreaditall */ moduleppfifo_sink#( parameterDATA_WIDTH=8 )( inputclk, inputrst, //PingPongFIFOInterface inputi_rd_rdy, outputrego_rd_act, input[23:0]i_rd_size, outputrego_rd_stb, input[DATA_WIDTH-1:0]i_rd_data ); //LocalParameters //Registers/Wires reg[23:0]r_count; //Submodules //AsynchronousLogic //SynchronousLogic always@(posedgeclk)begin //De-AssertStrobes o_rd_stb<=??0; ??if?(rst)?begin ????o_rd_act??????????<=??0; ????r_count???????????<=??0; ????o_rd_stb??????????<=??0; ??end ??else?begin ????if?(i_rd_rdy?&&?!o_rd_act)?begin ??????r_count?????????<=??0; ??????o_rd_act????????<=??1; ????end ????else?if?(o_rd_act)?begin ??????if?(r_count?
下面設計一個簡單的測試模塊來演示 Ping Pong FIFO。
源代碼地址:
https://github.com/CospanDesign/verilog_ppfifo_demo
下面是幾個簡單模擬的截圖:
在讀事務開始和下一個寫事務開始時放大仿真區域:
在讀取事務之間放大
半放大
截圖可能不清晰,建議自己仿真。
總結
PPFIFO除了上面用于解決FIFO的“痛處”外,常見的還是處理高速數據流處理,下面是一個10M數據流分成兩個5M數據流的例子。
審核編輯:彭靜
-
FPGA
+關注
關注
1630文章
21759瀏覽量
604302 -
FPGA設計
+關注
關注
9文章
428瀏覽量
26553 -
數據
+關注
關注
8文章
7081瀏覽量
89188 -
fifo
+關注
關注
3文章
389瀏覽量
43743
原文標題:乒乓操作實例講解-FIFO
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論