计算机组成原理实验
-单周期CPU的设计与实现
电子科技大学计算机科学与工程学院
实验报告
(实验)课程名称:计算机组成原理实验
电子科技大学教务处制
电子科技大学
实验报告
学生姓名:郫县尼克杨学号: 2014666666666指导教师:陈虹 实验
地点:主楼A2-411实验时间:12周-15周
一、 实验室名称:
主楼A2-411
二、 实验项目名称:
单周期CPU的设计与实现。
三、 实验学时:
8学时
四、 实验原理:
(一) 概述
单周期(Single Cycle)CPU是指CPU从取出1条指令到执行完该指令
只需1个时钟周期。
1个时钟周期
Clock
一条指令的执行过程包括:取指令?分析指令?取操作数?执行指令?保存结果。对于单周期CPU来说,这些执行步骤均在一个时钟周期内完成。
(二) 单周期cpu总体电路
本实验所设计的单周期CPU的总体电路结构如下。
(三) MIPS指令
化
2
MIPS指令系统结构有MIPS-32和MIPS-64两种。本实验的MIPS指令选用MIPS-32。以下所说的MIPS指令均指MIPS-32。
MIPS的指令格式为32位。下图给出MIPS指令的3种格式。
31 26 25 21 20 16 15 11 10 6 5 0
R型指令
31 op 26 25 rs 21 20 rt 16 15 rd sa func 0
I型指令
31 op 26 25 rs rt immediate 0
J型指令 op address
本实验只选取了9条典型的MIPS指令来描述CPU逻辑电路的设计方法。下图列出了本实验的所涉及到的9条MIPS指令。
五、 实验目的
1、掌握单周期CPU的工作原理、实现方法及其组成部件的原理和设计方法,如控制器、运算器等。
2、认识和掌握指令与CPU的关系、指令的执行过程。
3、熟练使用硬件描述语言Verilog、EDA工具软件进行软件设计与仿真,以培养学生的分析和设计CPU的能力。
六、 实验内容
(一)拟定本实验的指令系统,指令应包含R型指令、I型指令和J型指令,指令数为9条。
(二)CPU各功能模块的设计与实现。
(三)对设计的各个模块的仿真测试。
(四)整个CPU的封装与测试。
七、 实验器材(设备、元器件):
(一)安装了Xilinx ISE Design Suite 13.4的PC机一台 3
(二)FPGA开发板:Anvyl Spartan6/XC6SLX45
(三)计算机与FPGA开发板通过JTAG(Joint Test Action Group)接口连接,其连接方式如图所示。
八、 实验步骤
一个CPU主要由ALU(运算器)、控制器、寄存器堆、取指部件及其它基本功能部件等构成。
在本实验中基本功能部件主要有:32位2选1多路选择器、5位2选1多路选择器、32位寄存器堆、ALU等。
(一)新建工程(New Project)
启动ISE Design Suite 13.4软件,然后选择菜单File?New Project,弹出New Project Wizard对话框,在对话框中输入工程名CPU,并指定工作路径D:\Single_Cycle_CPU。
(二)基本功能器件的设计与实现
(1)多路选择器的设计与实现
a.5位2选1多路选择器(MUX5_2_1)的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:MUX5_2_1,然后输入其实现代码:
MODULE MUX5_2_1(
INPUT [4:0] A,
INPUT [4:0] B,
INPUT SEL,
OUTPUT [4:0] O
);
ASSIGN O = SEL ? B : A;
ENDMODULE
在ISE集成开发环境中,对模块MUX5_2_1进行综合(Synthesize),综合结果如图所示:
4
在ISE集成开发环境中,对模块MUX5_2_1进行仿真(Simulation)。输入如下测式代码:
MODULE MUX5_2_1_T;
// INPUTS REG [4:0] A; REG [4:0] B; REG SEL; // OUTPUTS WIRE [4:0] C; //
INSTANTIATE THE UNIT UNDER TEST (UUT) MUX5_2_1 UUT
( .A(A), .B(B), .SEL(SEL), .C(C) ); INITIAL BEGIN // INITIALIZE
INPUTS A = 0; B = 0; SEL = 0; // WAIT 100 NS FOR GLOBAL RESET TO FINISH
#100;
A = 5'B10100;
B = 0;
SEL = 1;
// WAIT 100 NS FOR GLOBAL RESET TO FINISH
#100;
A = 1;
B = 5'B10000;
SEL = 0;
// WAIT 100 NS FOR GLOBAL RESET TO FINISH
#100;
A = 5'B00000;
B = 5'B11000;
SEL = 1;
// ADD STIMULUS HERE
END
5
ENDMODULE
然后进行仿真,仿真结果如图所示:
b.32位2选1多路选择器的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:
MUX32_2_1,然后输入其实现代码:
MODULE MUX32_2_1(
INPUT [31:0]A ,
INPUT [31:0]B,
INPUT SEL,
OUTPUT [31:0] O
);
ASSIGN O= SEL?B:A;
ENDMODULE
在ISE集成开发环境中,对模块MUX32_2_1进行综合(Synthesize),
综合结果如图所示:
在ISE集成开发环境中,对模块MUX32_2_1进行仿真(Simulation)。
首先输入如下测式代码:
MODULE MUX32_2_1_T;
// INPUTS REG [31:0] A; REG [31:0]
B; 6
REG SEL; // OUTPUTS WIRE [31:0] O; // INSTANTIATE THE UNIT UNDER TEST (UUT) MUX32_2_1 UUT ( .A(A), .B(B), .SEL(SEL), .O(O) ); INITIAL BEGIN A=0; B=0; SEL=0; // WAIT 100 NS FOR GLOBAL RESET TO FINISH #100; A=32'H00000001; B=32'H00000000;
SEL=1; #100; A=32'H00000101; B=32'H00000010; SEL =0; // ADD STIMULUS HERE END
ENDMODULE
然后进行仿真,仿真结果如图所示
:
(2)符号扩展(Sign_Extender)的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:
Sign_Extender,然后输入其实现代码:
7
MODULE SIGN_EXTENDER(
INPUT [15:0] D, OUTPUT [31:0] O
); ASSIGN O = (D[15:15] == 1'B0) ? {16'B0, D[15:0]} : {16'B1, D[15:0]};
ENDMODULE
在ISE集成开发环境中,对模块Sign_Extender进行综合(Synthesize),
综合结果如图所示。
在ISE集成开发环境中,对模块MUX32_2_1进行仿真(Simulation)。
首先输入如下测式代码:
MODULE SIGN_EXTENDER_T;
// INPUTS REG [15:0] D; // OUTPUTS WIRE [31:0] O; // INSTANTIATE THE UNIT UNDER TEST (UUT) SIGN_EXTENDER UUT ( .D(D), .O(O) ); INITIAL
BEGIN // INITIALIZE INPUTS D = 0; // WAIT 100 NS FOR GLOBAL RESET
TO FINISH 8
#100; // ADD STIMULUS HERE D = 16'H0011; #100; D =
16'H1011; END
ENDMODULE
然后进行仿真,仿真结果如图所示
:
(3)32位寄存器堆(RegFile)的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:
RegFile,然后输入其实现代码:
MODULE REGFILE(
INPUT [4:0] RN1, RN2, WN,
INPUT WRITE,
INPUT [31:0] WD,
OUTPUT [31:0] A, B,
INPUT CLOCK
);
REG [31:0] REGISTER[1:31];
ASSIGN A = (RN1 == 0) ? 0 : REGISTER[RN1];
ASSIGN B = (RN2 == 0) ? 0 : REGISTER[RN2];
ALWAYS @ (POSEDGE CLOCK) BEGIN
IF (WRITE && WN != 0)
REGISTER[WN] <= WD;
END
ENDMODULE
在ISE集成开发环境中,对模块RegFile进行综合(Synthesize),综合
结果如图所示。
9
在ISE集成开发环境中,对模块RegFile进行仿真(Simulation)。输入
如下测式代码:
MODULE REGFILE_T;
// INPUTS REG [4:0] RN1; REG [4:0] RN2; REG [4:0] WN; REG WRITE; REG [31:0] WD; REG CLOCK; // OUTPUTS WIRE [31:0] A; WIRE [31:0] B; // INSTANTIATE THE UNIT UNDER TEST (UUT) REGFILE UUT
( .RN1(RN1), .RN2(RN2), .WN(WN), .WRITE(WRITE), .WD(WD),
.A(A), .B(B), .CLOCK(CLOCK) ); INITIAL BEGIN // INITIALIZE INPUTS 10
RN1 = 0; RN2 = 0; WN = 0; WRITE = 0; WD = 0; CLOCK = 0; // WAIT 100 NS FOR GLOBAL RESET TO FINISH #100;
RN1 = 5'B00001;
RN2 = 5'B00001;
WN = 5'B00001;
WRITE = 1;
WD = 0;
CLOCK = 0;
#100;
CLOCK = 1;
#50;
WD = 32'HBBBBBBBB;
#50;
CLOCK = 0;
#100;
CLOCK = 1;
#100
CLOCK = 0;
// ADD STIMULUS HERE
END
ENDMODULE
然后进行仿真,仿真结果如图所示
:
(4)运算器(ALU)设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:
ALU,然后输入其实现代码:
11
MODULE ALU(
INPUT [31:0] A, B, INPUT [2:0] ALU_OPERATION, OUTPUT [31:0] RESULT, OUTPUT ZERO );
ASSIGN RESULT = (ALU_OPERATION == 3'B000) ? A + B :
(ALU_OPERATION == 3'B100) ? A - B : (ALU_OPERATION == 3'B001) ? A & B : (ALU_OPERATION == 3'B101) ? A | B : (ALU_OPERATION == 3'B010) ? A ^ B : (ALU_OPERATION == 3'B110) ? {B[15:0], 16'H0} : 32'HXXXXXXXX; ASSIGN ZERO = ~|RESULT;
ENDMODULE
在ISE集成开发环境中,对模块ALU进行综合(Synthesize),综合结
果如图所示
:
在ISE集成开发环境中,对模块ALU进行仿真(Simulation)。输入如
下测式代码:
MODULE ALU_TB;
// INPUTS REG [31:0] A; REG [31:0] B; REG [2:0] ALU_OPERATION; 12
// OUTPUTS WIRE [31:0] RESULT; WIRE ZERO; // INSTANTIATE THE UNIT UNDER TEST (UUT) ALU UUT
( .A(A), .B(B), .ALU_OPERATION(ALU_OPERATION), .RESULT(RESULT), .ZERO(ZERO) ); INITIAL BEGIN // INITIALIZE INPUTS A = 0; B = 0; ALU_OPERATION = 0; // WAIT 100 NS FOR GLOBAL RESET TO FINISH #100; A = 1; B = 1; ALU_OPERATION = 0; // ADD STIMULUS HERE
#100 A = 2; B = 2; ALU_OPERATION = 4;
#100 A = 1; B = 1; ALU_OPERATION = 1;
#100 A = 1; B = 1; ALU_OPERATION = 5;
#100 A = 1; B = 1; 13
ALU_OPERATION = 2; END
ENDMODULE
然后进行仿真,仿真结果如图所示
:
(5)控制器(Controller)的设计与实现
为了简化设计,控制器由控制单元Control和控制单元ALUop组成,
控制器结构如下所示。
a( Control的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:
Control,然后输入其实现代码:
MODULE CONTROL(
INPUT [5:0] OP, OUTPUT REGDST, OUTPUT REGWRITE, OUTPUT ALUSRC, OUTPUT MEMWRITE, OUTPUT MEMREAD, OUTPUT MEMTOREG, OUTPUT BRANCH, OUTPUT [1:0] ALUCTR
); WIRE I_RT=~|OP; WIRE I_LW=OP[5] & ~OP[3]; WIRE I_SW=OP[5] & OP[3]; WIRE I_BEQ =OP[2] & ~OP[1]; WIRE I_LUI=OP[3] & OP[2]; ASSIGN REGDST = I_RT; ASSIGN REGWRITE=I_RT|I_LW|I_LUI; ASSIGN
ALUSRC =I_LW|I_SW |I_LUI; ASSIGN MEMWRITE =I_SW; ASSIGN MEMREAD=I_LW; ASSIGN MEMTOREG= I_LW; ASSIGN BRANCH=I_BEQ; 14
ASSIGN ALUCTR[1]= I_RT|I_LUI; ASSIGN ALUCTR[0]=I_BEQ|I_LUI;
ENDMODULE
在ISE集成开发环境中,对模块Control进行综合(Synthesize), 综
合结果如图:
在ISE集成开发环境中,对模块Control进行仿真(Simulation)。首先
输入如下测式代码:
MODULE CONTROL_TB;
// INPUTS REG [5:0] OP; // OUTPUTS WIRE REGDST; WIRE REGWRITE; WIRE ALUSRC; WIRE MEMWRITE; WIRE MEMREAD; WIRE MEMTOREG; WIRE BRANCH; WIRE [1:0] ALUCTR; // INSTANTIATE THE UNIT UNDER TEST (UUT) CONTROL UUT
( .OP(OP), .REGDST(REGDST), .REGWRITE(REGWRITE), .ALUSRC(ALUSRC), 15
// WAIT 100 NS FOR GLOBAL RESET TO FINISH
#100;
OP = 6'B000000;
#100;
OP = 6'B100011;
#100;
OP = 6'B101011;
#100;
OP = 6'B000100;
#100;
OP = 6'B001111;
END
ENDMODULE ); .MEMWRITE(MEMWRITE), .MEMREAD(MEMREAD), .MEMTOREG(MEMTOREG), .BRANCH(BRANCH), .ALUCTR(ALUCTR) INITIAL BEGIN // INITIALIZE INPUTS OP = 0;
然后进行仿真,仿真结果如图所示:
b( ALUop的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:
ALUop,然后输入其实现代码:
MODULE ALUOP(
INPUT [5:0] FUNC, INPUT [1:0] ALUCTR, OUTPUT [2:0] ALU_OP
);
WIRE I_RT = ALUCTR[1] & ~ALUCTR[0];
16
ALU_OP[2]=(I_RT&((~FUNC[2]&FUNC[1])|(FUNC[2] &FUNC[0])))
ALUCTR[0];
ASSIGN ALU_OP[1]=(I_RT &FUNC[2] &FUNC[1])| (ALUCTR[1]& ALUCTR[0]); ASSIGN ALU_OP[0]=(I_RT &FUNC[2] &~FUNC[1]);
ENDMODULE ASSIGN |
在ISE集成开发环境中,对模块ALUop进行综合(Synthesize), 综合
结果如图:
在ISE集成开发环境中,对模块ALUop进行仿真(Simulation)。首先
输入如下测式代码:
MODULE ALU_TB;
// INPUTS REG [31:0] A; REG [31:0] B; REG [2:0] ALU_OPERATION; // OUTPUTS WIRE [31:0] RESULT; WIRE ZERO; // INSTANTIATE THE UNIT UNDER TEST (UUT) ALU UUT
( .A(A), .B(B), .ALU_OPERATION(ALU_OPERATION), .RESULT(RESULT), .ZERO(ZERO) ); INITIAL BEGIN 17
// WAIT 100 NS FOR GLOBAL RESET TO FINISH #100;
A = 1;
B = 1;
ALU_OPERATION = 0;
// ADD STIMULUS HERE
#100
A = 2;
B = 2;
ALU_OPERATION = 4;
#100
A = 1;
B = 1;
ALU_OPERATION = 1;
#100
A = 1;
B = 1;
ALU_OPERATION = 5;
#100
A = 1;
B = 1;
ALU_OPERATION = 2;
END
ENDMODULE // INITIALIZE INPUTS A = 0; B = 0;
ALU_OPERATION = 0;
然后进行仿真,仿真结果如图所:
c( 将Control与ALUop封装成Controller 18
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:Controller,然后输入其实现代码:
MODULE CONTROLLER(
INPUT [5:0] OP, INPUT [5:0] FUNC, OUTPUT REGDST, OUTPUT REGWRITE, OUTPUT ALUSRC, OUTPUT MEMWRITE, OUTPUT MEMREAD, OUTPUT MEMTOREG, OUTPUT BRANCH, OUTPUT [2:0] ALU_OP
);
WIRE [1:0] ALUCTR;
CONTROL U0 (OP, REGDST, REGWRITE, ALUSRC, MEMWRITE, MEMREAD, MEMTOREG, BRANCH, ALUCTR);
ALUOP U1 (FUNC, ALUCTR, ALU_OP);
ENDMODULE
在ISE集成开发环境中,对模块Controller进行综合(Synthesize),综
合结果如图:
19
在ISE集成开发环境中,对模块Controller进行仿真(Simulation)。首
先输入如下测式代码:
MODULE CONTROLLER_TB;
// INPUTS REG [5:0] OP; REG [5:0] FUNC; // OUTPUTS WIRE REGDST; WIRE REGWRITE; WIRE ALUSRC; WIRE MEMWRITE; WIRE MEMREAD; WIRE MEMTOREG; WIRE BRANCH; WIRE [2:0] ALU_OP; // INSTANTIATE THE UNIT UNDER TEST (UUT) CONTROLLER UUT
( .OP(OP), .FUNC(FUNC), .REGDST(REGDST), .REGWRITE(REGWRITE), .ALUSRC(ALUSRC), .MEMWRITE(MEMWRITE), .MEMREAD(MEMREAD), .MEMTOREG(MEMTOREG), .BRANCH(BRANCH), .ALU_OP(ALU_OP
) ); INITIAL BEGIN // INITIALIZE INPUTS OP = 0; FUNC = 0; // WAIT
100 NS FOR GLOBAL RESET TO FINISH #100; OP =6'B100011; #100
OP=6'B101011; 20
#100
OP=6'B000100;
#100
OP=6'B001111;
END
ENDMODULE
然后进行仿真,仿真结果如图所示
:
(6)取指电路的设计与实现
取指电路需完成ADD32、PC寄存器、多路选择器和左移两位模块,从而实现该取指电路。
a(ADD32的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:ADD32,然后输入其实现代码:
MODULE ADD32(
INPUT [31:0] A, B, OUTPUT [31:0] C );
ASSIGN C = A + B;
ENDMODULE
在ISE集成开发环境中,对模块Controller进行综合(Synthesize),综合结果如图:
21
b(左移两位模块(Left_2_Shifter)的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:Left_2_Shifter,然后输入其实现代码:
MODULE LEFT_2_SHIFTER(
INPUT [31:0] D,
OUTPUT [31:0] O
);
ASSIGN O = {D[29:0], 2'B00};
ENDMODULE
在ISE集成开发环境中,对模块Controller进行综合(Synthesize),综合结果如图:
c(综合取指电路(Fetch)的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:Fetch,然后输入其实现代码:
MODULE FETCH(
INPUT RESET, INPUT CLOCK, INPUT [31:0] B_ADDR, INPUT Z, B, OUTPUT
[31:0] ADDR
); REG [31:0] PC; WIRE [31:0] U0_O; WIRE [31:0] U1_C; WIRE [31:0] U2_C; WIRE [31:0] NEXT_PC; WIRE SEL = Z & B; 22
LEFT_2_SHIFTER U0 (B_ADDR, U0_O); ADD32 U1 (PC, 4, U1_C); ADD32 U2 (U1_C, U0_O, U2_C); MUX32_2_1 M1 (U1_C, U2_C, SEL, NEXT_PC); ASSIGN ADDR = PC; ALWAYS @ (POSEDGE CLOCK OR NEGEDGE RESET) BEGIN IF (RESET == 0) PC = 0; ELSE PC = NEXT_PC; END
ENDMODULE
在ISE集成开发环境中,对模块Fetch进行综合(Synthesize),综合结
果如图:
在ISE集成开发环境中,对模块Fetch进行仿真(Simulation)。首先输
入如下测式代码:
MODULE FETCH_T;
// INPUTS REG CLOCK; REG RESET; REG [31:0] B_ADDR; REG B; 23
REG Z; // OUTPUTS WIRE [31:0] INST; WIRE [31:0] O_ADDR; WIRE [31:0] O_SUM; WIRE [31:0] O_SUM1; // INSTANTIATE THE UNIT UNDER TEST (UUT) FETCH UUT
( .CLOCK(CLOCK), .RESET(RESET), .B_ADDR(B_ADDR), .B(B), .Z(Z),
.INST(INST), .O_ADDR(O_ADDR), .O_SUM(O_SUM), .O_SUM1(O_SUM1) ); INITIAL BEGIN // INITIALIZE INPUTS CLOCK = 0; RESET = 0; B_ADDR = 0; B = 0; Z = 0; // WAIT 100 NS FOR GLOBAL RESET TO FINISH #100; CLOCK=1; #100; CLOCK=0; #100; CLOCK=1; #100; CLOCK=0; #100; CLOCK=1; #100; CLOCK=0; #100; 24
#100;
Z=1;
B=1;
B_ADDR=32'H4;
CLOCK=0;
#100;
CLOCK=1;
#100;
CLOCK=0;
B=0;
Z=0;
#100;
CLOCK=1;
#100;
CLOCK=0;
#100;
CLOCK=1;
B_ADDR=32'B0;
#100;
CLOCK=0;
#100;
RESET=1;
CLOCK=1;
#100;
CLOCK=0;
#100;
CLOCK=1;
#100;
CLOCK=0;
// ADD STIMULUS HERE
// ADD STIMULUS HERE
END
ENDMODULE
CLOCK=1;
然后进行仿真,仿真结果如图所示
:
25
(7)数据通路Data_Flow的设计与实现
除去指令存储器Instruction ROM、数据存储器DATA MEM,将剩余的电路封装成一个单周期的CPU数据通路(Data_Flow)模块。
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:Data_Flow,然后输入其实现代码:
MODULE DATA_FLOW(
INPUT RESET, INPUT CLOCK, INPUT [31:0] INST, INPUT [31:0] DATA, OUTPUT MEMWRITE, OUTPUT MEMREAD, OUTPUT [31:0] RESULT, OUTPUT [31:0] B_DATA, OUTPUT [31:0] NEXTPC
FETCH U0 (RESET, CLOCK, B_ADDR, Z, B, NEXTPC);
CONTROLLER U1 (INST[31:26], INST[5:0], REGDST, REGWRITE, ALUSRC,
MEMWRITE, MEMREAD, MEMTOREG, B, ALU_OP);
ALU U2 (ALU_A, ALU_B, ALU_OP, RESULT, Z);
REGFILE U3 (INST[25:21], INST[20:16], WN, REGWRITE, WD, ALU_A, B_DATA, CLOCK);
MUX5_2_1 U4 (INST[20:16], INST[15:11], REGDST, WN);
MUX32_2_1 U5 (B_DATA, B_ADDR, ALUSRC, ALU_B);
SIGN_EXTENDER U6 (INST[15:0], B_ADDR);
MUX32_2_1 U7 (NEXTPC, DATA, MEMTOREG, WD);
ENDMODULE ); WIRE [31:0] B_ADDR; WIRE Z, B; WIRE REGDST; WIRE REGWRITE; WIRE ALUSRC; WIRE MEMTOREG; WIRE [2:0] ALU_OP; WIRE [31:0] ALU_A, ALU_B; WIRE [4:0] WN; WIRE [31:0] WD;
在ISE集成开发环境中,对模块Controller进行综合(Synthesize),综
合结果如图:
26
在ISE集成开发环境中,对模块Data_Flow进行仿真(Simulation)。首
先输入如下测式代码:
MODULE DATA_FLOW_TB;
// INPUTS REG RESET; REG CLOCK; REG [31:0] INST; REG [31:0] DATA; //
OUTPUTS WIRE MEMWRITE; 27
WIRE MEMREAD;
WIRE [31:0] RESULT;
WIRE [31:0] B_DATA;
WIRE [31:0] NEXTPC;
// INSTANTIATE THE UNIT UNDER TEST (UUT)
DATA_FLOW UUT (
.RESET(RESET),
.CLOCK(CLOCK),
.INST(INST),
.DATA(DATA),
.MEMWRITE(MEMWRITE),
.MEMREAD(MEMREAD),
.RESULT(RESULT),
.B_DATA(B_DATA),
.NEXTPC(NEXTPC)
);
INITIAL BEGIN
// INITIALIZE INPUTS
RESET = 0;
CLOCK = 0;
INST = 0;
DATA = 0;
// WAIT 100 NS FOR GLOBAL RESET TO FINISH
#100;
RESET = 1;
//#100;
INST = 32'H00002820;//R型,ADD,0号0号寄存器内容相加保存到5号寄存器,执行后MW,MR应为零,B_DATA应为零
DATA = 32'H12345678;
#100;
CLOCK = 1;
#100;
CLOCK = 0;
#100;
INST = 32'H8CB10000;//I,LW,5号与立即数符号扩展相加作为地址,将内存单元内容DATA送到9号寄存器,执行:
//MR应为1,MW应为0,B_DATA应为DATA的值32'H12345678
#100;
CLOCK = 1;
#100;
28
CLOCK = 0;
#100
INST = 32'HACA00000;//I,SW,5号与立即数符号扩展相加作为地址,将0号寄存器的内容送到内存单元,执行:
//MR应为0,MW应为1,B_DATA应为0号寄存器内容0
#100;
CLOCK = 1;
#100;
RESET = 0;
// ADD STIMULUS HERE
END
ENDMODULE
然后进行仿真,仿真结果如图所示
:
(8)Instruction ROM的设计与实现
假定一个只有32个32位单元的指令存储器,由于只读无需写入,所以可以设置为简化的32个wire型变量,每个变量可被赋值为一条指令。
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,创建一个Verilog Module模块,名称为:Inst_ROM,然后输入其实现代码:
MODULE INST_ROM(
INPUT [31:0] ADDRESS, OUTPUT [31:0] INST
); WIRE [31:0] RAM [0:31]; ASSIGN RAM [0] =
32'B000000_00001_00010_00011_00000100000;//AND ASSIGN RAM [1] = 32'B000000_00001_00010_00011_00000100000;//AND ASSIGN RAM [2] = 32'B100011_00101_10001_0000000000000000;//LW ASSIGN RAM [3] = 32'B100011_00101_10010_0000000000000100;//LW 29
ASSIGN RAM [4] =
32'B000000_10001_10010_10001_00000100000;//AND ASSIGN RAM [5] = 32'B100011_00101_10010_0000000000001000;//LW ASSIGN RAM [6] = 32'B000100_10001_10001_0000000000000001;//BEP ASSIGN RAM [7] = 32'B101011_00101_00000_0000000000001100;//SW ASSIGN RAM [8] = 32'B000000_00000_00000_0010100000100000;//AND ASSIGN INST = RAM[ADDRESS[6:2]];
ENDMODULE
在ISE集成开发环境中,对模块Inst_ROM进行综合(Synthesize),综
合结果如图
:
在ISE集成开发环境中,对模块Inst_ROM进行仿真(Simulation)。首
先输入如下测式代码:
MODULE INST_ROM_TB;
// INPUTS REG [31:0] ADDRESS; // OUTPUTS WIRE [31:0] INST; // INSTANTIATE THE UNIT UNDER TEST (UUT) INST_ROM UUT
( .ADDRESS(ADDRESS), .INST(INST) ); INITIAL BEGIN // INITIALIZE INPUTS ADDRESS = 0; 30
// WAIT 100 NS FOR GLOBAL RESET TO FINISH #100;
ADDRESS = 0;
#100;
ADDRESS = 4;
#100;
ADDRESS = 8;
#100;
ADDRESS = 12;
#100;
ADDRESS = 16;
#100;
ADDRESS = 20;
#100;
ADDRESS = 24;
#100;
ADDRESS = 28;
// ADD STIMULUS HERE
END
ENDMODULE
然后进行仿真,仿真结果如图
:
(9)Data Mem模块的设计与实现
对于实验而言,32个32位单元的数据存储器已满足需求(实际情况
应该是以字节编址)。由于需要保存并写入数据,所以应设置32个reg型
变量,要求初始化0、1、2号单元的内容为2、3、5。
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出 的菜单中选择New Source命令,创建一个Verilog Module模块,名称
为:data_mem,然后输入其实现代码:
MODULE DATA_MEM(ADDR, READ, WRITE, DATAIN, CLOCK, DATAOUT);
INPUT [31:0] ADDR; INPUT READ, WRITE; INPUT [31:0] DATAIN; INPUT CLOCK; OUTPUT [31:0] DATAOUT; REG [31:0] RAM [0:31]; ASSIGN DATAOUT = READ ? RAM[ADDR[6:2]] : 32'HXXXXXXXX; 31
ALWAYS @ (POSEDGE CLOCK) BEGIN RAM[ADDR[6:2]] = WRITE ? DATAIN : 32'HXXXXXXXX; END INTEGER I; FOR(I = 0;I<32;I = I + 1) RAM[I] = I; INITIAL BEGIN END
ENDMODULE
在ISE集成开发环境中,对模块data_mem进行综合(Synthesize), 综
合结果如图
:
(10)MainBoard模块的设计与实现
在ISE集成开发环境中,在工程管理区任意位置单击鼠标右键,在弹
出 的菜单中选择New Source命令,创建一个Verilog Module模块,名称
为:MainBoard,然后输入其实现代码:
MODULE MAINBOARD(
INPUT CLOCK,RESET, OUTPUT [31:0] INST, OUTPUT [31:0] PC,
OUTPUT [31:0] ALUOUT, OUTPUT [31:0] B_DATA
);
WIRE [31:0] ADDR_FTI;
WIRE [31:0] DATA_DTF;
WIRE MEMWRITE,MEMREAD;
32
WIRE [31:0] RESULT;
WIRE [31:0] NEXTPC;
DATA_FLOW U0(RESET, CLOCK, INST, DATA_DTF, MEMWRITE, MEMREAD,
RESULT, B_DATA, NEXTPC);
INST_ROM U1(NEXTPC, INST);
DATA_MEM U2(CLOCK, DATA_DTF, B_DATA, RESULT, MEMWRITE,
MEMREAD);
ASSIGN PC = NEXTPC;
ASSIGN ALUOUT = RESULT;
ENDMODULE
在ISE集成开发环境中,对模块MIPS_CPU进行综合(Synthesize), 综
合结果如图22所示。
在ISE集成开发环境中,对模块Inst_ROM进行仿真(Simulation)。首
先输入如下测式代码:
MODULE MAINBOARD_TB;
// INPUTS REG CLOCK; REG RESET; // OUTPUTS WIRE [31:0] INST; WIRE [31:0] PC; 33
WIRE [31:0] ALUOUT; WIRE [31:0] B_DATA; // INSTANTIATE THE UNIT UNDER TEST (UUT) MAINBOARD UUT
( .CLOCK(CLOCK), .RESET(RESET), .INST(INST), .PC(PC), .ALUOUT(ALUOUT), .B_DATA(B_DATA) ); INITIAL BEGIN // INITIALIZE INPUTS CLOCK = 0; RESET = 0; // WAIT 100 NS FOR GLOBAL RESET TO FINISH #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; RESET = 1; #100;
CLOCK = ~CLOCK; 34
RESET = 1; #100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
#100;
CLOCK = ~CLOCK;
RESET = 1;
END
ENDMODULE
然后进行仿真,仿真结果如图
:
在该转移的地方进行了转移,成功。 35
九、 实验数据及结果分析:
在一个时钟周期内所设计的CPU能够完成一条指令的执行,指令执行结果与预期的结果是一致的。通过仿真可以看到最终顺利实现了每个模块的功能,成功解决了之前出错的PC转移问题,整个CPU按照设计好的指令运行。
十、 实验结论:
单周期CPU在一个时钟周期完成指令的所有执行步骤,简化了CPU的设计,但是这样没有考虑不同部件完成时间上的差异,所以导致CPU各部件的利用率不高,采用多周期流水线CPU可以提高利用率,但是难度也会增大许多。 十一、 总结及心得体会:
我本身对这次实验很兴趣,指导教师陈老师也非常和蔼耐心地指导,所以比较顺利地完成了整个实验。
本次实验完全是独立完成,没有任何抄袭,包括实验报告的编写,每一段代码都是自己写出来的,每一张图片也都是自己截的图,虽然整个过程花的时间比较多,但确实收获很多,很开心,也希望能得到一个好的成绩。
本次实验让我切实感受到了仿真的好处,计算机仿真在实际生产中的作用,也很好地锻炼了自己的逻辑思维能力,对课堂第四章第五章的内容有了更为深刻的理解。
要合理地将本次实验中“把庞大的部件分割为许多小部件,逐一解决”的方法运用到对其它问题的解决中。
十二、 对本实验过程及方法、手段的改进建议:
建议增加2个实验学时,同时将要实现的指令增加为十一条,增加运算器溢出信号Overflow、判断溢出的加法运算,以及J型指令的设计与实现,从而进一步锻炼自己。
报告评分:
指导教师签字:
36