先進(jìn)先出緩存電路FIFO在大規(guī)模邏輯設(shè)計(jì)當(dāng)中,得到普遍地使用。幾乎每個(gè)芯片都會(huì)涉 及到它。也就是說(shuō)每個(gè)大規(guī)模邏輯設(shè)計(jì)者都必須掌握該種電路的設(shè)計(jì)方法。但在實(shí)際應(yīng) 用中,F(xiàn)IFO的類型又不盡相同。有的電路需要的是同步FIFO(即:讀寫時(shí)鐘為同一個(gè)時(shí) 鐘),有的需要異步FIFO(即:讀寫時(shí)鐘的頻率或相位不一樣),有的電路對(duì)FIFO的速 度要求不高,有的則需要高速FIFO(比如工作頻率在100MHz以上)。同時(shí)具體電路對(duì)FI FO的空滿標(biāo)志的產(chǎn)生也有一定的要求,有按一個(gè)深度進(jìn)行讀寫的,也有連續(xù)讀寫一塊的 (Burst read/write),有讀寫位寬一致的(256深×80bit <==> 256深×80bit,也有讀 寫位寬是倍數(shù)關(guān)系的(256深×80bit<==>1024深×20bit)。異步FIFO的讀寫地址轉(zhuǎn)變?yōu)? 格雷碼再進(jìn)行比較,產(chǎn)生空滿標(biāo)志,從而保證電路的可靠性。 XILINX的Coregen軟件可以生成一些通用的同步和異步FIFO,如果它不能滿足你的特定要 求,只好你自己動(dòng)手了!不管是什么類型的FIFO,其關(guān)鍵點(diǎn)是產(chǎn)生讀、寫地址和空、滿 標(biāo)志。好的FIFO設(shè)計(jì)的基本要求是: 寫滿而不溢出; 讀空又不多讀。 同步FIFO的設(shè)計(jì) 同步FIFO的讀寫時(shí)鐘為相同的一個(gè),所以讀寫地址是同步的。通過(guò)判斷FIFO中已經(jīng)存在 多少個(gè)沒有被讀走的數(shù)據(jù)Cnt_fifo,來(lái)判斷讀空了,還是寫滿了。Cnt_fifo的產(chǎn)生:當(dāng) FIFO進(jìn)行讀但不寫時(shí),自增加1,當(dāng)FIFO進(jìn)行寫但不讀時(shí),自減1,如果FIFO又讀又寫或 不讀也不寫,則該計(jì)數(shù)器不變。 滿標(biāo)志的產(chǎn)生:復(fù)位時(shí),F(xiàn)ull信號(hào)初始化為1,表示FIFO滿;如果FIFO不讀,并且Cnt_f ifo等于FIFO的深度Deepth_fifo時(shí),或者Cnt_fifo等于(Deepth_fifo-1),并且正在寫( 即寫使能Write_enble有效)時(shí),滿標(biāo)志應(yīng)該置1;其余情況置為0。 空標(biāo)志的產(chǎn)生:復(fù)位時(shí),讓Empty信號(hào)為1,表示FIFO空;當(dāng)FIFO中的Cnt_fifo等于0或者 等于1并且正在讀FIFO時(shí),Empty就應(yīng)置1,表示讀空了;其余情況則不空。置為0。 幾乎空Almost_empty和幾乎滿Almost_full標(biāo)志的產(chǎn)生:在實(shí)際應(yīng)用中為了便于正確產(chǎn)生 讀寫使能,避免多讀和寫溢出,經(jīng)常使用幾乎空和幾乎滿標(biāo)志,來(lái)提前預(yù)告FIFO的狀態(tài) 。要求FIFO還剩下可編程數(shù)量Cnt_empty的數(shù)據(jù)沒讀走時(shí),就報(bào)告幾乎空,但是仍允許讀 走幾個(gè)?;蛘邔懭隖IFO的數(shù)據(jù)個(gè)數(shù)超過(guò)可編程數(shù)量Cnt_full的時(shí)候,就報(bào)告幾乎滿,但 仍允許寫入幾個(gè)數(shù)據(jù)。也就是說(shuō)當(dāng)Cnt_fifo>Cnt_full時(shí),F(xiàn)IFO就要置Almost_full為1, 表示幾乎空了。當(dāng)Cnt_fifo<Cnt_empty時(shí),F(xiàn)IFO就要置Almost_empty為1,表示幾乎滿了 。 讀寫FIFO的使能的產(chǎn)生:為了確保FIFO即不多讀又不多寫,采用了自我保護(hù)方式,即: 真正的寫FIFO使能為外部的寫使能和FIFO不滿的組合; (assign Write_allow = Write_enable && ! Full ;) 真正的讀FIFO使能為外部的讀使能和非空的組合; (assign Read_allow = Read_enable && ! Empty ; )。 FIFO的讀寫地址產(chǎn)生比較簡(jiǎn)單,當(dāng)讀使能有效時(shí),在時(shí)鐘作用下,讀地址加1;當(dāng)寫使能 有效時(shí),寫地址加1。 當(dāng)FIFO深度較大時(shí),同時(shí)FIFO的速度要求較高時(shí),可以采用線性反饋移位計(jì)數(shù)器(LFSR )。它的速度非常快,但是要犧牲一個(gè)地址。 異步FIFO的設(shè)計(jì) 所謂異步是指讀、寫時(shí)鐘是完全獨(dú)立并且不一致的,或者不同頻率,或者同頻但不同相 。讀地址和空標(biāo)志是由讀時(shí)鐘產(chǎn)生的,而寫地址和滿標(biāo)志則由寫時(shí)鐘產(chǎn)生,當(dāng)要產(chǎn)生FI FO的空、滿標(biāo)志時(shí),必須進(jìn)行讀寫地址的比較時(shí),問題就來(lái)臨了。如果直接采樣地址比 較的話,地址線一般有多位,寫地址的每一位在寫時(shí)鐘作用下,跳變得不一致,即產(chǎn)生 毛刺,要過(guò)一小段時(shí)間才能穩(wěn)定。在未穩(wěn)定期內(nèi),剛好讀時(shí)鐘進(jìn)行采樣寫地址,這時(shí)就 出現(xiàn)誤判斷,邏輯錯(cuò)誤。同時(shí)采樣讀寫地址相差N個(gè)來(lái)產(chǎn)生空滿信號(hào),時(shí)間上會(huì)多一些, 因?yàn)樯婕凹雍蜏p操作。 為避免地址跳變的不一致造成讀寫地址誤判斷,通常采用格雷碼。此外,還要根據(jù)實(shí)際 情況的具體要求采用不同的解決辦法,如: 1、加入一個(gè)高速時(shí)鐘,使讀寫時(shí)鐘頻差在4倍以上; 2、在需要對(duì)FIFO包尾進(jìn)行特殊處理,必須把包尾讀出FIFO的情況下,可在異步FIFO后在 加上一個(gè)小同步FIFO; 3、還可以通過(guò)FIFO備份,讀寫操作在兩個(gè)FIFO間按包切換等; 4、還可以強(qiáng)制讀寫指針在讀完一個(gè)包和寫完一個(gè)包時(shí)跳變加上一個(gè)恒值。 5、請(qǐng)參閱第1章“跨越異步時(shí)鐘邊界傳輸數(shù)據(jù)的解決方案”部分的內(nèi)容。 格雷碼的優(yōu)點(diǎn)是相鄰兩值只有一位跳變,其他不變,這樣地址變化的時(shí)間較短,極大提 高比較精度。 格雷碼的時(shí)序 格雷碼是不能進(jìn)行加減產(chǎn)生空滿標(biāo)志的,那怎么辦?采樣延時(shí)一拍的方法。用讀地址Rd _addr產(chǎn)生讀地址的格雷碼Rd_next_gray_addr,將Rd_next_gray_addr延一拍得到Rd_gr ay_addr,再將Rd_gray_addr延一拍得到Rd_last_gray_addr。你會(huì)發(fā)現(xiàn)在絕對(duì)時(shí)間上, Rd_next_gray_addr、Rd_gray_addr、Rd_last_gray_addr這個(gè)地址有先后關(guān)系,從大到 小排列,并且相差1。如圖1所示。 寫地址的格雷碼的產(chǎn)生也類似。即: Wt_next_gray_addr、Wt_gray_addr、Wt_last_gr ay_addr。利用這6個(gè)格雷碼進(jìn)行比較,同時(shí)加上讀寫使能,就能等待空和滿標(biāo)志。 先說(shuō)空標(biāo)志Empty吧!當(dāng)讀寫格雷碼地址相等(Rd_gray_addr = = Wt_gray_addr)或者 FIFO內(nèi)還剩下一個(gè)深度的字(Rd_next_gray_addr = = Wt_gray_addr),并且正在不空 的情況下執(zhí)行讀操作(Read_enable = = 1),這時(shí)Empty標(biāo)志應(yīng)該置為有效(高電平有 效)。 滿標(biāo)志Full:當(dāng)寫FIFO的格雷碼地址等于上次讀的格雷碼地址時(shí)(Wt_gray_addr= = Rd _last_gray_addr),或者下次要寫的格雷碼地址等于上次讀的格雷碼地址(Wt_next_g ray_addr= = Rd_last_gray_addr),并且正在執(zhí)行寫操作。此時(shí)需要置Full標(biāo)志有效。 如果要產(chǎn)生幾乎空、幾乎滿標(biāo)志時(shí),可以多做幾個(gè)格雷碼的延時(shí)地址,利用這些讀、寫 格雷碼地址距離遠(yuǎn)近關(guān)系就可以靈活的產(chǎn)生特定讀寫地址間距的幾乎空或幾乎滿標(biāo)志。 如果需要在大間距內(nèi)時(shí),產(chǎn)生幾乎空滿信號(hào)(比如讀寫地址相差10),那必須采用另外 一種方法:以幾乎空為例。當(dāng)(讀地址-10)的格雷碼等于寫地址的格雷碼時(shí),幾乎空 信號(hào)可以置位了。 讀寫地址的產(chǎn)生:如果外部寫使能(Write_enable)來(lái)了,同時(shí)FIFO的不滿的話,寫地 址自增1;如果讀使能(Read_enable)有效,同時(shí)FIFO不空的話,讀地址自增1。在進(jìn)行 地址的遞增時(shí)判斷FIFO的空滿標(biāo)志是為了自我保護(hù),避免讀寫地址交錯(cuò),產(chǎn)生錯(cuò)誤邏輯 。 位寬變換FIFO 實(shí)際應(yīng)用中,需要進(jìn)行數(shù)據(jù)位寬的變換,比如輸入1024×16bit的數(shù)據(jù),輸出256×64bi t的數(shù)據(jù)。或者顛倒過(guò)來(lái)。如圖2所示。 FIFO的位寬的轉(zhuǎn)換 在我們的FIFO中使用到了雙端口RAM,它可以同時(shí)進(jìn)行讀和寫操作。就以輸入1024×16b it的數(shù)據(jù),輸出256×64bit數(shù)據(jù)的FIFO為例說(shuō)明,其他情況一樣。 顯然我們需要一個(gè)256×64bit的雙端口RAM。讀地址(Wt_addr[7:0])比較好辦,該地址 就是FIFO的深度。但是寫地址(Rd_addr[9:0])就要分為兩個(gè)部分,一個(gè)是與FIFO的深 度對(duì)應(yīng)的地址(Rd_addr[9:2]),另一個(gè)是位寬方向的地址(Rd_addr[1:0])。因?yàn)?個(gè) 寫地址才對(duì)應(yīng)一個(gè)讀地址。比較寫地址和讀地址的高8位就可以產(chǎn)生空、滿標(biāo)志(與前面 的FIFO類似)。 經(jīng)常與包打交道時(shí),包有包頭,有包尾。當(dāng)讀到包尾時(shí),不僅讀地址的低2位要變,高8 位也要變,要跳躍到下一個(gè)包的包頭。而包尾在4個(gè)地址中的位置,決定了讀地址的跳變 方式。 按塊操作的FIFO 實(shí)際應(yīng)用中,有執(zhí)行突發(fā)性(burst)的連續(xù)讀、寫N個(gè)深度的FIFO。也就是說(shuō)對(duì)FIFO要 按照塊操作。說(shuō)白了也就是分為高低地址。高地址為塊號(hào),低地址為塊內(nèi)的地址。FIFO 的空滿標(biāo)志有讀寫的高位地址比較產(chǎn)生。 |
|
來(lái)自: zhangquanling > 《FPGA_混飯吃的》