問題提出:ready時序如何優(yōu)化?
在valid/ready 握手協(xié)議中,valid 與 data的時序優(yōu)化比較容易理解。
但是有時候,關(guān)鍵路徑是在ready信號上,如何對ready信號打拍呢?
首先將把目標(biāo)設(shè)計想象成一個黑盒子,如圖1所示,我們的目標(biāo)是將READY_DOWN通過打拍的方法獲得時序優(yōu)化。
(圖1)
嘗試直接對ready打一拍
(僅示例,非verilog代碼。下同)
這樣是行不通的。
一個簡單的例子(case 1)就是你讓READY_DOWN像一個時鐘一個,間隔一個cycle起來一次,那么VALID_UP && READY_UP 與 VALID_DOWN && READY_DOWN無法同步,數(shù)據(jù)無法傳輸下去。
思路:將其分解成兩個interfaces
將ready打拍的邏輯想象成一個黑盒子,去分析這個黑盒子的設(shè)計,分為up interface 和down interface將問題細(xì)化:
-
up interface 有VALID_UP, DATA_UP, READY_UP
-
down interface 有VALID_DOWN, DATA_DOWN, READY_DOWN
可以總結(jié)成下面的樣子:
如果去解決剛才例子(case 1),那么這個黑盒子:
當(dāng)READY_UP為高的時候,可以接受數(shù)據(jù);
當(dāng)READY_DOWN為高的時候, 如果我們有數(shù)據(jù)可發(fā)的話 ,我們可以向downstream發(fā)送數(shù)據(jù);
是不是很像一個FIFO?
用FIFO去解決
將一個FIFO插在黑盒子這里,那么就會變成這樣子:
(圖2)
VALID_UP/READ_YUP ==> FIFO ==> VALID_DOWN/READY_DOWN
也就是:
現(xiàn)在問題變成了:如何設(shè)計這個FIFO呢?
- 這個FIFO深度多少?
- 怎么設(shè)計,能夠保證READY_UP是READY_DOWN打過一拍的呢?
FIFO設(shè)計多深?
因為本身valid/ready協(xié)議是 反壓協(xié)議 ( 也就是READY_UP為0的時候,不會寫FIFO,而不會導(dǎo)致FIFO溢出 )而且此處的讀寫時鐘是同一個時鐘,是一個同步FIFO,所以FIFO深度是1或者2就足夠了。
深度是1還是2要看極端情況下需要存儲幾筆數(shù)據(jù)。
簡單分析可以知道,只有一種情況會去向FIFO中存儲數(shù)據(jù):
- READY_UP是1,可以從upstream接收數(shù)據(jù)
- 同時READY_DOWN是0,不可以向downstream發(fā)送數(shù)據(jù)
這種情況在極端情況下最多維持多久呢?
答案是: 一個周期 。
因為如果cycle a 時:READY_DOWN=0,那么cycle a+1時,READY_UP變?yōu)?了,開始反壓,所以只用存一個數(shù)就夠了。
所以設(shè)計為一個深度為1的FIFO就可以了。
深度為1的FIFO有很多特點,設(shè)計起來比較簡單。比如:wr_ptr/rd_ptr始終指向地址0,所以我們可以刪掉wr_ptr和rd_ptr,因為是一個常值0。
簡單的depth-1 FIFO實現(xiàn)
使用depth-1 FIFO傳輸數(shù)據(jù),可以這樣設(shè)計:
這解決了READY打拍的問題。但是這里有一些可以改進(jìn)的地方,比如:
- 是不是可以擠掉多于的氣泡?
- 在FIFO為空的時候,數(shù)據(jù)是不是可以直接bypass FIFO?
無氣泡傳輸
具體的說,就是既然你這里有個深度為1的FIFO了,那么我是不是可以利用起來,放點數(shù)據(jù)啊……
當(dāng)READY_DOWN持續(xù)是0的時候,READY_UP依然可以有一個cycle去接收一筆數(shù)據(jù),把FIFO資源利用起來:
同樣的原因,在RESET情況下,READY_UP可以為1,可以將復(fù)位值修改。
那么FIFO穿越呢?
FIFO穿越
考慮一個特殊情況(case 2):
假設(shè)READY_DOWN在復(fù)位之后始終為1,
然后某個時刻開始VALID_UP為1了。
是不是每個周期,數(shù)據(jù)都可以直接傳下來而不用進(jìn)入FIFO,即使READY_DOWN打過一拍?
換句話說: ***如果READY_UP=1, READY_DOWN=1, FIFO是空的這種情況下,數(shù)據(jù)可以直通*** 。
- 上文特殊情況(case 2),READY_DOWN/READY_UP一直是1,顯然可以。
- READY_UP從0到1的跳變:READY_DOWN也會在前一周期有一個從0到1的跳變。在READY_DOWN為0時,有一筆數(shù)據(jù)存到FIFO里邊(無氣泡傳輸);當(dāng)READY_DOWN在時刻a從0變到1時,READY_UP在時刻a+1也會從0變?yōu)?。如果此時READY_DOWN也為1,可以直通,不用進(jìn)入FIFO。也就是:
注意在直通時,我們不希望數(shù)據(jù)進(jìn)入FIFO:
將所有這些結(jié)合起來:
(注:代碼未經(jīng)詳細(xì)驗證)
換一種思路
經(jīng)過上面對FIFO的分析,我們可以總結(jié)起來,主要是以下幾點:
- 加入一個深度為1的同步FIFO,這個FIFO在READY_DOWN為0,且READY_UP為1時暫存一個數(shù)據(jù);
- 在READY_DOWN從0->1時,F(xiàn)IFO里邊的數(shù)據(jù)先輸出到下級;
- 如果READY_DOWN繼續(xù)為1,數(shù)據(jù)可以繞過FIFO直通;
深度為1的FIFO(不管是同步還是異步FIFO),都是一個特殊的邏輯單元。
對于深度為1的同步FIFO,其實就是一拍寄存器打拍。
所以,我們可以這樣重新設(shè)計:
-
加一級寄存器作為buffer(實際上就是深度為1的FIFO)
-
當(dāng)以下條件滿足,這一級寄存器會暫存一級數(shù)據(jù):
2.1 READY_DOWN是0,并且
2.2 READY_UP是1,并且
2.3 VALID_UP是1;
也就是:
- 當(dāng)READY_UP是1時,數(shù)據(jù)可以直接暴露在下級接口:READY_UP為1時,BUFFER中一定是空的,因為上一個時鐘周期數(shù)據(jù)已經(jīng)排空了。也就是:
這其實就是上面的FIFO直通模式。同樣我們可以擠掉氣泡:
把這所有的總結(jié)起來:
(注:代碼未經(jīng)詳細(xì)驗證)
其他
- 我在電腦上簡單跑了兩個波形,F(xiàn)IFO方法和Buffer方法結(jié)果是一樣的。
- 用FIFO去隔離開上下兩個interface思考,比較容易想明白。
- 無氣泡傳輸、FIFO直通這兩個小feature拿掉,也可以工作、也是能實現(xiàn)READY_DOWN時序優(yōu)化的設(shè)計目標(biāo)的。
-
寄存器
+關(guān)注
關(guān)注
31文章
5336瀏覽量
120238 -
AXI總線
+關(guān)注
關(guān)注
0文章
66瀏覽量
14261 -
FIFO存儲
+關(guān)注
關(guān)注
0文章
103瀏覽量
5969
發(fā)布評論請先 登錄
相關(guān)推薦
評論