?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-533274.html
一、設(shè)計(jì)目的
1、了解提高CPU性能的方法。
2、掌握流水線微處理器的工作原理。
3、理解數(shù)據(jù)冒險(xiǎn)、控制冒險(xiǎn)的概念以及流水線沖突的解決方法。
4、掌握流水線微處理器的測(cè)試方法。
二、設(shè)計(jì)要求
設(shè)計(jì)一種五級(jí)流水線的基于MIPS指令集的處理器,其可支持部分指令,能夠處理指令相關(guān)和數(shù)據(jù)相關(guān),使流水線能夠正常運(yùn)行。源碼q3026159745
三、設(shè)計(jì)內(nèi)容
1、各模塊設(shè)計(jì)
1.1、存儲(chǔ)器設(shè)計(jì)
Instruction指令存儲(chǔ)器,ROM
存儲(chǔ)微處理器的指令,讀出對(duì)應(yīng)地址的指令
Regfile寄存器堆
存儲(chǔ)各個(gè)寄存器的值,0號(hào)地址存R0的值,1號(hào)地址存儲(chǔ)R1的值,以此類(lèi)推
Data數(shù)據(jù)存儲(chǔ)器,RAM
存儲(chǔ)用戶的數(shù)據(jù),本實(shí)驗(yàn)存儲(chǔ)器中存儲(chǔ)的數(shù)據(jù)是對(duì)應(yīng)地址的值

?
圖1.1存儲(chǔ)器設(shè)計(jì)
?
1.2、ALU設(shè)計(jì)
ALU有A、B兩個(gè)輸入,F(xiàn)運(yùn)算類(lèi)型,Y為輸出
F與CU的ALUControl相連,控制ALU的運(yùn)算
具體功能如下
module alu(A,B,F,Y);
input [31:0]A;
input [31:0]B;
input [2:0]F;
output reg[31:0]Y;
always@(*)
begin
case(F)
3'b000:Y=A&B;
3'b001:Y=A|B;
3'b010:Y=A+B;
3'b011:Y=A/B;
3'b100:Y=A&~B;
3'b101:Y=A|~B;
3'b110:Y=A-B;
3'b111:Y=(A<B);
default:Y=32'bx;
endcase
end

?
圖1.2ALU設(shè)計(jì)
1.3、ALUForward的設(shè)計(jì)
ALUForward由兩個(gè)三路選擇器和一個(gè)二路選擇器組成,三路選擇器輸出SrcAE由ForwardAE控制
具體功能如下
moduleALU_Forward(ForwardAE,ForwardBE,RD1E,
RD2E,SignlmmE,ALUSrcE,ALUOutM,ResultW,
WriteDataE,SrcAE,SrcBE);
input[1:0]ForwardAE,ForwardBE;
inputALUSrcE;
input[31:0]ALUOutM,ResultW,RD1E,RD2E,SignlmmE;
outputreg[31:0]SrcAE,SrcBE,WriteDataE;
always@(*) begin
case(ForwardAE)
2'b00:SrcAE<=RD1E;
2'b01:SrcAE<=ResultW;
2'b10:SrcAE<=ALUOutM;
endcase
case(ForwardBE)
2'b00:WriteDataE<=RD2E;
2'b01:WriteDataE<=ResultW;
2'b10:WriteDataE<=ALUOutM;
endcase
if(ALUSrcE)
SrcBE<=SignlmmE;
else
SrcBE<=WriteDataE;
?
end
endmodule

?
圖1.3ALUForward的設(shè)計(jì)
?
1.4、Control_Unit設(shè)計(jì)
采用op 和 funct進(jìn)行譯碼,產(chǎn)生各個(gè)模塊的控制信號(hào)。
根據(jù)操作碼譯出相應(yīng)控制信號(hào)

?
圖1.4
moduleControl_Unit(
op,
funct,
RegWriteD,
RegDstD,
AluSrcD,
BranchD,
MemWriteD,
MemtoRegD,
ALUControlD
);
input[5:0]op;
input[5:0]funct;
outputreg RegWriteD;
outputreg RegDstD;
outputreg AluSrcD;
outputreg BranchD;
outputreg MemWriteD;
outputreg MemtoRegD;
outputreg[2:0]ALUControlD;
always@(*)
begin
case (op)
6'b000000:
begin
case (funct)
6'b100000:beginRegWriteD<=1;RegDstD<=1;AluSrcD<=0;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b010;end//add
6'b100001:beginRegWriteD<=1;RegDstD<=1;AluSrcD<=0;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b110;end//sub
6'b100100:beginRegWriteD<=1;RegDstD<=1;AluSrcD<=0;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b000;end//and
6'b100101:beginRegWriteD<=1;RegDstD<=1;AluSrcD<=0;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b001;end//or
6'b101010:beginRegWriteD<=1;RegDstD<=1;AluSrcD<=0;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b111;end//slt
?
6'b111111:beginRegWriteD<=1;RegDstD<=1;AluSrcD<=0;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b011;end//div
default: beginRegWriteD <= 0;RegDstD <= 0;AluSrcD <= 0;BranchD <= 0;MemWriteD<= 0;MemtoRegD <= 0;ALUControlD <= 3'b000;end //NOP
endcase
end
6'b100011:beginRegWriteD<=0;RegDstD<=0;AluSrcD<=1;BranchD<=0;MemWriteD<=1;MemtoRegD<=0;ALUControlD<=3'b010;end //sw
6'b101011:beginRegWriteD<=1;RegDstD<=0;AluSrcD<=1;BranchD<=0;MemWriteD<=0;MemtoRegD<=1;ALUControlD<=3'b010;end //lw
?
6'b001000:beginRegWriteD<=1;RegDstD<=0;AluSrcD<=1;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b010;end //addi
6'b001000:beginRegWriteD<=1;RegDstD<=0;AluSrcD<=1;BranchD<=0;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b110;end //subi
6'b000100:beginRegWriteD<=0;RegDstD<=0;AluSrcD<=0;BranchD<=1;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b110;end //beq
6'b000101:beginRegWriteD<=0;RegDstD<=0;AluSrcD<=0;BranchD<=1;MemWriteD<=0;MemtoRegD<=0;ALUControlD<=3'b110;end //bne
default: begin RegWriteD <=0;RegDstD <= 0;AluSrcD <= 0;BranchD <= 0;MemWriteD <= 0;MemtoRegD<= 0;ALUControlD <= 3'b000;end //NOP
endcase
end
endmodule
?
1.5、五級(jí)流水線clk設(shè)計(jì)
1.5.1clkPC
(1)取指令階段,如果復(fù)位rst不為低電平,則每次時(shí)鐘上升沿PCF刷新,若為低電平則PCF賦值為零
(2)StallF停頓,StallF為低電平,則PCF保持不變
(3)PCF的值即為本次取指令的地址,取出Instruction中的指令
(4)PCF來(lái)源有兩個(gè),一個(gè)是PC的累加,一個(gè)是相對(duì)轉(zhuǎn)移地址
moduleclkPC(clk,rst,StallF,PC,PCF);
inputclk,rst,StallF;
input[31:0] PC;
output reg[31:0] PCF;
always @(posedge clk)
begin
if(!rst)
PCF <= 32'b0;
else if(StallF==1'b0)
PCF <= PC;
else
PCF <= PCF;
end
?
endmodule

?
圖1.5.1clkPC clkFetch_Decode
1.5.2clkFetch_Decode
時(shí)鐘上升沿判斷
(1)是否有停頓,若有停頓則clk模塊輸出的信號(hào)保持不變;
(2)clr是否為高電平,若是,則將模塊輸出信號(hào)清零
(3)若停頓和清零信后均為低,則模塊輸入值對(duì)應(yīng)賦給輸出值
moduleclkFetch_Decode(clk,clr,StallD,RD,PCPlus4F,InstrD,PCPlus4D);
inputclk,clr,StallD;
input[31:0] RD,PCPlus4F;
outputreg[31:0] InstrD,PCPlus4D;
always @(posedge clk)
begin
if(StallD)begin
InstrD<=InstrD;
PCPlus4D<=PCPlus4D;
end
else if(clr)begin
InstrD <= 32'b0;
PCPlus4D<=32'b0;
end
else begin
InstrD<=RD;
PCPlus4D <= PCPlus4F;
end
end
endmodule
1.5.3 clkDecode_Excute
每當(dāng)時(shí)鐘信號(hào)上升沿判斷FLUSH信號(hào)是否為高電平,若是,則清零模塊的輸出信號(hào),若否則輸入信號(hào)賦給相應(yīng)的輸出信號(hào)。
Branch信號(hào)單周期在ALU判斷Rt和Rs是否相等并轉(zhuǎn)移,而流水線CPU中可以提前判斷是否轉(zhuǎn)移
moduleclkDecode_Excute(clk,clr,RegWriteD,RegDstD,ALUSrcD,
BranchD,MemWriteD,MemtoRegD,
ALUControlD,RD1,RD2,RsD,RtD,RdD,SignlmmD,RegWriteE,RegDstE,ALUSrcE,
MemWriteE,MemtoRegE,ALUControlE,RD1E,RD2E,RtE,RdE,RsE,SignlmmE);
?
inputclk,clr,RegWriteD,RegDstD,ALUSrcD,MemWriteD,MemtoRegD,BranchD;
input[2:0] ALUControlD;
input[4:0] RtD,RdD,RsD;
input[31:0] RD1,RD2,SignlmmD;
?
outputreg RegWriteE,RegDstE,ALUSrcE,MemWriteE,MemtoRegE;
outputreg[2:0] ALUControlE;
outputreg[4:0] RtE,RdE,RsE;
outputreg[31:0] RD1E,RD2E,SignlmmE;
?
always @(posedge clk)
begin
?
if(!clr)
begin
RegWriteE<=RegWriteD;
RegDstE<=RegDstD;
ALUSrcE<=ALUSrcD;
MemWriteE<=MemWriteD;
MemtoRegE<=MemtoRegD;
ALUControlE<=ALUControlD;
?
RD1E<=RD1;
RD2E<=RD2;
RsE<=RsD;
RtE<=RtD;
RdE<=RdD;
SignlmmE<=SignlmmD;
end
?
else
begin//清空流水線
RegWriteE<=0;
RegDstE<=0;
ALUSrcE<=0;
MemWriteE<=0;
MemtoRegE<=0;
ALUControlE<=3'b0;
RD1E<=32'b0;
RD2E<=32'b0;
RsE<=5'b0;
RtE<=5'b0;
RdE<=5'b0;
SignlmmE<=32'b0;
end
end
?
endmodule

?
圖1.5.3clkDecode_Excute
?
1.5.4 clkExcude_Memory
moduleclkExcude_Memory(clk,RegWriteE,MemtoRegE,MemWriteE,
ALUResult,WriteDataE,WriteRegE,
RegWriteM,MemtoRegM,MemWriteM,ALUOutM,WriteDataM,WriteRegM);
?
input clk,RegWriteE,MemtoRegE,MemWriteE;
input [4:0] WriteRegE;
input [31:0] ALUResult,WriteDataE;
?
output reg RegWriteM,MemtoRegM,MemWriteM;
output reg[4:0] WriteRegM;
output reg[31:0] ALUOutM,WriteDataM;
always @ (posedge clk)
begin
RegWriteM<=RegWriteE;
MemWriteM<=MemWriteE;
MemtoRegM<=MemtoRegE;
ALUOutM<=ALUResult;
WriteDataM<=WriteDataE;
WriteRegM<=WriteRegE;
end
endmodule
1.5.5 clkMemory_Writeback
moduleclkMemory_Writeback(clk,RegWriteM,MemtoRegM,ALUOutM,RD,WriteRegM,
RegWriteW,MemtoRegW,ALUOutW,ReadDaraW,WriteRegW);
?
input clk,RegWriteM,MemtoRegM;
input [4:0] WriteRegM;
input [31:0] RD,ALUOutM;
output reg RegWriteW,MemtoRegW;
output reg[4:0] WriteRegW;
output reg[31:0] ALUOutW,ReadDaraW;
always @ (posedge clk)
begin
RegWriteW<=RegWriteM;
MemtoRegW<=MemtoRegM;
ALUOutW<=ALUOutM;
ReadDaraW<=RD;
WriteRegW<=WriteRegM;
end
?
endmodule
1.6 HazardUnit
我們知道影響流水線性能的有三個(gè)冒險(xiǎn):數(shù)據(jù)冒險(xiǎn),結(jié)構(gòu)冒險(xiǎn),控制冒險(xiǎn)。
(1)由于數(shù)據(jù)存儲(chǔ)器和指令存儲(chǔ)器分離,所以流水線讀指令和寫(xiě)數(shù)據(jù)可以并行執(zhí)行,不存在存儲(chǔ)器爭(zhēng)用問(wèn)題,寄存器堆采用讀寫(xiě)雙端口,因此也不會(huì)出現(xiàn)資源爭(zhēng)用問(wèn)題。
(2)數(shù)據(jù)冒險(xiǎn)
寄存器的值還沒(méi)有被寫(xiě)回寄存器,若此時(shí)讀取寄存器數(shù)據(jù)并用此數(shù)據(jù)參與運(yùn)算就會(huì)造成錯(cuò)誤。
a.不訪存的數(shù)據(jù)冒險(xiǎn)

?
圖1.6.1不訪存的數(shù)據(jù)冒險(xiǎn)
add $s0,$s2,$s3
add $t0,$s0,$s1
第二條add要用s0的數(shù)據(jù)進(jìn)行計(jì)算時(shí),也就是execute階段,可以將第一條正處于memory階段的AluOutM結(jié)果給第二條指令的ALU輸入。
這就是所謂的旁路技術(shù)
if ((rsE != 0) AND (rsE == WriteRegM) AND RegWriteM)
then ForwardAE = 10
elseif ((rsE != 0) AND (rsE == WriteRegW) AND RegWriteW)//訪問(wèn)存儲(chǔ)器
then ForwardAE = 01
else ForwardAE= 00
?
b.訪存造成的數(shù)據(jù)冒險(xiǎn)

?
圖1.6.2訪存造成的數(shù)據(jù)冒險(xiǎn)
lw $s0,40($0)
add$s0,$s0,$s1
add的execute階段,需要用到上一條指令寫(xiě)回的$s0的數(shù)值,而上一條指令要從存儲(chǔ)器取數(shù)據(jù),在Writeback階段才能得到$s0的數(shù)值,所以需要停頓一個(gè)時(shí)鐘周期,等到lw指令進(jìn)入Writeback階段再通過(guò)旁路技術(shù)將ResultW引入到add的執(zhí)行階段。
本條指令停頓了,后面的指令也要跟著停頓一個(gè)時(shí)鐘周期。
lwstall=
((rsD==rtE) OR (rtD==rtE))AND MemtoRegE
?
StallF = StallD = FlushE = lwstall
?
(3)控制冒險(xiǎn)

?
圖1.6.3控制冒險(xiǎn)1
在Memory階段進(jìn)行轉(zhuǎn)移判斷會(huì)造成后面三條不該執(zhí)行的指令執(zhí)行,流水線數(shù)值改變,所以應(yīng)該清空流水線。

?
圖1.6.4控制冒險(xiǎn)2
?
如果在指令譯碼后直接判斷Rs和Rt是否相等,則只有一條不該執(zhí)行的指令執(zhí)行了。
如果判斷的Rs或者Rt還沒(méi)有被寫(xiě)入到寄存器堆,則產(chǎn)生新的數(shù)據(jù)冒險(xiǎn),由于Decode階段要用到Rs和Rt,而寄存器的值需要在Memory階段或者Writeback階段產(chǎn)生,所以不僅要有前向通路,還要有停頓才可以處理此數(shù)據(jù)相關(guān)。
?
Forwardinglogic:
ForwardAD = (rsD!=0) AND (rsD == WriteRegM) AND RegWriteM
ForwardBD = (rtD !=0) AND (rtD == WriteRegM) AND RegWriteM
Stallinglogic:
branchstall = BranchD AND RegWriteEAND
(WriteRegE == rsDOR WriteRegE == rtD)
OR
BranchD AND MemtoRegM AND
(WriteRegM == rsDOR WriteRegM == rtD)
StallF = StallD= FlushE = lwstall OR branchstall

?
圖1.6.5冒險(xiǎn)控制單元
?

?
圖1.6.6提前獲得轉(zhuǎn)移判斷
?
moduleHazardUnit(StallF,StallD,
BranchD,ForwardAD,ForwardBD,ForwardAE,ForwardBE,
RsD,RtD,RsE,RtE,FlushE,RegWriteE,MemtoRegE,
WriteRegE,WriteRegM,RegWriteM,RegWriteW,WriteRegW,
MemtoRegM);
?
inputRegWriteE,RegWriteM,RegWriteW,MemtoRegE,MemtoRegM,BranchD;
input[4:0] RsD,RtD,RsE,RtE,WriteRegE,WriteRegM,WriteRegW;
outputreg [1:0] ForwardAE,ForwardBE;
outputreg ForwardAD,ForwardBD,StallF,StallD,FlushE;
?
reglwstall,branchstall;
?
always @( * )
begin
if( (RsE != 0)&& (RsE ==WriteRegM) && RegWriteM) //上一條指令的寫(xiě)回寄存器(WriteRegM)與本條指令的寄存器一致,
//采用旁路技術(shù),將上一條指令的結(jié)果直接送到執(zhí)行處。
ForwardAE= 2'b10;
else if ((RsE != 0)&& (RsE ==WriteRegW) && RegWriteW) //上上條指令的寫(xiě)回寄存器(WriteRegW)與本條指令的寄存器RS一致
//旁路技術(shù),ResultW送入執(zhí)行處
ForwardAE = 2'b01;
else ForwardAE= 2'b00;
?
if((RtE != 0)&&(RtE == WriteRegM)&& RegWriteM)
ForwardBE <= 2'b10; //上一條指令的寫(xiě)回地址(WriteRegM)與本條指令的操作數(shù)地址(寄存器RT)一致,
//采用旁路技術(shù),將上一條指令的結(jié)果直接送到執(zhí)行處。
else if ( (RtE != 0)&&(RtE ==WriteRegW) && (RegWriteW))
ForwardBE <= 2'b01;
else ForwardBE <= 2'b00;
?
//bne指令,在譯碼階段開(kāi)始判斷RS和RT的值,提前判斷,防止之后的指令執(zhí)行
//當(dāng)上上條指令要寫(xiě)回寄存器參與本次bne比較,通過(guò)旁路技解決,RD1/RD2<=ALUOut
ForwardAD <= (RsD != 0)&&(RsD==WriteRegM)&& RegWriteM;
ForwardBD <= (RtD != 0)&&(RtD==WriteRegM)&& RegWriteM;
?
branchstall <= (BranchD &&RegWriteE && (WriteRegE == RsD || WriteRegE == RtD) )//上一條指令要寫(xiě)這次比較的操作數(shù)
|| (BranchD && MemtoRegM&& (WriteRegM == RsD || WriteRegM == RtD));//上兩條指令要寫(xiě)這次比較的操作數(shù)
?
//stall
lwstall <= ((RsD==RtE) || (RtD==RtE))&& MemtoRegE;
StallF <= lwstall || branchstall;
StallD <= StallF;
FlushE <= StallD;//清空流水線防止再次判斷并轉(zhuǎn)移
?
?
end
endmodule
?
?

?
表1.6.1、停頓以及前向通路的舉例分析
2.Top模塊設(shè)計(jì)
頂層模塊全部采用例化連接
頂層模塊所有信號(hào)和連接代碼如下
inputclk,rst;
wireRegWriteD,RegDstD,ALUSrcD,BranchD,MemWriteD,MemtoRegD,PCSrcD;//decode_cu EqualD
wireRegWriteE,RegDstE,ALUSrcE,MemWriteE,MemtoRegE;//excute_cu
wireRegWriteM,MemtoRegM,MemWriteM;//memory_cu
wireMemtoRegW,RegWriteW;//writeback_cu
wire[2:0] ALUControlD,ALUControlE;//cu
wireForwardAD,ForwardBD,StallF,StallD,FlushE;//冒險(xiǎn)
wire[1:0] ForwardAE,ForwardBE;
wire[4:0] WriteRegW,WriteRegE,WriteRegM,RtE,RdE,RsE;
wire[31:0] PC,PCF,A,PCPlus4F,PCPlus4D,PCBranchD,RD,InstrD,WD3,RD1,RD2,SignlmmD,
RD1E,RD2E,SignlmmE,SrcAE,SrcBE,ALUResult,
ReadDataW,ALUOutW,WriteDataE,ALUOutM,WriteDataM,ReadData,ResultW;
module Top(clk,rst);
?
input clk,rst;
wireRegWriteD,RegDstD,ALUSrcD,BranchD,MemWriteD,MemtoRegD,PCSrcD;//decode_cu EqualD
wire RegWriteE,RegDstE,ALUSrcE,MemWriteE,MemtoRegE;//excute_cu
wire RegWriteM,MemtoRegM,MemWriteM;//memory_cu
wire MemtoRegW,RegWriteW;//writeback_cu
wire [2:0] ALUControlD,ALUControlE;//cu
?
wire ForwardAD,ForwardBD,StallF,StallD,FlushE;//冒險(xiǎn)
wire [1:0] ForwardAE,ForwardBE;
wire [4:0] WriteRegW,WriteRegE,WriteRegM,RtE,RdE,RsE;
wire [31:0]PC,PCF,A,PCPlus4F,PCPlus4D,PCBranchD,RD,InstrD,WD3,RD1,RD2,SignlmmD,
RD1E,RD2E,SignlmmE,SrcAE,SrcBE,ALUResult,
ReadDataW,ALUOutW,WriteDataE,ALUOutM,WriteDataM,ReadData,ResultW;
?
//clk 五級(jí)流水
clkPC clkPC(.clk(clk),.rst(rst),.StallF(StallF),.PC(PC),.PCF(PCF));
clkFetch_Decodeclk Fetch_Decode(.clk(clk),.clr(PCSrcD),.StallD(StallD),
.RD(RD),.PCPlus4F(PCPlus4F),.InstrD(InstrD),.PCPlus4D(PCPlus4D));
?
clkDecode_Excuteclk Decode_Excute(.clk(clk),.clr(FlushE),.RegWriteD(RegWriteD),
.RegDstD(RegDstD),.ALUSrcD(ALUSrcD),
.BranchD(BranchD),.MemWriteD(MemWriteD),.MemtoRegD(MemtoRegD),.ALUControlD(ALUControlD),
.RD1(RD1),.RD2(RD2),.RsD(InstrD[25:21]),.RtD(InstrD[20:16]),.RdD(InstrD[15:11]),.SignlmmD(SignlmmD),.RegWriteE(RegWriteE),
.RegDstE(RegDstE),.ALUSrcE(ALUSrcE),.MemWriteE(MemWriteE),.MemtoRegE(MemtoRegE),
.ALUControlE(ALUControlE),.RD1E(RD1E),.RD2E(RD2E),.RtE(RtE),.RdE(RdE),.RsE(RsE),.SignlmmE(SignlmmE));
?
clkExcude_Memory clkExcude_Memory(clk,RegWriteE,MemtoRegE,MemWriteE,
ALUResult,WriteDataE,WriteRegE
RegWriteM,MemtoRegM,MemWriteM,ALUOutM,WriteDataM,WriteRegM);
?
clkMemory_Writeback clkMtoW(clk,RegWriteM,MemtoRegM,ALUOutM,ReadData,
WriteRegM,RegWriteW,MemtoRegW,ALUOutW,ReadDataW,WriteRegW);
//各個(gè)小模塊
PCPlus PCPlus(PCF,PCPlus4F);
instruction instruction(PCF>>2,RD);
regfile regfile(.clk(clk),.a1(InstrD[25:21]),.a2(InstrD[20:16]),.a3(WriteRegW),.we3(RegWriteW),.wd3(ResultW),.rd1(RD1),.rd2(RD2));
PC1 PC1(PCBranchD,PCPlus4F,PCSrcD,PC);
PCBranch PCBranch(PCPlus4D,SignlmmD,PCBranchD);
WriteReg_2to1 WriteReg_2to1(RegDstE,RdE,RtE,WriteRegE);//WriteRegE的選擇
//控制單元
Control_Unit Control_Unit(InstrD[31:26],InstrD[5:0],RegWriteD,RegDstD,
ALUSrcD,BranchD,MemWriteD,MemtoRegD,ALUControlD);
Sign_Extend Sign_Extend(InstrD[15:0],SignlmmD);
?
ALU_Forward ALU_Forward(ForwardAE,ForwardBE,RD1E,RD2E,SignlmmE,
ALUSrcE,ALUOutM,ResultW,WriteDataE,SrcAE,SrcBE);
alu alu(SrcAE,SrcBE,ALUControlE,ALUResult);
data data(ReadData,clk,MemWriteM,ALUOutM,WriteDataM);
EqualD equal(ForwardAD,ForwardBD,ALUOutM,RD1,RD2,BranchD,PCSrcD);
//數(shù)據(jù)冒險(xiǎn)和控制冒險(xiǎn)
HazardUnit HazardUnit(StallF,StallD,BranchD,ForwardAD,ForwardBD,
ForwardAE,ForwardBE,InstrD[25:21],InstrD[20:16],
RsE,RtE,FlushE,RegWriteE,MemtoRegE,WriteRegE,WriteRegM,RegWriteM,RegWriteW,WriteRegW,MemtoRegM);
ResultWritebackResultWriteback(MemtoRegW,ReadDataW,ALUOutW,ResultW);
?
endmodule
圖2.1頂層模塊連接
3.代碼設(shè)計(jì)
代碼實(shí)現(xiàn)從數(shù)據(jù)存儲(chǔ)器1號(hào)地址里的數(shù)累加到100號(hào)地址里的數(shù),再除以100取平均數(shù),由于數(shù)據(jù)存儲(chǔ)器存的數(shù)為對(duì)應(yīng)的地址,所以累加和為5050,平均數(shù)為50
001000_00000_00001_0000_0000_0000_0001//addiR1,R0,0 R1為變址寄存器X
001000_00000_00010_0000_0000_0000_0000//addiR2,R0,0 R2存放結(jié)果
001000_00000_00011_0000_0000_0110_0100//addiR3,R0,100 R3存放100
001000_00001_00001_0000_0000_0000_0001//addiR1,R1,1 R1自加一 即INX
101011_00001_00100_0000_0000_0000_0000//lw M(R1)->(R4)數(shù)據(jù)相關(guān),R1還未加一,旁路技術(shù)解決此數(shù)據(jù)相關(guān)
000000_00010_00100_00010_00000_100000//add (R2)+(R4)->(R2) //R4還未寫(xiě)回寄存器堆,停頓加旁路技術(shù)解決此數(shù)據(jù)相關(guān)
000101_00001_00011_1111_1111_1111_1100 //BNE (R1) (R3) -4
000000_00010_00011_00010_00000_111111//DIV (R2)/(R3)->(R2)
?
四、仿真結(jié)果

?
控制信號(hào)初始狀態(tài)不定,需要譯碼后產(chǎn)生。
可以看到取出的第一個(gè)數(shù)是1,也就是地址1里的數(shù)。
第二次取出的數(shù)是2,累加結(jié)果為3

?
結(jié)果分析:
每次RtD等于RtE都是R4時(shí)會(huì)有l(wèi)wstall,停頓一個(gè)時(shí)鐘周期以便旁路技術(shù)將WriteBack階段
的結(jié)果寫(xiě)回到execute
累加結(jié)果為5050
可以看到仿真最后WriteBack的值是平均值50
五、設(shè)計(jì)心得
5.1遇到的問(wèn)題
(1)線路連接不對(duì),例化時(shí)建議直接將模塊名和頂層信號(hào)名對(duì)應(yīng),不需要.(clk)這樣比較麻煩
(2)位寬不對(duì),導(dǎo)致出錯(cuò)
(3)不加Reg不能在always賦值
(4)assign不能對(duì)reg賦值
(5)readmemh讀十六進(jìn)制數(shù)存十進(jìn)制數(shù)
(6)指令讀取后若無(wú)停頓及clr,PC自動(dòng)加4,所以判斷不相等轉(zhuǎn)移指令要考慮PC加4了
5.2我的收獲
(1)CPU流水線加快了CPU的運(yùn)行速度,開(kāi)發(fā)了CPU的并行性,若沒(méi)有停頓,五級(jí)流水線的運(yùn)行速度會(huì)是單周期的五倍
(2)數(shù)據(jù)冒險(xiǎn)可以通過(guò)前向通路和停頓解決,控制冒險(xiǎn)可以通過(guò)在Decode階段提前判斷是否符合轉(zhuǎn)移條件提前轉(zhuǎn)移,同時(shí)清空流水線,防止流水線數(shù)據(jù)混亂。
(3)do文件可以快速完成文件的編譯,仿真波形添加,大大提升了使用modelsim的效率。
(4)verilog語(yǔ)言很好地可以實(shí)現(xiàn)硬件的設(shè)計(jì),我們要好好掌握,為更復(fù)雜的集成電路設(shè)計(jì)打下堅(jiān)實(shí)基礎(chǔ)。
?
以上介紹包含了關(guān)鍵代碼,同學(xué)們可以參考學(xué)習(xí),是我的一個(gè)課程設(shè)計(jì),不明白的地方可以私信我,評(píng)論留言也可文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-533274.html
?
到了這里,關(guān)于基于Verilog的mips指令集單周期/五級(jí)流水cpu,modelsim/vivado仿真設(shè)計(jì) 設(shè)計(jì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!