This repository contains a comprehensive series of laboratory implementations for a complete ARM-style 5-stage pipelined processor. The project demonstrates fundamental and advanced computer architecture concepts through incremental development, from basic pipeline structures to advanced memory hierarchies and optimization techniques.
Each LAB_* directory represents a progressive implementation stage, building upon previous work to create a fully functional processor capable of executing ARM instruction set operations.
The final processor implements a classic 5-stage pipeline:
- IF (Instruction Fetch): Program counter management and instruction retrieval
- ID (Instruction Decode): Instruction decoding and register file access
- EXE (Execute): ALU operations and address calculations
- MEM (Memory): Data memory access and load/store operations
- WB (Write Back): Result write-back to register file
Advanced features include hazard detection, data forwarding, SRAM integration, and FPGA implementation with debugging capabilities.
- Provide a working 5-stage pipelined ARM-like CPU (IF, ID, EXE, MEM, WB).
- Demonstrate pipeline control, forwarding (bypass), hazard detection, memory hierarchy (SRAM + optional cache), and FPGA integration/debugging using VIO/ILA.
- Supply modular testbenches so students can verify individual stages and end-to-end behavior.
LAB_1/ to LAB_6/ # Incremental lab implementations
├── README.md # Comprehensive lab documentation
├── AGENTS.md # AI assistant instructions
├── CLAUDE.md # Claude-specific guidelines
├── description/ # Lab specifications and documentation
├── code/ # Main source code implementation
│ ├── modules/ # Modular Verilog components
│ ├── wrappers/ # FPGA wrappers and top-level modules
│ └── [testbenches] # Simulation testbenches
├── hw/ # Hardware-specific files (.xdc, .vhd)
├── docs/ # Additional documentation and diagrams
├── results/ # Simulation results and analysis
│ ├── logs/ # Simulation log files
│ ├── reports/ # Performance and synthesis reports
│ └── scripts/ # Analysis and measurement scripts
├── report/ # Laboratory report (LaTeX)
└── archive/ # Previous versions and backups
archive/— Legacy projects and shared componentsdocs/— Course documentation and reference materialsFinal_Report/— Comprehensive project documentation
See per-lab READMEs for lab-specific instructions (LAB_5/README.md is included and contains forwarding & VIO instructions).
ARM.v— top-level CPU (instantiates stages and pipeline registers).IF_stage,ID_stage,EXE_Stage,MEM_Stage,WB_Stage— stage implementations.*_stage_reg.v— pipeline registers (IF/ID, ID/EXE, EXE/MEM, MEM/WB).Forwarding_Unit.v,Hazard_Detection_Unit— hazard resolution and forwarding control.dist_mem_gen_0/InstructionMemory/*.coe— instruction ROM wrappers.- LAB_5:
sram.v,sram_controller.v— behavioral SRAM model + controller for 64-bit transfers. - LAB_7:
cache_controller.v— 2-way set-associative cache (optional in that lab).
Prerequisites: Icarus Verilog, ModelSim/Questa, or Verilator depending on your preferred simulator.
Icarus Verilog example (fast, functional simulation):
# compile (example for LAB_5 base code)
iverilog -o sim \
LAB_5/base_code/IF_stage.v \
LAB_5/base_code/ID_stage.v \
LAB_5/base_code/EXE_stage.v \
LAB_5/base_code/MEM_stage.v \
LAB_5/base_code/WB_stage.v \
LAB_5/base_code/ARM.v \
LAB_5/base_code/ARM_TB.v
# run
vvp simModelSim/Questa: use vlog to compile and vsim -c to run the TB with run -all.
Verilator (cycle-accurate C++ harness): use verilator --cc --exe --build then run ./obj_dir/V<top>.
Notes: include sram.v and sram_controller.v when testing memory/cache interactions. If Xilinx IP (dist_mem_gen_0) is missing, use the provided .coe or InstructionMemory wrapper.
- Open the lab project in Vivado and add the sources in the chosen
LAB_*folder. - Create a block design if you want to add IP (ILA/VIO). Add an
ila_0core for debug capture and avio_0core if you want runtime control of forwarding. - If using VIO, configure it with a single output probe (1-bit) and connect its probe to the wrapper expecting
probe_out0(the wrapper has anifdef USE_VIOguarded instantiation). - Optionally assign a physical button to the
forward_entop port inpin_assignment.xdc(LAB_5 mapsforward_en->J15). - Synthesize, implement and generate a bitstream, then program the board.
- Use Hardware Manager to toggle the VIO probe and use ILA captures to compare pipeline behavior with forwarding ON/OFF.
Tip: define USE_VIO for the design when using vio_0 (e.g. add -D USE_VIO in synthesis settings or +define+USE_VIO for simulation flows).
- Forwarding enabled (
forward_en = 1): ALU RAW hazards are resolved by forwarding; only load-use hazards require a 1-cycle stall. - Forwarding disabled (
forward_en = 0): the Hazard Detection Unit behaves like earlier labs and stalls on any RAW hazard. - Control of forwarding:
- VIO: add
vio_0IP with 1 output probe; connect it and defineUSE_VIO. - Button: map
forward_ento a board pin (default:J15inpin_assignment.xdc).
- VIO: add
- ILA recommendations: use Number of Windows = 2, capture register file words and PC, then compare captures with forwarding ON vs OFF.
For full step-by-step guidance see LAB_5/README.md (included in this repo).
- LAB_1–LAB_3: basic pipeline, register file, hazards, and control.
- LAB_4: Hazard Detection & basic stalling behavior.
- LAB_5: SRAM model + forwarding (VIO/ILA integration).
- LAB_6–LAB_7: incremental additions (performance improvements, cache integration in LAB_7).
scripts/run_tests.shruns available testbenches using Icarus (ensure Icarus is installed).scripts/Makefilecontains convenience targets for simulation flows.- Consider adding your own CI or local scripts to run
iverilogand parse results.
If you'd like, I can add an automated testbench that toggles forwarding_enable during a simulation and asserts correct results — tell me and I’ll add it.
- Use explicit widths for signals. Avoid implicit sizes.
- Use non-blocking assignments (
<=) in sequential always blocks and blocking (=) in combinational always blocks. - Add module headers describing purpose, I/O, and author.
Please open feature branches and PRs for major changes and include tests that demonstrate behavior changes.
- For debug & validation use the included
ila_0to capture internal registers; add VIO to toggle control signals (forwarding) at runtime. - If you see mismatches between simulation and FPGA runs, verify IP core wrapper versions (e.g.,
dist_mem_gen) and timing constraints.
- For questions about labs or help running simulations, contact your course TA or the project maintainer listed in the course materials.
This repository is provided for educational use. If you plan to reuse code outside coursework, contact the original authors. For lab exercises, assume an MIT-style permissive approach.
If you'd like, I can now:
- Add an automated testbench that toggles forwarding and asserts behavior, or
- Add a small Vivado TCL script to automate ILA captures and VIO toggling.
Which would you like me to add next?