博客地址转至https://xisynotz.xyz
一、 实验要求
设计一个单周期MIPS CPU,依据给定过的指令集,设计核心的控制信号。依据给定的数据通路和控制单元信号进行设计。
二、 实验内容
1.数据通路设计:mips指令格式只有三种:
1)R类型 从寄存器堆中取出两个操作数,计算结果写回寄存器堆
2)I类型 用一个16位的立即数作为一个源操作数
3)J类型 用一个26位的立即数作为跳转的目标地址
根据以上三种类型可以设计相应的数据通路。基本原理如下
下面是实现之后的效果
2.相应模块设计
首先明确应该有哪些主要功能模块
逻辑电路:控制单元,选择器,ALU,符号位扩展单元,branch加法器等
时序电路:PC寄存器,指令/数据存储器,寄存器文件
对应的主要代码如下:
(1)top模块对各部分的例化:
下面是具体的主要模块的实现
(2)控制单元
module controlunit(
input [5:0] opcode,
input [5:0] funct, //本实验只考虑add所以暂时用不到这个字段
output reg mem_write,
output reg mem_toreg,
output reg branch,
output reg alu_src,
output reg reg_dst,
output reg reg_write,
output reg [2:0] alu_op,
output reg jump
);
always@(*)
case(opcode)
6'b000000: //add
begin
reg_dst=1;
alu_src=0;
mem_toreg=0;
reg_write=1;
mem_write=0;
branch=0;
alu_op=3'b001;
jump=0;
end
6'b001000: //addi
begin
reg_dst=0;
alu_src=1;
mem_toreg=0;
reg_write=1;
mem_write=0;
branch=0;
alu_op=3'b001;
jump=0;
end
6'b100011: //lw
begin
reg_dst=0;
alu_src=1;
mem_toreg=1;
reg_write=1;
mem_write=0;
branch=0;
alu_op=3'b001;
jump=0;
end
6'b101011: //sw
begin
reg_dst=0;
alu_src=1;
mem_toreg=0;
reg_write=0;
mem_write=1;
branch=0;
alu_op=2'b001;
jump=0;
end
6'b000010: //jump
begin
reg_dst=1;
alu_src=0;
mem_toreg=0;
reg_write=0;
mem_write=0;
branch=1;
alu_op=2'b001;
jump=1;
end
6'b000111: //bgtz
begin
reg_dst=1;
alu_src=0;
mem_toreg=0;
reg_write=0;
mem_write=0;
branch=1;
alu_op=2'b001;
jump=0;
end
default:
begin
reg_dst=1;
alu_src=0;
mem_toreg=0;
reg_write=1;
mem_write=0;
branch=0;
alu_op=2'b10;
end
endcase
endmodule
(3)符号位扩展单元
module signextension(num_in,num_out);
input wire[15:0] num_in;
output reg[31:0] num_out;
initial begin
num_out = 0;
end
always @(num_in) begin
num_out<= {{16{num_in[15]}},num_in[15:0]};
end
endmodule
(4)branch加法器模块
这里不进行左移操作,与至指令寄存器的设置相关,本实验中指令集寄存器每次读取32位数据,所以不需要像8位那样进行左移。
(5)pc自增模块
(6)选择器
这里是32位的,还有5位的型号,原理一致较为简单,此不赘述
(7)列一下关于两个ram的接口
(8)ALU,regfile参见前面几次实验,这里不作分析
三、 实验验证
1.编写coe文件
根据实验的要求以及个人设计的情况,测试代码如下:
(主要是因为pc寄存器指向的地址是32位而不是8位,所以做了修改,无关算法)
MEMORY_INITIALIZATION_RADIX=16;
MEMORY_INITIALIZATION_VECTOR=
20080000,
200d0014,
8dad0000,
200b0015,
8d6b0000,
200c0015,
8d8c0001,
ad0b0000,
ad0c0001,
21a9fffe,
8d0b0000,
8d0c0001,
016c5020,
ad0a0002,
21080001,
2129ffff,
1d20fff9,
08000011;
测试数据:
MEMORY_INITIALIZATION_RADIX=10;
MEMORY_INITIALIZATION_VECTOR=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,3,3;
2.仿真测试
这里主要是对pc的跳转进行分析,发现跳转无误,我们进入到ram里观察执行的情况,下面是dataram:
正好存储了斐波那契数列的前二十个数,符合要求。
四、 分析和总结
本实验实现了一个单周期mipscpu,实现了addi、add、lw、sw、bgtz、j六条指令。
实验的关键在于弄清楚cpu以及每条指令的数据通路,还有相应的控制信号的具体赋值。
在具体实现的时候,最为重要的的是确保指令的跳转正确,在此基础上对各个指令的执行debug就轻而易举。
需要注意的是,在实例化的时候各个对应的接口较为繁杂,应当注意不要出错,命名简单易懂。