MIPS Assembly Pipelined Processor

MIPS Pipelined Processor on Basys3 FPGA

A SystemVerilog implementation of a five-stage pipelined MIPS processor deployed on a Basys3 FPGA board. Converted from a single-cycle design by inserting pipeline registers and a dedicated hazard unit, then extended with custom instructions and synthesized to run on the board.

Pipelined processor with full hazard handling

Pipeline Stages

Five stages (Fetch, Decode, Execute, Memory, Writeback) connected through pipeline registers PipeWtoF, PipeFtoD, PipeDtoE, PipeEtoM, and PipeMtoW. Each register propagates the datapath values and control signals needed by the next stage, allowing up to five instructions to be in-flight simultaneously.

Hazard Detection

A dedicated HazardUnit fixes three classes of hazards:

  • Data hazards: forwarding paths from the M and W stages back to the E stage ALU inputs eliminate most stalls for back-to-back dependent instructions.
  • Load-use hazards: when a LW result is needed by the immediately following instruction, the unit inserts one stall cycle (bubbles the pipeline) before forwarding can resolve the dependency.
  • Branch hazards: branch decisions in the E stage cause the unit to flush in-flight instructions in F and D to prevent incorrect execution.

Instruction Set

Supports the standard MIPS-lite ISA across three encoding formats:

  • R-type: ADD, SUB, AND, OR, SLT
  • I-type: LW, SW, ADDI, BEQ, LUI (loads immediate into upper 16 bits of RF[rt], zeroing the lower half)
  • J-type: JAL (jump-and-link: jumps to target address and saves PC + 4 into $ra), JR (jumps to address stored in RF[rs])
  • Custom R-type: ROL (rotate left) left-rotates RF[rs] by shamt bits and writes the result to RF[rd]
    • Implemented as (a << shamt) | (a >> (32 - shamt))
    • Designed to forward cleanly through the existing hazard unit without introducing additional stall logic.

FPGA Integration

Running at 100 MHz on the Basys3 would make execution unobservable, so a pulse_controller module debounces and synchronizes a pushbutton into a single clock pulse per press. This effectively gives the user a manual clock. A second pulse_controller provides a hand-pushed reset. A display_controller multiplexes four hex digits onto the 7-segment display, while LEDs display memwrite and regwrite control signals for direct inspection.

← back to projects