多週期CPU仿真

經過單週期CPU的洗禮,我們接下來要做的就是多週期CPU了。因爲有很多單週期的代碼可以複用,所以多週期寫起來沒有那麼困難。

多週期CPU原理

多週期CPU就是指一條指令在多個時鐘週期內完成,本身並不涉及多級流水線的設計,所以執行指令的性能反而不如單週期CPU。不過每一條指令在不同的時鐘週期完成不同的階段,因此執行指令的流程會更容易理解。每一條指令最多包含以下五個階段:
1. 取指令:sIF狀態,讀取下一條指令地址 。
2. 指令譯碼:sID狀態,讀取下一條指令。
3. 指令執行:sEXE狀態,執行運算。
4. 存儲器訪問:sMEM狀態,讀寫數據存儲器。
5. 寫回:sWB狀態,寫入寄存器。

多週期CPU設計

多週期CPU和單週期CPU基本框架差不多,直接複用代碼並稍作調整。然後因爲每一條指令需要多個時鐘週期執行,所以需要記錄當前階段(即狀態)以及保存各階段數據,其中指令的讀取、狀態的轉移、寄存器的寫入和數據寄存器的刷新均由時鐘信號觸發,如何分配上升沿和下降沿觸發是多週期CPU設計的難點。

我的設計是由狀態驅動指令的執行,即所有控制信號都由當前的狀態和指令操作碼共同確定,這就需要嚴格保證在每一個階段先轉移狀態再執行指令。具體來說就是在每個時鐘週期的上升沿觸發狀態轉移,然後在下降沿讀指令、寫寄存器、刷新數據寄存器。因爲上升沿只觸發狀態轉移,所以狀態轉移不會與其它任何時序邏輯發生衝突,從而保證在下降沿當前狀態可以確定當前階段。雖然下降沿同時執行各種操作,但它們互不干擾,這是因爲時序邏輯模塊的觸發不會影響整個CPU,影響的範圍從當前時序邏輯模塊的輸出到下一個時序邏輯模塊的輸入爲止。那麼根據當前階段就可以保證對應時序邏輯模塊的觸發的正確性,至於其它時序邏輯模塊的觸發則有可能是正確的,也有可能是不正確的。對於讀操作,不正確的觸發不會對程序的運行造成實質性的影響;對於寫操作,不正確的觸發會導致錯誤,因此必須通過控制信號禁止在正確的階段以外進行寫操作。

經過測試發現有兩個特殊情況:
1. lw指令在寫回階段的下降沿要先刷新總線數據寄存器,再寫寄存器,因此無法保證觸發的先後順序。
2. jal指令要在指令譯碼階段下降沿先刷新指令寄存器,再寫寄存器,同樣無法保證觸發的先後順序。

我將指令寄存器的刷新調整爲上升沿觸發,這樣不但可以同時解決這兩個問題,而且不會對狀態轉移造成干擾。首先,對於第二個問題,在指令譯碼階段上升沿刷新指令寄存器,在下降沿寫寄存器,可以保證觸發的先後順序。然後,對於第一個問題,實際上在指令譯碼階段下降沿會不正確地觸發數據寄存器的刷新,從而提前完成指令執行階段,並且對於在指令譯碼階段之後的所有讀操作都將提前一個時鐘週期完成。因爲lw指令除了寫寄存器以外均爲讀操作,所以在訪問寄存器階段下降沿就會提前刷新總線數據寄存器,那麼在寫回階段下降沿就可以保證寫寄存器的正確性。最後,雖然指令寄存器的刷新和狀態轉移都是上升沿觸發,但兩者其實並不需要保證觸發的先後順序,因爲兩者的輸出均作爲控制單元的輸入,而控制單元爲組合邏輯電路,所以無論哪一個先觸發都可以保證在指令譯碼下降沿之前確定控制信號。

使用工具

vivado軟件和verilog語言

多週期CPU實現

多週期CPU的實現和單週期CPU差不多,除了加入數據寄存器模塊和調整時序邏輯以外,唯一需要注意的是單週期CPU仿真初始時鐘信號應爲1,多週期CPU仿真初始時鐘信號應爲0,因爲單週期CPU在執行第一條指令時不需要取指令(上升沿),多週期CPU在執行第一條指令時也不需要取指令(下降沿)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章