第1页/共7页实验八单时钟CPU设计实验报告姓名:XXX学号:XXX专业:计算机科学与技术课程名称:计算机组成同组学生姓名:无实验时间:实验地点:指导老师:XXX一、实验目的和要求1.理解数据通路的原理并掌握数据通路的设计方法2.理解单时钟CPU的原理并掌握单时钟CPU的设计方法3.掌握用程序验证CPU的方法二、实验内容和原理实验内容:1.设计数据通路,将基本单元结合在单时钟CPU中基本单元包括:CPU控制器、ALU和ALUcontroller、registerfile、instructionmemory、datamemory、和寄存器、加法器、符号位扩展、移位器、多路复用器等模块。2.用程序验证CPU,并观察程序的执行情况实验原理:1.数据通路原理图第2页/共7页2.测试的实例(要求实现的指令程序)三、主要仪器设备1.Spartan-III开发板1套2.装有ISE的PC机1台第3页/共7页四、操作方法与实验步骤实验步骤:1.创建新的工程和新的源文件2.编写verilog代码(包括以下模块top,c_dat_mem,c_instr_mem,display,single_mux5,single_mux9,single_mux32,pbdebounce,single_add,single__alu,single__aluc,single_ct1,single__gpr,single_pc,single_pc_plus4,single__signext)并创建和编写Instr.Mem和DataMem的coe文件3.编写UCF引脚文件,通过编译。5..生成FPGA代码,下载到实验板上并调试,看是否与实现了预期功能实验代码:已全部打包在文件夹中,在此只粘贴了top.vmoduletop(clk_btn,rst_btn,disp_clk,switch,seg,anode,led);inputclk_btn;//按键给入时钟inputrst_btn;//按键进行复位inputdisp_clk;//T9用于指令存储器,数据存储器input[6:0]switch;//选择显示的拨位输入output[7:0]seg;//数码管输出output[3:0]anode;//数码管位选output[5:0]led;//通过LED表示指令类型/////////////////////////////////////////////wirecpu_clk;//CPU系统时钟wirerst;//复位信号reg[7:0]clk_cnt;//计时wire[15:0]disp_num;//显示数据wire[8:0]i_pc;//PC寄存?鞯氖淙?wire[8:0]o_pc;//PC寄存器的输出wire[8:0]pc_plus4;//PC+4wire[31:0]instr;//instructionmemory中取出的指令wire[31:0]op2;//ALU的第二个输入数据wire[4:0]W1;wire[31:0]o_op1,o_op2,o_op3;//寄存器输出数据wire[31:0]WriteData;//寄存器写入数据wireALUsrc;//控制mux32_1的选择信号wireRegDst;//控制mux5的选择信号wireMemtoReg;//控制mux32_2的选择信号wire[1:0]ALUOp;//控制ALUC的信号第4页/共7页wire[2:0]operation;//ALUC输出,即ALU控制码wire[31:0]signext_out32;//符号位扩展后的数据wireo_zf;//ALUzerodetectorwire[31:0]alu_result;//ALUresultwire[31:0]ReadData_out;//Datamemory读取出的数据wire[31:0]o_add;//BEQwireo_and;//与门的输出结果wire[8:0]o_mux9;//mux91输出的数据//wire[31:0]jump_addr;//jump跳转输入值wireBranch,Jump,MemWrite,RegWrite;//Pc寄存器single_pcm_sp(cpu_clk,rst,i_pc,o_pc);//Pc+4模块single_pc_plus4m_sp4(o_pc,pc_plus4);//指令存储器,从内存中读取指令,PC寄存器的输出为读取地址c_instr_memm_cim(o_pc,disp_clk,instr);//5位2选1,由指令的[20:16],[15:11]决定rd的地址single_mux5m_sm5(instr[20:16],instr[15:11],RegDst,W1);//寄存器组??三路读(两路用于程序,一路用于检测),一路写single_gprm_sg(cpu_clk,rst,instr[25:21],instr[20:16],switch[6:2],W1,WriteData,RegWrite,o_op1,o_op2,o_op3);//ALU控制器single_alucm_sac(ALUOp,instr[5:0],operation);//op[1:0],func[3:0],operation[2:0]//16位至32位符号拓展single_signextm_sse(instr[15:0],signext_out32);//i_16,o_32//32位2选1,输出到ALU的B端single_mux32m_sm32_1(o_op2,signext_out32,ALUsrc,op2);//A,B,Ctrl,S//ALUsingle_alum_ma(o_op1,op2,operation,o_zf,alu_result);//i_a,i_b,ALUoper,o_zf,disp_code//数据存储器??读写??32位??寻址,512字地址空间第5页/共7页c_dat_memm_cdm(alu_result[8:0],disp_clk,o_op2,ReadData_out,MemWrite);//32位数据二选一,从ALU和数据存储器输出选择一路,输出到寄存器组的写入数据端single_mux32m_sm32_2(alu_result,ReadData_out,MemtoReg,WriteData);//A,B,Ctrl,S//32位加法器,计算pc+4与指令中立即数的和,用作BEQ转移地址选项single_addm_sa({23'b0,pc_plus4},signext_out32,o_add);//i_op1,i_op2,o_out//9位数据二选一,根据BEQ与门结果,与JUMP的2选1single_mux9m_sm9_1(pc_plus4,o_add[8:0],o_and,o_mux9[8:0]);//A,B,Ctrl,S//9位数据二选一,接mux32_3,与jump选择最后写?雙c??single_mux9m_sm9_2(o_mux9[8:0],instr[8:0],Jump,i_pc[8:0]);//单时钟CPU控制器,根据操作码产生控制信号single_ctlm_sc(rst,instr[31:26],Jump,ALUOp,Branch,MemWrite,RegWrite,MemtoReg,ALUsrc,RegDst);//防抖动函数pbdebounceI1(disp_clk,clk_btn,cpu_clk);pbdebounceI2(disp_clk,rst_btn,rst);//显示函数displayM1(disp_clk,disp_num[15:0],anode[3:0],seg[7:0]);initialclk_cnt=8'b0;//计时初始化always@(posedgecpu_clkorposedgerst)beginif(rst==1)clk_cnt=8'b0;elseclk_cnt=clk_cnt+1;endassignled[0]=clk_btn;//表示是否在执行指令assignled[1]=RegDst;//R型指令assignled[2]=MemtoReg;//LW指令assignled[3]=MemWrite;//SW指令assignled[4]=Branch;//BEQ指令assignled[5]=Jump;//Jump指令第6页/共7页assigno_and=Branch&o_zf;//BEQ判断结果,用于选择PC地址//assignjump_addr[27:0]=instr[25:0]2;//assignjump_addr[31:28]=4'b0;//将pc+4和instr[27:0]拼接成jump地址assigndisp_num=(switch[1:0]==2'b00)?o_op3[15:0]:((switch[1:0]==2'b01)?o_op3[31:16]:((switch[1:0]==2'b10)?{7'b0,o_pc[8:0]}:clk_cnt));endmodule五、实验结果与分析1.程序运行成功后,将代码下载到实验板spartan3上验证:a)先按复位键,查看各寄存器的内容查看寄存器寄存器低16位00_0001($1)000B(11)00_0010($2)000000_0011($3)000100_0100($4)0001b)继续按键,查看状态PC(10_xxxx)显示数位4,5,6,7,4,5,6,7,4……..表明程序正在执行循环。$2(00_0010)中显示每次相加的数:0000,0001,0003,0006……$3(00_0011)中显示每次相加的数:0000,0001,0002,0003…….时钟计数(11_xxxx)显示按键次数:0003,0004,0005,0006……最后发现程序正确执行,得到1+2…+10的结果为55,运算正确。c)led显示在执行指令的过程中,led灯的显示也是正确的,对于每一种不同的指令,都有不同的led灯亮2.程序实现的功能模块图第7页/共7页六、讨论、心得这个单周期实验做了很久,可能因为需要实现的模块较多,所以小错误不断。在实际中应该以模块为单位,认真检查是否有错。但在不断改正错误的过程中,我也在不断吸取教训,并加深对单周期的理解和认识。