头歌:5级流水线CPU实验
实验目的本关任务1.掌握流水线CPU的原理。2.具有流水线CPU的设计能力。3.熟悉 Vivado 的设计流程具备电路的设计仿真和硬件测试能力。4.能编写测试程序测试流水线 CPU 的功能。实验原理1.流水线 CPU 实现的指令集要求实现 20 条 MIPS 整数指令。2.流水线 CPU 的指令执行过程流水线技术不要等一条指令执行完成后再执行下一条指令而是把一条指令的执行分成若干“级”(Stage)不同的指令的不同的级可以在同一个周期同时执行。5级流水线CPU把指令执行分成5个阶段分别是:取指令IF级、指令译码ID级、指令执行EXE级、存储器访问MEM级和结果写回WB级。流水线CPU设计的难点在于流水线的控制有三大关键问题需要解决分别为结构相关、数据相关和控制相关。3.流水线计算机的总体设计实现 20 条 MIPS 整数指令的多周期计算机的总体电路设计如图所示由以下模块构成PC、IF级的组合电路、IF级与ID级之间的流水线寄存器、ID级的组合电路、ID级与EXE级之间的流水线寄存器、EXE级的组合电路、EXE级与MEM级之间的流水线寄存器、MEM级的组合电路、MEM级与WB级之间的流水线寄存器、WB级的组合电路。实验内容和要求根据设计的实验方案使用 Verilog HDL 编写相应代码。对编写的代码进行仿真得到正确的波形图。将以上设计作为一个单独的模块设计一个外围模块去调用该模块。将编写的代码进行综合布局布线进行硬件测试做好实验记录验证此设计的功能。撰写实验报告实验报告内容包括程序设计、仿真分析、硬件测试和实验操作步骤以及源程序代码、仿真波形图、数据记录和实验结果分析等。实验步骤创建工程新建一个文件夹 pipeline_cpu然后从中创建本实验的工程。启动 Vivado 软件选择 “File → Project → New”菜单命令输入工程名 “pipeline_cpu”选择工程的文件位置。模块设计1添加源文件根据 MIPS 指令集设计流水线CPU pipeline_cpu.v。添加已有 Verilog HDL 文件的方法为在项目管理区中单击 “Add Sources” 在弹出的对话框中选中 “Add or create design sources”。2添加外围展示模块按照实验要求还需要设计外围模块 pipeline_cpu_display.v 用于调用 pipeline_cpu.v 和触摸屏模块以便测试实验结果。功能仿真1仿真测试模块在进行功能仿真时需要先建立一个测试模块 pipeline_cpu_tb.v。本实验需要产生的输入激励就是时钟信号 clock 和复位信号 resetn。2波形仿真在左侧导航栏中单击 “Run Simulation”然后选择 “Run Behavioral Simulation”可以通过观察波形验证流水线 CPU 的功能。module pipeline_cpu(clock, memclock, resetn, pc, inst, ealu, malu, walu);input clock, memclock, resetn;output[31:0]pc, inst, ealu, malu, walu;wire[31:0]bpc, jpc, npc, pc4, ins;wire[31:0]dpc4, da, db, dimm;wire[31:0]epc4, ea, eb, eimm;wire[31:0]mb, mmo, wmo, wdi;wire[4:0]drn, ern0, ern, mrn, wrn;wire[3:0]daluc, ealuc;wire[1:0]pcsource_raw, pcsource;wire wpcir;wire dwreg_raw, dm2reg_raw, dwmem_raw, djal_raw;wire dwreg, dm2reg, dwmem, daluimm, dshift, djal;wire ewreg, em2reg, ewmem, ealuimm, eshift, ejal;wire mwreg, mm2reg, mwmem;wire wwreg, wm2reg;reg flushid;assign pcsourcepcsource_raw;assign dwregdwreg_raw~flushid;assign dm2regdm2reg_raw~flushid;assign dwmemdwmem_raw~flushid;assign djaldjal_raw~flushid;always (negedge resetn or posedge clock)if(!resetn)flushid1b0; else if (wpcir) flushid djal_raw; pipepc prog_cnt(npc, wpcir, clock, resetn, pc); pipeif if_stage(pcsource, pc, bpc, da, jpc, npc, pc4, ins); pipeir inst_reg(pc4, ins, wpcir, clock, resetn, dpc4, inst); pipeid id_stage(mwreg, mrn, ern, ewreg, em2reg, mm2reg, dpc4, inst, wrn, wdi, ealu, malu, mmo, wwreg, clock, resetn, bpc, jpc, pcsource_raw, wpcir, dwreg_raw, dm2reg_raw, dwmem_raw, daluc, daluimm, da, db, dimm, drn, dshift, djal_raw); pipedereg de_reg(dwreg, dm2reg, dwmem, daluc, daluimm, da, db, dimm, drn, dshift, djal, dpc4, clock, resetn, ewreg, em2reg, ewmem, ealuc, ealuimm, ea, eb, eimm, ern0, eshift, ejal, epc4); pipeexe exe_stage(ealuc, ealuimm, ea, eb, eimm, eshift, ern0, epc4, ejal, ern, ealu); pipeemreg em_reg(ewreg, em2reg, ewmem, ealu, eb, ern, clock, resetn, mwreg, mm2reg, mwmem, malu, mb, mrn); pipemem mem_stage(mwmem, malu, mb, clock, memclock, mmo); pipemwreg mw_reg(mwreg, mm2reg, mmo, malu, mrn, clock, resetn, wwreg, wm2reg, wmo, walu, wrn); mux2x32 wb_stage(walu, wmo, wm2reg, wdi); endmodule module pipepc(npc, wpcir, clk, resetn, pc); input [31:0] npc; input wpcir, clk, resetn; output [31:0] pc; dffe32 program_counter(npc, clk, resetn, wpcir, pc); endmodule module pipeif(pcsource, pc, bpc, rpc, jpc, npc, pc4, ins); input [31:0] pc, bpc, rpc, jpc; input [1:0] pcsource; output [31:0] npc, pc4, ins; mux4x32 next_pc(pc4, bpc, rpc, jpc, pcsource, npc); assign pc4 pc 32h4;pipeimem inst_mem(pc, ins);endmodule module pipeimem(a, inst);input[31:0]a;output[31:0]inst;reg[31:0]rom[0:31];initial begin rom[0]32h3c010000; rom[1] 32h34240050;rom[2]32h20050004; rom[3] 32h0c000018;rom[4]32hac820000; rom[5] 32h8c890000;rom[6]32h01244022; rom[7] 32h20050003;rom[8]32h20a5ffff; rom[9] 32h34a8ffff;rom[10]32h39085555; rom[11] 32h2009ffff;rom[12]32h312affff; rom[13] 32h01493025;rom[14]32h01494026; rom[15] 32h01463824;rom[16]32h10a00001; rom[17] 32h08000008;rom[18]32h2005ffff; rom[19] 32h000543c0;rom[20]32h00084400; rom[21] 32h00084403;rom[22]32h000843c2; rom[23] 32h08000017;rom[24]32h00004020; rom[25] 32h8c890000;rom[26]32h20840004; rom[27] 32h01094020;rom[28]32h20a5ffff; rom[29] 32h14a0fffb;rom[30]32h00081000; rom[31] 32h03e00008;end assign instrom[a[6:2]];endmodule module pipeir(pc4, ins, wpcir, clock, resetn, dpc4, inst);input[31:0]pc4, ins;input wpcir, clock, resetn;output[31:0]dpc4, inst;dffe32 pc_plus4(pc4, clock, resetn, wpcir, dpc4);dffe32 instruction(ins, clock, resetn, wpcir, inst);endmodule module pipeid(mwreg, mrn, ern, ewreg, em2reg, mm2reg, dpc4, inst, wrn, wdi, ealu, malu, mmo, wwreg, clock, resetn, bpc, jpc, pcsource, wpcir, dwreg, dm2reg, dwmem, daluc, daluimm, da, db, dimm, drn, dshift, djal);input[31:0]dpc4, inst, wdi, ealu, malu, mmo;input[4:0]ern, mrn, wrn;input mwreg, ewreg, em2reg, mm2reg, wwreg;input clock, resetn;output[31:0]bpc, jpc, da, db, dimm;output[4:0]drn;output[3:0]daluc;output[1:0]pcsource;output wpcir, dwreg, dm2reg, dwmem, daluimm, dshift, djal;wire[5:0]opinst[31:26];wire[4:0]rsinst[25:21];wire[4:0]rtinst[20:16];wire[4:0]rdinst[15:11];wire[5:0]funcinst[5:0];wire[31:0]qa, qb, br_offset;wire[31:0]da_mux, db_mux;wire[1:0]fwda, fwdb;wire regrt, sext, rsrtequ;wire signsextinst[15];wire load_rs_hazardewregem2reg(ern!0)(ernrs);wire load_rt_hazardewregem2reg(ern!0)(ernrt);assign dimm{{16{sign}}, inst[15:0]};assign br_offset{dimm[29:0],2b00}; assign jpc {dpc4[31:28], inst[25:0], 2b00};assign bpcdpc4 br_offset;assign rsrtequ~|(da ^ db);pipeidcu cu(op, func, rs, rt, mrn, mm2reg, mwreg, ern, em2reg, ewreg, rsrtequ, pcsource, wpcir, dwreg, dm2reg, dwmem, djal, daluc, daluimm, dshift, regrt, sext, fwdb, fwda);regfile rf(rs, rt, wdi, wrn, wwreg, ~clock, resetn, qa, qb);mux2x5 des_reg_no(rd, rt, regrt, drn);mux4x32 alu_a(qa, ealu, malu, mmo, fwda, da_mux);mux4x32 alu_b(qb, ealu, malu, mmo, fwdb, db_mux);assign daload_rs_hazard ?32h0 : da_mux; assign db load_rt_hazard ? 32h0:db_mux;endmodule module pipeidcu(op, func, rs, rt, mrn, mm2reg, mwreg, ern, em2reg, ewreg, rsrtequ, pcsource, wpcir, wreg, m2reg, wmem, jal, aluc, aluimm, shift, regrt, sext, fwdb, fwda);input[5:0]op, func;input[4:0]rs, rt, mrn, ern;input mm2reg, mwreg, em2reg, ewreg, rsrtequ;output[1:0]pcsource;output wpcir, wreg, m2reg, wmem, jal, aluimm, shift, regrt, sext;output[3:0]aluc;output reg[1:0]fwda, fwdb;wire r_type~|op;wire i_addr_type(func6b100000); wire i_sub r_type (func 6b100010);wire i_andr_type(func6b100100); wire i_or r_type (func 6b100101);wire i_xorr_type(func6b100110); wire i_sll r_type (func 6b000000);wire i_srlr_type(func6b000010); wire i_sra r_type (func 6b000011);wire i_jrr_type(func6b001000); wire i_addi (op 6b001000);wire i_andi(op6b001100); wire i_ori (op 6b001101);wire i_xori(op6b001110); wire i_lw (op 6b100011);wire i_sw(op6b101011); wire i_beq (op 6b000100);wire i_bne(op6b000101); wire i_lui (op 6b001111);wire i_j(op6b000010); wire i_jal (op 6b000011);wire i_rsi_add|i_sub|i_and|i_or|i_xor|i_jr|i_addi|i_andi|i_ori|i_xori|i_lw|i_sw|i_beq|i_bne;wire i_rti_add|i_sub|i_and|i_or|i_xor|i_sll|i_srl|i_sra|i_sw|i_beq|i_bne;assign wpcir~(ewregem2reg(ern!0)((i_rs(ernrs))|(i_rt(ernrt))));assign wreg(i_add|i_sub|i_and|i_or|i_xor|i_sll|i_srl|i_sra|i_addi|i_andi|i_ori|i_xori|i_lw|i_lui|i_jal)wpcir;assign regrti_addi|i_andi|i_ori|i_xori|i_lw|i_lui;assign jali_jal;assign m2regi_lw;assignshifti_sll|i_srl|i_sra;assign aluimmi_addi|i_andi|i_ori|i_xori|i_lw|i_lui|i_sw;assign sexti_addi|i_lw|i_sw|i_beq|i_bne;assign aluc[3]i_sra;assign aluc[2]i_sub|i_or|i_srl|i_sra|i_ori|i_lui;assign aluc[1]i_xor|i_sll|i_srl|i_sra|i_xori|i_beq|i_bne|i_lui;assign aluc[0]i_and|i_or|i_sll|i_srl|i_sra|i_andi|i_ori;assign wmemi_swwpcir;assign pcsource[1]i_jr|i_j|i_jal;assign pcsource[0](i_beqrsrtequ)|(i_bne~rsrtequ)|i_j|i_jal;always * begin fwda2b00; if (ewreg (ern ! 0) (ern rs)) begin if (~em2reg) fwda 2b01;endelseif(mwreg(mrn!0)(mrnrs)~mm2reg)fwda2b10; else if (mwreg (mrn ! 0) (mrn rs) mm2reg) fwda 2b11;fwdb2b00; if (ewreg (ern ! 0) (ern rt)) begin if (~em2reg) fwdb 2b01;endelseif(mwreg(mrn!0)(mrnrt)~mm2reg)fwdb2b10; else if (mwreg (mrn ! 0) (mrn rt) mm2reg) fwdb 2b11;end endmodule module pipedereg(dwreg, dm2reg, dwmem, daluc, daluimm, da, db, dimm, drn, dshift, djal, dpc4, clock, resetn, ewreg, em2reg, ewmem, ealuc, ealuimm, ea, eb, eimm, ern0, eshift, ejal, epc4);input dwreg, dm2reg, dwmem, daluimm, dshift, djal, clock, resetn;input[31:0]da, db, dimm, dpc4;input[3:0]daluc;input[4:0]drn;output reg ewreg, em2reg, ewmem, ealuimm, eshift, ejal;output reg[31:0]ea, eb, eimm, epc4;output reg[3:0]ealuc;output reg[4:0]ern0;always (negedge resetn or posedge clock)if(!resetn)begin ewreg0;em2reg0;ewmem0;ealuimm0;eshift0;ejal0;ea0;eb0;eimm0;epc40;ealuc0;ern00;endelsebegin ewregdwreg;em2regdm2reg;ewmemdwmem;ealuimmdaluimm;eshiftdshift;ejaldjal;eada;ebdb;eimmdimm;epc4dpc4;ealucdaluc;ern0drn;end endmodule module pipeexe(ealuc, ealuimm, ea, eb, eimm, eshift, ern0, epc4, ejal, ern, ealu);input[3:0]ealuc;input ealuimm, eshift, ejal;input[31:0]ea, eb, eimm, epc4;input[4:0]ern0;output[4:0]ern;output[31:0]ealu;wire[31:0]sa, alua, alub, ealu0, epc8;wire z;assign sa{27b0, eimm[10:6]}; assign epc8 epc4 32h4;assign ernern0|{5{ejal}};mux2x32 alu_ina(ea, sa, eshift, alua);mux2x32 alu_inb(eb, eimm, ealuimm, alub);alu al_unit(alua, alub, ealuc, ealu0, z);mux2x32 save_pc8(ealu0, epc8, ejal, ealu);endmodule module pipeemreg(ewreg, em2reg, ewmem, ealu, eb, ern, clk, clrn, mwreg, mm2reg, mwmem, malu, mb, mrn);input ewreg, em2reg, ewmem, clk, clrn;input[31:0]ealu, eb;input[4:0]ern;output reg mwreg, mm2reg, mwmem;output reg[31:0]malu, mb;output reg[4:0]mrn;always (negedge clrn or posedge clk)if(!clrn)begin mwreg0;mm2reg0;mwmem0;malu0;mb0;mrn0;endelsebegin mwregewreg;mm2regem2reg;mwmemewmem;maluealu;mbeb;mrnern;end endmodule module pipemem(we, addr, datain, clk, dmem_clk, dataout);input we, clk, dmem_clk;input[31:0]addr, datain;output[31:0]dataout;reg[31:0]ram[0:31];integer i;initial beginfor(i0;i32;ii 1)ram[i]32h0; ram[20] 32h000000a3;ram[21]32h00000027; ram[22] 32h00000079;ram[23]32h00000115; end assign dataout ram[addr[6:2]]; always (posedge dmem_clk) if (we ~clk) ram[addr[6:2]] datain; endmodule module pipemwreg(mwreg, mm2reg, mmo, malu, mrn, clk, clrn, wwreg, wm2reg, wmo, walu, wrn); input mwreg, mm2reg, clk, clrn; input [31:0] mmo, malu; input [4:0] mrn; output reg wwreg, wm2reg; output reg [31:0] wmo, walu; output reg [4:0] wrn; always (negedge clrn or posedge clk) if (!clrn) begin wwreg 0; wm2reg 0; wmo 0; walu 0; wrn 0; end else begin wwreg mwreg; wm2reg mm2reg; wmo mmo; walu malu; wrn mrn; end endmodule module regfile(rna, rnb, d, wn, we, clk, clrn, qa, qb); input [4:0] rna, rnb, wn; input [31:0] d; input we, clk, clrn; output [31:0] qa, qb; reg [31:0] register [1:31]; integer i; assign qa (rna 0) ? 32h0:register[rna];assign qb(rnb0)?32h0 : register[rnb]; always (posedge clk or negedge clrn) if (!clrn) begin for (i 1; i 32; i i 1) register[i] 32h0;endelseif(we(wn!0))begin register[wn]d;end endmodule module alu(a, b, aluc, s, z);input[31:0]a, b;input[3:0]aluc;output reg[31:0]s;output z;always * casex(aluc)4bx000: s a b; 4bx100: sa - b;4bx001: s a b; 4bx101: sa|b;4bx010: s a ^ b; 4bx110: s{b[15:0],16h0}; 4b0011: sba[4:0];4b0111: s b a[4:0]; 4b1111: s$signed(b)a[4:0];default: s32h0; endcase assign z ~|s; endmodule module mux2x32(a0, a1, s, y); input [31:0] a0, a1; input s; output [31:0] y; assign y s ? a1 : a0; endmodule module mux2x5(a0, a1, s, y); input [4:0] a0, a1; input s; output [4:0] y; assign y s ? a1 : a0; endmodule module mux4x32(a0, a1, a2, a3, s, y); input [31:0] a0, a1, a2, a3; input [1:0] s; output reg [31:0] y; always * case (s) 2b00: ya0;2b01: y a1; 2b10: ya2;2b11: y a3; endcase endmodule module dffe32(d, clk, clrn, e, q); input [31:0] d; input clk, clrn, e; output reg [31:0] q; always (negedge clrn or posedge clk) if (!clrn) q 32h0;elseif(e)qd;endmodule