实验4 简单CPU设计与仿真
- 格式:pdf
- 大小:171.63 KB
- 文档页数:8
预做实验报告4简单CPU设计与仿真
一、实验目的
理解并掌握CPU的基本电路结构及其设计方法,学会使用Verilog HDL对电路进行行为建模、结构建模以及仿真测试。
二、实验内容
利用Verilog HDL设计一个简单的CPU模型,并进行仿真测试。
要求该处理机能够实现下列指令系统:
31262521201615540指令000000rd rs1rs2and rd,rs1,rs2 000001rd rs1imme andi rd,rs1,imme 000010rd rs1rs2or rd,rs1,rs2 000011rd rs1imme ori rd,rs1,imme 000100rd rs1rs2add rd,rs1,rs2 000101rd rs1imme addi rd,rs1,imme 000110rd rs1rs2sub rd,rs1,rs2 000111rd rs1imme subi rd,rs1,imme 001000rd rs1imme load rd,rs1,imme 001001rd rs1imme store rd,rs1,imme 001010disp bne disp
001011disp beq disp
001100disp branch disp 要求把指令的执行分为以下5个步骤,每个步骤用一个时钟周期。
1、取指令及PC+1周期
2、指令译码、读寄存器及转移周期
3、ALU执行或者存储器地址计算周期
4、ALU指令结束周期或者存储器访问周期
5、写回周期
三、实验环境
PC机1台、Modelsim仿真软件1套。
四、实验步骤
1、电路结构设计与逻辑设计
多周期处理机的总体电路图
P C
寄存器堆ALU
A
B
ZERO 存储器Addres s
Dataou t Detain CS
OE
WE WRITEMEM
ALUOP
ZERO
WRITEZERO
M U X
M U X M U X
1
偏移量符号扩展
立即数符号扩展
WRITEREG DI AD A1
A2Q2
Q1
SELLOAD
SELST
偏移量
立即数
Rd rs1rs2Rd
WRITEPC
M U X
I R
M U X
SELLDST
SELALUA
SELALUB
A
B IM WRITEIR
ZERO
OPCODE 控制部件
控制信
2、建立Verilog 模型
module TOP(clk,rst,start,memwe,memin,memaddr,zero,n,v,c,dataout);input clk,rst,start,memwe;input [31:0]memin;input [4:0]memaddr;output [31:0]dataout;output n,v,c,zero;wire clk,rst;
wire writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,writezero;wire [5:0]opcode;
wire [1:0]aluop,selalub;wire zero;datapath
u0(writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,selalub,aluop,w ritezero,clk,rst,memin,memaddr,memwe,zero,n,v,c,opcode,dataout);control
u1(clk,start,zero,opcode,writepc,selldst,writemem,writeir,selload,selst,writereg,se lalua,selalub,aluop,writezero);endmodule
module
datapath(writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,selalub,al
ZERO
uop,writezero,clk,rst,memin,memaddr,memwe,zero,n,v,c,opcode,dataout); input
writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,writezero,clk,rst,m emwe;
input[1:0]selalub,aluop;
input[4:0]memaddr;
input[31:0]memin;
output zero,n,v,c;
output[5:0]opcode;
output[31:0]dataout;
wire[4:0]pcout,address,memaddr,mux3out;
wire[31:0]memin,mux4out,mux5out,imme,disp;
wire memwe,zero1;
wire[31:0]dataout,Q1,datain,irout,f,aluout;
pc pc1(pcout,aluout[4:0],writepc,clk,rst);
mux21_5mux1(address,pcout,aluout[4:0],selldst);
memory
mem(dataout,datain,address,writemem,memin,memaddr,memwe,clk,rst);
//memin,memaddr,memweÊÇΪÁËÔڼĴæÆ÷ÖÐÊäÈëÊý¾Ý¶øÓÃ
ir ir1(irout,dataout,clk,rst,writeir);
mux21_32mux2(f,aluout,dataout,selload);
mux21_5mux3(mux3out,irout[4:0],irout[25:21],selst);
registerfile
registerfile(Q1,datain,f,clk,rst,writereg,irout[25:21],irout[20:16],mux3out); mux21_32mux4(mux4out,Q1,{27'b0,pcout},selalua);
assign
imme={irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[1 5],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],iro ut[15:0]};
assign
disp={irout[25],irout[25],irout[25],irout[25],irout[25],irout[25],irout[25:0]}; mux41_32mux5(mux5out,datain,imme,32'd1,disp,selalub);
ALU alu1(aluop,mux4out,mux5out,aluout,n,v,c,zero1);
dff zeroflag(zero,zero1,clk,rst,writezero);
assign opcode=irout[31:26];
endmodule
module
control(clk,start,zero,opcode,writepc,selldst,writemem,writeir,selload,selst,writer eg,selalua,selalub,aluop,writezero);
input clk,start,zero;
input[5:0]opcode;
output writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,writezero;
output[1:0]selalub,aluop;
reg[3:0]q;
wire[3:0]d;
wire zero;
always@(posedge clk)
begin
if(start)
q<=4'd0;
else
q<=d;
end
assign
d[0]=(~q[3]&~q[2]&~q[1]&~q[0])|((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&op code[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&op code[0]))|(~q[3]&~q[2]&q[1]&q[0])|(~q[3]&q[2]&~q[1]&q[0]);
assign
d[1]=((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&~opcode[0]))|((~q[3]&~q[2]&~q [1]&q[0])&(~opcode[3]&opcode[0]))|(~q[3]&~q[2]&q[1]&~q[0])|(~q[3]&~q[2]& q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0]);
assign
d[2]=((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&~opcod e[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&opcod e[0]))|(~q[3]&~q[2]&q[1]&~q[0])|(~q[3]&~q[2]&q[1]&q[0]);
assign
d[3]=(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]& ~q[0]);
assign
writepc=(~q[3]&~q[2]&~q[1]&~q[0])|((~q[3]&~q[2]&~q[1]&q[0])&((opcode[3]& opcode[2]&~opcode[1]&~opcode[0])|(opcode[3]&~opcode[2]&opcode[1]&~opco de[0]&~zero)|(opcode[3]&~opcode[2]&opcode[1]&opcode[0]&zero)));
assign
selldst=(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1] &~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign writemem=q[3]&~q[2]&~q[1]&q[0];
assign writeir=~q[3]&~q[2]&~q[1]&~q[0];
assign
selload=(~q[3]&q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&q[1] &~q[0]);
assign selst=(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]&q[0]);
assign
writereg=(~q[3]&q[2]&q[1]&~q[0])|(~q[3]&q[2]&q[1]&q[0])|(q[3]&~q[2]&q[1] &~q[0]);
assign selalua=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0]); assign selalub[1]=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0]);
assign
selalub[0]=(~q[3]&~q[2]&~q[1]&q[0])|(~q[3]&~q[2]&q[1]&q[0])|(~q[3]&q[2]&~ q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(~q[3]&q[2]&q[1]&q[0])|(q[3]&~q[2]&~q [1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign writezero=(~q[3]&q[2]&q[1]&~q[0])|(~q[3]&q[2]&q[1]&q[0]);
assign
aluop[1]=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0])|((~q[3]&~q[2] &q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&~q[2]&q[1]&q[0])&(~opcode[ 3]&opcode[2]))|(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|((~q[3]&q[
2]&q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&q[2]&q[1]&q[0])&(~opcode[
3]&opcode[2]))|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[ 2]&q[1]&~q[0]);
assign
aluop[0]=((~q[3]&~q[2]&q[1]&~q[0])&(~opcode[3]&opcode[1]))|((~q[3]&~q[2] &q[1]&q[0])&(~opcode[3]&opcode[1]))|((~q[3]&q[2]&q[1]&~q[0])&(~opcode[3] &opcode[1]))|((~q[3]&q[2]&q[1]&q[0])&(~opcode[3]&opcode[1])); endmodule
module memory(dataout,datain,address,we,memin,memaddr,memwe,clk,reset); output[31:0]dataout;
input[31:0]datain,memin;
input[4:0]address,memaddr;
input clk,reset,we,memwe;
wire we1;
wire[4:0]address1;
wire[31:0]decoderout;
wire[31:0]regen;
wire[31:0]datain1;
wire[31:0]
q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21, q22,q23,q24,q25,q26,q27,q28,q29,q30,q31;
assign address1=memwe?memaddr:address;
assign datain1=memwe?memin:datain;
decoder dec0(decoderout,address1);
assign we1=we|memwe;
assign regen[0]=decoderout[0]&we1;
assign regen[1]=decoderout[1]&we1;
assign regen[2]=decoderout[2]&we1;
assign regen[3]=decoderout[3]&we1;
assign regen[4]=decoderout[4]&we1;
assign regen[5]=decoderout[5]&we1;
assign regen[6]=decoderout[6]&we1;
assign regen[7]=decoderout[7]&we1;
assign regen[8]=decoderout[8]&we1;
assign regen[9]=decoderout[9]&we1; assign regen[10]=decoderout[10]&we1; assign regen[11]=decoderout[11]&we1; assign regen[12]=decoderout[12]&we1; assign regen[13]=decoderout[13]&we1; assign regen[14]=decoderout[14]&we1; assign regen[15]=decoderout[15]&we1; assign regen[16]=decoderout[16]&we1; assign regen[17]=decoderout[17]&we1; assign regen[18]=decoderout[18]&we1; assign regen[19]=decoderout[19]&we1; assign regen[20]=decoderout[20]&we1; assign regen[21]=decoderout[21]&we1; assign regen[22]=decoderout[22]&we1; assign regen[23]=decoderout[23]&we1; assign regen[24]=decoderout[24]&we1; assign regen[25]=decoderout[25]&we1; assign regen[26]=decoderout[26]&we1; assign regen[27]=decoderout[27]&we1; assign regen[28]=decoderout[28]&we1; assign regen[29]=decoderout[29]&we1; assign regen[30]=decoderout[30]&we1; assign regen[31]=decoderout[31]&we1; register reg0(q0,datain1,clk,reset,regen[0]); register reg1(q1,datain1,clk,reset,regen[1]); register reg2(q2,datain1,clk,reset,regen[2]); register reg3(q3,datain1,clk,reset,regen[3]); register reg4(q4,datain1,clk,reset,regen[4]); register reg5(q5,datain1,clk,reset,regen[5]); register reg6(q6,datain1,clk,reset,regen[6]); register reg7(q7,datain1,clk,reset,regen[7]); register reg8(q8,datain1,clk,reset,regen[8]); register reg9(q9,datain1,clk,reset,regen[9]); register reg10(q10,datain1,clk,reset,regen[10]); register reg11(q11,datain1,clk,reset,regen[11]); register reg12(q12,datain1,clk,reset,regen[12]); register reg13(q13,datain1,clk,reset,regen[13]); register reg14(q14,datain1,clk,reset,regen[14]); register reg15(q15,datain1,clk,reset,regen[15]); register reg16(q16,datain1,clk,reset,regen[16]); register reg17(q17,datain1,clk,reset,regen[17]); register reg18(q18,datain1,clk,reset,regen[18]); register reg19(q19,datain1,clk,reset,regen[19]); register reg20(q20,datain1,clk,reset,regen[20]);
register reg21(q21,datain1,clk,reset,regen[21]);
register reg22(q22,datain1,clk,reset,regen[22]);
register reg23(q23,datain1,clk,reset,regen[23]);
register reg24(q24,datain1,clk,reset,regen[24]);
register reg25(q25,datain1,clk,reset,regen[25]);
register reg26(q26,datain1,clk,reset,regen[26]);
register reg27(q27,datain1,clk,reset,regen[27]);
register reg28(q28,datain1,clk,reset,regen[28]);
register reg29(q29,datain1,clk,reset,regen[29]);
register reg30(q30,datain1,clk,reset,regen[30]);
register reg31(q31,datain1,clk,reset,regen[31]);
mux_32
mux0(dataout,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q 18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31,address); endmodule
3、设计测试文件
`timescale1ns/1ns
module TOP_test;
reg clk,rst,start,memwe;
reg[31:0]memin;
reg[4:0]memaddr;
wire zero,n,v,c;
wire[31:0]dataout;
TOP u(clk,rst,start,memwe,memin,memaddr,zero,n,v,c,dataout);
always#50clk=~clk;
initial
begin
clk=1;
rst=0;
start=0;
#20rst=1;
//load instruction and data to memory.
#100rst=0;
memwe=1;
memin=32'b001000_00000_11111_0000000000010000;
//load r0,r31,16
memaddr=5'd0;
#100memwe=1;
memin=32'b001001_00000_11111_0000000000010001;
//store r0,r31,17
memaddr=5'd1;
#100memwe=1;
memin=32'b001000_00001_11111_0000000000010001;
//load r1,r31,17
memaddr=5'd2;
#100memwe=1;
memin=32'b000001_00010_00000_0101010101010101;
//andi r2,r0,16'b0101010101010101
memaddr=5'd3;
#100memwe=1;
memin=32'b000101_00011_00010_0000000000001011;
//addi r3,r2,16'b0000000000001011
memaddr=5'd4;
#100memwe=1;
memin=32'b001100_11111111111111111111111011;
//branch-5
memaddr=5'd5;
#100memwe=1;
memin=32'hFFFF_FFFF;
//load data to memory
memaddr=5'd16;
//start to execuit instructions.
#100memwe=0;
start=1;
#100start=0;
#10000$stop;
end
endmodule
注意:测试的完备性。
4、将设计文件和测试文件输入Modesim仿真工具,并进行编译和功能仿真。
5、观测仿真波形图,分析结果是否正确。
若有错误,则修改设计文件或测试文件,重新编译和仿真。
五、实验结果
序号输入数据仿真结果正确结果仿真结
果的正
确性
1
2
3
六、实验分析与总结
七、实验思考题。