數(shù)字IC手撕代碼-流水握手(利用握手解決流水線斷流、反壓問題)
????????之前在這篇專欄中講過流程之間的握手操作。
????????數(shù)字IC手撕代碼-握手信號(READY-VALID) - 嗶哩嗶哩 (bilibili.com)
????????今天講講流水線技術(shù),以及如何用握手操作解決流水線因上游斷流及下游反壓導(dǎo)致的可能的數(shù)據(jù)丟失及計算錯誤問題。
????????所謂流水線,其實就是通過將一段具有長延時的組合邏輯,利用寄存器,切分成多段具有小延時的組合邏輯,從而達(dá)到提升整個模塊時鐘頻率的目的。
????????例如我們在兩個寄存器之間有一段組合邏輯,實現(xiàn)4個8bit數(shù)的乘加計算,代碼寫為:
????????assign result = a1*b1 + a2*b2 + a3*b3 + a4*b4;
????????這條語句的組合邏輯延時很大,有幾個原因,一個是四個乘法在一個組合邏輯實現(xiàn),且串行執(zhí)行,再考慮四個數(shù)的加法,這樣組合邏輯的延時就會很大,可以利用流水線技術(shù)對這段組合邏輯進(jìn)行切分,將乘法和加法分開執(zhí)行且并行執(zhí)行,例如:

? ? ? ? 如圖所示,將一段長的乘加組合邏輯,切了兩級流水,把乘法和加法分開來,好處是顯而易見的,原來的組合邏輯延時是4個8bit乘法和3個16bit加法的延時,現(xiàn)在最大的組合邏輯延時是一個8bit乘法(因為四個乘法是并行執(zhí)行的),或者3個16bit加法延時,該模塊的最大時鐘頻率可以提高很多,這就是流水線技術(shù)。

????????運行結(jié)果如上,可以看到,數(shù)據(jù)因為做了兩級流水,結(jié)果會比直接一條組合邏輯走到底的慢一個周期,但是流水線完全轉(zhuǎn)起來之后,吞吐量都是一樣的。

????????好,前一專欄講完了握手,本文講完了流水線,下面講怎么把兩個結(jié)合在一起,實現(xiàn)流水握手。上面只有兩級流水,太短了,我們把戰(zhàn)線拉長一點,在原來的基礎(chǔ)上,令a1=c1+c2;b1=c3+c4;

即多加一級流水,分成如下3級。

????? ?確定好切分幾級流水以及各個流水的工作內(nèi)容后,就可以為各級流水線添加握手信號了。
????????握手信號我們采用的是預(yù)?。╬re-fetch)的方式,這種方式的握手可以解決數(shù)據(jù)卡在流水線中出不來的情況:對于本級來說,如果下一級準(zhǔn)備好了,或者本級的輸出為0(即本級流水肚子里沒貨),那么本級就可以接收數(shù)據(jù)。各級流水線運轉(zhuǎn)的條件是:本級流水準(zhǔn)備好(ready為高,且上級流水輸出有效valid為高,即ready_本級 && valid_上級時,本級流水才開始工作,如果上一級數(shù)據(jù)不有效或者本級還沒準(zhǔn)備好,那么流水線就會一直停滯,直到數(shù)據(jù)有效和流水ready同時滿足。

????????在第一級流水中,我們對a2~a4,b2~b4做了打一拍的操作,這里解釋下為什么,因為我們輸入的時候,a2~a4,b2~b4是跟c1~c4一起輸入的,但是我們規(guī)劃的流水線的第一級并沒有對a2~a4,b2~b4進(jìn)行操作而是在第二級對他們操作,所以如果我們不對輸入的a2~a4,b2~b4有效數(shù)據(jù)進(jìn)行一拍的緩存的話,若輸入數(shù)據(jù)僅有效一個周期時,那么下個周期的時候,流水線使用的a2~a4,b2~b4就會出錯,所以要在這里對第一級沒有處理的數(shù)據(jù)進(jìn)行打一拍,保證同時刻進(jìn)來的數(shù)據(jù)走同一條流水。
同理可以寫第二級和第三級的流水:


如上,就完成了對三級流水線添加握手信號的操作。下面我們來測試一下:
????????在tb中分別模擬流水線正常工作、上游斷流、下游反壓以及最后數(shù)據(jù)傳輸完畢之后的狀態(tài),看看在不同狀態(tài)下,流水線是否會出現(xiàn)數(shù)據(jù)傳輸錯誤或者數(shù)據(jù)丟失的情況。

????????這里關(guān)鍵就是這個波形,請一定要看好,流水握手掌握了之后,在我們寫項目的過程中非常有用!

????????把整個模塊包裝成一個module后,我們這個就相當(dāng)于一個流水處理一段長延時組合邏輯的IP。對于我們這個IP來說,valid_i和ready_o同時為高時,數(shù)據(jù)有效,即a2\b2=2,3,6時數(shù)據(jù)是有效的,一開始數(shù)據(jù)有效了兩拍,分別是2和3,過了三拍后,數(shù)據(jù)輸出valid_o拉高兩拍,因為ready_i為1,所以下游可以接收數(shù)據(jù),所以valid_o拉高兩周期把輸出的數(shù)據(jù)傳完后就拉低了。
????????輸入數(shù)據(jù)有效兩周期后,流水線斷流,從而導(dǎo)致輸入數(shù)據(jù)無效,所以流水線在輸出兩個結(jié)果后valid_o保持為低,直到上游又輸入有效數(shù)據(jù)。
????????此時進(jìn)入下游反壓狀態(tài),下游反壓并不會立刻反饋到第一級的流水,而是由下至上逐級反饋,所以下游反壓的時候,空的流水線不會立即停止,而是等數(shù)據(jù)把流水線灌滿之后才停止。下游反壓時,流水線進(jìn)了三周期數(shù)據(jù)6,把流水線灌滿之后,流水線就停滯了(表現(xiàn)為ready_o拉低,告訴上游我吃不進(jìn)數(shù)據(jù)了)。
????????數(shù)據(jù)停止傳輸時,又把ready_i拉高,即下游不反壓了,但此刻上游數(shù)據(jù)已經(jīng)傳輸完畢,所以流水線不再接受數(shù)據(jù),而是把之前吃進(jìn)來的三周期數(shù)據(jù)6,計算后再吐出來,可以看到確實輸出時ready_i和valid_o同時保持三周期高,把三級流水線內(nèi)部數(shù)據(jù)吐完后,valid_o拉低,流水線清空。
????? ? 這段流水握手的代碼是我寫的比較好看的一段代碼,解決了我特別多的數(shù)據(jù)傳輸問題,大家感興趣的可以借鑒。
????????相關(guān)的.v文件我上傳網(wǎng)盤了,大概總量一百多行,b站顯示不全所以直接傳網(wǎng)盤分析,喜歡的同學(xué)可以點個贊,感謝。
鏈接:https://pan.baidu.com刪除中文/s/1FyszPR5h7YC9刪除中文TTN51wlpfw?
提取碼:t3wm?