已开源在GitHub上,欢迎各位大佬给Star
实验内容
1. 掌握MIPS R型和I型指令的综合数据通路设计,掌握数据流的多路选通控制方法
2. 掌握取数指令lw和存数指令sw的寻址方式及其有效地址产生的方法
3. 实现MIPS的部分I型和 R型指令的功能
解决方法
1. 分析MIPS I型指令的特点,与R型指令有明显的不同:没有rd寄存器,使用rt作为目的寄存器;源操作数中有一个为立即数,位于指令的低16位
2. 在寄存器堆模块的写地址输入端口设置二选一选择器,由于R型和I型的目的寄存器不同,由rd_rt_s控制
3. 16位的立即数imm需要经过扩展才能与rs执行运算操作,对于有符号数的操作,执行的是符号扩展,对于无符号数的操作,执行的是0扩展
4. R型指令执行rs和rt运算,结果送rd;而I型立即数即数寻址指令则执行rs和扩展后的立即数imm运算,结果送rt。因此ALU的输入数据B端有两个选择:rt或者imm,仍可以通过二选一数据选择器,用rt_imm_s控制信号
5. 需要添加一个数据存储器RAM存放指令访问的数据,读出的数据,意味着要在寄存器堆的写端口加个选择器,用alu_mem_s控制信号,其中要注意一点就是数据存储器的clk至少是CPU频率的2倍以上,我使用了两个clk输入解决这个问题
6. 在实际写代码时,要注意顶层模块中,实例下层模块的顺序,由于译码模块变量多,我将其抽离出来,为了使顶层模块看起来简洁
7. 涉及实验: 具体用到的实验是多功能ALU设计实验、寄存器堆设计实验、取指令与指令译码实验
8. 代码展示
顶层模块
module CPU(clk,rst,OF,ZF,F,ALU_OP,M_R_Data,rd_rt_s,imm_s,rt_imm_s,Mem_Write,alu_mem_s,Write_Reg,clk_M,R_Data_B,Inst_code);
input clk,rst,clk_M;
wire [31:0]Inst_code;
wire [5:0]op_code,funct;
wire [4:0]rs_addr,rt_addr,rd_addr,shamt;
output [31:0]F;
output OF,ZF;
output [31:0]M_R_Data;
output [2:0]ALU_OP;
wire [31:0]Mem_Addr;
wire [4:0]W_Addr;
output rd_rt_s,imm_s,rt_imm_s,Mem_Write,alu_mem_s,Write_Reg;
output [31:0]Inst_code;
wire [31:0]imm_data;
wire [31:0]R_Data_A;
output [31:0] R_Data_B;
wire [15:0]imm;
wire [31:0]ALU_B;
wire [31:0]W_Data;
PC pc1(clk,rst,Inst_code);
assign op_code = Inst_code[31:26];
assign rs_addr = Inst_code[25:21];
assign rt_addr = Inst_code[20:16];
assign rd_addr = Inst_code[15:11];
assign shamt = Inst_code[10:6];
assign funct = Inst_code[5:0];
assign imm = Inst_code[15:0];
OP_Func op(op_code,funct,Write_Reg,ALU_OP,rd_rt_s,imm_s,rt_imm_s,Mem_Write,alu_mem_s);
assign W_Addr = (rd_rt_s)?rt_addr:rd_addr;
assign imm_data = (imm_s)?{
{
16{
imm[15]}},imm}:{
{
16{