Skip to content

Latest commit

 

History

210 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RISC-V 32IM CPU

ICA-ALAS-EXAMPLE - final

Introduction

We developed 5 distinct CPUs: a single-cycle processor, pipelined RV32IM, pipelined with cache, pipelined with branch prediction and a pipelined CPU that combines all cache multiply & branch prediction capabilities.

Quick Access

  • main branch: Final Pipelined CPU with multiply, data cache and branch prediction capabilites combined.
  • SingleCycle branch: Verified single-cycle CPU
  • Pipeline-MUL branch: Pipelined RV32IM perofrming complex maths instructions
  • Cache-final branch: Pipelined with Cache
  • Branch Prediction branch: Pipelined with branch prediction
  • some branches left for other utiilties and referencing, but all inherit from their main function name eg Cache, Mul, Pipelined etc

Project Progression

image

The Team

Name Personal Statement
Samuel Amos-Osebeyo Statement
Louis Canning Statement
Archie Kendall Statement
Adil Shah Statement

image

We used lucid-chart throughout the project, a digital 'drawing board' where we could collaborate and evolve designs in real time. It enabled us to visually and functionally keep up with what we were doing on git, with different pages and schematics for our differenct branches. This also enabled us to switch to different branches and help eachother debug as we could look up the relevant schematic on the shared notes.

Project Structure

.
├── .gitignore
├── ReadMe.md
├── rtl
│   ├── adder.sv
│   ├── branch_prediction
│   │   ├── branch_history_table.sv
│   │   ├── branch_predictor.sv
│   │   └── branch_target_buffer.sv
│   ├── decode
│   │   ├── D_E_reg.sv
│   │   ├── alu_decoder.sv
│   │   ├── control_unit.sv
│   │   ├── decode.sv
│   │   ├── regfile.sv
│   │   └── sign_extend.sv
│   ├── execute
│   │   ├── E_M_reg.sv
│   │   ├── alu.sv
│   │   ├── branch_comparator.sv
│   │   ├── div.sv
│   │   └── execute.sv
│   ├── fetch
│   │   ├── F_D_reg.sv
│   │   ├── fetch.sv
│   │   ├── instrMem.sv
│   │   └── pc_reg.sv
│   ├── hazard_unit
│   │   ├── control_hazard.sv
│   │   └── hazard_unit.sv
│   ├── memory
│   │   ├── M_W_reg.sv
│   │   ├── cache.sv
│   │   ├── cache_L1.sv
│   │   ├── cache_controller.sv
│   │   ├── cache_data_parser.sv
│   │   ├── datamem.sv
│   │   └── memory.sv
│   ├── mux.sv
│   ├── mux4.sv
│   ├── top.sv
│   └── writeback
│       └── writeback.sv
└── tb
    ├── Units
    │   ├── Testing_Guide.md
    │   ├── [testbench headers]
    │   ├── [verify implementations]
    │   └── doitunit.sh
    ├── asm
    │   ├── 1_addi_bne.s
    │   ├── 2_li_add.s
    │   ├── 3_lbu_sb.s
    │   ├── 4_jal_ret.s
    │   ├── 5_pdf.s
    │   ├── f1.s
    │   └── predictor.s
    ├── cache_testing
    │   └── [cache test assemblies]
    ├── hazards_test_asm
    │   ├── [data hazard tests]
    │   ├── div.s
    │   └── mul.s
    ├── custom_tests
    │   ├── custom_cpu_testbench.h
    │   └── custom_verify.cpp
    ├── reference
    │   └── [PDF reference materials]
    ├── assemble.sh
    ├── cacheit.sh
    ├── custom_doit.sh
    └── doit.sh

Running the Project

All commands should be executed from the /tb directory or the subsequent test folder use +chmod +x *<scriptname> to give yourself access

Command Purpose
./doit.sh Execute standard test suite
./doitunit.sh [unit name] Run module tests in Units folder
./custom_doit.sh Run our directory of our own tests
./pdf.sh [distribution name] Run PDF distribution visualization
./f1.sh Run F1 starting lights simulation
./cacheit.sh Run Cache Test suite and performance tests

Single Cycle Implementation

ICA-ALAS-EXAMPLE - Page 13

Design Overview

Our single-cycle CPU implements all RV32I instructions (except fence, ecall & ebreak) , enabling single-cycle execution of arithmetic, logical, memory, and control flow operations. This satisfies the requirements of stretch goal 3 from the brief.

Module Contributions

Component Samuel Louis Archie Adil
Program Counter x
ALU x
Register File x
Instruction Memory x x
Control Unit x
Sign Extension x
Data Path Integration x x
Data Memory x x
Top-Level Assembly x x
Unit Testing x
Integration Testing x x
F1 Program x
Vbuddy integration x

Testing & Verification

Single cycle test results

The testing script validated the CPU functionality through the given tests, modular tests were completed before integration as well.

Integration onto VBuddy

F1 Starting Lights Sequence

Our F1 implementation demonstrates correct timing and state machine behavior:

F1_normal.mp4
F1_random.mp4
Gaussian.mp4
Noisy.mp4

PDF Distribution Tests

Successfully visualizes probability distributions with proper data handling:

Gaussian Distribution: Smooth bell curve with correct statistical properties

Noisy Distribution: Demonstrates proper random number generation

Triangle Distribution: Linear probability distribution correctly implemented

Implementation Detail: To achieve smooth visualization, we display values every 3 clock cycles:

bool is_paused = vbdFlag();
top->trigger = is_paused;
if (!is_paused) {
    j++;
    if (j % 3 == 0) {
        vbdCycle(j);
        vbdPlot(top->a0, 0, 255);
    }
}

Pipelined Implementation

image

Architecture Overview

Our pipelined processor achieves higher throughput through instruction-level parallelism across 5 pipeline stages: fetch, decode, execute, memory & writeback. An additional hazard unit was created to detect and mitigate any data, control and structural hazards that arose. This design processes multiple instructions concurrently, with each stage handling a different instruction simultaneously. As well as continuing to pass key fundamental tests. This satisfies the requirements for stretch goal 2 from the brief.

Key Features:

  • Full RV32IM instruction set support
  • Data and Control Hazard Detection with forwarding and stalling

Testing & Validation

We developed custom testing scripts to test our specialised assembly files to ensure the design behaved as desired.

The specialised assembly programs were needed to either evaluate extension performance or for debugging purposes. The test prints from the script can be seen below.

image


Implementing Further Extensions

Integration Overview

ICA-ALAS-EXAMPLE - Page 13 (2)

Our extensions: These were all done on a fully pipelined cpu and all worked correctly

  • RV32IM extension
  • Branch Prediction
  • 2 way set associative Cache

These are all explored in more depth in our individual statements, all exentions had a quantifiable improvement over the standard pipelined version while still maintaining correctness across the board giving us the same test prints as the image seen just above. They were developed parallely on the base pipeline CPU and once extensive testing was completed, all these improvements were compiled into the one CPU.

With the completion of the cache all recommended stretch goals menmtioned in the brief have been achieved.

Extention Contributions

Component Samuel Louis Archie Adil
Pipelining x x x x
Forwarding x
Load stalls x
Control Hazards x
Branch Predictions x
Pipeline debug x x
RV32IM extension x
Cache x

Key Integration Challenges

  • Hazard Coordination: Synchronizing data forwarding, load-use stalls, and cache stalls while handling simultaneous conditions from cache misses and division operations without corrupting the pipeline.

  • Clock Synchronization: Standardizing all modules to posedge clk after early race conditions from mixed edge triggers in the BTB and register file caused unpredictable behavior.

  • Metadata Propagation: Ensuring branch prediction flags and opcode validity bits propagate correctly through stages and clear during flushes to prevent spurious stalls and incorrect forwarding.

  • Multi-Cycle Stalls: Coordinating 32-cycle division and cache miss stalls with selective pipeline freezing strategies while preventing instruction loss or state corruption.

  • Interface Consistency: Resolving signal naming ambiguities and polarity mismatches between modules (e.g., memUnsigned control signal) that caused instruction-specific bugs requiring GTKWave debugging.

Integration Success Through Modular Development

Our strategy of isolating and thoroughly testing individual modules before integration proved essential to the project's success. Each team member developed and verified their components independently using comprehensive unit tests, ensuring correct functionality before system-level assembly. This modular approach enabled parallel development across multiple extensions simultaneously - with in person code reviews of modules to ensure each member gained insight into each feature.

This collaborative workflow demonstrated our team coordination, with clear interfaces and regular communication ensuring smooth integration of complex features into a fully functional enhanced, pipelined CPU.


Appendix

Development Tools

  • Verilator for simulation
  • GTest for C++ testbenches
  • GTKWave for waveform analysis
  • RISC-V GNU toolchain for assembly
  • VBuddy for hardware visualization

References

  • Harris & Harris: Digital Design and Computer Architecture: RISC-V Edition

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages