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

Subversion Repositories mips32r1

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

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.