1 |
2 |
ayersg |
`timescale 1ns / 1ps
|
2 |
|
|
/*
|
3 |
|
|
* File : Hazard_Detection.v
|
4 |
|
|
* Project : University of Utah, XUM Project MIPS32 core
|
5 |
|
|
* Creator(s) : Grant Ayers (ayers@cs.utah.edu)
|
6 |
|
|
*
|
7 |
|
|
* Modification History:
|
8 |
|
|
* Rev Date Initials Description of Change
|
9 |
|
|
* 1.0 23-Jul-2011 GEA Initial design.
|
10 |
|
|
* 2.0 26-May-2012 GEA Release version with CP0.
|
11 |
|
|
*
|
12 |
|
|
* Standards/Formatting:
|
13 |
|
|
* Verilog 2001, 4 soft tab, wide column.
|
14 |
|
|
*
|
15 |
|
|
* Description:
|
16 |
|
|
* Hazard Detection and Forward Control. This is the glue that allows a
|
17 |
|
|
* pipelined processor to operate efficiently and correctly in the presence
|
18 |
|
|
* of data, structural, and control hazards. For each pipeline stage, it
|
19 |
|
|
* detects whether that stage requires data that is still in the pipeline,
|
20 |
|
|
* and whether that data may be forwarded or if the pipeline must be stalled.
|
21 |
|
|
*
|
22 |
|
|
* This module is heavily commented. Read below for more information.
|
23 |
|
|
*/
|
24 |
|
|
module Hazard_Detection(
|
25 |
3 |
ayersg |
input [7:0] DP_Hazards,
|
26 |
|
|
input [4:0] ID_Rs,
|
27 |
|
|
input [4:0] ID_Rt,
|
28 |
|
|
input [4:0] EX_Rs,
|
29 |
|
|
input [4:0] EX_Rt,
|
30 |
|
|
input [4:0] EX_RtRd,
|
31 |
|
|
input [4:0] MEM_RtRd,
|
32 |
|
|
input [4:0] WB_RtRd,
|
33 |
2 |
ayersg |
input ID_Link,
|
34 |
3 |
ayersg |
input EX_Link,
|
35 |
|
|
input EX_RegWrite,
|
36 |
|
|
input MEM_RegWrite,
|
37 |
|
|
input WB_RegWrite,
|
38 |
|
|
input MEM_MemRead,
|
39 |
2 |
ayersg |
input MEM_MemWrite, // Needed for Store Conditional which writes to a register
|
40 |
|
|
input InstMem_Read,
|
41 |
3 |
ayersg |
input InstMem_Ready,
|
42 |
|
|
input Mfc0, // Using fwd mux; not part of haz/fwd.
|
43 |
2 |
ayersg |
input IF_Exception_Stall,
|
44 |
|
|
input ID_Exception_Stall,
|
45 |
|
|
input EX_Exception_Stall,
|
46 |
|
|
input M_Stall_Controller, // Determined by data memory controller
|
47 |
3 |
ayersg |
output IF_Stall,
|
48 |
|
|
output ID_Stall,
|
49 |
|
|
output EX_Stall,
|
50 |
2 |
ayersg |
output M_Stall,
|
51 |
|
|
output WB_Stall,
|
52 |
3 |
ayersg |
output [1:0] ID_RsFwdSel,
|
53 |
|
|
output [1:0] ID_RtFwdSel,
|
54 |
|
|
output [1:0] EX_RsFwdSel,
|
55 |
|
|
output [1:0] EX_RtFwdSel,
|
56 |
|
|
output M_WriteDataFwdSel
|
57 |
|
|
);
|
58 |
|
|
|
59 |
|
|
/* Hazard and Forward Detection
|
60 |
|
|
*
|
61 |
|
|
* Most instructions read from one or more registers. Normally this occurs in
|
62 |
|
|
* the ID stage. However, frequently the register file in the ID stage is stale
|
63 |
|
|
* when one or more forward stages in the pipeline (EX, MEM, or WB) contains
|
64 |
|
|
* an instruction which will eventually update it but has not yet done so.
|
65 |
|
|
*
|
66 |
|
|
* A hazard condition is created when a forward pipeline stage is set to write
|
67 |
|
|
* the same register that a current pipeline stage (e.g. in ID) needs to read.
|
68 |
|
|
* The solution is to stall the current stage (and effectively all stages behind
|
69 |
|
|
* it) or bypass (forward) the data from forward stages. Fortunately forwarding
|
70 |
|
|
* works for most combinations of instructions.
|
71 |
|
|
*
|
72 |
|
|
* Hazard and Forward conditions are handled based on two simple rules:
|
73 |
|
|
* "Wants" and "Needs." If an instruction "wants" data in a certain pipeline
|
74 |
|
|
* stage, and that data is available further along in the pipeline, it will
|
75 |
|
|
* be forwarded. If it "needs" data and the data is not yet available for forwarding,
|
76 |
|
|
* the pipeline stage stalls. If it does not want or need data in a certain
|
77 |
|
|
* stage, forwarding is disabled and a stall will not occur. This is important
|
78 |
|
|
* for instructions which insert custom data, such as jal or movz.
|
79 |
|
|
*
|
80 |
|
|
* Currently, "Want" and "Need" conditions are defined for both Rs data and Rt
|
81 |
|
|
* data (the two read registers in MIPS), and these conditions exist in the
|
82 |
|
|
* ID and EX pipeline stages. This is a total of eight condition bits.
|
83 |
|
|
*
|
84 |
|
|
* A unique exception exists with Store instructions, which don't need the
|
85 |
|
|
* "Rt" data until the MEM stage. Because data doesn't change in WB, and WB
|
86 |
|
|
* is the only stage following MEM, forwarding is *always* possible from
|
87 |
|
|
* WB to Mem. This unit handles this situation, and a condition bit is not
|
88 |
|
|
* needed.
|
89 |
|
|
*
|
90 |
2 |
ayersg |
* When data is needed from the MEM stage by a previous stage (ID or EX), the
|
91 |
|
|
* decision to forward or stall is based on whether MEM is accessing memory
|
92 |
|
|
* (stall) or not (forward). Normally store instructions don't write to registers
|
93 |
|
|
* and thus are never needed for a data dependence, so the signal 'MEM_MemRead'
|
94 |
|
|
* is sufficient to determine. Because of the Store Conditional instruction,
|
95 |
|
|
* however, 'MEM_MemWrite' must also be considered because it writes to a register.
|
96 |
|
|
*
|
97 |
3 |
ayersg |
*/
|
98 |
|
|
|
99 |
|
|
wire WantRsByID, NeedRsByID, WantRtByID, NeedRtByID, WantRsByEX, NeedRsByEX, WantRtByEX, NeedRtByEX;
|
100 |
|
|
assign WantRsByID = DP_Hazards[7];
|
101 |
|
|
assign NeedRsByID = DP_Hazards[6];
|
102 |
|
|
assign WantRtByID = DP_Hazards[5];
|
103 |
|
|
assign NeedRtByID = DP_Hazards[4];
|
104 |
|
|
assign WantRsByEX = DP_Hazards[3];
|
105 |
|
|
assign NeedRsByEX = DP_Hazards[2];
|
106 |
|
|
assign WantRtByEX = DP_Hazards[1];
|
107 |
|
|
assign NeedRtByEX = DP_Hazards[0];
|
108 |
2 |
ayersg |
|
109 |
3 |
ayersg |
// Trick allowed by RegDst = 0 which gives Rt. MEM_Rt is only used on
|
110 |
|
|
// Data Memory write operations (stores), and RegWrite is always 0 in this case.
|
111 |
|
|
wire [4:0] MEM_Rt = MEM_RtRd;
|
112 |
|
|
|
113 |
|
|
// Forwarding should not happen when the src/dst register is $zero
|
114 |
|
|
wire EX_RtRd_NZ = (EX_RtRd != 5'b00000);
|
115 |
|
|
wire MEM_RtRd_NZ = (MEM_RtRd != 5'b00000);
|
116 |
|
|
wire WB_RtRd_NZ = (WB_RtRd != 5'b00000);
|
117 |
|
|
|
118 |
|
|
// ID Dependencies
|
119 |
|
|
wire Rs_IDEX_Match = (ID_Rs == EX_RtRd) & EX_RtRd_NZ & (WantRsByID | NeedRsByID) & EX_RegWrite;
|
120 |
|
|
wire Rt_IDEX_Match = (ID_Rt == EX_RtRd) & EX_RtRd_NZ & (WantRtByID | NeedRtByID) & EX_RegWrite;
|
121 |
|
|
wire Rs_IDMEM_Match = (ID_Rs == MEM_RtRd) & MEM_RtRd_NZ & (WantRsByID | NeedRsByID) & MEM_RegWrite;
|
122 |
|
|
wire Rt_IDMEM_Match = (ID_Rt == MEM_RtRd) & MEM_RtRd_NZ & (WantRtByID | NeedRtByID) & MEM_RegWrite;
|
123 |
|
|
wire Rs_IDWB_Match = (ID_Rs == WB_RtRd) & WB_RtRd_NZ & (WantRsByID | NeedRsByID) & WB_RegWrite;
|
124 |
|
|
wire Rt_IDWB_Match = (ID_Rt == WB_RtRd) & WB_RtRd_NZ & (WantRtByID | NeedRtByID) & WB_RegWrite;
|
125 |
|
|
// EX Dependencies
|
126 |
|
|
wire Rs_EXMEM_Match = (EX_Rs == MEM_RtRd) & MEM_RtRd_NZ & (WantRsByEX | NeedRsByEX) & MEM_RegWrite;
|
127 |
|
|
wire Rt_EXMEM_Match = (EX_Rt == MEM_RtRd) & MEM_RtRd_NZ & (WantRtByEX | NeedRtByEX) & MEM_RegWrite;
|
128 |
|
|
wire Rs_EXWB_Match = (EX_Rs == WB_RtRd) & WB_RtRd_NZ & (WantRsByEX | NeedRsByEX) & WB_RegWrite;
|
129 |
|
|
wire Rt_EXWB_Match = (EX_Rt == WB_RtRd) & WB_RtRd_NZ & (WantRtByEX | NeedRtByEX) & WB_RegWrite;
|
130 |
|
|
// MEM Dependencies
|
131 |
|
|
wire Rt_MEMWB_Match = (MEM_Rt == WB_RtRd) & WB_RtRd_NZ & WB_RegWrite;
|
132 |
2 |
ayersg |
|
133 |
|
|
|
134 |
3 |
ayersg |
// ID needs data from EX : Stall
|
135 |
|
|
wire ID_Stall_1 = (Rs_IDEX_Match & NeedRsByID);
|
136 |
|
|
wire ID_Stall_2 = (Rt_IDEX_Match & NeedRtByID);
|
137 |
|
|
// ID needs data from MEM : Stall if mem access
|
138 |
|
|
wire ID_Stall_3 = (Rs_IDMEM_Match & (MEM_MemRead | MEM_MemWrite) & NeedRsByID);
|
139 |
|
|
wire ID_Stall_4 = (Rt_IDMEM_Match & (MEM_MemRead | MEM_MemWrite) & NeedRtByID);
|
140 |
|
|
// ID wants data from MEM : Forward if not mem access
|
141 |
|
|
wire ID_Fwd_1 = (Rs_IDMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
|
142 |
|
|
wire ID_Fwd_2 = (Rt_IDMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
|
143 |
|
|
// ID wants/needs data from WB : Forward
|
144 |
|
|
wire ID_Fwd_3 = (Rs_IDWB_Match);
|
145 |
|
|
wire ID_Fwd_4 = (Rt_IDWB_Match);
|
146 |
|
|
// EX needs data from MEM : Stall if mem access
|
147 |
|
|
wire EX_Stall_1 = (Rs_EXMEM_Match & (MEM_MemRead | MEM_MemWrite) & NeedRsByEX);
|
148 |
|
|
wire EX_Stall_2 = (Rt_EXMEM_Match & (MEM_MemRead | MEM_MemWrite) & NeedRtByEX);
|
149 |
|
|
// EX wants data from MEM : Forward if not mem access
|
150 |
|
|
wire EX_Fwd_1 = (Rs_EXMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
|
151 |
|
|
wire EX_Fwd_2 = (Rt_EXMEM_Match & ~(MEM_MemRead | MEM_MemWrite));
|
152 |
|
|
// EX wants/needs data from WB : Forward
|
153 |
|
|
wire EX_Fwd_3 = (Rs_EXWB_Match);
|
154 |
|
|
wire EX_Fwd_4 = (Rt_EXWB_Match);
|
155 |
|
|
// MEM needs data from WB : Forward
|
156 |
|
|
wire MEM_Fwd_1 = (Rt_MEMWB_Match);
|
157 |
2 |
ayersg |
|
158 |
|
|
|
159 |
3 |
ayersg |
// Stalls and Control Flow Final Assignments
|
160 |
2 |
ayersg |
assign WB_Stall = M_Stall;
|
161 |
|
|
assign M_Stall = IF_Stall | M_Stall_Controller;
|
162 |
|
|
assign EX_Stall = (EX_Stall_1 | EX_Stall_2 | EX_Exception_Stall) | M_Stall;
|
163 |
|
|
assign ID_Stall = (ID_Stall_1 | ID_Stall_2 | ID_Stall_3 | ID_Stall_4 | ID_Exception_Stall) | EX_Stall;
|
164 |
|
|
assign IF_Stall = InstMem_Read | InstMem_Ready | IF_Exception_Stall;
|
165 |
|
|
|
166 |
3 |
ayersg |
// Forwarding Control Final Assignments
|
167 |
|
|
assign ID_RsFwdSel = (ID_Link) ? 2'b11 : ((ID_Fwd_1) ? 2'b01 : ((ID_Fwd_3) ? 2'b10 : 2'b00));
|
168 |
|
|
assign ID_RtFwdSel = (Mfc0) ? 2'b11 : ((ID_Fwd_2) ? 2'b01 : ((ID_Fwd_4) ? 2'b10 : 2'b00));
|
169 |
2 |
ayersg |
assign EX_RsFwdSel = (EX_Fwd_1) ? 2'b01 : ((EX_Fwd_3) ? 2'b10 : 2'b00);
|
170 |
3 |
ayersg |
assign EX_RtFwdSel = (EX_Link) ? 2'b11 : ((EX_Fwd_2) ? 2'b01 : ((EX_Fwd_4) ? 2'b10 : 2'b00));
|
171 |
|
|
assign M_WriteDataFwdSel = MEM_Fwd_1;
|
172 |
|
|
|
173 |
2 |
ayersg |
endmodule
|
174 |
3 |
ayersg |
|