• 方案介紹
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

RISC五級流水線CPU設(shè)計verilog仿真

加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

名稱:RISC五級流水線CPU設(shè)計verilog仿真

軟件:Quartus/modelsim

語言:verilog

本文實現(xiàn)的CPU是一個五級流水線的精簡版CPU(也叫PCPU,即pipeline),包括IF(取指令)、ID(解碼)、EX(執(zhí)行)、MEM(內(nèi)存操作)、WB(回寫)。

指令集:RISC

指令集大?。?^5 = 32

數(shù)據(jù)寬度:16bit

數(shù)據(jù)內(nèi)存:2^8×16bit = 256個16bit

指令內(nèi)存:2^8×16bit = 256個16bit

通用寄存器:8×16bit

標(biāo)志寄存器:NF(negative flag)、ZF(zero flag)、CF(carry flag)

控制信號:clock、reset、enable、start

演示視頻:

1.介紹與設(shè)計

1.1.CPU頂層視圖

第一步只要求實現(xiàn)簡單的五級流水線,不要求實現(xiàn)指令內(nèi)存、數(shù)據(jù)內(nèi)存模塊,因此CPU內(nèi)部與內(nèi)存有關(guān)的信號都簡化為輸入輸出信號了,CPU的頂層視圖看起來應(yīng)該如下圖,其中select_y、y信號是跟CPU板級測試有關(guān)的,這一步暫且沒用到。

1.2.指令集

指令為三地址格式,操作碼長度5bit,根據(jù)操作數(shù)的不同可以把指令分為三種類型,即寄存器類型R type、立即數(shù)類型I type、混合類型RI type,不過后面在代碼編寫的時候,為了方便,會依據(jù)其它標(biāo)準(zhǔn)進(jìn)行劃分。

規(guī)范一下表示方式,r1或者gr[r1]表示訪問寄存器r1,m[r2+val3]表示訪問r2+val3這個地址,{val2,val3}表示立即數(shù)訪問,val2為MSB,val3為LSB。

匯編代碼示例:

本文設(shè)計一共實現(xiàn)了28條機(jī)器指令,剩下未用的4個操作碼(10100,10101,10110,10111)可自行補(bǔ)充為其它操作,比如自增INC、自減DEC。這里指令的編碼是比較隨意的,而且由于代碼實現(xiàn)中使用了宏定義,因此可以任意更改指令的編碼,不過如果想做進(jìn)一步的優(yōu)化,就要仔細(xì)考慮編碼方式了。以下是指令集的具體格式與操作,設(shè)計CPU的時候有兩張圖是必須時刻看著的,我都把它們打印出來,這是其中一張。

1.3.五級流水線

除了指令集之外,設(shè)計CPU最重要的就是下面這張CPU塊級電路圖,五級流水線的代碼實現(xiàn)都必須依賴于這張圖,因此必須理解圖中每一步的作用。

圖中所有矩形框標(biāo)出來的都是CPU內(nèi)部的寄存器,整個電路圖展示了CPU內(nèi)部指令以及數(shù)據(jù)的流動方向。每到時鐘上升沿,上一級流水線的寄存器的數(shù)據(jù)就會經(jīng)過中間的組合邏輯電路流動到下一級流水線的寄存器,因此,5個時鐘周期之后一條機(jī)器指令便執(zhí)行完畢了。

簡單描述一條指令的執(zhí)行過程就是,

●首先根據(jù)PC的值到內(nèi)存中取一條指令,

●解碼指令提取兩個操作數(shù)

●進(jìn)行運(yùn)算,

●根據(jù)指令功能以及運(yùn)算結(jié)果決定是否訪問數(shù)據(jù)內(nèi)存以及如何訪問,

●最后同樣根據(jù)指令功能決定是否要進(jìn)行回寫操作,即修改寄存器的值。

下面將分別講解CPU控制以及五級流水線每一級的行為,為了簡單起見,這里僅考慮NOP、HALT、LOAD、STORE、ADD、CMP、BZ、BN這幾條指令,明白了流水線的行為之后再加上其它的指令也是一樣的道理

1.4.CPU控制

CPU控制自然是基于狀態(tài)機(jī),只有兩個狀態(tài)idle和exec,CPU在idle狀態(tài)下只有enable、start同時使能才會進(jìn)入exec狀態(tài)。

1.5.IF

IF階段的任務(wù)就是要根據(jù)PC的值從指令內(nèi)存中讀取一條指令,并且設(shè)置下一周期PC的值(指令可以順序執(zhí)行,也可以跳轉(zhuǎn)到某個特定的地址)。因為讀取內(nèi)存是內(nèi)存模塊實現(xiàn)的功能,因此這里CPU只需要給出指令地址i_addr就能得到對應(yīng)的指令i_datain。

1.6.ID

ID階段要根據(jù)指令的功能(即操作碼)從指令中提取對應(yīng)的操作數(shù),操作數(shù)可能來自通用寄存器r0-r7,也可能是立即數(shù)。另外如果指令是STORE指令,也要準(zhǔn)備好要存儲到內(nèi)存中的數(shù)據(jù)。

1.7.EX

EX階段執(zhí)行的是ALU運(yùn)算和標(biāo)志寄存器設(shè)置,另外如果是STORE指令也要給出內(nèi)存寫的使能信號dw以及將要寫到內(nèi)存中的數(shù)據(jù)smdr1。

1.8.MEM

MEM階段要根據(jù)指令功能和上一階段的運(yùn)算結(jié)果(內(nèi)存操作的時候作為內(nèi)存地址)決定是否要訪問內(nèi)存以及如何訪問,只對需要內(nèi)存操作的指令有效。

1.9.WB

WB階段同樣根據(jù)指令的功能以及上一階段的結(jié)果決定是否要修改寄存器的值以及如何修改,只對需要修改寄存器值的指令有效。

CPU仿真(通過內(nèi)存實現(xiàn))

內(nèi)存其實就是一個 reg 數(shù)組,讀內(nèi)存用組合邏輯電路,寫內(nèi)存用時序電路,如下圖代碼所示。對內(nèi)存的初始化可以通過 reset 信號,或者軟件仿真的時候可以直接在 test bench 文件的 initial 里面初始化。

這時候,pcpu的測試文件就要另外再通過memory.v實例化兩個內(nèi)存模塊i_mem、d_mem分別用作指令內(nèi)存和數(shù)據(jù)內(nèi)存了,pcpu模塊與內(nèi)存有關(guān)的所有信號(i_datain、d_datain等等)都要連接到這兩個模塊。initial初始化內(nèi)存的方式如下圖:

另外一種reset信號初始化內(nèi)存的方式需要分開定義指令內(nèi)存i_memory.v和數(shù)據(jù)內(nèi)存d_memory.v,然后在pcpu的測試文件里面實例化這兩個文件的模塊。d_memory.v大致如下

Testbench:

仿真圖.png

仿真圖

仿真圖2.png

仿真圖3.png

點(diǎn)擊鏈接獲取代碼文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=693

相關(guān)推薦