MIPS五级流水线(含data hazard)_mips hazard检查-程序员宅基地

设计参考图
在这里插入图片描述

旁路单元

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/24 10:30:49
// Design Name: 
// Module Name: FORWARDING
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module FORWARDING(
input [4:0]ID2EXE_rs,
input [4:0]ID2EXE_rt,
input [4:0]EXE2MEM_RegRd,
input [4:0]MEM2WB_RegRd,
input EXE2MEM_RegWrite,
input MEM2WB_RegWrite,
output reg [1:0]ForwardA,
output reg [1:0]ForwardB
);
//ForwardA
always@(*)
begin
if(EXE2MEM_RegWrite==1&&(EXE2MEM_RegRd!=0)&&EXE2MEM_RegRd==ID2EXE_rs)
    ForwardA=2'b10;                                       // 来自EXE/MEM
else if(MEM2WB_RegWrite==1&&(MEM2WB_RegRd!=0)&&MEM2WB_RegRd==ID2EXE_rs)
    ForwardA=2'b01;                                       // 来自MEM/WB
else
    ForwardA=2'b00;                                       // 来自ID/EXE
end                                                      
//ForwardB
always@(*)
begin
if(EXE2MEM_RegWrite==1&&(EXE2MEM_RegRd!=0)&&EXE2MEM_RegRd==ID2EXE_rt)
    ForwardB=2'b10;
else if(MEM2WB_RegWrite==1&&(MEM2WB_RegRd!=0)&&MEM2WB_RegRd==ID2EXE_rt)
    ForwardB=2'b01;
else
    ForwardB=2'b00;
end

endmodule

冒险检测单元

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/24 10:44:46
// Design Name: 
// Module Name: HAZARD_DETECTION
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module HAZARD_DETECTION(
input ID2EXE_MemRead,
input [4:0]ID2EXE_rt,
input [4:0]IF2ID_rs,
input [4:0]IF2ID_rt,
output reg PCWrite,
output reg IF2ID_Write,
output reg ID2EXE_Stall
    );
always@(*)
begin
if(ID2EXE_MemRead&&((ID2EXE_rt==IF2ID_rs)||(ID2EXE_rt==IF2ID_rt)))               //流水线阻塞1个clk
begin
    ID2EXE_Stall=1'b1;                                  //ID2EXE段的控制命令清0                           
    PCWrite=1'b0;                                       //PC保持不变
    IF2ID_Write=1'b0;                                   //IF2ID段寄存器保持不变
end
else
begin
    ID2EXE_Stall=1'b0;
    PCWrite=1'b1;
    IF2ID_Write=1'b1;
end
end

endmodule

ALUSrc多路选择器

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/24 10:55:12
// Design Name: 
// Module Name: mux3_1
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mux3_1(
input [31:0]a,
input [31:0]b,
input [31:0]c,
input [1:0]select,
output reg [31:0]out
    );
always@(*)
case (select)
    2'b00:out=a;
    2'b10:out=b;
    2'b01:out=c; 
    default:out=32'd0;
endcase
endmodule

总体代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/23 15:31:35
// 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
    );
reg [31:0] RegFile [0:31];
reg [31:0] IMEM [0:255];
reg [31:0] DMEM [0:255];

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

initial
begin
    for(i=0;i<32;i=i+1)
        RegFile[i]<=i;
end

initial
begin
    IMEM[0]=32'h00430820;
    IMEM[4]=32'h00252022;
    IMEM[8]=32'h00e13020;
    IMEM[12]=32'h8d480004;
    IMEM[16]=32'h010c5820;
    IMEM[20]=32'h8dcdfffc;
    IMEM[24]=32'h00000020;
    IMEM[28]=32'h01ad7820;
    IMEM[32]=32'h8e100004;
    IMEM[36]=32'had90000c;
end

wire IF2ID_Write;
wire PCWrite;
wire ID2EXE_Stall;
wire [31:0]ALUSrcA;                  
wire [31:0]ALUSrcB;
wire [1:0]ForwardA;
wire [1:0]ForwardB;
wire [4:0]IF2ID_rs;
wire [4:0]IF2ID_rt;
wire [31:0]MEM2WB_Data;


//IF
reg [31:0] PC;
reg [31:0] IF2ID_NPC;
reg [31:0] IF2ID_IR;
//ID
reg [4:0]ID2EXE_rs;                //Rs寄存器号 约定大写为数据,小写为寄存器号
reg [4:0]ID2EXE_rt;                //Rt寄存器号
reg [4:0]ID2EXE_rd;                //Rd寄存器号
reg [31:0]ID2EXE_Rs;               //Rs寄存器内容
reg [31:0]ID2EXE_Rt;               //Rt寄存器内容
reg [31:0]ID2EXE_Imm;              //符号扩展后的立即数
reg [31:0]ID2EXE_NPC;                  

reg ID2EXE_RegDst;
reg ID2EXE_ALUSrc;
reg ID2EXE_MemRead;
reg ID2EXE_MemWrite;
reg ID2EXE_Branch;
reg ID2EXE_MemtoReg;
reg ID2EXE_RegWrite;
reg [1:0] ID2EXE_ALUOp;
//EXE
reg [31:0]EXE2MEM_ALUOut;
reg [31:0]EXE2MEM_BranchPC;
reg [31:0]EXE2MEM_Rt;
reg [4:0]EXE2MEM_RegRd;                    //WB阶段写寄存器号

reg EXE2MEM_MemRead;
reg EXE2MEM_MemWrite;
reg EXE2MEM_Branch;
reg EXE2MEM_MemtoReg;
reg EXE2MEM_RegWrite;
//MEM
reg [31:0]MEM2WB_LDM;
reg [31:0]MEM2WB_ALUOut;
reg [4:0]MEM2WB_RegRd;

reg MEM2WB_RegWrite;
reg MEM2WB_MemtoReg;

/****************************************************************************************/

assign IF2ID_rs=IF2ID_IR[25:21];
assign IF2ID_rt=IF2ID_IR[20:16];
assign MEM2WB_Data=(MEM2WB_MemtoReg)?MEM2WB_LDM:MEM2WB_ALUOut;

//IF
always@(posedge clk,posedge rst)
begin
if(rst)
begin
    PC<=32'd0;
    IF2ID_NPC<=32'd0;
    IF2ID_IR<=32'd0;
end
else
begin
    if(PCWrite)
        PC<=PC+32'd4;
    else
        PC<=PC;
    if(IF2ID_Write)
    begin
        IF2ID_NPC<=PC+4;
        IF2ID_IR<=IMEM[PC];
    end
    else
    begin
        IF2ID_NPC<=IF2ID_NPC;
        IF2ID_IR<=IF2ID_IR;
    end
end
end

//ID
HAZARD_DETECTION U1(
.ID2EXE_MemRead(ID2EXE_MemRead),
.IF2ID_rs(IF2ID_rs),
.IF2ID_rt(IF2ID_rt),
.ID2EXE_rt(ID2EXE_rt),
.PCWrite(PCWrite),
.ID2EXE_Stall(ID2EXE_Stall),
.IF2ID_Write(IF2ID_Write)
);

always@(posedge clk,posedge rst)
if(rst)
begin
    ID2EXE_RegDst<=1'b0;
    ID2EXE_ALUSrc<=1'b0;
    ID2EXE_ALUOp<=2'b00;
    ID2EXE_MemRead<=1'b0;
    ID2EXE_MemWrite<=1'b0;
    ID2EXE_Branch<=1'b0;
    ID2EXE_RegWrite<=1'b0;
    ID2EXE_MemtoReg<=1'b0;
end
else if(ID2EXE_Stall)
begin
    ID2EXE_RegDst<=1'b0;
    ID2EXE_ALUSrc<=1'b0;
    ID2EXE_ALUOp<=2'b00;
    ID2EXE_MemRead<=1'b0;
    ID2EXE_MemWrite<=1'b0;
    ID2EXE_Branch<=1'b0;
    ID2EXE_RegWrite<=1'b0;
    ID2EXE_MemtoReg<=1'b0;
end
else
case(IF2ID_IR[31:26])
6'b000000:begin
    {
    ID2EXE_RegDst,ID2EXE_ALUSrc,ID2EXE_MemtoReg,ID2EXE_RegWrite,ID2EXE_MemRead,
    ID2EXE_MemWrite,ID2EXE_Branch,ID2EXE_ALUOp}<=9'b100100010;
end
6'b100011:begin
    {
    ID2EXE_RegDst,ID2EXE_ALUSrc,ID2EXE_MemtoReg,ID2EXE_RegWrite,ID2EXE_MemRead,
    ID2EXE_MemWrite,ID2EXE_Branch,ID2EXE_ALUOp}<=9'b011110000;
end
6'b101011:begin
    {
    ID2EXE_RegDst,ID2EXE_ALUSrc,ID2EXE_MemtoReg,ID2EXE_RegWrite,ID2EXE_MemRead,
    ID2EXE_MemWrite,ID2EXE_Branch,ID2EXE_ALUOp}<=9'b010001000;
end
6'b000100:begin
    {
    ID2EXE_RegDst,ID2EXE_ALUSrc,ID2EXE_MemtoReg,ID2EXE_RegWrite,ID2EXE_MemRead,
    ID2EXE_MemWrite,ID2EXE_Branch,ID2EXE_ALUOp}<=9'b000000101;
end
default:
    {
    ID2EXE_RegDst,ID2EXE_ALUSrc,ID2EXE_MemtoReg,ID2EXE_RegWrite,ID2EXE_MemRead,
    ID2EXE_MemWrite,ID2EXE_Branch,ID2EXE_ALUOp}<=9'b000000000;
endcase

always@(posedge clk,posedge rst)
if(rst)
begin
    ID2EXE_rs<=5'd0;
    ID2EXE_rt<=5'd0;
    ID2EXE_rd<=5'd0;
    ID2EXE_Rs<=32'd0;
    ID2EXE_Rt<=32'd0;
    ID2EXE_Imm<=32'd0;
    ID2EXE_NPC<=32'd0;
end
else
begin
    ID2EXE_rs<=IF2ID_IR[25:21];
    ID2EXE_rt<=IF2ID_IR[20:16];
    ID2EXE_rd<=IF2ID_IR[15:11];
    ID2EXE_Rs<=RegFile[IF2ID_IR[25:21]];
    ID2EXE_Rt<=RegFile[IF2ID_IR[20:16]];
    ID2EXE_Imm<={
    {
    16{
    IF2ID_IR[15]}},IF2ID_IR[15:0]};
    ID2EXE_NPC<=IF2ID_NPC;
end

//EXE

FORWARDING U2(
.ID2EXE_rs(ID2EXE_rs),
.ID2EXE_rt(ID2EXE_rt),
.EXE2MEM_RegRd(EXE2MEM_RegRd),
.MEM2WB_RegRd(MEM2WB_RegRd),
.EXE2MEM_RegWrite(EXE2MEM_RegWrite),
.MEM2WB_RegWrite(MEM2WB_RegWrite),
.ForwardA(ForwardA),
.ForwardB(ForwardB)
);
//ALUSrcA三选一
mux3_1 U3(
.a(ID2EXE_Rs),
.b(EXE2MEM_ALUOut),
.c(MEM2WB_Data),
.select(ForwardA),
.out(ALUSrcA)
);
//ALUSrcB
mux3_1 U4(
.a(ID2EXE_Rt),
.b(EXE2MEM_ALUOut),
.c(MEM2WB_Data),
.select(ForwardB),
.out(ALUSrcB)
);

always@(posedge clk,posedge rst)
if(rst)
begin
    EXE2MEM_MemRead<=1'b0;
    EXE2MEM_MemWrite<=1'b0;
    EXE2MEM_Branch<=1'b0;
    EXE2MEM_MemtoReg<=1'b0;
    EXE2MEM_RegWrite<=1'b0;
end
else
begin
    EXE2MEM_MemRead<=ID2EXE_MemRead;
    EXE2MEM_MemWrite<=ID2EXE_MemWrite;
    EXE2MEM_Branch<=ID2EXE_Branch;
    EXE2MEM_MemtoReg<=ID2EXE_MemtoReg;
    EXE2MEM_RegWrite<=ID2EXE_RegWrite;
end

always@(posedge clk,posedge rst)
if(rst)
begin
    EXE2MEM_ALUOut<=32'd0;
    EXE2MEM_RegRd<=5'd0;
    EXE2MEM_Rt<=32'd0;
    EXE2MEM_BranchPC<=32'd0;
end
else
begin
    EXE2MEM_RegRd<=(ID2EXE_RegDst)?ID2EXE_rd:ID2EXE_rt;
    EXE2MEM_Rt<=ALUSrcB;               //ID2EXE_Rt or forwarded from EXE2MEM or forwarded from MEM2WB
    EXE2MEM_BranchPC<=ID2EXE_NPC+(ID2EXE_Imm<<2);
    case(ID2EXE_ALUOp)
        2'b00:EXE2MEM_ALUOut<=ALUSrcA+ID2EXE_Imm;          //lw or sw
        2'b01:EXE2MEM_ALUOut<=ALUSrcA-ALUSrcB;
        2'b10:
        case (ID2EXE_Imm[5:0])
            6'b100000:EXE2MEM_ALUOut<=ALUSrcA+ALUSrcB;
            6'b100010:EXE2MEM_ALUOut<=ALUSrcA-ALUSrcB;
            6'b100100:EXE2MEM_ALUOut<=ALUSrcA&ALUSrcB;
            6'b100101:EXE2MEM_ALUOut<=ALUSrcA|ALUSrcB;
            6'b101010:EXE2MEM_ALUOut<=(ALUSrcA<ALUSrcB)?1:0;
        default: EXE2MEM_ALUOut<=EXE2MEM_ALUOut;
        endcase
        default:
            EXE2MEM_ALUOut<=EXE2MEM_ALUOut;
    endcase
end

//MEM
always@(posedge clk,posedge rst)
if(rst)
begin
    MEM2WB_RegWrite<=1'b0;
    MEM2WB_MemtoReg<=1'b0;
end
else
begin
    MEM2WB_RegWrite<=EXE2MEM_RegWrite;
    MEM2WB_MemtoReg<=EXE2MEM_MemtoReg;
end

always@(posedge clk,posedge rst)
if(rst)
begin
    MEM2WB_LDM<=32'd0;
    MEM2WB_ALUOut<=32'd0;
    MEM2WB_RegRd<=5'd0;
end
else
begin
    MEM2WB_ALUOut<=EXE2MEM_ALUOut;
    MEM2WB_RegRd<=EXE2MEM_RegRd;
    if(EXE2MEM_MemRead)
        MEM2WB_LDM<=DMEM[EXE2MEM_ALUOut];
    else if(EXE2MEM_MemWrite)
        DMEM[EXE2MEM_ALUOut]<=EXE2MEM_Rt;
end

//WB
always@(posedge clk,posedge rst)
if(rst)
    ;
else if(MEM2WB_RegWrite)
    if(MEM2WB_MemtoReg)
        RegFile[MEM2WB_RegRd]<=MEM2WB_LDM;
    else
        RegFile[MEM2WB_RegRd]<=MEM2WB_ALUOut;
        
endmodule

仿真已通过。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40268672/article/details/107563537

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签