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