存儲器是FPGA設計中的常用單元,對存儲器的操作,最基礎的就是讀寫操作,還有一種就是讀改寫操作,即先讀出存儲器中的數據,對其進行修改后,再寫入存儲器。這樣的操作其實在大多數情況下都是非常簡單的,不值一提,但是在某些有性能要求的場景下,就需要一些考慮。
比如輸入是一個8bit的數據,取值為0-255,求每個數值出現的次數,即同時0出現多少次,1出現多少次……
讀改寫的問題
我們先以最簡單的例子,對FPGA內部的RAM進行讀改寫操作,看看是什么情況,假定需要對RAM中的數據讀出來加1后再寫回原地址,如下圖所示:
通過讀地址A,在下一個cycle得到數據X,然后對X進行加一操作后,再寫回地址A。我們可以看到,整個過程需要3個cycle的時間。如果再對地址A開啟讀操作,就需要在第四個cycle開始,否則就讀不到最新的數據。換句話說,上述操作無法進行流水操作,每次讀改寫操作至少需要3個cycle的時間(對于其他更加復雜的“改”操作,可能需要消耗更多的時間)。對于性能要求較高的場景,必須要流水操作的時候,如何處理呢?
解決方案
我們知道不能流水的原因是因為最新的數據可能沒有寫回RAM,還在數據總線上,因此判斷最新的數據在哪里就是解決這個問題的關鍵。這里還需要用到一個“cache”,用reg來實現,主要是記錄即將要寫入RAM的地址和數據,即記錄寫總線上的地址和數據。其實現原理可以用一個時序圖來展示。
我們假定要讀的地址是AABA,但是為了區分,我們用A1、A2、B1、A3來表示(A1、A2、A3其實是同一個地址)。我們看看如何利用“cache”實現流水式的讀改寫操作。
第1個時鐘周期,讀A1的內容,此時cache的內容也為0;
第2個時鐘周期,A1的內容在dout上,為x,我們同時拿A1這個地址去“cache”查詢,由于“cache”為空,不取“cache”中的值,直接取dout上的值作為改寫的對象;同時也開始讀A2的內容;
第3個時鐘周期,主要做2個更新,一是根據第2個周期中出現的A1和dout的值,更新到“cache”中,二是將更新的數據和地址放在寫總線上,這2個更新的內容其實是一致的,都是改和寫的過程;同時拿A2去查詢“cache”;
第4個時鐘周期,根據查詢的結果,例子中為“cache”命中,選擇“cache”中的內容x+1為改寫對象,而不是dout上讀取的值,所以寫入的內容為x+2。同時根據第三個時鐘周期中的A2來更新cache,將A2和對應寫入的值x+2更新到“cache”中,此時“cache”中有2個內容,一個是A1和值x+1,一個是A2和值x+2;
從第4個時鐘周期可以看到,讀A2這個地址得到的值,不是從dout上獲取的,而是從“cache”中獲取的,這就是利用“cache”來實現讀改寫的流水操作。
在第5個時鐘周期,用A3去查詢“cache”時,“cache”中有2個A,即A1和A2,這時我們去最“新”的A,即A2的值x+2作為改寫對象。
總結
在高性能的讀改寫場景下,利用“cache”可以實現讀改寫的流水操作,大大提高了處理性能。當然如果輸入的數據并不是流水的,采用最簡單的方式實現讀改寫即可。
-
FPGA
+關注
關注
1630文章
21798瀏覽量
606044 -
FPGA設計
+關注
關注
9文章
428瀏覽量
26632 -
存儲器
+關注
關注
38文章
7528瀏覽量
164348 -
RAM
+關注
關注
8文章
1369瀏覽量
115023
發布評論請先 登錄
相關推薦
評論