【计组实验】P3 Verilog多周期处理器开发 MIPS指令集
全部代碼+測試指令:
鏈接:CPUMultiCycle p3正確運行_百度網盤
提取碼:gmzb
(實驗P1P2)Logisim電路圖以及Verilog單周期處理器設計,見以下博客:
【計算機組成原理課設】logisim完成單周期處理器開發 MIPS指令集
【完結】Modelsim Verilog單周期處理器開發 MIPS指令集
實驗要求
a) MIPS-Lite2={MIPS-Lite1,lb,sb}。
b) MIPS-Lite1={addu,subu,ori,lw,sw,beq,j,lui,addi,addiu,slt,jal,jr }。
c) 所有運算類指令均可以不支持溢出。
筆記
控制信號
各控制信號含義
控制信號真值表
狀態轉移圖
測試指令
34100001 34110003 34080001 340cabab 3c0d000a 00102021 00082821
0c000c33 00028021 02288823 1211fffa 34080004 3c017fff 3421ffff
0001c021 27090003 270a0005 23160006 ad09fffc ad010000 810e0003
a10c0007 8d0f0004 a104fffd 8112ffff 00082021 00092821 0c000c33
0148c82a 13200018 0184a02a 12800001 3c0cffff 34000001 3c13efef
3c01abab 3421cdcd 00011821 24640002 20770005 0c000c33 00024021
00082021 00092821 0c000c33 00024821 01004821 3c0a0069 11090001
1000fff4 08000c37 00851021 21801234 03e00008 201a5678
答案:mars運行結果
verilog波形
全部代碼
mips.v
`timescale 1ns/1nsmodule mips(input clk,input reset);//以下是每個模塊的輸出//Control控制單元wire [1:0]RegDst; //寫寄存器的目標寄存器號來源:0-rt 1-rdwire ALUSrc; //第二個ALU操作數的來源 :0-讀寄存器2 1-指令低16位的符號拓展wire [1:0] MemToReg; //寫入寄存器的數據來源wire RegWrite; //寄存器寫使能有效wire MemWrite; //將數據寫入到指定存儲器單元中wire PCSrc; //判斷是否執行分支(PC+4 or PC+4+offset)wire [1:0]ExtOp; //控制Extender的拓展方式wire [2:0]ALUctr; //3bit 控制ALU的運算wire j_ctr; //控制PC是否轉移到J指令指示的地址wire jr_ctr; //jr指令wire DMSrc;wire [15:0]immediate16;//addresswire [25:0]immediate26;//J指令 26位跳轉地址wire NPC_ctr;wire sb_ctr;//IM指令存儲器wire [31:0] imout;wire [5:0] opcode;wire [4:0] rs;wire [4:0] rt;wire [4:0] rd;wire [5:0] shamt;wire [5:0] func;//GPR寄存器堆wire [31:0] rd1; //讀出的數據1wire [31:0] rd2; //讀出的數據2//DM數據存儲器wire [31:0] dout; //讀出的數據wire [31:0] lbout; //lb讀出的數據//ALU算數邏輯單元wire [31:0] Result;wire zero;wire overflow;//Ext拓展單元wire [31:0] EXTout;//MUX多路選擇器wire [31:0] DataToDM;wire [31:0] DataToALU;wire [31:0] RegWriteData;wire [4:0] RegWriteAddress;//NPCwire [31:0] NPC; //下一條指令的地址wire [31:0] jalPC; //jal跳轉的地址//PCwire [31:0] PC; //PC輸出下一條指令的地址//DataLate延遲模塊wire [31:0] rd1_late; //寄存器讀數據1wire [31:0] rd2_late; //寄存器讀數據2wire [31:0] Result_late; //ALU結果wire overflow_late; //ALU溢出標志位wire[31:0]imout_late; //取出的整條指令wire[5:0]opcode_late; //輸出 6位操作碼opwire[4:0]rs_late; //輸出 源1wire[4:0]rt_late; //輸出 源2wire[4:0]rd_late; //輸出 目的wire[4:0]shamt_late; //只用于移位指令sllwire[5:0]func_late; //指出ALU的功能wire[15:0]immediate16_late; //beq的低16位分支地址wire[25:0]immediate26_late; //J指令的低26位跳轉地址wire j_ctr_late;wire jr_ctr_late;wire PCSrc_late;wire [31:0] dout_late; //讀出的數據wire [31:0] lbout_late; //讀出的數據//以下是各個模塊的實例化 就是用導線把他們接在一起 注意函數參數要與上方的輸出相同 否則會出現變量未定義的問題control Control(clk,opcode[5:0],zero,func[5:0],overflow_late,RegDst[1:0],ALUSrc,MemToReg[1:0],RegWrite,MemWrite,PCSrc,ExtOp[1:0],ALUctr[2:0],j_ctr,jr_ctr,sb_ctr,DMSrc,NPC_ctr);/*opcode[5:0],zero, //beq指令func[5:0],overflow,RegDst[1:0], //寫寄存器的目標寄存器號來源:0-rt 1-rdALUSrc, //第二個ALU操作數的來源MemToReg[1:0], //寫入寄存器的數據來源RegWrite, //寄存器寫使能有效MemWrite, //將數據寫入到指定存儲器單元中PCSrc, //判斷是否執行分支(PC+4 or PC+4+offset)ExtOp[1:0], //控制Extender的拓展方式ALUctr[2:0], //3bit 控制ALU的運算j_ctr, //控制PC是否轉移到J指令指示的地址jr_ctr, //jr指令DMSrc*/DataLate_J_JR late_J(j_ctr, clk, j_ctr_late);DataLate_J_JR late_JR(jr_ctr, clk, jr_ctr_late);DataLate_J_JR late_PCSrc(PCSrc, clk, PCSrc_late);im_4k im (PC[11:2],imout[31:0],opcode[5:0],rs[4:0],rt[4:0],rd[4:0],shamt[4:0],func[5:0],immediate16[15:0],immediate26[25:0]);/*input [11:2]addr,//與上一個模塊以導線相連 10bit 要取出的指令地址output reg[31:0]dout,//取出的整條指令output reg[5:0]op,//輸出 6位操作碼opoutput reg[4:0]rs,//輸出 源1output reg[4:0]rt,//輸出 源2output reg[4:0]rd,//輸出 目的output reg[4:0]shamt,//只用于移位指令slloutput reg[5:0]func,//指出ALU的功能output reg[15:0]immediate16,//beq的低16位分支地址output reg[25:0]immediate26//J指令的低26位跳轉地址*/DataLateIM dlIM (clk,imout[31:0],opcode[5:0],rs[4:0],rt[4:0],rd[4:0],shamt[4:0],func[5:0],immediate16[15:0],immediate26[25:0],imout_late[31:0],opcode_late[5:0],rs_late[4:0],rt_late[4:0],rd_late[4:0],shamt_late[4:0],func_late[5:0],immediate16_late[15:0],immediate26_late[25:0]);/*input clk,input[31:0]dout,//取出的整條指令input[5:0]op,//輸出 6位操作碼opinput[4:0]rs,//輸出 源1input[4:0]rt,//輸出 源2input[4:0]rd,//輸出 目的input[4:0]shamt,//只用于移位指令sllinput[5:0]func,//指出ALU的功能input[15:0]immediate16,//beq的低16位分支地址input[25:0]immediate26//J指令的低26位跳轉地址output reg[31:0]imout_late,//取出的整條指令output reg[5:0]op_late,//輸出 6位操作碼opoutput reg[4:0]rs_late,//輸出 源1output reg[4:0]rt_late,//輸出 源2output reg[4:0]rd_late,//輸出 目的output reg[4:0]shamt_late,//只用于移位指令slloutput reg[5:0]func_late,//指出ALU的功能output reg[15:0]immediate16_late,//beq的低16位分支地址output reg[25:0]immediate26_late//J指令的低26位跳轉地址*/GPR gpr (PC,clk,reset,RegWrite,rs[4:0],rt[4:0],RegWriteAddress,RegWriteData,rd1[31:0],rd2[31:0]);/*WPC[31:0], //writePCclk,reset,RegWrite, //寄存器寫使能ra1[4:0], //ReadAddress1ra2[4:0], //ReadAddress2wa[4:0], //RegWriteAddresswd[31:0], //WriteDatard1[31:0], //ReadData1rd2[31:0] //ReadData2*/DataLate32A ADR(rd1[31:0], clk, rd1_late[31:0]);DataLate32B BDR(rd2[31:0], clk, rd2_late[31:0]);dm_4k dm (Result_late[11:0],Result_late[11:2],rd2[31:0],MemWrite,sb_ctr,clk,dout[31:0],lbout[31:0]);/*input [11:0]addr12, //lb指令專用input [11:2]addr, //(sw指令)由Result[11:2](ALU基地址+偏移的計算結果)輸入,表示要寫入的數據單元的地址input [31:0]din, //dataininput we, //MemWrite數據存儲器寫使能input clk,output [31:0] dout, //dataout 取出的數據output reg [31:0] lbout //dataout lb專用*/DataLate32RAM dlRAM(dout[31:0], clk, dout_late[31:0]);DataLate32RAMLB dlRAMLB(lbout[31:0], clk, lbout_late[31:0]);ALU Alu (rd1[31:0],DataToALU,5'b0,ALUctr[2:0],Result[31:0],zero,overflow);/*A[31:0], //輸入32位AB[31:0], //輸入32位Bsl[4:0], //左移的位數 sl是移位指令 沒用ALUctr[2:0], //3位ALU控制信號Result[31:0], //因為要在always里面賦值,所以定義為regzero //零標志位*/DataLate32ALU ALUout(Result[31:0], clk, Result_late[31:0]); DataLate1 OverFlowLate(overflow, clk, overflow_late); EXT ext (immediate16[15:0],ExtOp[1:0],EXTout[31:0]);/*EXTin[15:0], //輸入EXT的數據ExtOp[1:0],EXTout[31:0] //拓展后輸出的數據*///計算參與運算的ALU數據2mutiplexer32_1 MuxDataToALU(ALUSrc,rd2[31:0],EXTout,DataToALU);/*control,//ALU數據2來源:0-讀寄存器2 1-指令低16位的符號拓展din0 [31:0], //讀寄存器2din1 [31:0], //指令低16位的符號拓展out32_1 [31:0]*///RegWriteData的計算mutiplexer32_2 mux32_2(MemToReg,Result_late,dout_late,jalPC,lbout_late,RegWriteData);//MUX RegWriteData/*control [1:0], //MemToReg: 00ALU運算結果(包含高16拓展\普通運算) 01數據存儲器的輸出 10jalPC JAL跳轉的PC+4 用于RegWriteData的計算din0 [31:0], //00 ALU運算結果(包含高16拓展\普通運算)din1 [31:0], //01 DM輸出din2 [31:0], //10 jalPC JAL跳轉的PC+4din3 [31:0], //11 lbout32_2 [31:0]*///RegWriteAddress的計算 mutiplexer5 mux5(RegDst,rt,rd,5'b11111,RegWriteAddress);/*control [1:0],//Regdst寫寄存器的目標寄存器號來源 0-rt 1-rddin0 [4:0], //rt lui應該寫到rtdin1 [4:0], //rddin2 [4:0], //5'b11111 31號寄存器out5 [4:0]*/NextPC npc (NPC_ctr,PC[31:0],immediate16[15:0],immediate26[25:0],rd1[31:0],PCSrc_late,j_ctr_late,jr_ctr_late,NPC[31:0],jalPC[31:0]);/*PC[31:0],imm16[15:0], //beqimm26[25:0], //j,jalrsd[31:0], //jr跳轉至寄存器 對應接口是rd1[31:0] 是從寄存器讀出的第一個數據branch_ctr,j_ctr,jr_ctr,NPC[31:0], //下一條指令的地址jalPC[31:0] //jal跳轉的地址*/Pc mypc (NPC_ctr,NPC[31:0],clk,reset,PC[31:0]);/*NPC[31:0], //NextPC計算單元clk, //時鐘信號reset, //復位PC[31:0] //輸出下一條指令的地址*/ endmodulegpr.v
//GPR寄存器堆 `timescale 1ns / 1ns //注意組合邏輯(always敏感列表)用=賦值,時序邏輯(clk控制)用<=賦值 module GPR(input [31:0] WPC, //由PC輸入 writePC 僅用于控制臺輸出input clk,input reset,input RegWrite, //寫使能input [4:0] ra1, //ReadAddress1input [4:0] ra2, //ReadAddress2input [4:0] wa, //WriteAddressinput [31:0]wd, //WriteDataoutput [31:0] rd1, //ReadData1output [31:0] rd2 //ReadData2);reg[31:0] regfile[31:0]; //定義32個 32-bit寄存器assign rd1 = regfile[ra1]; //第一個讀出的數據assign rd2 = regfile[ra2]; //第二個讀出的數據integer i;initialbeginfor(i = 0; i < 32; i = i + 1) regfile[i] <= 0;end//時序邏輯always@(negedge clk, posedge reset)beginif(reset)beginfor(i = 0; i < 32; i = i + 1) regfile[i] <= 0;endelse if(RegWrite==1 && wa != 0)//wa就是WriteAddress 不能寫0號寄存器beginregfile[wa] <= wd;//寫入數據$display($time,,"(Write GPR)PC%b: WriteAddress%b <= Data%b", WPC, wa, wd);#1begin$display($time,,"(Show GPR)");for(i = 0; i < 32; i = i + 1)begin$display($time,,"GPR%d = %h", i, regfile[i]);endendendelse if(RegWrite==0)//寫使能無效begin$display($time,,"(GPR)Write:false");endelse//寫使能有效但是寄存器地址為0begin$display($time,,"(GPR)DEFAULT:You CANNOT Write To GPR Address 0x00000000");endend endmoduleim.v
`timescale 1ns/1ns //IM 指令存儲器 與上一個模塊以導線相連wire輸入 將本模塊數據輸出到下一個模塊reg輸出 module im_4k(input [11:2]addr,//與上一個模塊以導線相連 10bit 要取出的指令地址output reg[31:0]dout,//取出的整條指令output reg[5:0]op,//輸出 6位操作碼opoutput reg[4:0]rs,//輸出 源1output reg[4:0]rt,//輸出 源2output reg[4:0]rd,//輸出 目的output reg[4:0]shamt,//只用于移位指令slloutput reg[5:0]func,//指出ALU的功能output reg[15:0]immediate16,//beq的低16位分支地址output reg[25:0]immediate26//J指令的低26位跳轉地址);reg [31:0]im[1023:0];//im存儲讀取的所有指令 2^10wire [11:2]address;//因為im一共只有2^10,所以address的位寬為10assign address=addr;//按字節尋址,address自動取addr的左移兩位 實際超出去沒關系 im一共只有2^10,地址只取[11:2]這段 雖然PC復位后初值為0x0000_3000與MARS的Memory Configuration相配合 但是實際尋址時,超出部分被忽略integer i;initial begin$readmemh("p3-test.txt",im);//從文件中讀取指令 格式:$readmemb("<數據文件名>",<存貯器名>,<起始地址>);begin$display("(IM)Finish Read File",im);for(i=0;i<128;i=i+1)$write("%h ", im[i]);$write("\n");//換行專用endendalways @(*)//分離輸出指令的各個部分beginop=im[address][31:26];rs=im[address][25:21];rt=im[address][20:16];rd=im[address][15:11];shamt=im[address][10:6];func=im[address][5:0];immediate16=im[address][15:0];immediate26=im[address][25:0];$display($time,,"(IM)Current Code:%b %b %b %b %b %b ; TheAddrOfCurCode = %b ",op,rs,rt,rd,shamt,func,addr);endendmodulemips_tb.v
//用于測試整個處理器 `timescale 1ns/1ns //仿真時間單位/時間精度 `include "mips.v"module mips_tb;reg clk;reg reset;mips mymips(clk, reset);always #10 clk = ~clk;initial clk = 0;initialbegin$monitor($time,,"(mips_tb)clk = %b",clk);$display("display is Valid");#4500$finish;endendmodulemultiplexer
//多路選擇器`timescale 1ns / 1ns//注意組合邏輯(敏感列表)用=賦值,時序邏輯(clk控制)用<=賦值//二選一 32bit module mutiplexer32_1(input control,input [31:0] din0,input [31:0] din1,output reg [31:0] out32_1);always @(*)beginif(control==0) out32_1 = din0;else out32_1 = din1;$display($time,,"(MUX DataTo DM/ALU)control = %b, din0 = %b, din1 = %b, out = %b", control, din0, din1, out32_1);end endmodule//四選一 32bit 00ALU運算結果 01數據存儲器的輸出 10JAL跳轉的目的地址 11沒用 module mutiplexer32_2(input [1:0]control, //MemToReginput [31:0] din0, //00 ALU運算結果(包含高16拓展\普通運算)input [31:0] din1, //01 數據存儲器的輸出input [31:0] din2, //10 jalPC JAL跳轉的PC+4input [31:0] din3, //11 將lb指令從RAM中取出的數據存儲到Regoutput reg [31:0] out32_2);always @(*)beginif(control==0) out32_2=din0;else if(control==2'b01) out32_2=din1; //lwelse if(control==2'b10) out32_2=din2;else if(control==2'b11) out32_2=din3; //lb$display($time,,"(MUX RegWriteData)control = %b, din0 = %b, din1 = %b, din2 = %b, din3 = %b, out = %b", control, din0, din1, din2, din3, out32_2);end endmodule//3選1 5bit module mutiplexer5 (input [1:0] control, //Regdst寫寄存器的目標寄存器號來源 00:rt (lui) 01:rd 10:5'b11111 reg31input [4:0] din0, //00:rt (lui)input [4:0] din1, //01:rdinput [4:0] din2, //10:5'b11111 31號寄存器output reg [4:0] out5);always @(*)beginif(control==0) out5=din0;else if(control==2'b01) out5=din1;else if(control==2'b10) out5=din2;$display($time,,"(MUX RegWriteAddr)control = %b, din0 = %b, din1 = %b, out = %b", control, din0, din1, out5);end endmodulenpc.v
`timescale 1ns / 1ns //計算下一條指令的地址 //輸入的PC是當前指令的地址 //輸出的NPC是下一條指令的地址 //計算機組成原理與設計P47:MIPS是按字節編址的,所以字的起始地址必須是4的倍數 lw sw的偏移地址單位是字節,即字*4 module NextPC(input NPC_ctr, //控制PC是否更改input [31:0] PC, //當前指令的地址input [15:0] imm16, //當前指令的16位立即數,用于beq指令的分支地址input [25:0] imm26, //j,jalinput [31:0] rsd, //(jr指令)由rd1[31:0]輸入,通常是從31號寄存器中讀出的數據input branch_ctr, //PCSrc 判斷是否執行分支(PC+4 or PC+4+offset)input j_ctr, //判斷當前指令是否是J指令input jr_ctr,output reg [31:0] NPC, //下一條指令的地址output [31:0] jalPC //jal跳轉的地址 JAL跳轉的下一條地址是PC+4將要存在reg31z中 用于RegWriteData的計算);reg [31:0]imm16ex;assign jalPC = PC + 4;always @(NPC_ctr or j_ctr or jr_ctr)beginif(NPC_ctr)beginbeginif(j_ctr) NPC = {PC[31:28], imm26, 2'b0}; //j jal指令 需要將imm左移兩位才是要跳轉的地址else if(jr_ctr) NPC = rsd; //jr指令else if(branch_ctr) //beq指令,branch判斷是否執行分支 拓展時需要將imm16左移兩位beginif(imm16[15]==0) imm16ex={14'b00000000000000,imm16[15:0],2'b0}; //正數手動符號拓展else if(imm16[15]==1) imm16ex={14'b11111111111111,imm16[15:0],2'b0}; //負數手動符號拓展NPC = PC + 4 + imm16ex;$display($time,,"(NPC beq)imm16:%b imm16ex:%b PC+4:%b",imm16,imm16ex,PC + 4);endelse NPC = PC + 4;$display($time,,"(NPC)CurPCAddr:%b NextPcAddr:%b j_ctr=%b jr_ctr=%b ",PC,NPC,j_ctr,jr_ctr);endendendendmodulepc.v
//輸入:NPC代表的下一條指令的地址 //輸出:"下一條指令" 即 "當前指令"。如果不reset,則根據clk輸出當前指令PC的地址 `timescale 1ns / 1ns module Pc( input NPC_ctr, //控制PC是否更改input [31:0] NPC, //NextPC計算單元input clk, //時鐘信號input reset, //復位output reg [31:0] PC //輸出下一條指令的地址);initialbeginPC <= 32'h0000_3000; //PC復位后初值為0x0000_3000,目的是與MARS的Memory Configuration相配合endalways@(posedge clk, posedge reset)//任何一個變動都可以觸發beginif(NPC_ctr)beginif(reset) PC <= 32'h0000_3000;//PC復位后初值為0x0000_3000,目的是與MARS的Memory Configuration相配合else PC <= NPC;$display($time,,"(PC)NextPcAddr%b",PC);endend endmodulealu.v
`timescale 1ns / 1ns /** Module Name: ALU* File Created: 2019-4-4 16:11:12* Notes: overflow是溢出標志位* ALUOp 3'b000: Result=($signed(A)<$signed(B))?32'h0000_0001:32'h0000_0000;//若A<B,則result=1 3'b001: Result=A|B;//或 3'b010: Result=A+B;//加 3'b011: Result={B[15:0],16'h0000};//拓展到高16位 3'b101: Result=B<<sl;//邏輯左移 3'b110: Result=A-B;//減 3'b111: Result = 32'h0000_0000//default*///注意組合邏輯(敏感列表)用=賦值,時序邏輯(clk控制)用<=賦值module ALU( input [31:0] A, //輸入32位Ainput [31:0] B, //輸入32位Binput [4:0] sl, //左移的位數input [2:0] ALUctr, //3位ALU控制信號output reg[31:0] Result, //因為要在always里面賦值,所以定義為regoutput reg zero, //零標志位output reg overflow //溢出標志位 addi加立即數支持溢出,如果溢出,(CTRL)讓寄存器寫使能無效);initial overflow = 0;always@(*) //(*)表示自動添加敏感列表begincase(ALUctr)//決定ALU操作3'b000: //若A<B,則result=1beginResult=($signed(A)<$signed(B))?32'h0000_0001:32'h0000_0000;$display($time,,"(ALU)(if a<b,res=1)A = %b, B = %b, Result = %b", A, B, Result);end3'b001: //或beginResult=A|B;$display($time,,"(ALU)(or)A = %b, B = %b, Result = %b", A, B, Result);end3'b010: //加beginResult=A+B;if((A[31]==1'h0&&B[31]==1'h0&&Result[31]==1'h1) || (A[31]==1'h1&&B[31]==1'h1&&Result[31]==1'h0))beginoverflow=1'h1;//正溢/負溢$write("OVERFLOW!\n");endelse overflow=1'h0;//如果沒有這一句 會產生鎖存器?反正會有明明不溢出卻被判斷溢出的bug$display($time,,"(ALU)(add)A = %b, B = %b, Result = %b A[31]=%b B[31]=%b overflow=%b", A, B, Result,A[31],B[31],overflow);end3'b011: //拓展到高16位 luibeginResult={B[15:0],16'h0000};$display($time,,"(ALU)(16toUp32)A = %b, B = %b, Result = %b", A, B, Result);end3'b101: //邏輯左移beginResult=B<<sl;$display($time,,"(ALU)(<<)A = %b, B = %b, Result = %b", A, B, Result);end3'b110: //減beginResult=A-B;$display($time,,"(ALU)(sub)A = %b, B = %b, Result = %b", A, B, Result);enddefault:beginResult<=32'h0000_0000;$display($time,,"(ALU)(DEFAULT)");endendcaseif(A==B) zero=1;//計算零標志位else zero=0;endendmodulecrtl
//控制單元controller `timescale 1ns/1ns /* ALUOp 3'b000: Result=($signed(A)<$signed(B))?32'h0000_0001:32'h0000_0000;//若A<B,則result=1 3'b001: Result=A|B;//或 3'b010: Result=A+B;//加 3'b011: Result={B[15:0],16'h0000};//拓展到高16位 3'b101: Result=B<<sl;//邏輯左移 3'b110: Result=A-B;//減 3'b111: Result = 32'h0000_0000//defaultEXTOp 2'b00:無符號16to32 2'b01:有符號16to32 2'b10:拓展到高16位 */ module control(input clk,input [5:0] opcode, //6位操作碼input zero, //beq指令input [5:0] func,input overflow, //溢出標志位 addi專用output reg [1:0]RegDst, //寫寄存器的目標寄存器號來源:00:rt (lui) 01:rd 10:5'b11111 reg31output reg ALUSrc, //第二個ALU操作數的來源output reg [1:0] MemToReg, //寫入寄存器的數據來源 00ALU運算結果 01數據存儲器的輸出 10JAL跳轉的目的地址output reg RegWrite, //寄存器寫使能有效output reg MemWrite, //將數據寫入到指定存儲器單元中output reg PCSrc, //判斷是否執行分支(PC+4 or PC+4+offset)output reg [1:0]ExtOp, //控制Extender的拓展方式output reg [2:0]ALUctr, //3bit 控制ALU的運算output reg j_ctr, //控制PC是否轉移到J指令指示的地址output reg jr_ctr, //jr指令output reg sb_ctr, //sb指令output reg DMSrc, //(冗余)輸入到DM中的數據來源output reg NPC_ctr //控制PC是否更改);parameter [2:0] sif = 3'b000,sid = 3'b001,exe = 3'b010,mem = 3'b011,wb = 3'b100;reg [2:0] state;reg [2:0] next_state;parameter [5:0] j_op = 6'b000010;parameter [5:0] jal_op = 6'b000011;parameter [5:0] jr_op = 6'b000000 ,jr_func = 6'b001000;parameter [5:0] addu_op = 6'b000000 ,addu_func = 6'b100001;parameter [5:0] subu_op = 6'b000000 ,subu_func = 6'b100011;parameter [5:0] slt_op = 6'b000000 ,slt_func = 6'b101010;parameter [5:0] ori_op = 6'b001101;parameter [5:0] lw_op = 6'b100011;parameter [5:0] sw_op = 6'b101011;parameter [5:0] beq_op = 6'b000100;parameter [5:0] lui_op = 6'b001111;parameter [5:0] addi_op = 6'b001000;parameter [5:0] addiu_op = 6'b001001;parameter [5:0] lb_op = 6'b100000;parameter [5:0] sb_op = 6'b101000;reg [2:0]defaulter = 0; //為了不讓第一個指令被跳過//初始化initial beginRegDst = 2'b00; //寫寄存器的目標寄存器號來源:00:rt(lui) 01:rd 10:5'b11111 reg31ALUSrc = 0; //第二個ALU操作數的來源0-讀寄存器2 1-指令低16位的符號拓展MemToReg = 2'b0; //寫入寄存器的數據來源 00ALU運算結果 01數據存儲器的輸出 10JAL跳轉的目的地址RegWrite = 0; //寄存器寫使能有效MemWrite = 0; //將數據寫入到指定存儲器單元中PCSrc = 0; //判斷是否執行分支(PC+4 or PC+4+offset)ExtOp = 2'b0; //控制Extender的拓展方式00無符號16to32 01:有符號16to32 10拓展到高16ALUctr = 3'b111; //3bit 控制ALU的運算j_ctr = 0; //控制PC是否轉移到J指令指示的地址jr_ctr = 0; //jr指令sb_ctr = 0; //sb指令 除了sb_ctr以外sb指令完全模仿sw DMSrc = 0;NPC_ctr = 0;end//狀態根據時鐘轉移always @(posedge clk) beginstate <= next_state;end//狀態機 此部分根據當前狀態確定下一個狀態 狀態轉移過程always @(state or opcode or func) begincase(state)sif: beginnext_state = sid;$display("(CTRL)sif next:sid");endsid: begincase (opcode)j_op:beginnext_state = sif; // j$display("(CTRL)sid next:sif");endjal_op:beginnext_state = wb; // jal$display("(CTRL)sid next:wb");end6'b000000:beginif(func == jr_func) beginnext_state = sif; //jr$display("(CTRL)sid next:sif");endelse beginnext_state = exe; //除了 j jal以外的所有op=000000指令$display("(CTRL)sid next:exe");endenddefault: beginnext_state = exe; //上述以外所有指令$display("(CTRL)sid next:exe");endendcaseendexe: begincase (opcode)beq_op: beginnext_state = sif; // beq$display("(CTRL)exe next:sif");endlw_op: beginnext_state = mem; // lw$display("(CTRL)exe next:mem");endsw_op: beginnext_state = mem; // sw$display("(CTRL)exe next:mem");endlb_op: beginnext_state = mem; // lb$display("(CTRL)exe next:mem");endsb_op: beginnext_state = mem; // sb$display("(CTRL)exe next:mem");enddefault:beginnext_state = wb; //上述以外所有指令$display("(CTRL)exe next:wb");endendcaseendmem:beginif(opcode == lw_op || opcode == lb_op)beginnext_state = wb; //lw lb$display("(CTRL)mem next:wb");endelse beginnext_state = sif; //sw$display("(CTRL)mem next:sif");end endwb: beginnext_state = sif;$display("(CTRL)wb next:sif");enddefault: beginnext_state = sif; //理論上不應該存在此項defaulter = 2;$display("(CTRL)default next:sif defaulter=%d",defaulter);endendcase//輸出beginif(opcode==j_op) $display($time,"(CTRL)J OpCode = %b func = %b",opcode,func);else if(opcode==jal_op) $display($time,"(CTRL)JAL OpCode = %b func = %b",opcode,func);else if(opcode==jr_op && func==jr_func) $display($time,"(CTRL)JR OpCode = %b func = %b",opcode,func);else if(opcode==addu_op && func==addu_func) $display($time,"(CTRL)ADDU OpCode = %b func = %b",opcode,func);else if(opcode==subu_op && func==subu_func) $display($time,"(CTRL)SUBU OpCode = %b func = %b",opcode,func);else if(opcode==slt_op && func==slt_func) $display($time,"(CTRL)SLT OpCode = %b func = %b",opcode,func);else if(opcode==ori_op) $display($time,"(CTRL)ORI OpCode = %b func = %b",opcode,func);else if(opcode==lw_op) $display($time,"(CTRL)LW OpCode = %b func = %b",opcode,func);else if(opcode==sw_op) $display($time,"(CTRL)SW OpCode = %b func = %b",opcode,func);else if(opcode==beq_op) $display($time,"(CTRL)BEQ OpCode = %b func = %b",opcode,func);else if(opcode==lui_op) $display($time,"(CTRL)LUI OpCode = %b func = %b",opcode,func);else if(opcode==addi_op) $display($time,"(CTRL)ADDI OpCode = %b func = %b",opcode,func);else if(opcode==addiu_op) $display($time,"(CTRL)ADDIU OpCode = %b func = %b",opcode,func);else if(opcode==lb_op) $display($time,"(CTRL)LB OpCode = %b func = %b",opcode,func);else if(opcode==sb_op) $display($time,"(CTRL)SB OpCode = %b func = %b",opcode,func);else $display($time,"(CTRL)NO SUCH INSTRUCT!");endend//狀態改變->信號量改變 此部分根據當前狀態確定信號量always @(state or opcode or func) begin// 確定RegDst的值if (state == wb)beginif(opcode == jal_op) RegDst = 2'b10; // jalelse if(opcode == 6'b000000 && (func == addu_func || func == subu_func || func == slt_func))RegDst = 2'b01; //addu subu sltelse RegDst = 2'b00;endelse RegDst = 2'b00;// 確定ALUSrc的值if (state == exe)beginif(opcode == 6'b000000 && (func == addu_func || func == subu_func || func == slt_func)) ALUSrc = 0;else if(opcode == ori_op) ALUSrc = 1;else if(opcode == lw_op || opcode == sw_op || opcode == lui_op || opcode == addi_op || opcode == addiu_op || opcode == lb_op || opcode == sb_op) ALUSrc = 1;else ALUSrc = 0;endelse if(state == wb && func == ori_op) ALUSrc = 1;else ALUSrc = 0;// 確定MemToReg的值if (state == sid && opcode == j_op) MemToReg = 2'b00;else if(state == wb)beginif(opcode == jal_op) MemToReg = 2'b10;else if(opcode == lw_op) MemToReg = 2'b01;else if(opcode == lb_op) MemToReg = 2'b11;else MemToReg = 2'b00;endelse MemToReg = 2'b00;// 確定RegWrite的值:wb狀態下 只有在addi才檢測溢出,其余情況直接 =1if (state == wb)beginif(opcode == addi_op && overflow == 1)RegWrite = 0;//addi溢出的情況 不能寫regelse RegWrite = 1;endelse RegWrite = 0;// 確定MemWrite的值if (state == mem && (opcode == sw_op || opcode == sb_op)) MemWrite = 1;else MemWrite = 0;// 確定PCSrc的值if (state == exe && opcode == beq_op && zero == 1) PCSrc = 1;else PCSrc = 0;// 確定ExtOp的值if (state == exe &&(opcode == lw_op || opcode == sw_op || opcode == beq_op || opcode == addi_op || opcode == addiu_op || opcode == lb_op || opcode == sb_op)) ExtOp = 2'b01;else ExtOp = 2'b00;// 確定ALUctr的值if (state == exe)beginif (opcode == addu_op && func == addu_func) ALUctr = 3'b010;else if (opcode == subu_op && func == subu_func) ALUctr = 3'b110;else if (opcode == slt_op && func == slt_func) ALUctr = 3'b000;else if (opcode == ori_op) ALUctr = 3'b001;else if (opcode == lw_op || opcode == sw_op || opcode == addi_op || opcode == addiu_op || opcode == lb_op || opcode == sb_op) ALUctr = 3'b010;else if (opcode == lui_op) ALUctr = 3'b011;else ALUctr = 3'b111;endelse ALUctr = 3'b111;// 確定j_ctr的值 這樣寫行嗎 我是說真值表填的對不對if (opcode == j_op && state == sid) j_ctr = 1;else if (opcode == jal_op && state == wb) j_ctr = 1;else j_ctr = 0;// 確定jr_ctr的值if (opcode == jr_op && func == jr_func && state == sid) jr_ctr = 1;else jr_ctr = 0;// 確定DMSrc的值 沒用DMSrc = 0;// 確定NPC_ctr的值if (state == sif)NPC_ctr = 1;else NPC_ctr = 0;//確定sb_ctr的值if (state == mem && opcode == sb_op) sb_ctr = 1;else sb_ctr = 0;//保護第一條指令不被跳過if(defaulter > 0 && defaulter != 3)begin$display("defaulter=%d",defaulter);defaulter = defaulter - 1;$display("defaulter=%d",defaulter);if(defaulter == 0)beginNPC_ctr = 0;defaulter = 3;endend$display($time,"(CTRL)OpCode=%b func=%b RegDst=%b ALUSrc=%b MemToReg=%b RegWrite=%b MemWrite=%b PCSrc=%b ExtOp=%b ALUctr=%b j_ctr=%b jr_ctr=%b DMSrc=%b NPC_ctr=%b defaulter=%d",opcode,func,RegDst,ALUSrc,MemToReg,RegWrite,MemWrite,PCSrc,ExtOp,ALUctr,j_ctr,jr_ctr,DMSrc,NPC_ctr,defaulter);end endmoduledm.v
`timescale 1ns / 1ns //DM數據寄存器 module dm_4k(input [11:0]addr12, //lb sb指令專用input [11:2]addr, //(sw指令)由Result[11:2](ALU基地址+偏移的計算結果)輸入,表示要寫入的數據單元的地址input [31:0]din, //datain sw sb指令input we, //MemWrite數據存儲器寫使能input sb_ctr,input clk,output [31:0] dout, //dataout 取出的數據output reg [31:0] lbout //dataout lb專用);wire [11:2] address; //以字為單位的地址,因為寄存器是1024"字"assign address = addr;reg[31:0] dm[1023:0]; //32bit*1024字的數據存儲器//普通的讀數據assign dout = dm[address];//始終輸出integer i;initialbeginfor(i = 0; i < 1024; i = i + 1) dm[i] <= 0;//初始化數據存儲器為0end//給lb專用的數據輸出always@(*)begincase(addr12[1:0])2'b00:beginif(dm[address][7]==0)lbout = {24'b0000_0000_0000_0000_0000_0000,dm[address][7:0]};else lbout = {24'b1111_1111_1111_1111_1111_1111,dm[address][7:0]};end2'b01:beginif(dm[address][15]==0)lbout = {24'b0000_0000_0000_0000_0000_0000,dm[address][15:8]};else lbout = {24'b1111_1111_1111_1111_1111_1111,dm[address][15:8]};end2'b10:beginif(dm[address][23]==0)lbout = {24'b0000_0000_0000_0000_0000_0000,dm[address][23:16]};else lbout = {24'b1111_1111_1111_1111_1111_1111,dm[address][23:16]};end2'b11:beginif(dm[address][31]==0)lbout = {24'b0000_0000_0000_0000_0000_0000,dm[address][31:24]};else lbout = {24'b1111_1111_1111_1111_1111_1111,dm[address][31:24]};endendcase$display($time,,"(DM LBread)addr12[1:0]=%b lbout=%b", addr12[1:0], lbout);//lb專用送出endalways@(negedge clk)begin //寫寄存器if(we)beginif(sb_ctr) //sb指令只寫一個字節 不能影響旁邊begin$display($time,,"(DM)Before MemWrite:");beginfor(i=0;i<128;i=i+1)$write("%h ", dm[i]);$write("\n");//換行專用endcase(addr12[1:0])2'b00:dm[address][7:0] <= din[7:0];2'b01:dm[address][15:8] <= din[7:0];2'b10:dm[address][23:16] <= din[7:0];2'b11:dm[address][31:24] <= din[7:0];endcase#1begin$display($time,,"(DM MemWrite)dmAddr%b <= Data%b", addr, din);$display($time,,"(DM)Finish MemWrite:");beginfor(i=0;i<128;i=i+1)$write("%h ", dm[i]);$write("\n");//換行專用endendendelse //sw指令begin$display($time,,"(DM)Before MemWrite:");beginfor(i=0;i<128;i=i+1)$write("%h ", dm[i]);$write("\n");//換行專用enddm[address] <= din;#1begin$display($time,,"(DM MemWrite)dmAddr%b <= Data%b", addr, din);$display($time,,"(DM)Finish MemWrite:");beginfor(i=0;i<128;i=i+1)$write("%h ", dm[i]);$write("\n");//換行專用endendendendend endmoduleext.v
//Extender位拓展 /* EXTOp 2'b00:無符號16to32 2'b01:有符號16to32 2'b10:拓展到高16位 *///注意組合邏輯(always敏感列表)用=賦值,時序邏輯(clk控制)用<=賦值 `timescale 1ns / 1ns module EXT(input [15:0] EXTin, //輸入EXT的數據input [1:0]ExtOp,output reg [31:0] EXTout //拓展后輸出的數據);always@(*)begincase(ExtOp)2'b00://無符號16to32beginEXTout = {16'b0,EXTin[15:0]};$display($time,,"(EXT)EXTOp = 00; EXTin = %b EXTout = %b",EXTin, EXTout);end2'b01://有符號16to32beginif(EXTin[15]==1)EXTout = {16'b1111_1111_1111_1111,EXTin[15:0]};else EXTout = {16'b0000_0000_0000_0000,EXTin[15:0]};$display($time,,"(EXT)EXTOp = 01; EXTin = %b EXTout = %b",EXTin, EXTout);end2'b10://拓展至高16beginEXTout = {EXTin[15:0],16'b0000_0000_0000_0000};$display($time,,"(EXT)EXTOp = 10; EXTin = %b EXTout = %b",EXTin, EXTout);enddefault: begin$display($time,,"(EXT)EXTOp = default");EXTout = 32'b0;endendcaseend endmoduledatalate
`timescale 1ns / 1ns//32位 module DataLate32A(input [31:0] i_data, //ininput clk,output reg [31:0] o_data //out);always @(negedge clk) begino_data <= i_data;$display($time,,"(DataLate_A)in:%b out:%b",i_data,o_data);end endmodulemodule DataLate32B(input [31:0] i_data, //ininput clk,output reg [31:0] o_data //out);always @(negedge clk) begino_data <= i_data;$display($time,,"(DataLate_B)in:%b out:%b",i_data,o_data);end endmodulemodule DataLate32ALU(input [31:0] i_data, //ininput clk,output reg [31:0] o_data //out);always @(negedge clk) begino_data <= i_data;$display($time,,"(DataLate_ALU)in:%b out:%b",i_data,o_data);end endmodulemodule DataLate32RAM(input [31:0] i_data, //ininput clk,output reg [31:0] o_data //out);always @(negedge clk) begino_data <= i_data;$display($time,,"(DataLate_RAM)in:%b out:%b",i_data,o_data);end endmodulemodule DataLate32RAMLB(input [31:0] i_data, //ininput clk,output reg [31:0] o_data //out);always @(negedge clk) begino_data <= i_data;$display($time,,"(DataLate_RAM_LB)in:%b out:%b",i_data,o_data);end endmodule//1位 module DataLate1(input i_data, //ininput clk,output reg o_data //out);always @(negedge clk) begino_data <= i_data;$display($time,,"(DataLateOverFlow)out:%b",o_data);end endmodule//j+jr_ctr module DataLate_J_JR(input i_data, //ininput clk,output reg o_data //out);always @(posedge clk) begino_data <= i_data;$display($time,,"(DataLate_J/JR/PCsrc)in:%b out:%b",i_data,o_data);end endmodule部分控制臺輸出結果
# (CTRL)wb next:sif # 5030(CTRL)ADDU OpCode = 000000 func = 100001 # 5030(CTRL)OpCode=000000 func=100001 RegDst=01 ALUSrc=0 MemToReg=00 RegWrite=1 MemWrite=0 PCSrc=0 ExtOp=00 ALUctr=111 j_ctr=0 jr_ctr=0 DMSrc=0 NPC_ctr=0 defaulter=3 # 5030 (MUX RegWriteAddr)control = 01, din0 = 00000, din1 = 01001, out = 01001 # 5030 (ALU)(DEFAULT) # 5030 (ALU)(DEFAULT) # 5030 (mips_tb)clk = 1 # 5040 (Write GPR)PC00000000000000000011000010111000: WriteAddress01001 <= Data00101011101010111100110111010001 # 5040 (DataLate_A)in:00101011101010111100110111010001 out:00101011101010111100110111010001 # 5040 (DataLate_B)in:00000000000000000000000000000000 out:00000000000000000000000000000000 # 5040 (DataLate_RAM)in:00000000000000000000000000000000 out:10000000000000000000001000000010 # 5040 (DataLate_RAM_LB)in:00000000000000000000000000000000 out:00000000000000000000000000000010 # 5040 (DataLate_ALU)in:00000000000000000000000000000000 out:00101011101010111100110111010001 # 5040 (DataLateOverFlow)out:0 # 5040 (DM LBread)addr12[1:0]=00 lbout=00000000000000000000000000000010 # 5040 (MUX RegWriteData)control = 00, din0 = 00000000000000000000000000000000, din1 = 00000000000000000000000000000000, din2 = 00000000000000000011000010111100, din3 = 00000000000000000000000000000000, out = 00000000000000000000000000000000 # 5040 (mips_tb)clk = 0 # 5041 (Show GPR) # 5041 GPR 0 = 00000000 # 5041 GPR 1 = ababcdcd # 5041 GPR 2 = ababcdd3 # 5041 GPR 3 = ababcdcd # 5041 GPR 4 = 2babcdd1 # 5041 GPR 5 = 80000002 # 5041 GPR 6 = 00000000 # 5041 GPR 7 = 00000000 # 5041 GPR 8 = 2babcdd1 # 5041 GPR 9 = 2babcdd1 # 5041 GPR 10 = 80000004 # 5041 GPR 11 = 00000000 # 5041 GPR 12 = 0000abab # 5041 GPR 13 = 000a0000 # 5041 GPR 14 = 0000007f # 5041 GPR 15 = ab000000 # 5041 GPR 16 = 00000003 # 5041 GPR 17 = 00000001 # 5041 GPR 18 = ffffff80 # 5041 GPR 19 = efef0000 # 5041 GPR 20 = 00000000 # 5041 GPR 21 = 00000000 # 5041 GPR 22 = 00000000 # 5041 GPR 23 = ababcdd2 # 5041 GPR 24 = 7fffffff # 5041 GPR 25 = 00000001 # 5041 GPR 26 = 00000000 # 5041 GPR 27 = 00000000 # 5041 GPR 28 = 00000000 # 5041 GPR 29 = 00000000 # 5041 GPR 30 = 00000000 # 5041 GPR 31 = 000030b4 # 5050 (DataLate_J/JR/PCsrc)in:0 out:0 # 5050 (DataLate_J/JR/PCsrc)in:0 out:0 # 5050 (DataLate_J/JR/PCsrc)in:0 out:0 # (CTRL)sif next:sid # 5050(CTRL)ADDU OpCode = 000000 func = 100001 # 5050(CTRL)OpCode=000000 func=100001 RegDst=00 ALUSrc=0 MemToReg=00 RegWrite=0 MemWrite=0 PCSrc=0 ExtOp=00 ALUctr=111 j_ctr=0 jr_ctr=0 DMSrc=0 NPC_ctr=1 defaulter=3 # 5050 (NPC)CurPCAddr:00000000000000000011000010111000 NextPcAddr:00000000000000000011000010111100 j_ctr=0 jr_ctr=0 # 5050 (MUX RegWriteAddr)control = 00, din0 = 00000, din1 = 01001, out = 00000 # 5050 (mips_tb)clk = 1 # 5060 (GPR)Write:false # 5060 (DataLate_A)in:00101011101010111100110111010001 out:00101011101010111100110111010001 # 5060 (DataLate_B)in:00000000000000000000000000000000 out:00000000000000000000000000000000 # 5060 (DataLate_RAM)in:10000000000000000000001000000010 out:00000000000000000000000000000000 # 5060 (DataLate_RAM_LB)in:00000000000000000000000000000010 out:00000000000000000000000000000000 # 5060 (DataLate_ALU)in:00000000000000000000000000000000 out:00000000000000000000000000000000 # 5060 (DataLateOverFlow)out:0 # 5060 (MUX RegWriteData)control = 00, din0 = 00000000000000000000000000000000, din1 = 10000000000000000000001000000010, din2 = 00000000000000000011000010111100, din3 = 00000000000000000000000000000010, out = 00000000000000000000000000000000 # 5060 (mips_tb)clk = 0 # 5070 (DataLate_J/JR/PCsrc)in:0 out:0 # 5070 (DataLate_J/JR/PCsrc)in:0 out:0 # 5070 (DataLate_J/JR/PCsrc)in:0 out:0 # 5070 (PC)NextPcAddr00000000000000000011000010111000 # 5070 (MUX RegWriteData)control = 00, din0 = 00000000000000000000000000000000, din1 = 10000000000000000000001000000010, din2 = 00000000000000000011000011000000, din3 = 00000000000000000000000000000010, out = 00000000000000000000000000000000 # 5070 (IM)Current Code:001111 00000 01010 00000 00001 101001 ; TheAddrOfCurCode = 0000101111 # (CTRL)sid next:exe # 5070(CTRL)ADDU OpCode = 000000 func = 100001 # 5070(CTRL)OpCode=000000 func=100001 RegDst=00 ALUSrc=0 MemToReg=00 RegWrite=0 MemWrite=0 PCSrc=0 ExtOp=00 ALUctr=111 j_ctr=0 jr_ctr=0 DMSrc=0 NPC_ctr=0 defaulter=3 # 5070 (MUX DataTo DM/ALU)control = 0, din0 = 10000000000000000000000000000100, din1 = 00000000000000000100100000100001, out = 10000000000000000000000000000100 # 5070 (MUX RegWriteAddr)control = 00, din0 = 01010, din1 = 00000, out = 01010 # (CTRL)sid next:exe # 5070(CTRL)LUI OpCode = 001111 func = 101001 # 5070(CTRL)OpCode=001111 func=101001 RegDst=00 ALUSrc=0 MemToReg=00 RegWrite=0 MemWrite=0 PCSrc=0 ExtOp=00 ALUctr=111 j_ctr=0 jr_ctr=0 DMSrc=0 NPC_ctr=0 defaulter=3 # 5070 (EXT)EXTOp = 00; EXTin = 0000000001101001 EXTout = 00000000000000000000000001101001 # 5070 (ALU)(DEFAULT) # 5070 (ALU)(DEFAULT) # 5070 (MUX DataTo DM/ALU)control = 0, din0 = 10000000000000000000000000000100, din1 = 00000000000000000000000001101001, out = 10000000000000000000000000000100 # 5070 (mips_tb)clk = 1 # 5080 (GPR)Write:false # 5080 (DataLate_A)in:00000000000000000000000000000000 out:00101011101010111100110111010001 # 5080 (DataLate_B)in:10000000000000000000000000000100 out:00000000000000000000000000000000 # 5080 (DataLate_RAM)in:10000000000000000000001000000010 out:10000000000000000000001000000010 # 5080 (DataLate_RAM_LB)in:00000000000000000000000000000010 out:00000000000000000000000000000010 # 5080 (DataLate_ALU)in:00000000000000000000000000000000 out:00000000000000000000000000000000 # 5080 (DataLateOverFlow)out:0 # 5080 (mips_tb)clk = 0 # 5090 (DataLate_J/JR/PCsrc)in:0 out:0 # 5090 (DataLate_J/JR/PCsrc)in:0 out:0 # 5090 (DataLate_J/JR/PCsrc)in:0 out:0 # (CTRL)exe next:wb # 5090(CTRL)LUI OpCode = 001111 func = 101001 # 5090(CTRL)OpCode=001111 func=101001 RegDst=00 ALUSrc=1 MemToReg=00 RegWrite=0 MemWrite=0 PCSrc=0 ExtOp=00 ALUctr=011 j_ctr=0 jr_ctr=0 DMSrc=0 NPC_ctr=0 defaulter=3 # 5090 (ALU)(16toUp32)A = 00000000000000000000000000000000, B = 10000000000000000000000000000100, Result = 00000000000001000000000000000000 # 5090 (MUX DataTo DM/ALU)control = 1, din0 = 10000000000000000000000000000100, din1 = 00000000000000000000000001101001, out = 00000000000000000000000001101001 # 5090 (ALU)(16toUp32)A = 00000000000000000000000000000000, B = 00000000000000000000000001101001, Result = 00000000011010010000000000000000 # 5090 (mips_tb)clk = 1 # 5100 (GPR)Write:false # 5100 (DataLate_A)in:00000000000000000000000000000000 out:00000000000000000000000000000000 # 5100 (DataLate_B)in:10000000000000000000000000000100 out:10000000000000000000000000000100 # 5100 (DataLate_RAM)in:10000000000000000000001000000010 out:10000000000000000000001000000010 # 5100 (DataLate_RAM_LB)in:00000000000000000000000000000010 out:00000000000000000000000000000010 # 5100 (DataLate_ALU)in:00000000011010010000000000000000 out:00000000000000000000000000000000 # 5100 (DataLateOverFlow)out:0 # 5100 (MUX RegWriteData)control = 00, din0 = 00000000011010010000000000000000, din1 = 10000000000000000000001000000010, din2 = 00000000000000000011000011000000, din3 = 00000000000000000000000000000010, out = 00000000011010010000000000000000 # 5100 (mips_tb)clk = 0 # 5110 (DataLate_J/JR/PCsrc)in:0 out:0 # 5110 (DataLate_J/JR/PCsrc)in:0 out:0 # 5110 (DataLate_J/JR/PCsrc)in:0 out:0 # (CTRL)wb next:sif # 5110(CTRL)LUI OpCode = 001111 func = 101001 # 5110(CTRL)OpCode=001111 func=101001 RegDst=00 ALUSrc=0 MemToReg=00 RegWrite=1 MemWrite=0 PCSrc=0 ExtOp=00 ALUctr=111 j_ctr=0 jr_ctr=0 DMSrc=0 NPC_ctr=0 defaulter=3 # 5110 (ALU)(DEFAULT) # 5110 (MUX DataTo DM/ALU)control = 0, din0 = 10000000000000000000000000000100, din1 = 00000000000000000000000001101001, out = 10000000000000000000000000000100 # 5110 (ALU)(DEFAULT) # 5110 (ALU)(DEFAULT) # 5110 (mips_tb)clk = 1 # 5120 (Write GPR)PC00000000000000000011000010111100: WriteAddress01010 <= Data00000000011010010000000000000000 # 5120 (DataLate_A)in:00000000000000000000000000000000 out:00000000000000000000000000000000 # 5120 (DataLate_B)in:10000000000000000000000000000100 out:10000000000000000000000000000100 # 5120 (DataLate_RAM)in:10000000000000000000001000000010 out:10000000000000000000001000000010 # 5120 (DataLate_RAM_LB)in:00000000000000000000000000000010 out:00000000000000000000000000000010 # 5120 (DataLate_ALU)in:00000000000000000000000000000000 out:00000000011010010000000000000000 # 5120 (DataLateOverFlow)out:0 # 5120 (MUX DataTo DM/ALU)control = 0, din0 = 00000000011010010000000000000000, din1 = 00000000000000000000000001101001, out = 00000000011010010000000000000000 # 5120 (MUX RegWriteData)control = 00, din0 = 00000000000000000000000000000000, din1 = 10000000000000000000001000000010, din2 = 00000000000000000011000011000000, din3 = 00000000000000000000000000000010, out = 00000000000000000000000000000000 # 5120 (ALU)(DEFAULT) # 5120 (mips_tb)clk = 0 # 5121 (Show GPR) # 5121 GPR 0 = 00000000 # 5121 GPR 1 = ababcdcd # 5121 GPR 2 = ababcdd3 # 5121 GPR 3 = ababcdcd # 5121 GPR 4 = 2babcdd1 # 5121 GPR 5 = 80000002 # 5121 GPR 6 = 00000000 # 5121 GPR 7 = 00000000 # 5121 GPR 8 = 2babcdd1 # 5121 GPR 9 = 2babcdd1 # 5121 GPR 10 = 00690000 # 5121 GPR 11 = 00000000 # 5121 GPR 12 = 0000abab # 5121 GPR 13 = 000a0000 # 5121 GPR 14 = 0000007f # 5121 GPR 15 = ab000000 # 5121 GPR 16 = 00000003 # 5121 GPR 17 = 00000001 # 5121 GPR 18 = ffffff80 # 5121 GPR 19 = efef0000 # 5121 GPR 20 = 00000000 # 5121 GPR 21 = 00000000 # 5121 GPR 22 = 00000000 # 5121 GPR 23 = ababcdd2 # 5121 GPR 24 = 7fffffff # 5121 GPR 25 = 00000001 # 5121 GPR 26 = 00000000 # 5121 GPR 27 = 00000000 # 5121 GPR 28 = 00000000 # 5121 GPR 29 = 00000000 # 5121 GPR 30 = 00000000 # 5121 GPR 31 = 000030b4總結
以上是生活随笔為你收集整理的【计组实验】P3 Verilog多周期处理器开发 MIPS指令集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【算法设计与分析】流水作业调度问题 动态
- 下一篇: C# 枚举类型在switch case语