MIPS32三種指令集格式
注意右邊為低位,左邊為高位。
R型指令
| 6bits | 5bits | 5bits | 5bits | 5bits | 6bits |
|---|---|---|---|---|---|
| $$OP$$ | $$R_{s}$$ | $$R_{t}$$ | $$R_{d}$$ | $$shamt$$ | $$funct$$ |
R型指令的 OP 恆為0;
由於mips提供了32個通用寄存器,故 OP 后是三個5bits的寄存器編號:Rs 和 Rt 為兩個源寄存器, Rd 為目的寄存器;
shamt 表示用於移位的偏移量,5bits可以表示0-31位的偏移量;
funct 表示其指令功能,如32為加法、34為減法。
I型指令
| 6bits | 5bits | 5bits | 16bits |
|---|---|---|---|
| $$OP$$ | $$R_{s}$$ | $$R_{t}$$ | 立即數 |
OP 表示指令功能;
Rs 為源寄存器, Rt 有可能作為目標寄存器用於寫入。
J型指令
| 6bits | 26bits |
|---|---|
| $$OP$$ | 立即數 |
6bits操作碼和26bits的立即數。
所以對於指令的解析,如果 OP 為0那么看 funct ,反之通過 OP 可以唯一確認指令的功能。
需要實現的八條指令
五條I型指令


三條R型指令


單周期硬布線控制器
指令譯碼邏輯
電路模板中給出了 OP 、 FUNC (funct)通道,以及需要實現的八種指令分別的通道。另外還給出了 R_TYPE 即R型指令通道來辨別R型運算指令(注意SYSCALL是特殊的R型指令,不在這一類別)。
對照之前的MIPS指令格式,編寫譯碼邏輯。如果 OP 非0,那么通過 OP 判斷指令功能;如果為0(R型指令),那么通過 FUNC 來判斷指令功能;如果是R型運算指令,則 R_TYPE 置高電平。
最終效果:

ALU控制邏輯
即生成 ALU_OP 。一共有五個指令需要通過 ALU_OP 調用對應的ALU運算功能,分別為 LW 、 SW 、 ADDI 、 ADD 和 SLT 。只有 SLT 為小於比較,其他均為加法。 LW 、 SW 兩個指令的地址是通過基址尋址產生的,所以需要調用加法運算。
查看題目提供的MIPS ALU可以看到所需的 ALU_OP : 加法為5H, 小於比較為BH。可以通過多路分配器來實現,執行 SLT 時輸出BH,反之為5H:

另外 BEQ 和 BNE 指令也使用到了ALU,它們使用ALU判斷兩個操作數是否相等,這有獨立的信號引出,和 ALU_OP 無關。
控制信號邏輯
需要將指令譯碼信號轉換為控制信號,這里解釋一下每個信號的連線含義:
根據題意, SYSCALL 表示了 Halt 停機, BEQ 和 BNE 是兩個條件跳轉指令,這三個信號直接和對應的信號相連。
MemToReg 即從存儲器中讀取數據寫入寄存器, MemWrite 即將寄存器中的數據寫入存儲器。顯然對應 LW 和 SW ,直接相連即可。
AluSrc 控制ALU操作數的來源。注意需要調用ALU的指令,它們的第二個操作數可能來自於寄存器,也可能來自於立即數( ADDI 、 LW 和 SW )。我的電路中用1代表第二個操作數為立即數,0代表存儲在寄存器中。
RegWrite 控制寄存器文件的寫入,即該條指令需要將運算結果寫入寄存器,顯然兩條R型運算指令以及 ADDI 和 LW 需要。
RegDst 控制計算結果的地址。由於R型指令和I型指令的指令格式中,指定目的寄存器的五位二進制數位置不同(R型11-15,I型16-20),所以需要區分。我的電路中用1代表R型指令,0代表I型指令。
最終實現如下:

單周期MIPS(硬布線)
需要使用CS3410中的MIPS RAM,Memory中的ROM、Register、Counter,實驗模板提供的MIPS ALU、MIPS Regifile,以及其他Logisim自帶的模塊。
PC 、 IR 等信號都已引出, RegWrite 和 MemWrite 與單周期硬布線控制器中的信號對應。 RDin 為寄存器文件寫入信號,應引出RegFile的Din腳相連;而 MDin 為存儲器寫入信號,應與MIPS RAM的數據寫入端相連。
由於我們實現的是8條MIPS32指令,每條指令的長度是相同的。所以PC每次加4 (Bytes),且對ROM尋址時,低兩位忽略才是字地址。根據指令格式可以將指令的每個部分拆分出來,注意立即數需要進行有符號擴展為32bits才能參與運算:

實驗測試使用的指令(sort.hex)需要自己寫入ROM中,只有很短一小段:
2010ffff 20110000 ae300200 22100001 22310004 ae300200 22100001 22310004
ae300200 22100001 22310004 ae300200 22100001 22310004 ae300200 22100001
22310004 ae300200 22100001 22310004 ae300200 22100001 22310004 ae300200
8020 2011001c 8e130200 8e340200 274402a 11000002 ae330200 ae140200
2231fffc 1611fff8 22100004 2011001c 1611fff5 2002000a c
指令解析出的操作數地址、寫入地址和立即數會被立即送到RegFile中;寄存器文件將R1#和R2#的數據取出送到R1和R2,它們和立即數被送向ALU。由於無論是何種指令,該過程都會進行,所以RegDst、RegWrite和AluSrc控制着整個單元取用需要的數據而舍棄垃圾值。ALU將運算結果和比較結果從“=”腳和“R”腳送出。注意如果計算的是地址,獲得的是字節地址。
添加上RAM相關的兩個信號 MemToReg 和 MemWrite 就是簡單模式了,這里就不說了。

PC每個時鍾周期+4,如果符合調整條件,則附加上偏移量,注意偏移量為指令條數。總周期數用Counter計數。Halt停機,停止PC和周期數計數器即可,正常應在第224個周期停機。

其實按照實驗提供的示意圖依樣畫葫蘆會更容易點,分塊主要為了講解相對清晰。最終的電路如下:

By SDUST weilinfox
