A pipelined core overlaps fetch, decode, execute, memory, and writeback. A hazard is any reason a later instruction cannot yet use an earlier result.
flowchart LR F[Fetch] --> D[Decode] D --> E[Execute] E --> M[Memory] M --> W[Writeback]
| Kind | Typical cause | Cheap RTL fix |
|---|---|---|
| Data | add then and using the same rd |
Forward from EX/MEM; stall on load-use |
| Control | Taken branch while fetch already ran | Redirect PC; optional delay slot (avoid) |
| Structural | One memory port, two accesses | Stall FETCH on a load/store |
wire load_use = mem_read_e && (rs1_d == rd_e || rs2_d == rd_e);
always_comb begin
stall_f = load_use;
stall_d = load_use;
end
Wrong vs right
Wrong — ignore load-use and hope the testbench never hits it.
Right — detect the one-cycle gap after a load, stall decode, and forward ALU results so independent ALU ops do not stall.