程序源代码 联系企鹅号 3270516346
一、计算机系统概述
1、设计内容
本设计为一个单周期CPU,采用MIPS结构。此CPU支持多种指令集,能够满足基本的功能需求。在此设计中,编写了一个求平均数和实现位反转的程序,通过modelsim等仿真工具进行仿真,以验证CPU功能的正确性。
2、计算机的基本硬件组成
计算机系统的主要硬件组成包括:
计算机硬件系统由计算器、控制器、存储器、输入设备和输出设备组成,是计算机系统的物理组成部分。
1、控制器:它是分析输入指令并统一控制计算机各部件完成一定任务的部件。 它通常由指令寄存器、状态寄存器、指令译码器、时间电路和控制电路组成,是指挥和协调其他部件的中心。
2、运算器:又称算术逻辑单元,是进行算术和逻辑操作的组件,计算机的基本操作都由运算器执行。
3、存储器:它是计算机记忆或临时存储数据的组成部分,又分为内部存储器和外部存储器,可以使计算机随时存储和检索数据。
4、输入设备:它是一个重要的人机接口,用于接收用户输入的原始数据和程序,并将其转换为计算机识别的二进制存储到内存中。
5、输出设备:输出计算机处理结果的设备,用于将存储在内存中的计算机处理结果转换为可接受的输出形式。
3、指令执行的各个阶段
取指令(IF)、译码(ID)、执行(EX)、访存(MEM)、回写(WB)
二、指令系统设计
1、指令格式
① R型指令:寄存器操作
op: 操作码
rs、rt :源操作数
rd :目的操作数
funct : 使用操作码告诉计算机执行什么操作
shamt:位移指令的位移量,不是位移指令就为0
②I型指令:立即数型
op : 操作码
rs : 源操作数
rt : 目的操作数
imm: 立即数
③J型指令:跳转类型
op : 操作数
addr: 立即数,跳转地址
2、CPU寄存器
MIPS架构的CPU拥有32个通用寄存器和32个浮点寄存器,每个寄存器的编号、代号以及用途如下:
3、设计的指令及功能
add: R-R型,寄存器相加运算
sub : R-R型,寄存器相减运算
and :R-R型,寄存器与运算
div :R-R型,寄存器相除
addi : R-I型,立即数与寄存器相加运算
andi R-I型指令,与
j :跳转指令
lw : R-I型指令 ,加载存储字
sw : R-I型指令 ,存储字
ben :R-I型,相等时转移
4、10个数累加并求平均数的指令设计
三、模块详细设计
1、寄存器模块设计
①程序计数器设计(PC)
程序计数器为一个32位的寄存器,它决定下一条将要执行的命令的地址。PC有一个输入端输入下一地址,一个输出端决定当前程序执行地址,在此PC中还加入了一个使能位,以配合流水线CPU的控制。
module PC(
input clk,
input reset,
input [31:0] di, //
output reg [31:0] do //
);
always @(posedge clk,negedge reset)
begin
if(!reset)
do<=32'b0;
else
do<=di;
end
endmodule
②次地址计算单元(NPC)
次地址计算单元的功能为计算下一地址,当指令不是转移类指令时,它就是加4,次地址为连续的下一地址单元。
③指令寄存器(IM)
IM用于存储指令,为只读存储器。它有两个端口,一个为地址输入,另一个为指定地址处的数据输出。
④寄存器堆(RF)
寄存器堆为CPU中指令执行时所用到的寄存器,在该寄存器堆设计中,用两个读取数据端,对应指令中两个源操作数,一个数据写入段,用于对数据的写入。
⑤数据存储器(DM)
DM为RAM型存储器,它有一个读写控制端,读写控制端为低电平时,对DM读操作,高电平时,对DM读操作。
2、算数逻辑单元(ALU)
ALU的功能为对输入的数据进行加减等算数运算,ALU有一个控制端F,根据输入F的不同,对输入的数据进行不同的运算。
module ALU(
input [31:0] A, //输入A
input [31:0] B, //输入B
input [2:0] F, //选择信号
output reg [31:0] Y, //输出Y
output zero //判0信号
);
always @(*)
begin
case(F)
3'b000: Y<=A&B;
3'b001: Y<=A|B;
3'b010: Y<=A+B;
3'b011: Y<=A/B;
3'b100: Y<=A&(~B);
3'b101: Y<=A|(~B);
3'b110: Y<=A-B;
3'b111: begin
if(A<B)
Y<=1;
else
Y<=0;
end
endcase
end
assign zero=(A==B)?1'b1:1'b0;
endmodule
3、数据扩展模块(EXT)
对于立即数类的指令,立即数为16位数据,立即数要与RF输出的32位数据进行运算。为了在运算时对数据进行匹配,需要将立即数扩展为32位,对输入的立即数进行补码扩展。
4 、主控制器(CU)
控制器的职责为根据指令的操作码和funct域计算出每条指令在执行时控制信号应取何值。
控制器首先判断OP位是否为零(即指令是否为寄存器型指令),当OP为为零时,CU则根据funct位输出相应的控制信号,否则则根据OP位输出相应的控制信号。
CU有7种输出控制信号:cs为NPC的控制位,决定NPC如何计算下一地址;rf_wr为寄存器堆读写控制信号;dm_wr为数据存储器控制信号;ALUop为ALU的控制信号,决定ALU做怎样的运算;m1sel、m2sel、m3sel为三个MUX的选择控制信号。
module CU(
input [5:0] op,
input [5:0] fun,
output reg [2:0] cs,
output reg m1sel,
output reg m2sel,
output reg m3sel,
output reg rf_wr,
output reg dm_wr,
output reg [2:0] f
);
wire [5:0] func;//控制信号
assign func=(op==6'b000000)?fun:op;//判断控制信号来源
always @(*) //组合逻辑,译码电路
begin
case(func)
6'b100001: begin //add
cs<=3'b000;
m1sel<=1'b1;
m2sel<=1'b0;
m3sel<=1'b0;
rf_wr<=1'b1;
dm_wr<=1'b0;
f<=3'b010;
end
6'b100010: begin //sub
cs<=3'b000;
m1sel<=1'b1;
m2sel<=1'b0;
m3sel<=1'b0;
rf_wr<=1'b1;
dm_wr<=1'b0;
f<=3'b110;
end
四、设计完整微处理器硬件
1、数据通路的设计
在对每条指令都完成建模工作后,将各条指令对应的指令级别数据通路合成一个完整的指令级别数据通路。在将各条指令的指令级别数据通路汇总后,下一步就是进行数据通路综合。数据通路综合就是按照列方向合并每个输人信号的输入源。在合并过程中,对于重复的输入来源,只保留一个。
有些功能部件的输入信号具有两个以上的输入源。例如RF的 A3端口有3个输入来源。根据数字电路知识可知,当将多个输出信号输出至同一个输入信号时,则需要部署一个3选1的MUX来实现上述需求。
下图就是整个数据通路的描述,描述了在微控制器中数据是如何流动的:
2、控制通路的设计
控制器的职责是根据指令的 opcode和funct域计算每条指令在执行时控制信号应取何值。
下图是单周期CPU控制信号生成框图。从该图中可以看出,首先是根据每条指令的op-code和funct域将每条指令都用一个1位的布尔变量表示。
五、设计结果分析
采用Modelsim进行仿真,对顶层模块外加时钟信号和复位信号,仿真波形如下:
从使用的寄存器值的变化可以看出指令执行过程正确,最终的的结果正确(图中y0y5代表寄存器s0s5,y为最终存放结果的存储器)。
下图是微处理器在仿真过程中内部信号的变化,从PC值的改变可以看出,处理器的PC值的改变符合预期取出相应的指令进行执行。我们还可以看到执行不同的指令的时候,多路选择器选择不同的数据。寄存器堆栈在执行相应的指令的时候取出或存入相应的数据。
文章来源:https://www.toymoban.com/news/detail-552764.html
附录
1、完整微处理器硬件结构图:
文章来源地址https://www.toymoban.com/news/detail-552764.html
2、顶层文件代码(部分)
module cpu_top(
input clk,
input reset,
output [31:0] y0,
output [31:0] y1,
output [31:0] y2,
output [31:0] y3,
output [31:0] y4,
output [31:0] y5,
output [31:0] y
);
wire [31:0] pc,npc,im_d;
wire [31:0] RD1,RD2,ext,Y,RD;
wire m1sel,m2sel,m3sel,zero;
PC PC_inst(
.clk(clk),
.reset(reset),
.di(npc),
.do(pc)
);
wire [2:0] cs;
NPC NPC_inst(
.pc(pc),
.imm(im_d[25:0]),
.ra(RD1),
.cs(cs),
.zero(zero),
.npc(npc)
);
IM IM_inst(
.A(pc),
.D(im_d)
);
wire [4:0] A3=(m1sel==1)?im_d[15:11]:im_d[20:16];
wire [31:0] wd=(m2sel)?RD:Y;
wire rf_wr;
RF RF_inst(
.A1(im_d[25:21]),
.A2(im_d[20:16]),
.A3(A3),
.WD(wd),
.wr(rf_wr),
.clk(clk),
.RD1(RD1),
.RD2(RD2),
.s0(y0),
.s1(y1),
.s2(y2),
.s3(y3),
.s4(y4),
.s5(y5)
);
EXT EXT_inst(
.in16(im_d[15:0]),
.out32(ext)
);
wire dm_wr;
DM DM_inst(
.A(Y),
.WD(RD2),
.wr(dm_wr),
.clk(clk),
.RD(RD),
.x(y)
);
wire [31:0] B;
assign B=(m3sel==1'b0)?RD2:ext;
wire [2:0] f;
ALU ALU_inst(
.A(RD1),
.B(B),
.F(f),
.Y(Y),
.zero(zero)
);
CU CU_inst(
.op(im_d[31:26]),
.fun(im_d[5:0]),
.m1sel(m1sel),
.m2sel(m2sel),
.m3sel(m3sel),
.cs(cs),
.f(f),
.rf_wr(rf_wr),
.dm_wr(dm_wr)
);
// assign y=pc;
endmodule
到了这里,关于单周期CPU设计,MIPS结构,modelsim仿真实现,多条指令的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!