欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

多周期MIPS的Verilog设计

程序员文章站 2022-07-10 21:14:59
`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date: 2020/07/18 16:29:06// Design Name: // Module Name: MIPS// Project Name: // Target Devices: // Tool V...

所有控制信号在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