当前位置: 移动技术网 > IT编程>网页制作>HTML > 多周期MIPS的Verilog设计

多周期MIPS的Verilog设计

2020年07月20日  | 移动技术网IT编程  | 我要评论

所有控制信号在ID阶段生成,在IF阶段操作:
IR=IMEM[PC];
NPC=PC+4;
在ID阶段操作:
生成所有控制信号;
Rs=RegFile[rs];
Rt=RegFile[rt];
Imm={{16{imm[15]}},imm}; //符号扩展
在EXE阶段操作:
ALUOut=Rs op Rt或者ALUOut=Rs + Imm;
Branch_PC=Rs+Imm<<2;
在MEM阶段:
存储器的读写;
PC=NPC or Branch_PC;
在WB阶段:
RegFile[rt](or rd)=ALUOut(or LDM);
具体参见《计算机组成与设计-软件/硬件接口》第五版
下面的代码已经通过仿真。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/18 16:29:06
// Design Name: 
// Module Name: MIPS
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module MIPS(
input clk,
input rst,
input start
    );
parameter IF =0 ;
parameter ID =1 ;
parameter EXE =2 ;
parameter MEM =3 ;
parameter WB =4 ;
parameter IDLE =5 ;

reg [31:0] RegFile [0:31];           //寄存器堆
reg [31:0] IMEM [0:255];             //指令存储器
reg [31:0] DMEM [0:255];             //数据存储器

//控制信号
reg RegDst;                          //0:写寄存器的目标寄存器号来自rt 1:来自rd
reg RegWrite;                        //寄存器堆写使能
reg ALUSrc;                          //0:第二个源操作数来自rt 1:来自立即数
reg PCSrc;                           //0:PC+4 1:PC由分支目标地址取代
reg MemRead;                         //数据存储器读使能
reg MemWrite;                        //数据存储器写使能
reg MemtoReg;                        //0:写入寄存器的数据来自ALU 1:写入寄存器的数据来自数据存储器
reg [1:0]ALUOp;                      //ALU操作码,和funct一同指示ALU
reg Branch;                          //指示是否为分支指令


reg [2:0]state;
reg [2:0]next_state;

reg [31:0]IR;                        //指令寄存器
reg [31:0]Rs;                        //第一源操作数
reg [31:0]Rt;                        //第二源操作数
reg [31:0]Imm;                       //符号扩展后的立即数操作数
reg [31:0]ALUOut;                    //ALU输出
reg [31:0]PC;                        //程序计数器
reg [31:0]NPC;                       //NEXT PC
reg [31:0]LMD;                       //load指令读取结果存储位置
reg [31:0]Branch_PC;                 //分支跳转地址

wire [5:0]op;                         //MIPS指令操作字段
wire [4:0]rs;                         //MIPS指令第一源操作数
wire [4:0]rt;                         //MIPS指令第二源操作数
wire [4:0]rd;                         //MIPS指令目的寄存器
wire [4:0]shamt;                      //R型指令移位量
wire [5:0]funct;                      //R型指令功能码
wire [15:0]imm;                       //MIPS 16位立即数

assign op=IR[31:26];            
assign rs=IR[25:21];
assign rt=IR[20:16];
assign rd=IR[15:11];               
assign shamt=IR[10:6];                //R型指令移位字段,本实验没有用到
assign funct=IR[5:0];                 //R型指令的功能字段
assign imm=IR[15:0];                  //立即数字段

//初始化IMEM、DMEM、RegFile
integer i;
initial
begin
    for(i=0;i<32;i=i+1)
        RegFile[i]=i;
end

initial
begin
    for(i=0;i<256;i=i+1)
        DMEM[i]=i;
end

initial
begin
    IMEM[0]=32'h8d490004;
    IMEM[4]=32'h8daa0004;
    IMEM[8]=32'h012a7020;
    IMEM[12]=32'h012a7822;
    IMEM[16]=32'hadae0000;
    IMEM[20]=32'h1129fffe;
end

//状态机
always@(posedge clk,posedge rst)
begin
    if(rst)
        state<=IDLE;
    else
        state<=next_state;
end

always@(*)
begin
    case(state)
        IDLE:if(start)
                next_state=IF;
             else
                next_state=IDLE;
        IF:
            next_state=ID;
        ID: 
            next_state=EXE;
        EXE:
            next_state=MEM;
        MEM:
            next_state=WB;
        WB:
            next_state=IF;
        default:
            next_state=IDLE;
    endcase
end

//控制模块,所有控制信号由ID阶段生成
always@(posedge clk,posedge rst)
begin
if(rst)
begin
    RegDst<=1'b0;
    ALUSrc<=1'b0;
    MemtoReg<=1'b0;
    RegWrite<=1'b0;                               //关闭写寄存器堆使能
    MemRead<=1'b0;                              
    MemWrite<=1'b0;                               //关闭写存储器使能
    Branch<=1'b0;
    ALUOp<=2'b0;
end
else if(state==ID)
begin
    case(op) 
        6'b000000:begin                           //R型
            RegDst<=1'b1;
            ALUSrc<=1'b0;
            MemtoReg<=1'b0;
            RegWrite<=1'b1;
            MemRead<=1'b0;
            MemWrite<=1'b0;
            ALUOp<=2'b10;
        end
        6'b100011:begin                           //lw
            RegDst<=1'b0;
            ALUSrc<=1'b1;
            MemtoReg<=1'b1;
            RegWrite<=1'b1;
            MemRead<=1'b1;
            MemWrite<=1'b0;
            Branch<=1'b0;
            ALUOp<=2'b00;
        end
        6'b101011:begin                           //sw
            RegDst<=RegDst;
            ALUSrc<=1'b1;
            MemtoReg<=MemtoReg;
            RegWrite<=1'b0;
            MemRead<=1'b0;
            MemWrite<=1'b1;
            Branch<=1'b0;
            ALUOp<=2'b00;
        end
        6'b000100:begin                            //beq
           RegDst<=RegDst;
           ALUSrc<=1'b0;
           MemtoReg<=MemtoReg;
           RegWrite<=1'b0;
           MemRead<=1'b0;
           MemWrite<=1'b0;
           Branch<=1'b1;
           ALUOp<=2'b01;
        end
        default:begin
           RegDst<=RegDst;
           ALUSrc<=ALUSrc;
           MemtoReg<=MemtoReg;
           RegWrite<=RegWrite;
           MemRead<=MemRead;
           MemWrite<=MemWrite;
           Branch<=Branch;
           ALUOp<=ALUOp;
        end
    endcase
end
end

//各个阶段的操作

always@(posedge clk,posedge rst)
if(rst)
begin
    IR<=32'd0;
    Rs<=32'd0;
    Rt<=32'd0;
    Imm<=16'd0;
    ALUOut<=32'd0;
    PC<=32'd0;
end
else
    case(state)
        IF:
        begin
            IR<=IMEM[PC];
            NPC<=PC+4;
        end
        ID:
        begin
           Rs<=RegFile[rs];
           Rt<=RegFile[rt];
           Imm<={{16{imm[15]}},imm};                              //符号扩展
        end
        EXE:
           case(ALUOp)
              2'b00:begin                                       //lw or sw指令
                  ALUOut<=Rs+Imm;
              end
              2'b10:begin                                       //R型指令
                  case(funct)
                      6'b100000:
                          ALUOut<=Rs+Rt;
                      6'b100010:
                          ALUOut<=Rs-Rt;
                      6'b100100:
                          ALUOut<=Rs&Rt;
                      6'b100101:
                          ALUOut<=Rs|Rt;
                      6'b101010:
                          ALUOut<=(Rs<Rt)?1'b1:1'b0;
                      default:
                          ALUOut<=ALUOut;
                  endcase
              end
              2'b01:begin
                  ALUOut<=Rs-Rt;
                  Branch_PC<=NPC+(Imm<<2);
              end                                               //beq指令
           endcase
           
        MEM:begin
            if(MemRead)
               LMD<=DMEM[ALUOut];
            else if(MemWrite)
               DMEM[ALUOut]<=Rt;
            if(Branch&&(ALUOut==0))
               PC<=Branch_PC;
            else
               PC<=NPC;
        end
        WB:if(RegWrite)
                case({RegDst,MemtoReg})
                  2'b00:
                      RegFile[rt]<=ALUOut;
                  2'b01:
                      RegFile[rt]<=LMD;
                  2'b10:
                      RegFile[rd]<=ALUOut;
                  2'b11:
                      RegFile[rd]<=LMD;
                endcase
        default:
            ;
    endcase

endmodule

本文地址:https://blog.csdn.net/qq_40268672/article/details/107447568

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网