FIFO 是FPGA設計中最有用的模塊之一。FIFO 在模塊之間提供簡單的握手和同步機制,是設計人員將數據從一個模塊傳輸到另一個模塊的常用選擇。
在這篇文章中,展示了一個簡單的 RTL 同步 FIFO,可以直接在自己的設計中配置和使用它,該設計是完全可綜合的。
那么,為什么呢?網上有很多關于 FIFO 的 Verilog/VHDL 代碼的資源,過去,我自己也使用過其中的一些。但令人沮喪的是,它們中的大多數都存在問題,尤其是在上溢出和下溢出條件下。所以想一勞永逸地解決這些問題。
/*===============================================================================================================================
???Design???????:?Single-clock?Synchronous?FIFO
???Description??:?Fully?synthesisable,?configurable?Single-clock?Synchronous?FIFO?based?on?registers.
??????????????????-?Configurable?Data?width.
??????????????????-?Configurable?Depth.
??????????????????-?Configurable?Almost-full?and?Almost-empty?signals.?
===============================================================================================================================*/
module?my_fifo?#(
???????????????????parameter?DATA_W???????????=?4??????,????????//?Data?width
???????????????????parameter?DEPTH????????????=?8??????,????????//?Depth?of?FIFO???????????????????
???????????????????parameter?UPP_TH???????????=?4??????,????????//?Upper?threshold?to?generate?Almost-full
???????????????????parameter?LOW_TH???????????=?2???????????????//?Lower?threshold?to?generate?Almost-empty
????????????????)
????????????????(
???????????????????input???????????????????clk?????????,????????//?Clock
???????????????????input???????????????????rstn????????,????????//?Active-low?Synchronous?Reset
???????????????????
???????????????????input???????????????????i_wren??????,????????//?Write?Enable
???????????????????input??[DATA_W?-?1?:?0]?i_wrdata????,????????//?Write-data
???????????????????output??????????????????o_alm_full??,????????//?Almost-full?signal
???????????????????output??????????????????o_full??????,????????//?Full?signal
???????????????????input???????????????????i_rden??????,????????//?Read?Enable
???????????????????output?[DATA_W?-?1?:?0]?o_rddata????,????????//?Read-data
???????????????????output??????????????????o_alm_empty?,????????//?Almost-empty?signal
???????????????????output??????????????????o_empty??????????????//?Empty?signal
????????????????);
/*-------------------------------------------------------------------------------------------------------------------------------
???Internal?Registers/Signals
-------------------------------------------------------------------------------------------------------------------------------*/
logic?[DATA_W?-?1????????:?0]?data_rg?[DEPTH]?;????????//?Data?array
logic?[$clog2(DEPTH)?-?1?:?0]?wrptr_rg????????;????????//?Write?pointer
logic?[$clog2(DEPTH)?-?1?:?0]?rdptr_rg????????;????????//?Read?pointer
logic?[$clog2(DEPTH)?????:?0]?dcount_rg???????;????????//?Data?counter
??????
logic?????????????????????????wren_s??????????;????????//?Write?Enable?signal?generated?iff?FIFO?is?not?full
logic?????????????????????????rden_s??????????;????????//?Read?Enable?signal?generated?iff?FIFO?is?not?empty
logic?????????????????????????full_s??????????;????????//?Full?signal
logic?????????????????????????empty_s?????????;????????//?Empty?signal
/*-------------------------------------------------------------------------------------------------------------------------------
???Synchronous?logic?to?write?to?and?read?from?FIFO
-------------------------------------------------------------------------------------------------------------------------------*/
always?@?(posedge?clk)?begin
???if?(!rstn)?begin?????
??????????
??????data_rg???<=?'{default:?'0}?;
??????wrptr_rg??<=?0??????????????;
??????rdptr_rg??<=?0??????????????;??????
??????dcount_rg?<=?0??????????????;
???end
???else?begin
??????ready_rg?<=?1'b1?;
??????
??????/*?FIFO?write?logic?*/????????????
??????if?(wren_s)?begin??????????????????????????
?????????
?????????data_rg?[wrptr_rg]?<=?i_wrdata?;????????//?Data?written?to?FIFO
?????????if?(wrptr_rg?==?DEPTH?-?1)?begin
????????????wrptr_rg?<=?0???????????????;????????//?Reset?write?pointer??
?????????end
?????????else?begin
????????????wrptr_rg?<=?wrptr_rg?+?1????;????????//?Increment?write?pointer????????????
?????????end
??????end
??????/*?FIFO?read?logic?*/
??????if?(rden_s)?begin?????????
?????????if?(rdptr_rg?==?DEPTH?-?1)?begin
????????????rdptr_rg?<=?0???????????????;????????//?Reset?read?pointer
?????????end
?????????else?begin
????????????rdptr_rg?<=?rdptr_rg?+?1????;????????//?Increment?read?pointer????????????
?????????end
??????end
??????/*?FIFO?data?counter?update?logic?*/
??????if?(wren_s?&&?!rden_s)?begin???????????????//?Write?operation
?????????dcount_rg?<=?dcount_rg?+?1?;
??????end????????????????????
??????else?if?(!wren_s?&&?rden_s)?begin??????????//?Read?operation
?????????dcount_rg?<=?dcount_rg?-?1?;?????????
??????end
???end
end
/*-------------------------------------------------------------------------------------------------------------------------------
???Continuous?Assignments
-------------------------------------------------------------------------------------------------------------------------------*/
//?Full?and?Empty?internal
assign?full_s??????=?(dcount_rg?==?DEPTH)???1'b1?:?0?;
assign?empty_s?????=?(dcount_rg?==?0????)???1'b1?:?0?;
//?Write?and?Read?Enables?internal
assign?wren_s??????=?i_wren?&?!full_s????????????????;??
assign?rden_s??????=?i_rden?&?!empty_s???????????????;
//?Full?and?Empty?to?output
assign?o_full??????=?full_s??????????????????????????;
assign?o_empty?????=?empty_s?????????????????????????;
//?Almost-full?and?Almost?Empty?to?output
assign?o_alm_full??=?(dcount_rg?>?UPP_TH)???1'b1?:?0?;
assign?o_alm_empty?=?(dcount_rg?'b1?:?0?;
//?Read-data?to?output
assign?o_rddata????=?data_rg?[rdptr_rg]??????????????;???
endmodule
/*=============================================================================================================================*/
在上面的步驟中,我們看到了一個基于寄存器的同步FIFO。接下來,我們來看看基于 RAM 的 FIFO。該 FIFO 在 RAM 而不是寄存器上實現其數據陣列。這適用于在硬件上實現大型 FIFO ;特別是在 FPGA 上,FPGA 里有大量的Block RAM 可用。這將降低資源利用率,也可以獲得更好的時序性能。
詳細代碼:
?https://github.com/iammituraj/FIFOs
?
END
往期精選?
?
?

FPGA技術江湖廣發江湖帖
無廣告純凈模式,給技術交流一片凈土,從初學小白到行業精英業界大佬等,從軍工領域到民用企業等,從通信、圖像處理到人工智能等各個方向應有盡有,QQ微信雙選,FPGA技術江湖打造最純凈最專業的技術交流學習平臺。
FPGA技術江湖微信交流群

加群主微信,備注姓名+公司/學校+崗位/專業進群
FPGA技術江湖QQ交流群

備注姓名+公司/學校+崗位/專業進群
