上一篇介紹了利用Flip Flop來(lái)作為存儲(chǔ)單元的同步FIFO設(shè)計(jì)。這一篇咱們來(lái)看如何利用2 Port SRAM來(lái)作為存儲(chǔ)單元設(shè)計(jì)同步FIFO。
開始往下讀之前,老李先問(wèn)一個(gè)問(wèn)題,假如現(xiàn)在讓你設(shè)計(jì)一個(gè)深度為N的基于2port SRAM的同步FIFO,請(qǐng)問(wèn)至少需要多大的SRAM? 假設(shè)SRAM的位寬就是你的數(shù)據(jù)寬度,那么問(wèn)題就是問(wèn)你需要的SRAM的行數(shù)至少是多少?如果你覺(jué)得答案是顯而易見的N,那么你值得讀完這一篇。
首先來(lái)說(shuō)為什么要用SRAM設(shè)計(jì)FIFO,很簡(jiǎn)單為了省面積。我們說(shuō)存1bit的數(shù)據(jù),SRAM里一個(gè)bit cell經(jīng)典結(jié)構(gòu)是6個(gè)晶體管,而一個(gè)flip flop需要的晶體管在20個(gè)左右,那么從面積上來(lái)說(shuō),肯定是SRAM小對(duì)吧?但是這里面有個(gè)平衡點(diǎn),對(duì)于一塊SRAM,算面積的時(shí)候不能僅僅算里面存儲(chǔ)單元bit cell的面積,還要算外圍的decode邏輯的面積。當(dāng)SRAM的row size x column size比較小的時(shí)候,外圍的decode邏輯占的比重比較大,反而這個(gè)時(shí)候SRAM的總面積不如row x column個(gè)flop的面積小。至于這個(gè)轉(zhuǎn)折點(diǎn)要看工藝和memory compiler的data sheet,具體面積要拿SRAM的data sheet去比較。老李自己總結(jié)的一個(gè)經(jīng)驗(yàn),不保證完全準(zhǔn)確,在5nm工藝下,這個(gè)轉(zhuǎn)折點(diǎn)大概在2k bit,低于2k bit,比如16x32的大小,那還是Flop劃算,如果遠(yuǎn)大于2k bit,那么就用SRAM,差不多在2-3k bit量級(jí)的時(shí)候要根據(jù)memory datasheet里的area number來(lái)比較。
再來(lái)說(shuō)說(shuō)什么是2 port SRAM,2 port 通常也被稱作dual port,一個(gè)端口為寫端口,一個(gè)端口為讀端口。這兩個(gè)端口可以同時(shí)工作,同一個(gè)周期內(nèi)既可以讀,也可以寫,簡(jiǎn)化的框圖如下圖所示
WCEN:Write Chip Enable Neg,當(dāng)這個(gè)信號(hào)為0的時(shí)候,要寫入數(shù)據(jù)
WDATA: 要寫入的數(shù)據(jù)
WADDR:要寫入的地址
RCEN:Read Chip Enable Neg,當(dāng)這個(gè) 信號(hào)為0的時(shí)候,要讀出數(shù)據(jù)
RDATA: 讀出的數(shù)據(jù)
RADDR: 讀出的地址
這里要注意,要寫入的數(shù)據(jù)是指WCEN為0那個(gè)周期的WDATA,而讀出的數(shù)據(jù)并不是RCEN為0那個(gè)周期的RDATA,而是下一個(gè)周期的RDATA。
時(shí)序圖如下圖所示
可以看到,cycle 1進(jìn)行寫操作,在地址A0寫入數(shù)據(jù)D0。在cycle 2進(jìn)行讀操作,要在cycle 3才能讀出D0。那你一定好奇如果給同一個(gè)地址在同一個(gè)周期又讀又寫怎么辦呢?這個(gè)不同的foundary的sram可以有不同的實(shí)現(xiàn),這里表示的是一個(gè)較為常見的實(shí)現(xiàn),看cycle 7,讀寫同時(shí)發(fā)生并且在同一個(gè)地址,在cycle 8讀出的還是之前寫入在這個(gè)地址的數(shù)據(jù)D0,而不是cycle 7寫入的新數(shù)據(jù)D1。只有再讀一次A0,你才能看到D1。
下面我們來(lái)考慮如何設(shè)計(jì)基于2port SRAM的同步FIFO。既然FIFO有push和pop端,也有wdata和rdata,那剛好對(duì)應(yīng)SRAM的write port和read port,看起來(lái)我們大概只需要直接把SRAM包起來(lái),用兩個(gè)計(jì)數(shù)器來(lái)分別計(jì)算write pointer和read pointer就可以了,如下圖所示
真的這么簡(jiǎn)單嗎?我們來(lái)思考一個(gè)問(wèn)題,用上面的FIFO來(lái)存第一個(gè)數(shù)D0,利用上面的結(jié)構(gòu),q能夠在push的下一個(gè)周期變?yōu)镈0嗎?
回顧一下我們想要的FIFO的時(shí)序
在cycle1的時(shí)候我們push D0,我們期望Q在cycle 2的時(shí)候就可以輸出FIFO最頭上的數(shù)D0,而且注意,這個(gè)時(shí)候我們并沒(méi)有進(jìn)行pop操作。
可是從上面SRAM的時(shí)序圖我們可以看到,要想讓RDATA輸出D0,我們至少要讓RCEN為0一個(gè)周期,而且RCEN為0必須得在WCEN為0之后,讓RDATA拿到D0最快也到了WCEN之后的2個(gè)周期,因而不滿足在PUSH之后下一個(gè)周期Q就輸出D0。
另外還有個(gè)問(wèn)題,當(dāng)我們push進(jìn)去一個(gè)數(shù)之后,如果這個(gè)數(shù)寫入了SRAM,那么我們必須要有一次讀SRAM的操作,才能把數(shù)讀出來(lái),這在上面的框圖里也就是要執(zhí)行一次pop。這也和FIFO的工作相背離,因?yàn)镕IFO可能并不是需要立刻pop。
那么我們?cè)趺醋霾拍茏孮在push的下一個(gè)周期輸出D0呢?環(huán)顧四周,好像除了利用Flip Flop也沒(méi)有別的辦法了。也就是說(shuō) ,第一個(gè)數(shù)我們把數(shù)不寫進(jìn)SRAM,而是寫到一個(gè)Flop里,然后讓Q從Flop輸出 。
等等,說(shuō)好了用SRAM來(lái)存數(shù)據(jù)的,怎么又把數(shù)據(jù)存到Flop里面去了呢?
別急,這里確實(shí)是沒(méi)有辦法的辦法,如果我們有可以和Flop時(shí)序一樣的SRAM,那么也可以不用這種辦法,但是在接受SRAM的時(shí)序是這樣的情況下,我們必須借助Flop來(lái)實(shí)現(xiàn)第一個(gè)數(shù)在push之后下一個(gè)周期就能夠出現(xiàn)在Q上。
當(dāng)然,我們不是說(shuō)所有的數(shù)都要用Flop來(lái)存,接下來(lái)push的數(shù)據(jù)我們還是要放在SRAM里面的,我們把上面的結(jié)構(gòu)改一改,可以先設(shè)計(jì)出下面的FIFO結(jié)構(gòu)。
在這個(gè)結(jié)構(gòu)中,我們從D可以直接把數(shù)據(jù)存到輸出級(jí)的這個(gè)Flop中,相當(dāng)于bypass了SRAM,然后我們的想法是:當(dāng)?shù)诙蝡ush的時(shí)候,我們?cè)侔褦?shù)據(jù)存到SRAM里,同時(shí),當(dāng)我們把第一個(gè)數(shù)據(jù)pop出來(lái)之后,我們就把數(shù)據(jù)從SRAM里拿到這個(gè)輸出級(jí)的Flop中,這樣是不是就對(duì)了呢?
不好意思,其實(shí)還是有問(wèn)題,我們假設(shè)FIFO里面已經(jīng)存了2個(gè)數(shù)據(jù),D0存在輸出級(jí)的Flop里,D1存在SRAM里,如下圖所示
那么當(dāng)我們要pop一次之后,我們期望的FIFO的時(shí)序是:在pop的下一個(gè)周期,Q就應(yīng)該是D1了,因?yàn)镈0被彈出,F(xiàn)IFO最頭上的數(shù)是D1了。如下圖所示
但是如果在pop為1的那個(gè)周期去讀SRAM,則要在下一個(gè)周期RDATA才能讀出D1,再還需要一個(gè)周期才能把D1存到輸出級(jí)的Flop上,也就是pop之后兩個(gè)周期才能看到D1, 這樣就不滿足FIFO的時(shí)序了。
那怎么辦呢?我們只好省去把D1從RDATA存到Flop上的那一步,而是把RDATA當(dāng)做Q來(lái)直接輸出。電路結(jié)構(gòu)變成了下面
我們的設(shè)計(jì)思路就變成了
- 往FIFO里push的第一個(gè)數(shù)要bypass SRAM,把數(shù)據(jù)直接存到輸出級(jí)Flop去。
- 如果SRAM里面存了數(shù),那么pop一次,就要把RDATA直接輸出到Q端。
看起來(lái)沒(méi)有問(wèn)題了吧?其實(shí)還有一個(gè)特殊情況沒(méi)有考慮到,也就是當(dāng)FIFO里只有一個(gè)數(shù)據(jù),而在push下一個(gè)數(shù)據(jù)的時(shí)候同時(shí)來(lái)了pop。如下圖所示
那么這個(gè)時(shí)候要push的D1是不能往SRAM里寫的,一旦寫進(jìn)去要讀出來(lái)還得多花一個(gè)周期,所以這個(gè)時(shí)候也是要bypass SRAM。
所以更加嚴(yán)謹(jǐn)?shù)臈l件是
- 往FIFO里push的第一個(gè)數(shù)要bypass SRAM, 或者FIFO里只有1個(gè)數(shù)據(jù),而且在push新數(shù)據(jù)的同時(shí)pop ,那么把數(shù)據(jù)直接存到輸出級(jí)Flop去。
- 當(dāng)FIFO里只有一個(gè)數(shù)據(jù)的時(shí)候,Q端來(lái)自于輸出級(jí)Flop
- 如果SRAM里面存了數(shù),那么pop一次,就要把RDATA直接輸出到Q端。
至此,我們利用一級(jí)flip flop來(lái)實(shí)現(xiàn)了省去一個(gè)讀SRAM的周期,可以實(shí)現(xiàn)FIFO的時(shí)序。
現(xiàn)在可以回答文章開頭的問(wèn)題了,因?yàn)橛辛溯敵黾?jí)Flop來(lái)存第一個(gè)數(shù)據(jù),那么SRAM其實(shí)并不需要存N個(gè)數(shù)據(jù),只需要存N-1個(gè)數(shù)據(jù)就好了。但是在實(shí)際工作中,Width x N 和Width x (N-1)的面積其實(shí)沒(méi)有差很多,你用Width xN的SRAM完全沒(méi)有問(wèn)題。當(dāng)然要注意,這個(gè)時(shí)候memory 的address pointer和我們上一講里的wr_ptr, rd_ptr就不是完全一樣了,因?yàn)榈谝粋€(gè)數(shù)據(jù)并不是存在SRAM里。
寫到這里,是不是就完全搞定問(wèn)題了呢?我們來(lái)分析一下,我們這樣設(shè)計(jì)可行其實(shí)是有一個(gè)前提,即SRAM的RDATA的timing是下面的。這里把開頭的圖再看一遍
我們說(shuō)FIFO的Q在不pop的時(shí)候是穩(wěn)定不變的,是利用了這里SRAM的特性,即讀完一次之后,RDATA的值會(huì)保持不變,一直到下一次讀操作(圖中的cycle 3-7),這樣我們就可以直接把RDATA輸出到Q。
但是并不是所有廠家的SRAM的時(shí)序是這樣的,大家要看廠家的memory的datasheet來(lái)確認(rèn)時(shí)序(TSMC家的是這樣的, 但是可能別的廠家并不保證)如果SRAM時(shí)序是下面這樣,那么我們的設(shè)計(jì)就不能滿足FIFO的要求了
而且上面的設(shè)計(jì)可能還有一個(gè)STA上的問(wèn)題,因?yàn)镼來(lái)自于RDATA,那么SRAM內(nèi)部的clock-to-rdata的timing可能比較大,這樣給后面FIFO輸出的Q后面所留有的空間就比較小了。如果Q之后還要做邏輯運(yùn)算,或者再下一級(jí)Flop距離比較遠(yuǎn),那么修timing的時(shí)候就比較挑戰(zhàn)。
要解決上面兩個(gè)問(wèn)題,一個(gè)必然的思路是不能直接輸出RDATA到Q,還是要把RDATA給flop住,這樣一方面使得輸出Q可以保持穩(wěn)定,另一方面,這一級(jí)flop依然在FIFO內(nèi)部,從Flop直接輸出對(duì)于FIFO后級(jí)的timing有幫助。你看,兜兜轉(zhuǎn)轉(zhuǎn),似乎還是要回到我們前面要斃掉的方案。那么我們要怎么設(shè)計(jì),才能解決前面那個(gè)方案不滿足FIFO時(shí)序要求的缺陷呢?大家可以自己先思考一下,老李下篇再帶來(lái)更深入的講解。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7157瀏覽量
89663 -
sram
+關(guān)注
關(guān)注
6文章
768瀏覽量
114904 -
fifo
+關(guān)注
關(guān)注
3文章
390瀏覽量
43882
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
同步FIFO設(shè)計(jì)詳解及代碼分享
![<b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>設(shè)計(jì)詳解及代碼分享](https://file1.elecfans.com/web2/M00/8B/7C/wKgZomSaSFKAaDpEAADEIlbq_-k385.jpg)
怎么實(shí)現(xiàn)一個(gè)同步FIFO 2點(diǎn)有兩個(gè)輸出eindpoints和兩個(gè)端點(diǎn)?
異步FIFO結(jié)構(gòu)
同步FIFO之Verilog實(shí)現(xiàn)
怎樣設(shè)計(jì)一個(gè)同步FIFO?(1)
怎樣設(shè)計(jì)一個(gè)同步FIFO?(3)
![<b class='flag-5'>怎樣</b>設(shè)計(jì)<b class='flag-5'>一</b><b class='flag-5'>個(gè)</b><b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>?(3)](https://file.elecfans.com/web2/M00/A2/C1/poYBAGRTY_iAfd7WAACd22p-m-U242.png)
FIFO設(shè)計(jì)—同步FIFO
![<b class='flag-5'>FIFO</b>設(shè)計(jì)—<b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>](https://file1.elecfans.com/web2/M00/88/BE/wKgaomRwac2AG6kWAAASYuKvLbc378.jpg)
FIFO設(shè)計(jì)—異步FIFO
![<b class='flag-5'>FIFO</b>設(shè)計(jì)—異步<b class='flag-5'>FIFO</b>](https://file1.elecfans.com/web2/M00/88/BE/wKgaomRwac2AG6kWAAASYuKvLbc378.jpg)
一個(gè)簡(jiǎn)單的RTL同步FIFO設(shè)計(jì)
基于寄存器的同步FIFO
基于Verilog的同步FIFO的設(shè)計(jì)方法
同步FIFO和異步FIFO的區(qū)別 同步FIFO和異步FIFO各在什么情況下應(yīng)用
同步FIFO和異步FIFO區(qū)別介紹
![<b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>和異步<b class='flag-5'>FIFO</b>區(qū)別介紹](https://file1.elecfans.com/web2/M00/EB/91/wKgZomZetI6ACXETAAAiwkYcoTM829.png)
評(píng)論