OpenCores
URL https://opencores.org/ocsvn/mips32r1/mips32r1/trunk

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [MIPS32_Standalone/] [Hazard_Detection.v] - Rev 6

Go to most recent revision | Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
/*
 * File         : Hazard_Detection.v
 * Project      : University of Utah, XUM Project MIPS32 core
 * Creator(s)   : Grant Ayers (ayers@cs.utah.edu)
 *
 * Modification History:
 *   Rev   Date         Initials  Description of Change
 *   1.0   23-Jul-2011  GEA       Initial design.
 *   2.0   26-May-2012  GEA       Release version with CP0.
 *
 * Standards/Formatting:
 *   Verilog 2001, 4 soft tab, wide column.
 *
 * Description:
 *   Hazard Detection and Forward Control. This is the glue that allows a
 *   pipelined processor to operate efficiently and correctly in the presence
 *   of data, structural, and control hazards. For each pipeline stage, it
 *   detects whether that stage requires data that is still in the pipeline,
 *   and whether that data may be forwarded or if the pipeline must be stalled.
 *
 *   This module is heavily commented. Read below for more information.
 */
module Hazard_Detection(
    input  [7:0] DP_Hazards,
    input  [4:0] ID_Rs,
    input  [4:0] ID_Rt,
    input  [4:0] EX_Rs,
    input  [4:0] EX_Rt,
    input  [4:0] EX_RtRd,
    input  [4:0] MEM_RtRd,
    input  [4:0] WB_RtRd,
    input  ID_Link,
    input  EX_Link,
    input  EX_RegWrite,
    input  MEM_RegWrite,
    input  WB_RegWrite,
    input  MEM_MemRead,
    input  MEM_MemWrite,        // Needed for Store Conditional which writes to a register
    input  InstMem_Read,
    input  InstMem_Ready,
    input  Mfc0,                // Using fwd mux; not part of haz/fwd.
    input  IF_Exception_Stall,
    input  ID_Exception_Stall,
    input  EX_Exception_Stall,
    input  M_Stall_Controller,  // Determined by data memory controller
    output IF_Stall,
    output ID_Stall,
    output EX_Stall,
    output M_Stall,
    output WB_Stall,
    output [1:0] ID_RsFwdSel,
    output [1:0] ID_RtFwdSel,
    output [1:0] EX_RsFwdSel,
    output [1:0] EX_RtFwdSel,
    output M_WriteDataFwdSel
    );
 
    /* Hazard and Forward Detection
     *
     * Most instructions read from one or more registers. Normally this occurs in
     * the ID stage. However, frequently the register file in the ID stage is stale
     * when one or more forward stages in the pipeline (EX, MEM, or WB) contains
     * an instruction which will eventually update it but has not yet done so.
     *
     * A hazard condition is created when a forward pipeline stage is set to write
     * the same register that a current pipeline stage (e.g. in ID) needs to read.
     * The solution is to stall the current stage (and effectively all stages behind
     * it) or bypass (forward) the data from forward stages. Fortunately forwarding
     * works for most combinations of instructions.
     *
     * Hazard and Forward conditions are handled based on two simple rules:
     * "Wants" and "Needs." If an instruction "wants" data in a certain pipeline
     * stage, and that data is available further along in the pipeline, it will
     * be forwarded. If it "needs" data and the data is not yet available for forwarding,
     * the pipeline stage stalls. If it does not want or need data in a certain
     * stage, forwarding is disabled and a stall will not occur. This is important
     * for instructions which insert custom data, such as jal or movz.
     *
     * Currently, "Want" and "Need" conditions are defined for both Rs data and Rt
     * data (the two read registers in MIPS), and these conditions exist in the
     * ID and EX pipeline stages. This is a total of eight condition bits.
     *
     * A unique exception exists with Store instructions, which don't need the
     * "Rt" data until the MEM stage. Because data doesn't change in WB, and WB
     * is the only stage following MEM, forwarding is *always* possible from
     * WB to Mem. This unit handles this situation, and a condition bit is not
     * needed.
     *
     * When data is needed from the MEM stage by a previous stage (ID or EX), the
     * decision to forward or stall is based on whether MEM is accessing memory
     * (stall) or not (forward). Normally store instructions don't write to registers
     * and thus are never needed for a data dependence, so the signal 'MEM_MemRead'
     * is sufficient to determine. Because of the Store Conditional instruction,
     * however, 'MEM_MemWrite' must also be considered because it writes to a register.
     *
     */
 
    wire WantRsByID, NeedRsByID, WantRtByID, NeedRtByID, WantRsByEX, NeedRsByEX, WantRtByEX, NeedRtByEX;
    assign WantRsByID = DP_Hazards[7];
    assign NeedRsByID = DP_Hazards[6];
    assign WantRtByID = DP_Hazards[5];
    assign NeedRtByID = DP_Hazards[4];
    assign WantRsByEX = DP_Hazards[3];
    assign NeedRsByEX = DP_Hazards[2];
    assign WantRtByEX = DP_Hazards[1];
    assign NeedRtByEX = DP_Hazards[0];
 
    // Trick allowed by RegDst = 0 which gives Rt. MEM_Rt is only used on
    // Data Memory write operations (stores), and RegWrite is always 0 in this case.
    wire [4:0] MEM_Rt = MEM_RtRd;
 
    // Forwarding should not happen when the src/dst register is $zero
    wire EX_RtRd_NZ  = (EX_RtRd  != 5'b00000);
    wire MEM_RtRd_NZ = (MEM_RtRd != 5'b00000);
    wire WB_RtRd_NZ  = (WB_RtRd  != 5'b00000);
 
    // ID Dependencies
    wire Rs_IDEX_Match  = (ID_Rs == EX_RtRd)  & EX_RtRd_NZ  & (WantRsByID | NeedRsByID) & EX_RegWrite;
    wire Rt_IDEX_Match  = (ID_Rt == EX_RtRd)  & EX_RtRd_NZ  & (WantRtByID | NeedRtByID) & EX_RegWrite;
    wire Rs_IDMEM_Match = (ID_Rs == MEM_RtRd) & MEM_RtRd_NZ & (WantRsByID | NeedRsByID) & MEM_RegWrite;
    wire Rt_IDMEM_Match = (ID_Rt == MEM_RtRd) & MEM_RtRd_NZ & (WantRtByID | NeedRtByID) & MEM_RegWrite;
    wire Rs_IDWB_Match  = (ID_Rs == WB_RtRd)  & WB_RtRd_NZ  & (WantRsByID | NeedRsByID) & WB_RegWrite;
    wire Rt_IDWB_Match  = (ID_Rt == WB_RtRd)  & WB_RtRd_NZ  & (WantRtByID | NeedRtByID) & WB_RegWrite;
    // EX Dependencies
    wire Rs_EXMEM_Match = (EX_Rs == MEM_RtRd) & MEM_RtRd_NZ & (WantRsByEX | NeedRsByEX) & MEM_RegWrite;
    wire Rt_EXMEM_Match = (EX_Rt == MEM_RtRd) & MEM_RtRd_NZ & (WantRtByEX | NeedRtByEX) & MEM_RegWrite;
    wire Rs_EXWB_Match  = (EX_Rs == WB_RtRd)  & WB_RtRd_NZ  & (WantRsByEX | NeedRsByEX) & WB_RegWrite;
    wire Rt_EXWB_Match  = (EX_Rt == WB_RtRd)  & WB_RtRd_NZ  & (WantRtByEX | NeedRtByEX) & WB_RegWrite;
    // MEM Dependencies
    wire Rt_MEMWB_Match = (MEM_Rt == WB_RtRd) & WB_RtRd_NZ  & WB_RegWrite;
 
 
    // ID needs data from EX  : Stall
    wire ID_Stall_1 = (Rs_IDEX_Match  &  NeedRsByID);
    wire ID_Stall_2 = (Rt_IDEX_Match  &  NeedRtByID);
    // ID needs data from MEM : Stall if mem access
    wire ID_Stall_3 = (Rs_IDMEM_Match &  (MEM_MemRead | MEM_MemWrite) & NeedRsByID);
    wire ID_Stall_4 = (Rt_IDMEM_Match &  (MEM_MemRead | MEM_MemWrite) & NeedRtByID);
    // ID wants data from MEM : Forward if not mem access
    wire ID_Fwd_1   = (Rs_IDMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
    wire ID_Fwd_2   = (Rt_IDMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
    // ID wants/needs data from WB  : Forward
    wire ID_Fwd_3   = (Rs_IDWB_Match);
    wire ID_Fwd_4   = (Rt_IDWB_Match);
    // EX needs data from MEM : Stall if mem access
    wire EX_Stall_1 = (Rs_EXMEM_Match &  (MEM_MemRead | MEM_MemWrite) & NeedRsByEX);
    wire EX_Stall_2 = (Rt_EXMEM_Match &  (MEM_MemRead | MEM_MemWrite) & NeedRtByEX);
    // EX wants data from MEM : Forward if not mem access
    wire EX_Fwd_1   = (Rs_EXMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
    wire EX_Fwd_2   = (Rt_EXMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
    // EX wants/needs data from WB  : Forward
    wire EX_Fwd_3   = (Rs_EXWB_Match);
    wire EX_Fwd_4   = (Rt_EXWB_Match);
    // MEM needs data from WB : Forward
    wire MEM_Fwd_1  = (Rt_MEMWB_Match);
 
 
    // Stalls and Control Flow Final Assignments    
    assign WB_Stall = M_Stall;
    assign  M_Stall = IF_Stall | M_Stall_Controller;
    assign EX_Stall = (EX_Stall_1 | EX_Stall_2 | EX_Exception_Stall) | M_Stall;
    assign ID_Stall = (ID_Stall_1 | ID_Stall_2 | ID_Stall_3 | ID_Stall_4 | ID_Exception_Stall) | EX_Stall;
    assign IF_Stall = InstMem_Read | InstMem_Ready | IF_Exception_Stall;
 
    // Forwarding Control Final Assignments
    assign ID_RsFwdSel = (ID_Link) ? 2'b11 : ((ID_Fwd_1) ? 2'b01 : ((ID_Fwd_3) ? 2'b10 : 2'b00));
    assign ID_RtFwdSel = (Mfc0) ? 2'b11 : ((ID_Fwd_2) ? 2'b01 : ((ID_Fwd_4) ? 2'b10 : 2'b00));  
    assign EX_RsFwdSel = (EX_Fwd_1) ? 2'b01 : ((EX_Fwd_3) ? 2'b10 : 2'b00);
    assign EX_RtFwdSel = (EX_Link)  ? 2'b11 : ((EX_Fwd_2) ? 2'b01 : ((EX_Fwd_4) ? 2'b10 : 2'b00));
    assign M_WriteDataFwdSel = MEM_Fwd_1;
 
endmodule
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.