Mips單週期CPU設計(logisim實現)

Saiwh發表於2024-10-29

Logisim單週期cpu設計文件與思考題


設計文件

支援指令集

指令 格式 描述(RTL) 機器碼 OPCODE/FUNCT
add add rd rs rt GPR[rd] <- GPR[rs]+GPR[rt] R型 0/100000
sub sub rd rs rt GPR[rd] <- GPR[rs]-GPR[rt] R型 0/100010
ori ori rt rs imme GPR[rt] <- GPR[rs] or imme I型 001101
lw lw rt offset(base) GPR[rt] <- memory[GPR[base]+offset] I型 100011
sw sw rt offset(base) memory[GPR[base]+offset] <- GPR[rt] I型 101011
beq beq rs rt offset if(GPR[rs]==GPR[rt]) PC <- PC+4+sign_extend(offset||00) I型 000100
lui lui rt imme GPR[rt] <- imme||0^16 I型 001111
jal jal target PC <- PC31..28||target||00 並且 GPR[31] <- PC + 4 J型 000011
jr jr rs PC <- GPR[rs] R型 0/001000
sll sll rd rt s GPR[rd] <- GPR[rt] << s R型 0/000000
jalr jalr rd rs PC <- GPR[rs] , GPR[rd] <- PC+4 R型 0/001001
lb lb rt offset(rs) GPR[rt] <- memory[GPR[rs]+offset] I型 100000
sb sb rt offset(rs) memory[GPR[rs]+offset] <- GPR[rt] I型 101000
slt slt rd rs rt GPR[rd] <- (GPR[rs] < GPR[rt]) R型 0/101010
nop null 不進行任何操作,空置一週期 null 0x00000000

注意

  • 其中sll指令為R型指令,這是因為我們最多移位31位,沒必要用16位的立即數儲存。故s為5位,是一種特殊的R型(只有兩個暫存器參與操作)
  • nop雖然不需要進行任何操作,但是仍然需要進行PC <- PC + 4,所以在設計NPCop時不要忘了2'b00也應該能被nop啟用。

mips指令集機器碼補充

R型指令

opcode rs rt rd shamt funct
位長 6 5 5 5 5 6
佔位 31-26 25-21 20-16 15-11 10-6 5-0

I型指令

opcode rs rt immediate
位長 6 5 5 16
佔位 31-26 25-21 20-16 15-0

J型指令

opcode instr_index
位長 6 26
佔位 31-26 25-0

資料通路形式建模

模組分析

  • IFU(Instruction Fetch Unit 取指令單元)

模組描述

  • 內部包括 PC(程式計數器)、IM(指令儲存器)、NPC(進行指令的轉移地址計算)。
  • PC 用暫存器實現,應具有非同步復位功能,復位值為起始地址。
  • 起始地址:0x00003000。
  • 地址範圍:0x00003000 ~ 0x00006FFF。
  • IM 用 ROM 實現,容量為 4096 × 32bit。
  • ROM 內部的起始地址是從 0 開始的,即 ROM 的 0 位置儲存的是 PC 為 0x00003000 的指令,每條指令是一個 32bit 常數。
  • 經過以上分析,不難發現 ROM 實際地址寬度僅需 12 位,請使用恰當的方法將 PC 中儲存的地址同 IM 聯絡起來。

模組功能及引腳定義

  • PC:當Reset=1時,非同步復位至地址0x0000_3000
訊號 方向 描述
CLK I 1 單週期的時鐘訊號
Reset I 1 非同步復位
DI I 1 NPC傳來的新的指令地址
DO O 1 當前指令地址
  • NPC:計算下一條指令的地址
訊號 方向 描述
PC I 32 當前指令地址
imm16 I 16 beq時跳轉到的地址
ZERO I 1 ALU減法結果是否為 0
NPCop I 2 決定NPC應該進行何種計算
NPC O 32 下一條指令的地址
  • IM:讀取指令機器碼並分解
訊號 方向 描述
PC I 32 當前指令地址
OPCODE O 6 當前指令的OPCODE
rs O 5 rs編號
rt O 5 rt編號
rd O 5 rd編號
imm16 O 16 立即數
FUNCT O 6 當前指令的FUNCT
  • GRF(暫存器堆)

模組描述

  • 用具有寫使能的暫存器實現,暫存器總數為 32 個,應具有非同步復位功能。
  • 0 號暫存器的值始終保持為 0。其他暫存器初始值(復位後)均為 0,無需專門設定。
  • 0號暫存器採用接地設計,故實際上只有31個暫存器。

模組功能及引腳定義

  • GRF:暫存器堆用於儲存暫存器中的資料
訊號 方向 描述
CLK I 1 時鐘訊號
Reset I 1 非同步復位訊號
GRFWe I 1 寫使能訊號
A1 I 5 rs暫存器編號
A2 I 5 rt暫存器編號
A3 I 5 rd暫存器編號
WD I 32 寫入rd的資料
RD1 O 32 rs暫存器讀出值
RD2 O 32 rt暫存器讀出值
  • ALU(算術邏輯單元)

模組描述

  • 提供 32 位加、減、或運算及大小比較功能。
  • 加減法按無符號處理(不考慮溢位)。

模組功能及引腳定義

訊號 方向 描述
A I 32 GPR[rs]
B I 32 GPR[rt] 或 擴充套件後的立即數
ALUop I 2 執行何種運算
RD O 32 運算結果
ZERO O 1 執行減法時結果是否為 0
  • 注:規定ALUop的2'b00,2'b01,2'b10分別表示add、sub、ori操作
  • DM(資料儲存器)

模組描述

  • 使用 RAM 實現,容量為 3072 × 32bit,應具有非同步復位功能,復位值為 0x00000000。
  • 起始地址:0x00000000。
  • 地址範圍:0x00000000 ~ 0x00002FFF。
  • RAM 應使用雙埠模式,即設定 RAM 的 Data Interface 屬性為 Separate load and store ports。

模組功能及引腳定義

訊號 方向 描述
A I 32 資料儲存器地址
DI I 32 寫入的資料
We I 1 寫使能
CLK I 1 時鐘訊號,非同步復位
Reset I 1 復位訊號
DO O 32 輸出的資料
  • EXT(擴充套件單元)

模組描述

  • 使用 Logisim 內建的 Bit Extender。
  • 作用為將immediate16擴充為32bit。
  • 具有擴充選擇訊號EXTop。

控制器(Controller)建模

  • 模組描述
  • 使用與或門陣列構造控制訊號。
  • 分析可知,決定控制訊號的就是當前在執行哪種指令,我們便需要建立每種訊號的布林表示式
  • 與陣列中,我們將每種指令作為輸出,布林表示式建立方法如:beq的opcode為000100,則beq=!op[5]!op[4]!op[3]op[2]!op[1]*!op[0]
  • 或陣列中,只需要把使得控制訊號為真的指令或起來即可。
  • 模組功能及引腳定義
訊號 方向 描述 多位控制訊號的具體描述
OPCODE I 6 指令的opcode
FUNCT I 6 指令的funct
NPCop O 2 決定NPC應該進行何種計算 2'b00 : +4
2'b01 : beq
2'b10 : jal
2'b11 : jr
WRSel O 2 GRF寫入地址來源 2'b00 : rt
2'b01 : rd
2'b10 : ra(jal)
WDSel O 2 GRF寫入資料來源 2'b00 : ALU的輸出
2'b01 : DM的輸出
2'b10 : 立即數
2'b11 : PC+4(jal)
EXTop O 2 如何擴充套件立即數 2'b00 : 無符號擴充套件
2'b01 : 有符號擴充套件
2'b10 : 在低位擴充套件16個0
GRFWe O 1 GRF寫使能
ALUop O 2 進行何種運算 2'b00 : 加法
2'b01 : 減法
2'b10 : 或運算
2'b11 : 左移運算
BSel O 1 運算數是否為立即數
DMWe O 1 DM寫使能

思考題

  1. 上面我們介紹了透過 FSM 理解單週期 CPU 的基本方法。請大家指出單週期 CPU 所用到的模組中,哪些發揮狀態儲存功能,哪些發揮狀態轉移功能。

    :單週期cpu涉及到的模組有:NPC、PC、IM、GRF、ALU、DM,可以將其劃分為兩個FSM:分別為NPC、PC、IM構成的Moore型FSM,稱之為IFU 和 GRF、ALU、DM構成的下游mealy型FSM。在IFU中,PC發揮狀態儲存功能,NPC發揮狀態轉移功能;在下游FSM中,GRF發揮狀態儲存功能,整個IFU發揮狀態轉移功能。


  2. 現在我們的模組中 IM 使用 ROM, DM 使用 RAM, GRF 使用 Register,這種做法合理嗎? 請給出分析,若有改進意見也請一併給出。
    :我認為合理。ROM是隻讀儲存器,只能讀取而無法寫入,在程式執行的過程中,我們已經將mips翻譯為機器碼匯入IM的ROM中,無須修改,故合理。DM是cpu的主存,會與ALU和GRF間互動資料,所以DM需要同時具有讀與寫的功能,使用RAM合理。GRF本來就是register file,臨時的儲存變數,符合暫存器的特性,合理。


  3. 在上述提示的模組之外,你是否在實際實現時設計了其他的模組?如果是的話,請給出介紹和設計的思路。
    :無。


  4. 事實上,實現 nop 空指令,我們並不需要將它加入控制訊號真值表,為什麼?
    :由於我們的controller是透過與或陣列實現的,nop的機器碼為0x0000_0000,在不考慮nop時,controller的與陣列的所有已經設計好的指令輸出都為低電平,即cpu不會有任何高電平寫使能、NPC也按照正常方式計算一下條指令地址,此時電路表現為空置一週期,故不需要考慮nop指令的設計。


  5. 閱讀 Pre 的 “MIPS 指令集及組合語言” 一節中給出的測試樣例,評價其強度(可從各個指令的覆蓋情況,單一指令各種行為的覆蓋情況等方面分析),並指出具體的不足之處。
    :我認為強度不夠。在指令集覆蓋方面缺少對sub指令的測試,同時在具體單種指令的測試上,ori的資料缺少邊界情況的測試如立即數為0x0或0xffff;add指令缺少運算數包含0x0的情況;sw指令測試存在問題:lw的偏移量是負數的情況沒有測試;lw與sw是同樣的問題;beq指令的問題是缺少暫存器是負數的判斷和跳轉。

    附上成功自測出GRFbug的改進資料。
     # add sub ori lw sw beq lui nop
     ori $a0 $0 123#a0 = 123
     ori $a1 $a0 456#a1 = 507
     ori $a1 $a1 0#a1 = 507
     ori $a2 0xffff#a2 = 0xffff
    
     lui $a3 123#a3 = 0x007B_0000
     lui $t0 0xffff
     ori $t0 $t0 0xffff#t0 = 0xffffffff (-1)
    
     # wrong from here s0 is -1(wrong)
     add $s0 $a0 $a2#s0 = 65658
     add $s1 $a0 $t0#s1 = 122
     add $s2 $t0 $t0#s2 = -2
     add $s3 $0 $t0#s3 = -1
    
     sub $s4 $a0 $a1#s4 = -384
     sub $s5 $a1 $a0#s5 = 384
     sub $s6 $t0 $t0#s6 = 0
     sub $s7 $a0 $t0#s7 = 124
    
    
     ori $t1 0x0000#t1 = 0
     sw $a0 0($t1)#123
     sw $a2 4($t1)#0xffff
     sw $0 8($t1)#0
     sw $t0 12($t1)#-1
     ori $t2 20#t2 = 20
     sw $a1 -4($t2)#507
    
     ori $t3 $0 4
     lw $t4 4($t3)#t4 = 0xffff
     lw $t5 8($t3)#t5 = 0
     lw $t6 12($t3)#t6 = -1
     lw $t7 -4($t3)#t7 = 507
    
     beq $a0 $a1 loop1#unequal
     beq $s3 $t0 loop2#equal
    
     loop1:lw $t8 0($t1)
     loop2:lw $t8 4($t1)#t8 = 0xffff
    

相關文章