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 : jrWRSel 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個0GRFWe O 1 GRF寫使能 ALUop O 2 進行何種運算 2'b00 : 加法
2'b01 : 減法
2'b10 : 或運算
2'b11 : 左移運算BSel O 1 運算數是否為立即數 DMWe O 1 DM寫使能
思考題
-
上面我們介紹了透過 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發揮狀態轉移功能。
-
現在我們的模組中 IM 使用 ROM, DM 使用 RAM, GRF 使用 Register,這種做法合理嗎? 請給出分析,若有改進意見也請一併給出。
答:我認為合理。ROM是隻讀儲存器,只能讀取而無法寫入,在程式執行的過程中,我們已經將mips翻譯為機器碼匯入IM的ROM中,無須修改,故合理。DM是cpu的主存,會與ALU和GRF間互動資料,所以DM需要同時具有讀與寫的功能,使用RAM合理。GRF本來就是register file,臨時的儲存變數,符合暫存器的特性,合理。
-
在上述提示的模組之外,你是否在實際實現時設計了其他的模組?如果是的話,請給出介紹和設計的思路。
答:無。
-
事實上,實現 nop 空指令,我們並不需要將它加入控制訊號真值表,為什麼?
答:由於我們的controller是透過與或陣列實現的,nop的機器碼為0x0000_0000,在不考慮nop時,controller的與陣列的所有已經設計好的指令輸出都為低電平,即cpu不會有任何高電平寫使能、NPC也按照正常方式計算一下條指令地址,此時電路表現為空置一週期,故不需要考慮nop指令的設計。
-
閱讀 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