搜索
您的当前位置:首页湘潭大学计算机原理实验四多周期MIPSCPU+存储器实验预习报告

湘潭大学计算机原理实验四多周期MIPSCPU+存储器实验预习报告

来源:乌哈旅游


实验四 多周期MIPS CPU +存储器实验

一.实验目的

1、深入理解MIPS—CPU指令系统的功能和工作原理; 2、掌握多周期CPU的工作原理和逻辑功能实现;

3、熟练掌握用Verilog HDL语言设计多周期存储器的方法;

4、熟练掌握对多周期存储器的仿真实验验证和硬件测试两种调试方法; 5、通过对多周期CPU的运行情况进行观察和分析,进一步加深理解。

二.实验设备

硬件:现代计算机组成原理实验系统(兼)Nios 32位嵌入式系统实验开发平台 EP1C12Q240

Core(TM)i3-3240 CPU@3.40GHz 3.39GHz 1.91GB的内存 软件:QuartusII 13.0sp1 Microsoft Windows xp

三.实验内容

1、设计一个32位MIPS多周期CPU具体的要求如下: 至少运行下列的6类32条MIPS指令。 (1)算术逻辑指令and、sub、addi

(2)逻辑运算指令and、0r、xor、 andi、 ori、xori (3)位移指令sll、srl、sra (4)条件分支指令beq、bne、 (5)无条件跳转指令j、jr (6)数据传送指令lw、sw 2.设计一个存储器

四.实验原理与步骤

实现上述原理框图根据功能将其分划分为控制单元(cunit)、执行单元(eunit)、指令单元(iunit)以及存储单元(munit)四大模块。

(1).控制单元(cunit)是多周期微处理器的核心控制微处理器取指令、指令译码和指令执行等工作。主要由指令译码器控制器(outputs control)、算术逻辑运算控制器(ALU control)两 个子模块组成。

(2).执行单元(eunit)主要由寄存器堆(registers)和算术逻辑单元(ALU)两个子模块组成。其中寄存器是微处理器最基本的元素MIPS系统的寄存器堆由32个32位寄存器组成而ALU则是微处理器的主要功能部件执行加、减、比较等算术运算和与、或、或非、异或等逻辑运算。指令单元(iunit)的作用是决定下一条指令的地址PC值。

(3).存储单元(munit)由存储器(memory)、指令寄存器(instruction register)和存储数据寄存 器(memory data register)组成。

五.实验源代码

寄存器元件代码:

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]; assign qa = (rna == 0) ? 0 : register[rna]; assign qb = (rnb == 0) ? 0 : register[rnb];

always @ (posedge clk or negedge clrn) begin if (clrn == 0) begin integer i; for (i=1; i<32; i=i+1) register[i] <= 0; end else begin if ((wn != 0) && (we == 1)) register[wn] <= d; end end endmodule

32位四选一选择器:

module mux4x32 (a0,a1,a2,a3,s,y); input [31:0] a0,a1,a2,a3; input [1:0] s; output [31:0] y; function [31:0] select; input [31:0] a0,a1,a2,a3; input [1:0] s; case (s) 2'b00: select = a0; 2'b01: select = a1; 2'b10: select = a2; 2'b11: select = a3; endcase endfunction assign y = select (a0,a1,a2,a3,s); endmodule

//r1-r31 //read //read

//reset

//write

5位二选一选择器:

module mux2x5 (a0,a1,s,y); input [4:0] a0,a1; input s; output[4:0] y; assign y = s ? a1 : a0; endmodule

32位二选一选择器:

module mux2x32 (a0,a1,s,y); input [31:0] a0,a1; input s; output [31:0] y; assign y = s ? a1 : a0; endmodule

存储器元件:

module mcmem (clk, dataout, datain, addr, we, inclk, outclk); input [31:0] datain; input [31:0] addr; input clk, we, inclk, outclk; output [31:0] dataout; wire write_enable = we & ~clk; lpm_ram_dq ram

(.data(datain),.address(addr[7:2]),.we(write_enable),.inclock(inclk),.outclock(outclk),.q(dataout)); defparam ram.lpm_width = 32; defparam ram.lpm_widthad = 6; defparam ram.lpm_indata = \"registered\"; defparam ram.lpm_outdata = \"registered\"; defparam ram.lpm_file = \"mcmem.mif\"; defparam ram.lpm_address_control = \"registered\"; endmodule

控制部件:

module mccu (op, func, z, clock, resetn, wpc, wir, wmem, wreg, iord, regrt, m2reg, aluc, shift, alusrca, alusrcb, pcsource, jal, sext, state); input [5:0] op, func; input z, clock, resetn; output reg wpc, wir, wmem, wreg, iord, regrt, m2reg; output reg [3:0] aluc; output reg [1:0] alusrcb, pcsource; output reg shift, alusrca, jal, sext; output reg [2:0] state;

reg [2:0] next_state; parameter[2:0] sif = 3'b000, // IF state sid = 3'b001, // ID state sexe = 3'b010, // EXE state smem = 3'b011, // MEM state swb = 3'b100; // WB state wire r_type,i_add,i_sub,i_and,i_or,i_xor,i_sll,i_srl,i_sra,i_jr;

wire i_addi,i_andi,i_ori,i_xori,i_lw,i_sw,i_beq,i_bne,i_lui,i_j,i_jal; and(r_type,~op[5],~op[4],~op[3],~op[2],~op[1],~op[0]);

and(i_add,r_type, func[5],~func[4],~func[3],~func[2],~func[1],~func[0]); and(i_sub,r_type, func[5],~func[4],~func[3],~func[2], func[1],~func[0]); and(i_and,r_type, func[5],~func[4],~func[3], func[2],~func[1],~func[0]); and(i_or, r_type, func[5],~func[4],~func[3], func[2],~func[1], func[0]); and(i_xor,r_type, func[5],~func[4],~func[3], func[2], func[1],~func[0]); and(i_sll,r_type,~func[5],~func[4],~func[3],~func[2],~func[1],~func[0]); and(i_srl,r_type,~func[5],~func[4],~func[3],~func[2], func[1],~func[0]); and(i_sra,r_type,~func[5],~func[4],~func[3],~func[2], func[1], func[0]); and(i_jr, r_type,~func[5],~func[4], func[3],~func[2],~func[1],~func[0]); and(i_addi,~op[5],~op[4], op[3],~op[2],~op[1],~op[0]); and(i_andi,~op[5],~op[4], op[3], op[2],~op[1],~op[0]); and(i_ori, ~op[5],~op[4], op[3], op[2],~op[1], op[0]); and(i_xori,~op[5],~op[4], op[3], op[2], op[1],~op[0]); and(i_lw, op[5],~op[4],~op[3],~op[2], op[1], op[0]); and(i_sw, op[5],~op[4], op[3],~op[2], op[1], op[0]); and(i_beq, ~op[5],~op[4],~op[3], op[2],~op[1], op[0]); and(i_bne, ~op[5],~op[4],~op[3], op[2],~op[1], op[0]); and(i_lui, ~op[5],~op[4], op[3], op[2], op[1], op[0]); and(i_j, ~op[5],~op[4],~op[3],~op[2], op[1],~op[0]); and(i_jal, ~op[5],~op[4],~op[3],~op[2], op[1], op[0]); wire i_shift;

or (i_shift,i_sll,i_srl,i_sra); always @* begin // control signals' dfault outputs: wpc = 0; // do not write pc wir = 0; // do not write ir wmem = 0; // do not write memory wreg = 0; // do not write register file iord = 0; // select pc as memory address aluc = 4'bx000; // ALU operation: add alusrca = 0; // ALU input a: reg a or sa alusrcb = 2'h0; // ALU input b: reg b regrt = 0; // reg dest no: rd m2reg = 0; // select reg c shift = 0; // select reg a pcsource = 2'h0; // select alu output

jal = 0; // not a jal sext = 1; // sign extend

case (state) //----------------------------------------------------- IF: sif: begin // IF state wpc = 1; // write pc wir = 1; // write IR alusrca = 1; // PC alusrcb = 2'h1; // 4 next_state = sid; // next state: ID end //----------------------------------------------------- ID: sid: begin // ID state if (i_j) begin // j instruction pcsource = 2'h3; // jump address wpc = 1; // write PC next_state = sif; // next state: IF end else if (i_jal) begin // jal instruction pcsource = 2'h3; // jump address wpc = 1; // write PC jal = 1; // reg no = 31 wreg = 1; // save PC+4 next_state = sif; // next state: IF end else if (i_jr) begin // jr instruction pcsource = 2'h2; // jump register wpc = 1; // write PC next_state = sif; // next state: IF end else begin // other instruction aluc = 4'bx000; // add alusrca = 1; // PC alusrcb = 2'h3; // branch offset next_state = sexe; // next state: EXE end end //----------------------------------------------------- EXE: sexe: begin // EXE state aluc[3] = i_sra; aluc[2] = i_sub | i_or | i_srl | i_sra | i_ori | i_lui ;

i_lui ;

aluc[1] = i_xor | i_sll | i_srl | i_sra | i_xori | i_beq | i_bne |

aluc[0] = i_and | i_or | i_sll | i_srl | i_sra | i_andi | i_ori ; if (i_beq || i_bne) begin // beq or bne instruction pcsource = 2'h1; // branch address wpc = i_beq & z | i_bne & ~z; // write PC next_state = sif; // next state: IF end else begin // other instruction if(i_lw || i_sw) begin // lw or sw instruction alusrcb = 2'h2; // select offset next_state = smem; // next state: MEM end else begin // other instruction if (i_shift) shift = 1; // shift instruction if (i_addi || i_andi || i_ori || i_xori || i_lui) alusrcb = 2'h2; // select immediate if (i_andi || i_ori || i_xori) sext = 0; // 0-extend next_state = swb; // next state: WB end end end

//----------------------------------------------------- MEM: smem: begin // MEM state iord = 1; // memory address = C if (i_lw) begin next_state = swb; // next state: WB end else begin // store wmem = 1; // write memory next_state = sif; // next state: IF end end

//----------------------------------------------------- WB: swb: begin // WB state if (i_lw) m2reg = 1; // select memory data if (i_lw || i_addi || i_andi || i_ori || i_xori || i_lui) regrt = 1; // reg dest no: rt wreg = 1; // write register file next_state = sif; // next state: IF

end //----------------------------------------------------- END default: begin next_state = sif; end endcase end always @ (posedge clock or negedge resetn) begin if (resetn == 0) begin state <= sif; end else begin state <= next_state; end end endmodule

32位带使能端触发器: module dffe32 (d,clk,clrn,e,q); input [31:0] d; input clk,clrn,e; output [31:0] q; reg [31:0] q; always @ (negedge clrn or posedge clk) if (clrn == 0) begin q <= 0; end else begin if(e == 1) q <= d; end endmodule

32位触发器:

module dff32 (d,clk,clrn,q); input [31:0] d; input clk,clrn; output [31:0] q; reg [31:0] q; always @ (negedge clrn or posedge clk) if (clrn == 0) begin q <= 0;

//default state // state registers

end else begin q <= d; end endmodule

ALU计算部件:

module alu (a,b,aluc,r,z); input [31:0] a,b; input [3:0] aluc; output [31:0] r; output z; assign r = cal(a,b,aluc); assign z = ~|r; function [31:0] cal; input [31:0] a,b; input [3:0] aluc; casex (aluc) 4'bx000: cal=a+b; 4'bx100: cal=a-b; 4'bx001: cal=a&b; 4'bx101: cal=a|b; 4'bx010: cal=a^b; 4'bx110: cal={b[15:0],16'h0}; 4'bx011: cal=b<>a[4:0]; 4'b1111: cal=$signed(b)>>>a[4:0]; endcase endfunction endmodule

其他部件:

module f (reg_dest,jal,wn); input [4:0] reg_dest; input jal; output [4:0] wn; assign wn = reg_dest | {5{jal}}; endmodule

module sa (di,dot); input [4:0] di; output [31:0] dot; assign dot = {27'b0,di}; endmodule

module out4 (out); output [31:0] out; assign out = 32'h4; endmodule

module e (immin,sext,immediate,offset); input [15:0] immin; input sext; output [31:0] immediate,offset; wire e = sext & immin[15]; wire [15:0] imm = {16{e}}; assign offset = {imm[13:0],immin[15:0],1'b0,1'b0}; assign immediate = {imm,immin[15:0]}; endmodule

module combine (address,pc,add); input [25:0] address; input [3:0] pc; output [31:0] add; assign add = {pc[3:0],address[25:0],1'b0,1'b0}; endmodule

module convert1 (dain,sain,op,func,rs,rt,rd,imm,addr); input [31:0] dain; output [4:0] sain,rs,rt,rd; output [5:0] op,func; output [15:0] imm; output [25:0] addr; assign sain = {dain[10:6]}; assign op = {dain[31:26]}; assign func = {dain[5:0]}; assign rs = {dain[25:21]}; assign rt = {dain[20:16]}; assign rd = {dain[15:11]}; assign imm = {dain[15:0]}; assign addr = {dain[25:0]}; endmodule

module convert2 (pc,pcout); input [31:0] pc; output [3:0] pcout; assign pcout = {pc[31:28]}; endmodule

存储器内的测试数据:

-- Copyright (C) 1991-2013 Altera Corporation

-- Your use of Altera Corporation's design tools, logic functions -- and other software and tools, and its AMPP partner logic -- functions, and any output files from any of the foregoing -- (including device programming or simulation files), and any -- associated documentation or information are expressly subject -- to the terms and conditions of the Altera Program License -- Subscription Agreement, Altera MegaCore Function License -- Agreement, or other applicable license agreement, including, -- without limitation, that your use is for the sole purpose of

-- programming logic devices manufactured by Altera and sold by -- Altera or its authorized distributors. Please refer to the -- applicable agreement for further details.

-- Quartus II generated Memory Initialization File (.mif)

DEPTH = 64; %Memory depth and width are required WIDTH = 32; %Enter a decimal number ADDRESS_RADIX = HEX; %Address and value radixes are optional DATA_RADIX = HEX; %Enter BIN, DEC, HEX, or OCT; unless %otherwise specified, radixes = HEX

CONTENT BEGIN

[0..3F] : 00000000; % Range--Every address from 0 to 3F = 00000000 0 : 3c010000; % (00) main: lui r1, 0 # address of data[0] 1 : 34240080; % (04) ori r4, r1, 0x80# address of data[0] 2 : 20050004; % (08) addi r5, r0, 4 # counter 3 : 0c000018; % (0c) call: jal sum # call function 4 : ac820000; % (10) sw r2, 0(r4) # store result 5 : 8c890000; % (14) lw r9, 0(r4) # check sw 6 : 01244022; % (18) sub r8, r9, r4 # sub: r8 <-- r9 - r4 7 : 20050003; % (1c) addi r5, r0, 3 # counter 8 : 20a5ffff; % (20) loop2: addi r5, r5,-1 # counter - 1 9 : 34a8ffff; % (24) ori r8, r5, 0xffff # zero-extend: 0000ffff A : 39085555; % (28) xori r8, r8, 0x5555 # zero-extend: 0000aaaa B : 2009ffff; % (2c) addi r9, r0, -1 # sign-extend: ffffffff C : 312affff; % (30) andi r10,r9, 0xffff # zero-extend: 0000ffff D : 01493025; % (34) or r6, r10,r9 # or: ffffffff E : 01494026; % (38) xor r8, r10,r9 # xor: ffff0000 F : 01463824; % (3c) and r7, r10,r6 # and: 0000ffff 10 : 10a00001;% (40) beq r5, r0, shift # if r5 = 0, goto shift 11 : 08000008;% (44) j loop2 # jump loop2 12 : 2005ffff; % (48) shift: addi r5, r0, -1 # r5 = ffffffff %

% % % %

% % % % % % % % % % % % % % % % % % % %

13 : 000543c0;% (4c) 14 : 00084400;% (50) 15 : 00084403;% (54) 16 : 000843c2;% (58) 17 : 08000017;% (5c) 18 : 00004020;% (60) 19 : 8c890000;% (64) 1A : 20840004;% (68) 1B : 01094020;% (6c) 1C : 20a5ffff; % (70) 1D : 14a0fffb; % (74) 1E : 00081000;% (78) 1F : 03e00008;% (7c) 20 : 000000A3;% (80) 21 : 00000027;% (84) 22 : 00000079;% (88) 23 : 00000115;% (8c) 24 : 00000000;% (90) END;

finish: sum: loop: data[0] data[1] data[2] data[3] sum sll sll sra srl j add lw addi r4, add addi r5, bne sll jr r8, r5, 15 # <<15 = ffff8000

r8, r8, 16 # <<16 = 80000000 r8, r8, 16 # >>16 = ffff8000(arith) r8, r8, 15 # >>15 = 0001ffff(logic) finish # dead loop r8, r0, r0 # sum r9, 0(r4) # load data r4, 4 # address + 4 r8, r8, r9 # sum r5, -1 # counter - 1 r5, r0, loop # finish? r2, r8, 0 # move result to v0 r31 # return %

% % % % % % % % % % % % % % % % %

六.EDA阶段的实验结果( “编译”、 “仿真” 等)

仿真结果如上图。

七.测试时的电路总体结构及其说明

实验电路图

八.测试计划(包括计划进行的系统测试、每一测试的测试过程、测试所需的测试数据、预期结果数据等)及其相关说明

输出说明:

由于引脚及输出需要,故下表ir对应ir[31..0]且将显示高四位,pc对应pc[31..0]且将显示低两位,alu对应alu[31..0]且将显示低两位

输入 clock mem_clk pc 输出 alu ir clock 输入 mem_clk pc 输出 alu ir

九.关于实验电路设计的其他说明

由于引脚及输出需要,故只输出ir、pc、aluir[31..0]切将显示ir高四位,pc[31..0]低两位,alu[31..0]低两位,q、adr、fromm、a、b、tom将不会输出

十.前期实验总结

本次实验,不仅加深了我对多周期CPU及存储器相关知识的理解,而且帮助自己回忆和复习了单周期CPU方面的知识,比如如何用Verilog HDL描述ALU模块、一些数据选择器、符号扩展电路、以及寄存器。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top