简单单周期MIPS指令处理器设计Verilog实现

一、实验目的:
1、利用Verilog语言完成单周期MIPS指令处理器的设计,
2、锻炼复杂电路的设计能力。
二、实验要求
完成单周期MIPS指令处理器设计,并下载到FPGA开发板上,开发板的LED灯显示ALU的计算结果,处理器的时钟由开发板上的按键产生,每按一次键,产生一个时钟脉冲。
单周期MIPS指令处理器能在一个时钟周期内完成add、sub、and、or、sw、lw、beq、j等一条MIPS指令的处理。
单周期MIPS指令处理器包括以下几部分电路:指令存储器、数据存储器、寄存器堆、算术逻辑运算单元、控制电路。
指令存储器:保存处理器的指令,起始地址为0x00400000;
数据存储器:保存处理器的数据,起始地址为0x10010000;
寄存器堆:32个32bit寄存器;
算术逻辑运算单元:完成各种运算;
控制电路:产生处理器的控制信号,包括PC生成。
三、实验内容
1、熟悉MIPS指令处理器的指令编码与电路结构,理解MIPS指令处理器工作过程,画出单周期MIPS指令处理器电路结构图。
2、熟悉软件Mars的使用方法,用add、sub、and、or、sw、lw、beq、j等指令编写一段有意义的程序,并在Mars上进行编译得到程序的机器码;
3、完成MIPS指令处理器的VerilogHDL代码,其中指令存储器、数据存储器的初值为实验内容第2点得到的指令与数据;
4、编写testbench,在ModelSim上对VerilogHDL代码进行仿真测试;
5、用QuartusⅡ对VerilogHDL代码进行综合,并下载到FPGA开发板上进行验证。
四、实验思路
由《计算机组成与设计:硬件、软件接口》可以得到单周期MIPS指令处理器的总体电路图:简单单周期MIPS指令处理器设计Verilog实现_第1张图片
由电路图可以知道电路总体可以分为以下几个部分:①程序计数器PC;②指令存储器;③程序计数加法器PC+4;④控制单元;⑤左移部件;⑥寄存器堆;⑦符号扩展单元;⑧ALU控制器;⑨ALU运算器;⑩加法器;⑪数据存储器;⑫数据选择器;⑬相应的门电路。下面分别给出每个组成部分的作用以及生成该部件的VerilogHDL代码。
1、程序计数器PC:指令地址存储器,存放当前正在执行的指令地址或下一条指令地址。由实验要求指令存储器的初始地址为0x00400000;所以上电时,程序计数器PC的指令自动跳转变为0x00400000,即找到存储器中的第一条指令。在实际开发中,由异步复位信号来决定指令处理器是否正常工作。

module PC(CLK,Address_in,Address_out,rst);
 input CLK,rst;
 input [31:0] Address_in;
 output reg [31:0] Address_out;
 
 always@(posedge CLK,negedge rst)
 begin
    if(!rst) Address_out<=32'h0040_0000;
  else Address_out<=Address_in;
 end
endmodule

2、指令存储器:该部件实际由ROM组成,根据给定的地址,读出地址对应的数据,即存储的指令。ROM中存储的数据需要进行初始化。因为PC的值总是+4,且要将ROM中的存储器全部都利用起来,所以所以地址的最低位应该为PC值的倒数第3位。

module Order_Mem(Address_in,Order);
 input [31:0] Address_in;
 output [31:0] Order;
 reg [31:0] Rom [31:0] /*synthesis ram_init_file="MIPS.mif" */;
 assign Order = Rom[Address_in[6:2]];
endmodule

其中的初始化mif文件为:简单单周期MIPS指令处理器设计Verilog实现_第2张图片
3、程序计数加法器PC+4:该部件的作用为自动使PC的值+4,找到下一条需要正常执行的地址。

module Add_PC(adr,n_adr);
 input [31:0] adr;
 output [31:0] n_adr;
 assign n_adr = adr + 32'd4;
endmodule

4、控制单元:该部件为整个MIPS指令器的“大脑”,根据其给出的控制信号来执行相应的指令功能。控制单元的输入为指令的操作码部分(指令 [31:26]),则根据信号,产生的控制信号如下表所示:
简单单周期MIPS指令处理器设计Verilog实现_第3张图片

module Control_Unit(op,RegDst,jump,Branch,MemRead,MemtoReg,ALUop,MemWrite,ALUSrc,RegWrite);
 input [5:0] op;
 output reg RegDst,jump,Branch,MemtoReg,ALUSrc,RegWrite,MemWrite,MemRead;
 output reg [1:0] ALUop;
 always @ *
 begin
  case(op)
  //R型指令
  6'd0:begin 
  RegDst <= 1; jump <= 0; ALUop <= 2'b10;
  Branch <= 0; MemtoReg <= 0; RegWrite <= 1;
  MemWrite <= 0; MemRead <= 0; ALUSrc <= 0;end
  //I型lw存指令
  6'd35:begin
  RegDst <= 0; jump <= 0; ALUop <= 2'b00;
  Branch <= 0; MemtoReg <= 1; RegWrite <= 1;
  MemWrite <= 0; MemRead <= 1; ALUSrc <= 1;end
  //I型sw取指令
  6'd43:begin
  RegDst <= 0; jump <= 0; ALUop <= 2'b00;
  Branch <= 0; MemtoReg <= 0; RegWrite <= 0;
  MemWrite <= 1; MemRead <= 0; ALUSrc <= 1;end
  //I型beq指令分支反指令
  6'd4:begin
  RegDst <= 0; jump <= 0; ALUop <= 2'b01;
  Branch <= 1; MemtoReg <= 0; RegWrite <= 0;
  MemWrite <= 0; MemRead <= 0; ALUSrc <= 0;end
  //J型指令
  6'd2:begin
  RegDst <= 0; jump <= 1; ALUop <= 0;
  Branch <= 0; MemtoReg <= 0; RegWrite <= 0;
  MemWrite <= 0; MemRead <= 0; ALUSrc <= 0;end
  default:begin
  RegDst <= 0; jump <= 0; ALUop <= 0;
  Branch <= 0; MemtoReg <= 0; RegWrite <= 0;
  MemWrite <= 0; MemRead <= 0; ALUSrc <= 0;end
  endcase
 end
endmodule

5、左移部件:电路中存在两个左移部件,其中一个部件的作用为将指令的高26位左移两位,低两位补0;另一个部件的作用为将整个指令左移两位,低两位补0;

module Left2(data,odata);
 input [31:0] data;
 output reg [31:0] odata;

 always @(data)
 begin
    odata[31:2]<=data[29:0];
  odata[1:0]<=2'b00;
 end
endmodule
module Left2_26(data,data1,odata);
 input [25:0] data;
 input [3:0] data1;
 output reg [31:0] odata;
 
 always @(data,data1)
 begin
    odata[27:2]<=data[25:0];
  odata[1:0]<=2'b00;
  odata[31:28]<=data1[3:0];
 end
endmodule

6、寄存器堆:该部件的作用是生成32个寄存器,上电即初始化为0(除第18个寄存器被初始化为数据存储器的初始地址外)

module Registers(Read_registers1,Read_registers2,Write_registers,Write_Data,Read_Data1,Read_Data2,RegWire,CLK);//寄存器堆
 input [4:0] Read_registers1,Read_registers2,Write_registers;
 input [31:0] Write_Data;
 input RegWire,CLK;
 output [31:0] Read_Data1,Read_Data2;
 reg [31:0] register[31:0] /*synthesis ram_init_file="Mif2.mif" */;
 
 assign Read_Data1 = register[Read_registers1];
 assign Read_Data2 = register[Read_registers2];
 //写信号上升沿到来
 always @(posedge CLK)
 begin
  //当RegWire信号有效时,进行写操作
    if(RegWire) register[Write_registers] <= Write_Data;
 end
endmodule

其中Mif2.mif文件内容如下:
简单单周期MIPS指令处理器设计Verilog实现_第4张图片
其中的第18个寄存器是用10进制表示,将其转化为16进制为0x10010000,即数据存储器的初始地址。

7、符号扩展单元:该部件的作用是将指令的后16位扩展成为32位,

module sign_ep(order,addr);
 input [15:0] order;
 output reg [31:0] addr;
 
 always @(order)
 begin
    if(order[15]==1) addr[31:16]=16'b1111111111111111;
  else addr[31:16]=16'b0000000000000000;
  addr[15:0]=order[15:0];
   end
endmodule
 

8、ALU控制器:该部件的功能为根据控制单元发出的信号ALUop和指令后五位代表的功能码共同作用于ALU控制器,来产生相应的信号控制ALU进行的运算操作。

module ALU_Control(ALUop,FunctionCode,ALUctr);
 input [1:0] ALUop; //一个占两位的控制字段
 input [5:0] FunctionCode; //一个6位功能码
 output reg [3:0] ALUctr; //输出为一个4位的ALU控制信号
 
 always @(ALUop,FunctionCode)
 begin
    case(ALUop)
  2'b00: ALUctr <= 4'b0010; //取、存字,加
  2'b01: ALUctr <= 4'b0110; //相等分支,减
  //R型
  2'b10:
  begin
   case(FunctionCode)
   6'b100000: ALUctr <= 4'b0010; //加
   6'b100010: ALUctr <= 4'b0110; //减
   6'b100100: ALUctr <= 4'b0000; //与
   6'b100101: ALUctr <= 4'b0001; //或
   default: ALUctr <= 4'b1111;
   endcase
  end
  default: ALUctr <= 4'b1111;
  endcase
 end
endmodule

9、ALU运算器:该部件的功能为根据ALU控制器给出的信号进行相应的运算。

module ALU(ctr,A,B,Zero,result);//ALU为组合逻辑电路
 input [3:0] ctr;
 input [31:0] A,B;
 output Zero;
 output reg [31:0] result;
 
 always @ (A,B,ctr)
 begin
    case(ctr)
  4'd0: result <= A&B;
  4'd1: result <= A|B;
  4'd2: result <= A+B;
  4'd6: result <= A-B;
  4'd7: result <= A<B ? 1:0;
  4'd12:result <= ~(A|B);
  default: result <= 0;
  endcase
 end
 
 assign Zero = (result==0);
endmodule

10、加法器:该部件的作用为计算跳转指令的地址;

module ALU_Add_32(addr1,addr2,out_addr);
 input [31:0] addr1,addr2;
 output [31:0] out_addr;
 assign out_addr = addr1+addr2;
endmodule

11、数据存储器:该部件的作用为存储运算的数据或地址;

module Data_Mem(input wire[31:0] Address_in,
        input wire[31:0] in_data,
      output wire[31:0] data,
        input wire CLK,MemWrite,MemRead);
 reg [31:0] mem [31:0] /*synthesis ram_init_file="m_ros.mif" */;
 always @(posedge CLK)
 begin 
  if(MemWrite) mem[Address_in[6:2]]<=in_data;
 end
 assign data = mem[Address_in[6:2]];
endmodule

初始化的m_ros.mif文件如下:
简单单周期MIPS指令处理器设计Verilog实现_第5张图片
其中的第1个存储器是用10进制表示,将其转化为16进制为0x10010000,即数据存储器的初始地址。

12、数据选择器:

module Mux_32(A,B,Src,S);
 input [31:0] A,B;
 input Src;
 output [31:0] S;
 assign S = (Src==0) ? A:B;
endmodule
module Mux_6(A,B,Src,S);
 input [5:0] A,B;
 input Src;
 output [5:0] S;
 assign S = (Src==0) ? A:B;
endmodule

顶层电路描述如下:

module MIPS(CLK,rst,out_ALU,clk1,data1,data2,data3,data4,Read_Data1,Read_Data2,Address_in_PC,Address_out_PC,Address_Add_PC,Order,Read_Data_Mem,Order_Left);
 input clk1;
 output CLK;
 input rst;
 output [6:0] data1,data2,data3,data4;
 output [31:0]out_ALU;
 assign CLK = ~clk1;
 output [31:0] Read_Data1,Read_Data2,Address_in_PC,Address_out_PC,Address_Add_PC,Order,Read_Data_Mem,Order_Left;
 wire [31:0] Read_Data1;
 wire [31:0] Read_Data2;
 wire [31:0] Address_in_PC,Address_out_PC;//用于PC的输入和输出
 wire [31:0] Address_Add_PC;//用于程序计数器正常指令进行加4的输出
 wire [31:0] Order;//用于指令存储器的指令输出
 wire RegDst,Jump,Branch,MemtoReg,ALUSrc,RegWrite,MemWrite,MemRead;//用于对控制信号的连线
 wire [1:0] ALUop;//控制信号ALUop的连线
 wire [5:0] Write_register;//寄存器堆中写入寄存器所在的位号的连线
 wire [31:0] Write_Data;//Read_Data1,Read_Data2;//寄存器堆中的连线
 wire [31:0] sign,out_sign,ALU1,out_ALU;
 wire [31:0] ALU_Add_32_out,Branch_or_normal;
 wire [3:0] ALU_ctr;
 wire [31:0] Read_Data_Mem;
 wire [31:0] Order_Left;
 wire zero,Mux32_EN;
 PC(CLK,Address_in_PC,Address_out_PC,rst);
 Add_PC(Address_out_PC,Address_Add_PC);
 Order_Mem(Address_out_PC,Order);
 Control_Unit(Order[31:26],RegDst,Jump,Branch,MemRead,MemtoReg,ALUop,MemWrite,ALUSrc,RegWrite);
 Mux_6(Order[20:16],Order[15:11],RegDst,Write_register);
 Registers(Order[25:21],Order[20:16],Write_register,Write_Data,Read_Data1,Read_Data2,RegWrite,CLK);
 sign_ep(Order[15:0],sign);
 Mux_32(Read_Data2,sign,ALUSrc,ALU1);
 ALU_Control(ALUop,Order[5:0],ALU_ctr);
 ALU(ALU_ctr,Read_Data1,ALU1,zero,out_ALU);
 Data_Mem(out_ALU,Read_Data2,Read_Data_Mem,CLK,MemWrite,MemRead);
 Mux_32(out_ALU,Read_Data_Mem,MemtoReg,Write_Data);
 Left2(sign,out_sign);
 ALU_Add_32(Address_Add_PC,out_sign,ALU_Add_32_out);
 and(Mux32_EN,Branch,zero);
 Mux_32(Address_Add_PC,ALU_Add_32_out,Mux32_EN,Branch_or_normal);
 Left2_26(Order[25:0],Address_Add_PC[31:28],Order_Left);
 Mux_32(Branch_or_normal,Order_Left,Jump,Address_in_PC);
 dec4_7(out_ALU[15:12],data1);
 dec4_7(out_ALU[11:8],data2);
 dec4_7(out_ALU[7:4],data3);
 dec4_7(out_ALU[3:0],data4);
endmodule
 

使用的Mars汇编指令如下:
简单单周期MIPS指令处理器设计Verilog实现_第6张图片
简单单周期MIPS指令处理器设计Verilog实现_第7张图片

你可能感兴趣的:(简单单周期MIPS指令处理器设计Verilog实现)