多周期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