FIFO 是FPGA設(shè)計中最有用的模塊之一。FIFO 在模塊之間提供簡單的握手和同步機(jī)制,是設(shè)計人員將數(shù)據(jù)從一個模塊傳輸?shù)搅硪粋€模塊的常用選擇。
在這篇文章中,展示了一個簡單的 RTL 同步 FIFO,可以直接在自己的設(shè)計中配置和使用它,該設(shè)計是完全可綜合的。
為什么要自己設(shè)計FIFO
那么,為什么呢?網(wǎng)上有很多關(guān)于 FIFO 的 Verilog/VHDL 代碼的資源,過去,我自己也使用過其中的一些。但令人沮喪的是,它們中的大多數(shù)都存在問題,尤其是在上溢出和下溢出條件下。所以想一勞永逸地解決這些問題。
FIFO 規(guī)格性能
同步,單時鐘。
基于寄存器的 FIFO,適用于中小型 FIFO。
Full、Empty、Almost-full、Almost-empty 標(biāo)志。
完全可配置的數(shù)據(jù)寬度、深度和標(biāo)志。
完全可綜合的系統(tǒng) Verilog 代碼。
/*=============================================================================================================================== Design:Single-clockSynchronousFIFO Description:Fullysynthesisable,configurableSingle-clockSynchronousFIFObasedonregisters. -ConfigurableDatawidth. -ConfigurableDepth. -ConfigurableAlmost-fullandAlmost-emptysignals. ===============================================================================================================================*/ modulemy_fifo#( parameterDATA_W=4,//Datawidth parameterDEPTH=8,//DepthofFIFO parameterUPP_TH=4,//UpperthresholdtogenerateAlmost-full parameterLOW_TH=2//LowerthresholdtogenerateAlmost-empty ) ( inputclk,//Clock inputrstn,//Active-lowSynchronousReset inputi_wren,//WriteEnable input[DATA_W-1:0]i_wrdata,//Write-data outputo_alm_full,//Almost-fullsignal outputo_full,//Fullsignal inputi_rden,//ReadEnable output[DATA_W-1:0]o_rddata,//Read-data outputo_alm_empty,//Almost-emptysignal outputo_empty//Emptysignal ); /*------------------------------------------------------------------------------------------------------------------------------- InternalRegisters/Signals -------------------------------------------------------------------------------------------------------------------------------*/ logic[DATA_W-1:0]data_rg[DEPTH];//Dataarray logic[$clog2(DEPTH)-1:0]wrptr_rg;//Writepointer logic[$clog2(DEPTH)-1:0]rdptr_rg;//Readpointer logic[$clog2(DEPTH):0]dcount_rg;//Datacounter logicwren_s;//WriteEnablesignalgeneratediffFIFOisnotfull logicrden_s;//ReadEnablesignalgeneratediffFIFOisnotempty logicfull_s;//Fullsignal logicempty_s;//Emptysignal /*------------------------------------------------------------------------------------------------------------------------------- SynchronouslogictowritetoandreadfromFIFO -------------------------------------------------------------------------------------------------------------------------------*/ always@(posedgeclk)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; assigno_alm_empty=(dcount_rg
基于 RAM 的 FIFO
在上面的步驟中,我們看到了一個基于寄存器的同步FIFO。接下來,我們來看看基于 RAM 的 FIFO。該 FIFO 在 RAM 而不是寄存器上實現(xiàn)其數(shù)據(jù)陣列。這適用于在硬件上實現(xiàn)大型 FIFO ;特別是在 FPGA 上,F(xiàn)PGA 里有大量的Block RAM 可用。這將降低資源利用率,也可以獲得更好的時序性能。
詳細(xì)代碼:
?
https://github.com/iammituraj/FIFOs
責(zé)任編輯:彭菁
-
寄存器
+關(guān)注
關(guān)注
31文章
5336瀏覽量
120228 -
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7002瀏覽量
88938 -
fifo
+關(guān)注
關(guān)注
3文章
387瀏覽量
43646
原文標(biāo)題:【手撕代碼】同步 FIFO、LIFO/Stack
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論