vivado实现MIPS五级流水线-含冒险分析-概念+代码

流水线五个时钟周期:

MIPS指令集中每条指令都可以在五个时钟周期内实现。

  1. IF:Instruction fetch cycle
    将程序计数器(PC)发送到存储器,从存储器提取当前指令。向程序计数器加4(因为每 条指令的长度为4个字节),将程序计数器更新到下一个连续程序计数器。
  2. ID:Instruction decode/register fetch cycle
    对指令进行译码,并从寄存器堆中读取与寄存器源说明符相对应的寄存器。在读取寄存器时对其进行相等测试,以确定是否为分支。必要时,对指令的偏移量字段进行符号扩展。符号扩展后的偏移量添加到所实现的程序计数器上,计算出可能的分支目标地址。由于一个指令的立即数部分也位于同一位置,所以在需要符号扩
    展立即数时,也是在这一周期计算的。
  3. EX:Execution/effective address cycle
    ALU对上一周期准备的操作数进行操作,根据指令类型执行三条指令之一。
    存储器引用—ALU将基址寄存器和偏移量加到一起,形成有效地址。
    寄存器寄存器-ALU指令—ALU对读自寄存器堆的值执行由ALU操作码指定的操作。
    寄存器-立即数ALU指令—ALU对读自寄存器堆的第一个值和符号扩展立即数执行由 ALU操作码指定的操作。
  4. MEM:Memory access
    如果该指令是一条载入指令,则使用上一周期计算的有效地址从存储器中读取数据。如果是一条存储指令,则使用有效地址将从寄存器堆的第二个寄存器读取的数据写入存储器。
  5. WB: Write-back cycle
    将结果写人寄存器堆,无论是来自寄存器系统(对于载入指令),还是来自ALU(对于ALU 指令) 。

MIPS指令

在这里插入图片描述

流水线设计

流水线结构:

本实验分支冒险在ID阶段进行判断,因此可能会造成数据冒险(本实验忽略该数据冒险)。
在这里插入图片描述
各阶段数据通路:
在这里插入图片描述
由于在ID阶段进行分支冒险的判断,ID阶段有些许更改:
在这里插入图片描述

数据冒险:

需要转发的情况:
在这里插入图片描述
转发实现过程:
在这里插入图片描述

代码实现

IF

PC模块:

在这里插入图片描述

module PC(clk,rst,stall,branchEn,branchAddr,pc);
input wire clk,rst,branchEn;
input wire[31:0] branchAddr;
input wire stall;
output reg[31:0] pc;
initial begin
    pc = 0;
end
always@(posedge clk or negedge rst)begin
    if(!rst) begin
        pc = 0;
    end
    else begin
        if(!stall)begin //pc未暂停
            if(!branchEn)
                pc = pc + 1;
            else 
                pc = branchAddr;
         end
        //若pc暂停,则维持原先的值不动
     end
end
endmodule

InsMeomory模块:

在这里插入图片描述

module InsMemory(Addr,Ins);
    input wire[31:0] Addr; //指令地址
    output reg[31:0] Ins;//读出指令寄存器中的指令
    reg [31:0]Rom[31:0];//指令寄存器
    initial begin
         Rom[8'h00]=32'h20010008;//addi $1,$0,8 $1=8 001000 00000 00001 0000000000001000
         Rom[8'h01]=32'h3402000C;//ori $2,$0,12 $2=12
         Rom[8'h02]=32'h00221820;//add $3,$1,$2 $3=20//数据冒险
         Rom[8'h03]=32'h00412022;//sub $4,$2,$1 $4=4
         Rom[8'h04]=32'h00222824;//and $5,$1,$2
         Rom[8'h05]=32'h00223025;//or $6,$1,$2
         Rom[8'h06]=32'h10220002;//beq $1,$2,2 不跳转
         Rom[8'h07]=32'h00221820;//add $3,$1,$2 $3=20
         Rom[8'h08]=32'h00412022;//sub $4,$2,$1 $4=4
         Rom[8'h09]=32'h14220004;// bnq $1,$2,3 //跳转
         Rom[8'h0A]=32'hXXXXXXXX;// 
         Rom[8'h0B]=32'hXXXXXXXX;
         Rom[8'h0C]=32'hXXXXXXXX;
         Rom[8'h0D]=32'hAD02000A;// sw $2 10($8) memory[$8+10]=12
         Rom[8'h0E]=32'h8D04000A;//lw $4 10($8) $4=12
         Rom[8'h0F]=32'h00441020;//add $2,$4,2//lw数据冒险
         Rom[8'h10]=32'h20210004;//addi $1,$1,4 //00100000001000010000000000000100
         Rom[8'h11]=32'h00222824;//and $5,$1,$2
         Rom[8'h12]=32'h14220006;//beq $1,$2,6
         Rom[8'h13]=32'h30470009;//andi $2,9,$7//控制冒险
         Rom[8'h14]=32'hXXXXXXXX;
         Rom[8'h15]=32'h00000020;
         Rom[8'h16]=32'h00000020;
         Rom[8'h17]=32'h00000020;
         Rom[8'h18]=32'h00000020;
         Rom[8'h19]=32'h00000020;
         Rom[8'h1A]=32'h00000020;
         Rom[8'h1B]=32'h00000020;
         Rom[8'h1D]=32'h00000020;
         Rom[8'h1E]=32'h00000020;
         Rom[8'h1F]=32'h00000020;
    end
    always@(*) begin
        Ins = Rom[Addr];
    end
    
endmodule

IF/ID模块:

在这里插入图片描述

module IF_ID(In_Ins,clk,rst,In_pc,stall,out_Ins,out_pc,branch_stall);
    input wire clk,rst;
    input wire[31:0] In_pc,In_Ins;
    input wire stall,branch_stall;//branch_stall判断是否为分支冒险
    output reg[31:0] out_pc,out_Ins;
    
    initial begin
        out_pc = 0;
        out_Ins=32'b000000_00000_00000_000
  • 8
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值