杭电计组实验十.docx
《杭电计组实验十.docx》由会员分享,可在线阅读,更多相关《杭电计组实验十.docx(16页珍藏版)》请在冰点文库上搜索。
![杭电计组实验十.docx](https://file1.bingdoc.com/fileroot1/2023-8/4/a1a30fdf-edb3-4ae9-9106-dc1505e78b44/a1a30fdf-edb3-4ae9-9106-dc1505e78b441.gif)
杭电计组实验十
实验报告
2016年5月11日成绩:
姓名
周勇
学号
14071225
班级
计科5班
专业
计算机科学与技术
课程名称
《数字电路课程设计》
任课老师
章复嘉老师
指导老师
章复嘉老师
机位号
实验序号
10
实验名称
R-I-J指令CPU
实验时间
5月11日
实验地点
1教225
实验设备号
一、实验程序源代码
顶层架构CPU模块:
modulecpu(clk,reset,ALU_OP,inst,rs,rt,rd,rs_data,rt_data,rd_data,ZF,OF,Write_Reg,PC,PC_new,rd_rt_s,W_Addr,imm,W_Data,imm_s,imm_data
ALU_B,rt_imm_s,Mem_Write,M_R_Data,ALU_Data,alu_mem_s,w_r_s,wr_data_s,PC_s,address);
inputwireclk;
inputreset;
output[2:
0]ALU_OP;//操作符
output[31:
0]inst;//指令存放
output[4:
0]rs;//rs地址
output[4:
0]rt;//rt地址
output[4:
0]rd;//rd地址
output[31:
0]rs_data;//rs数据
output[31:
0]rt_data;//rt数据
output[31:
0]rd_data;//rd数据
output[31:
0]PC;
output[31:
0]PC_new;
outputZF;
outputOF;
outputWrite_Reg;//是否写入
output[31:
0]W_Data;
outputrd_rt_s;//控制那个作为目的寄存器
output[4:
0]W_Addr;//目的操作数地址
output[15:
0]imm;//立即数
output[31:
0]imm_data;//被扩展的立即数
outputimm_s;//是否需要扩展
outputrt_imm_s;//B端选择rt或者是imm
output[31:
0]ALU_B;//ALU_B端口数据
outputMem_Write;//是否写入数据rom
output[31:
0]M_R_Data;//从数据rom读出来的数据
output[31:
0]ALU_Data;//ALU运算出来的结果,根据alu_mem_s选择由M_W_Data或者W_Data来赋值
outputalu_mem_s;//看上面
output[1:
0]w_r_s;
output[1:
0]wr_data_s;
output[1:
0]PC_s;//PC选择器
output[25:
0]address;//地址解析数据
//读指令
ex7pc(
.clka(clk),
.douta(inst),
.rst(reset),
.PC(PC),
.PC_new(PC_new),
.PC_s(PC_s),
.R_Data_A(rs_data),
.imm_data(imm_data),
.address(address)
//解析指令
);
analysis_instanalysis_inst(
.inst(inst),
.ALU_OP(ALU_OP),
.rs(rs),
.rt(rt),
.rd(rd),
.Write_Reg(Write_Reg),
.imm(imm),
.rd_rt_s(rd_rt_s),
.imm_s(imm_s),
.rt_imm_s(rt_imm_s),
.Mem_Write(Mem_Write),
.alu_mem_s(alu_mem_s),
.address(address),
.w_r_s(w_r_s),
.wr_data_s(wr_data_s),
.PC_s(PC_s),
.ZF(ZF)
);
//读取源操作数的值:
assignW_Addr=(w_r_s[1])?
5'b11111:
((w_r_s[0])?
rt:
rd);
assignimm_data=(imm_s)?
{{16{imm[15]}},imm}:
{{16{1'b0}},imm};
reg1Reg(
.R_Addr_A(rs),
.R_Addr_B(rt),
.Clk(clk),
.W_Addr(W_Addr),
.W_Data(W_Data),
.R_Data_A(rs_data),
.R_Data_B(rt_data),
.Reset(reset),
.Write_Reg(Write_Reg)//不写入
);
assignALU_B=(rt_imm_s)?
imm_data:
rt_data;
//对源操作数运算,存于目的操作数
ex3ALU(
.ALU_OP(ALU_OP),
.A(rs_data),
.B(ALU_B),
.F(ALU_Data),
.ZF(ZF),
.OF(OF)
);
//----
wireclk_temp;
wired_outn;
regd_out=0;
assignclk_temp=clk^d_out;
assignd_outn=~d_out;
//----
always@(posedgeclk_temp)
begin
d_out<=d_outn;
end
//数据存储器
Data_RomDatarom(
.clka(clk_temp),//inputclka
.wea(Mem_Write),//input[0:
0]wea
.addra(ALU_Data[5:
0]),//input[5:
0]addra
.dina(rt_data),//input[31:
0]dina
.douta(M_R_Data)//output[31:
0]douta
);
assignW_Data=(wr_data_s[1])?
PC_new:
(wr_data_s[0]?
M_R_Data:
ALU_Data);
endmodule
pc模块:
moduleex7(clka,douta,rst,PC,PC_new,PC_s,R_Data_A,imm_data,address
);
inputrst;
inputclka;
input[1:
0]PC_s;
outputwire[31:
0]douta;
outputreg[31:
0]PC;
output[31:
0]PC_new;
input[31:
0]R_Data_A;
input[31:
0]imm_data;
input[25:
0]address;
wire[31:
0]dina;
reg[0:
0]wea=0;
assignPC_new=PC+4;
ex77regrom(
.clka(clka),//inputclka
.wea(wea),//input[0:
0]wea
.addra(PC[7:
2]),//input[5:
0]addra
.dina(dina),//input[31:
0]dina
.douta(douta)//output[31:
0]douta
);
always@(posedgerstornegedgeclka)
begin
if(rst)
PC<=32'h00000000;
else
begin
case(PC_s)
2'b00:
PC<=PC_new;
2'b01:
PC<=R_Data_A;
2'b10:
PC<=PC_new+(imm_data<<2);
2'b11:
PC<={PC_new[31:
28],address,2'b00};
endcase
end
end
endmodule
analysis_inst模块:
moduleanalysis_inst(
inst,ALU_OP,rs,rt,rd,Write_Reg,imm,rd_rt_s,imm_s,rt_imm_s,Mem_Write,alu_mem_s,address,w_r_s,wr_data_s,PC_s,ZF
);
input[31:
0]inst;
outputreg[2:
0]ALU_OP;
outputreg[4:
0]rs;
outputreg[4:
0]rt;
outputreg[4:
0]rd;
outputregWrite_Reg;
outputreg[15:
0]imm;
outputregrd_rt_s;
outputregimm_s;
outputregrt_imm_s;
outputregMem_Write;
outputregalu_mem_s;
outputreg[25:
0]address;
outputreg[1:
0]w_r_s;
outputreg[1:
0]wr_data_s;
outputreg[1:
0]PC_s;
inputZF;
always@(*)
begin
//--------------------处理R型指令----------------------
if(inst[31:
26]==6'b000000)//判断是否为R型
begin
rd=inst[15:
11];//rd
rt=inst[20:
16];//rt
rs=inst[25:
21];//rs
w_r_s=2'b00;
imm_s=0;//此处无所谓
wr_data_s=2'b00;
//alu_mem_s=0;//此处废弃不用,被wr_data_s替代
Mem_Write=0;//是否写入数据存储器
//rd_rt_s=0;//rd作为目的存储器//此处废弃不用吧被w_r_s替代
rt_imm_s=0;//rt作为源操作数
case(inst[5:
0])//映射对应的ALU
6'b100000:
beginALU_OP=3'B100;Write_Reg=1;PC_s=2'b00;end
6'b100010:
beginALU_OP=3'B101;Write_Reg=1;PC_s=2'b00;end
6'b100100:
beginALU_OP=3'B000;Write_Reg=1;PC_s=2'b00;end
6'b100101:
beginALU_OP=3'B001;Write_Reg=1;PC_s=2'b00;end
6'b100110:
beginALU_OP=3'B010;Write_Reg=1;PC_s=2'b00;end
6'b100111:
beginALU_OP=3'B011;Write_Reg=1;PC_s=2'b00;end
6'b101011:
beginALU_OP=3'B110;Write_Reg=1;PC_s=2'b00;end
6'b000100:
beginALU_OP=3'B111;Write_Reg=1;PC_s=2'b00;end
6'b001000:
beginALU_OP=3'B100;Write_Reg=0;PC_s=2'b01;end
endcase
end
//------------------处理I型立即寻址指令------------------------
if(inst[31:
29]==3'b001)
begin
imm=inst[15:
0];
rt=inst[20:
16];//rt
rs=inst[25:
21];//rs
Mem_Write=0;//是否写入数据存储器
rd_rt_s=1;//rt作为目的存储器
rt_imm_s=1;//imm作为源操作数
//alu_mem_s=0;//以alu结果输出
w_r_s=2'b01;
Write_Reg=1;
wr_data_s=2'b00;
PC_s=2'b00;
//判断属于那条指令
case(inst[31:
26])
6'b001000:
beginimm_s=1;ALU_OP=3'B100;end
6'b001100:
beginimm_s=0;ALU_OP=3'B000;end
6'b001110:
beginimm_s=0;ALU_OP=3'B010;end
6'b001011:
beginimm_s=0;ALU_OP=3'B110;end
endcase
end
//----------------处理I型取数/存数指令------------------
if(inst[31:
30]==2'b10&&inst[28:
26]==3'b011)
begin
imm=inst[15:
0];
rt=inst[20:
16];//rt
rs=inst[25:
21];//rs
rd_rt_s=1;//rt作为目的存储器
rt_imm_s=1;//imm作为源操作数
imm_s=1;
w_r_s=2'b01;
wr_data_s=2'b01;
PC_s=2'b00;
//判断属于那条指令
//读取数据时,以mem输出的数据写入,所以alu_mem_s=1;
case(inst[31:
26])
6'b100011:
beginalu_mem_s=1;Mem_Write=0;Write_Reg=1;ALU_OP=3'B100;end
6'b101011:
beginMem_Write=1;Write_Reg=0;ALU_OP=3'B100;end
endcase
end
//----------------处理I型跳转指令------------------------
if(inst[31:
27]==5'b00010)
begin
imm=inst[15:
0];
rt=inst[20:
16];//rt
rs=inst[25:
21];//rs
case(inst[31:
26])
6'b000100:
beginrt_imm_s=0;ALU_OP=3'b101;Write_Reg=0;Mem_Write=0;PC_s=(ZF?
2'b10:
2'b00);end
6'b000101:
beginrt_imm_s=0;ALU_OP=3'b101;Write_Reg=0;Mem_Write=0;PC_s=(ZF?
2'b00:
2'b10);end
endcase
end
//----------------处理J型跳转指令-------------------------
if(inst[31:
27]==5'b00001)
begin
address=inst[25:
0];
case(inst[31:
26])
6'b000010:
beginw_r_s=2'b00;Write_Reg=0;Mem_Write=0;PC_s=2'b11;end
6'b000011:
beginw_r_s=2'b10;wr_data_s=2'b10;Write_Reg=1;Mem_Write=0;PC_s=2'b11;end
endcase
end
end
endmodule
Reg模块
modulereg1(R_Addr_A,R_Addr_B,Clk,W_Addr,W_Data,R_Data_A,R_Data_B,Reset,Write_Reg
);
inputClk,Reset;
inputwireWrite_Reg;
inputwire[4:
0]R_Addr_A;
inputwire[4:
0]W_Addr;
inputwire[4:
0]R_Addr_B;
inputwire[31:
0]W_Data;
reg[31:
0]REG_Files[31:
0];
outputwire[31:
0]R_Data_A;
outputwire[31:
0]R_Data_B;
integeri=0;
always@(posedgeClkorposedgeReset)//下降沿存储
begin
if(Reset)//初始化
begin
for(i=0;i<=31;i=i+1)
REG_Files[i]<=32'h00000000;
end
else
begin
if(Write_Reg)
REG_Files[W_Addr]<=W_Data;
end
end
assignR_Data_A=REG_Files[R_Addr_A];
assignR_Data_B=REG_Files[R_Addr_B];
endmodule
ALU模块:
moduleex3(ALU_OP,A,B,F,ZF,OF
);
input[2:
0]ALU_OP;
input[31:
0]A,B;
outputreg[31:
0]F;
outputregZF,OF;
regC32,C31;
reg[7:
0]i;
always@(*)
begin
case(ALU_OP)
3'b000:
F=A&B;
3'b001:
F=A|B;
3'b010:
F=A^B;
3'b011:
F=~(A|B);
3'b100:
begin{C32,F}=A+B;OF=C32^A[31]^B[31]^F[31];end
3'b101:
begin{C32,F}=A-B;OF=C32^A[31]^B[31]^F[31];end
3'b110:
beginif(A
F=1;
else
F=0;
end
3'b111:
F=B<default:
beginend
endcase
ZF=((F==32'h00000000)?
1:
0);
end
endmodule
二、仿真波形
三、电路图
四、引脚配置(约束文件)
五、思考与探索
有了之前的经验,J型指令还是几个比较容易实现的指令了。
没什么思考。
六、意见和建议
1.无