Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Verilog Simple RISC Processor

A modular, multi-cycle, accumulator-based RISC processor implemented in Verilog HDL for computer architecture education and digital system design.

Language Simulation License Status


Overview

This repository contains a complete RTL implementation of a simple accumulator-based Reduced Instruction Set Computer (RISC) processor written in synthesizable Verilog HDL.

The project is designed for education and experimentation. It demonstrates:

  • processor organization and RTL design;
  • separation of datapath and control logic;
  • multi-cycle instruction execution;
  • finite-state-machine control;
  • unified instruction and data memory;
  • module-level and CPU integration verification;
  • waveform-based debugging and architectural analysis.

The design prioritizes readability, modularity, and ease of extension rather than performance. Each hardware component is implemented as an independent RTL module.


Key Features

  • 8-bit accumulator-based datapath
  • 8-bit instructions with a 3-bit opcode and 5-bit operand
  • 32-address unified program and data memory
  • Eight native instructions
  • Multi-cycle finite-state-machine controller
  • Modular and synthesizable Verilog RTL
  • Automated regression and CPU integration tests
  • VCD waveform generation for GTKWave
  • Vivado RTL elaboration and synthesis support

Processor Specification

Feature Description
Architecture Accumulator-based RISC
Datapath width 8 bits
Instruction width 8 bits
Opcode width 3 bits
Operand width 5 bits
Address space 32 memory locations
Memory organization Unified program/data memory
Controller Finite-state machine
Execution model Multi-cycle
RTL language Verilog HDL
Primary simulator Icarus Verilog

Architecture

The processor consists of a compact datapath and a finite-state-machine controller. Because the architecture is accumulator-based, arithmetic and logical operations use a single general-purpose register: the accumulator (AC).

flowchart LR
    PC[Program Counter]
    IR[Instruction Register]
    MUX[Address Multiplexer]
    MEM[Unified Memory]
    BUS[8-bit Data Bus]
    AC[Accumulator]
    ALU[Arithmetic Logic Unit]
    CTRL[Controller FSM]

    PC --> MUX
    IR --> MUX
    MUX --> MEM
    MEM --> BUS
    BUS --> IR
    BUS --> ALU
    AC --> ALU
    ALU --> AC

    CTRL --> PC
    CTRL --> IR
    CTRL --> MEM
    CTRL --> AC
    CTRL --> MUX
Loading

The controller coordinates memory access, register updates, ALU operations, and program-counter changes over multiple clock cycles.

Vivado Elaborated RTL Schematic

Vivado elaborated RTL schematic

Elaborated RTL schematic showing the program counter, instruction register, address multiplexer, accumulator, ALU, unified memory, and FSM controller.

Detailed synthesized netlist

Detailed synthesized processor netlist


Instruction Set Architecture

Instruction Format

Each instruction occupies one byte:

+-------------+----------------+
| Opcode (3)  | Operand (5)    |
+-------------+----------------+
 7         5   4            0
  • Opcode identifies the operation.
  • Operand represents a memory address or jump destination.

Instruction Set

Opcode Mnemonic Operation
000 HLT Stop processor execution
001 SKZ Skip the next instruction when AC == 0
010 ADD addr AC ← AC + MEM[addr]
011 AND addr AC ← AC AND MEM[addr]
100 XOR addr AC ← AC XOR MEM[addr]
101 LDA addr AC ← MEM[addr]
110 STO addr MEM[addr] ← AC
111 JMP addr PC ← addr

Multi-Cycle Execution

Instructions are executed over multiple clock cycles so that datapath resources can be reused. A typical instruction passes through some or all of the following stages:

Instruction Address
        │
        ▼
Instruction Fetch
        │
        ▼
Instruction Load
        │
        ▼
Decode / Idle
        │
        ▼
Operand Address
        │
        ▼
Operand Fetch
        │
        ▼
Execute
        │
        ▼
Write Back

The controller selects only the states required by the current instruction.

Controller States

State Purpose
INST_ADDR Select the instruction address
INST_FETCH Read instruction memory
INST_LOAD Load the instruction register
IDLE Decode the current instruction
OP_ADDR Select the operand address
OP_FETCH Read the operand
ALU_OP Execute an arithmetic, logical, or control operation
STORE Write a result to memory

Control Signals

Signal Description
rd Memory read enable
wr Memory write enable
ld_ir Load the instruction register
ld_ac Load the accumulator
ld_pc Load the program counter
inc_pc Increment the program counter
sel Select the memory address source
data_e Enable data-bus output

RTL Modules

Module Responsibility
CPU.v Top-level processor and module integration
Controller.v FSM sequencing and control-signal generation
ALU.v Arithmetic and logical operations
Memory.v Unified instruction and data memory
PC.v Program counter
IR.v Instruction register
AC.v Accumulator register

CPU.v

The top-level module connects the datapath and controller. It selects memory addresses, routes the shared data bus, forwards control signals, and coordinates complete instruction execution.

Controller.v

The controller sequences instruction states and generates the signals required for memory access, register loading, ALU operation, and program-counter updates.

ALU.v

The ALU supports:

  • addition;
  • bitwise AND;
  • bitwise XOR;
  • accumulator loading.

It also produces the zero condition used by SKZ.

Memory.v

The unified memory stores both instructions and data.

  • 32 addressable locations
  • 8-bit data width
  • asynchronous read
  • synchronous write

PC.v

The program counter stores the address of the next instruction and supports:

  • increment;
  • loading a jump destination;
  • synchronous reset.

IR.v

The instruction register holds the current instruction so that its opcode and operand remain stable during execution.

AC.v

The accumulator is the processor's only general-purpose register. It can load an ALU result, retain its current value, or reset synchronously.

Simple RISC Processor in Verilog

A compact, accumulator-based RISC processor implemented in Verilog HDL. The design demonstrates the core principles of CPU organization, including instruction fetch, instruction decode, arithmetic and logic execution, memory access, program-counter control, and finite-state-machine-based control.

This repository contains the RTL source code, module-level testbenches, CPU integration testbenches, a Python-based simulation runner, waveform-oriented verification assets, and a LaTeX project report.


Table of Contents


Overview

The processor uses an 8-bit instruction format composed of a 3-bit opcode and a 5-bit operand field. This format supports eight instructions and provides access to a 32-location memory space. The datapath is built around an 8-bit accumulator register, an 8-bit bidirectional data bus, a 5-bit program counter, and a 32 × 8-bit memory.

The CPU operates synchronously with a clock signal and an active-high reset signal. Program execution continues until the HLT instruction is decoded and the controller asserts the halt signal.

Key characteristics:

  • 8-bit instruction width
  • 3-bit opcode and 5-bit operand
  • 8 supported instructions
  • 32-address memory space
  • 8-bit accumulator-based datapath
  • Multi-cycle instruction execution
  • 8-state controller finite state machine
  • Modular RTL implementation
  • Unit and integration testbenches
  • Automated simulation runner for Icarus Verilog and Vivado Simulator

Architecture

The top-level processor is implemented in src/CPU.v and integrates the following components:

              +----------------+
              |   Controller   |
              +----------------+
                 | control signals
                 v

+------+     +-------------+     +----------+
|  PC  | --> | Address MUX | --> |  Memory  |
+------+     +-------------+     +----------+
                                  ^      |
                                  |      v
                              +----------------+
                              | Instruction IR |
                              +----------------+
                                  | opcode / operand
                                  v
+--------------+     +------+     +------------+
| Accumulator  | --> | ALU  | --> | Accumulator|
+--------------+     +------+     +------------+

The CPU execution flow is divided into two main phases:

  1. Instruction Fetch Phase

    • INST_ADDR
    • INST_FETCH
    • INST_LOAD
    • IDLE
  2. Execution Phase

    • OP_ADDR
    • OP_FETCH
    • ALU_OP
    • STORE

A standard instruction is executed over these eight controller states. Control-flow instructions such as SKZ, JMP, and HLT update the program counter or halt state according to the opcode and ALU zero flag.


Instruction Set

Opcode Mnemonic Description ALU Output
000 HLT Halt processor execution inA
001 SKZ Skip next instruction when the accumulator is zero inA
010 ADD Add memory operand to accumulator inA + inB
011 AND Bitwise AND between accumulator and memory operand inA & inB
100 XOR Bitwise XOR between accumulator and memory operand inA ^ inB
101 LDA Load memory operand into accumulator inB
110 STO Store accumulator value into memory inA
111 JMP Jump to operand address inA

Instruction format:

bit[7:5]  opcode
bit[4:0]  operand / address

Example program:

LDA 20    ; AC <- MEM[20]
ADD 21    ; AC <- AC + MEM[21]
STO 22    ; MEM[22] <- AC
HLT       ; Stop execution

Repository Structure

Verilog-Simple-Risc-Processor/
├── src/
│   ├── CPU.v
│   ├── Controller.v
│   ├── ALU.v
│   ├── Memory.v
│   ├── PC.v
│   ├── IR.v
│   └── AC.v
├── testbench/
│   ├── test_001/
│   ├── test_002/
│   ├── ...
│   └── test_010/
├── docs/
│   └── images/
├── run_tests.py
├── LICENSE
.
├── src/
│   ├── AC.v
│   ├── ADD_MUX.v
│   ├── ALU.v
│   ├── CPU.v
│   ├── Controller.v
│   ├── IR.v
│   ├── Memory.v
│   └── PC.v
├── testbench/
│   ├── run_tests.py
│   ├── test_001/
│   │   ├── PC_tb.v
│   │   └── expected.txt
│   ├── test_002/
│   │   ├── AM_tb.v
│   │   └── expected.txt
│   ├── test_003/
│   │   ├── ALU_tb.v
│   │   └── expected.txt
│   ├── test_004/
│   │   ├── Controller_tb.v
│   │   └── expected.txt
│   ├── test_005/
│   │   ├── IR_tb.v
│   │   └── expected.txt
│   ├── test_006/
│   │   ├── AC_tb.v
│   │   └── expected.txt
│   ├── test_007/
│   │   ├── Memory_tb.v
│   │   └── expected.txt
│   ├── test_008/
│   │   ├── CPU_tb.v
│   │   └── expected.txt
│   ├── test_009/
│   │   ├── CPU2_tb.v
│   │   └── expected.txt
│   └── test_010/
│       └── CPU_tb_wave.v
├── report/
│   ├── chapters/
│   ├── figures/
│   ├── riscReport.tex
│   └── riscReport.pdf
├── flake.nix
├── flake.lock
├── run_tests.py
└── README.md

Verification

The project uses two complementary verification levels:

  1. Module-level verification checks individual RTL components.
  2. CPU integration verification checks complete program execution and interactions among processor components.

Tests are compiled with Icarus Verilog, executed with vvp, and evaluated against expected output.

RTL Source
     │
     ▼
Compile with iverilog
     │
     ▼
Simulate with vvp
     │
     ▼
Compare Output
     │
     ▼
PASS / FAIL

Test Coverage

Test Description
test_001 Program-counter verification
test_002 Memory-module verification
test_003 Instruction-register verification
test_004 Accumulator verification
test_005 ALU arithmetic and logical operations
test_006 Controller FSM verification
test_007 Datapath signal verification
test_008 CPU instruction execution
test_009 CPU integration test
test_010 Waveform-oriented CPU integration

All eight instructions are exercised by the integration tests:

Instruction Verified
HLT
SKZ
ADD
AND
XOR
LDA
STO
JMP

Behavioral Simulation Waveform

Vivado behavioral simulation waveform

Multi-cycle instruction execution showing datapath activity, controller sequencing, memory access, conditional skip, jump, and halt behavior.


Running the Project

Prerequisites

Install:

  • Python 3
  • Icarus Verilog
  • GTKWave for waveform inspection

Run All Tests

python3 run_tests.py --src src --testbench testbench --sim icarus

Run a Specific Test

python3 run_tests.py \
  --src src \
  --testbench testbench \
  --sim icarus \
  --filter test_010

Replace test_010 with the required test name.

Expected Output

Running test_001 ... PASS
Running test_002 ... PASS
...
Running test_010 ... PASS

Summary

Passed : 10
Failed : 0
Skipped: 0

Waveform Debugging

The waveform-oriented integration test produces a Value Change Dump (.vcd) file.

Open it with GTKWave:

gtkwave CPU_tb_wave.vcd

Useful signals include:

  • program counter;
  • instruction register;
  • accumulator;
  • ALU output;
  • memory address and data;
  • controller state;
  • internal data bus;
  • zero flag;
  • control signals.

A recommended debugging cycle is:

  1. Run the relevant test.
  2. Review the simulation output.
  3. Inspect the generated waveform.
  4. Locate incorrect datapath or controller behavior.
  5. Update the RTL.
  6. Run the full regression suite.

Vivado Synthesis

Synthesized Design

Vivado synthesized processor schematic

Synthesized processor schematic generated by Vivado, showing the main processor modules and FPGA-specific clock and I/O resources.

Detailed Synthesized Netlist

View detailed synthesized logic

Detailed Vivado synthesized processor netlist

Detailed gate-level view of the synthesized processor logic. This diagram illustrates how the RTL design is transformed into registers, multiplexers, combinational logic, and control circuitry.


Design Principles

The implementation intentionally favors clarity over performance:

  • one hardware component per source file;
  • explicit separation of datapath and control logic;
  • a single accumulator instead of a register file;
  • multi-cycle execution instead of pipelining;
  • a compact instruction set;
  • unified program and data memory;
  • consistent signal naming;
  • synthesizable Verilog constructs.

These choices make the project suitable for introductory computer architecture courses, digital-design laboratories, and architectural experiments.


Current Limitations

The following features are intentionally omitted:

Feature Status
General-purpose register file
Immediate instructions
Pipeline
Hazard detection
Branch prediction
Interrupt support
Cache memory
Separate instruction and data memory
Memory-mapped I/O
Exceptions

Future Work

Possible extensions include:

Instruction Set

  • SUB and OR
  • shift operations
  • compare instructions
  • immediate operands
  • additional conditional branches

Datapath and Architecture

  • register file
  • barrel shifter
  • status register and additional flags
  • Harvard memory organization
  • five-stage pipeline
  • forwarding and hazard detection
  • pipeline flushing
  • interrupt controller

Verification

  • functional coverage
  • constrained-random testing
  • SystemVerilog testbenches
  • assertion-based verification
  • continuous integration with GitHub Actions

Educational Outcomes

The project provides practical experience with:

  • register-transfer-level design;
  • modular hardware development;
  • datapath organization;
  • finite-state-machine control;
  • instruction decoding and execution;
  • ALU, memory, and program-counter design;
  • multi-cycle processor control;
  • hardware simulation and verification;
  • waveform analysis.

Contributing

Contributions are welcome, including new instructions, additional testbenches, documentation improvements, RTL optimizations, and bug fixes.

  1. Fork the repository.
  2. Create a feature branch.
  3. Commit your changes.
  4. Confirm that all regression tests pass.
  5. Open a pull request.

Project Status

Current version: 1.1

The project is functionally stable and suitable for educational use. The current release includes the modular RTL implementation, multi-cycle controller, complete original instruction set, automated regression tests, CPU integration tests, waveform debugging, and project documentation.


References

  • M. Morris Mano -Computer System Architecture
  • David A. Patterson and John L. Hennessy -Computer Organization and Design
  • Stephen Brown and Zvonko Vranesic -Fundamentals of Digital Logic with Verilog Design
  • IEEE Standard for the Verilog Hardware Description Language

Authors


Acknowledgements

This project was developed as part of undergraduate coursework in digital logic and computer architecture.

Special thanks to the instructors and teaching assistants whose lectures and laboratory exercises inspired this educational processor.

Modules

PC.v - Program Counter

The program counter stores the address of the current instruction. It supports reset, address loading, and increment operations.

Priority order:

rst > ld_pc > inc_pc > hold

ADD_MUX.v - Address Multiplexer

The address multiplexer selects the source address for memory access:

  • sel = 1: select program counter address
  • sel = 0: select instruction operand address

The module is parameterized through WIDTH.

Memory.v - Memory

The memory module provides a 32 × 8-bit storage array with a single bidirectional data port. Read and write operations are controlled by rd and wr.

  • Read: rd = 1, wr = 0
  • Write: rd = 0, wr = 1
  • High impedance: otherwise

IR.v - Instruction Register

The instruction register stores the current 8-bit instruction and separates it into:

  • opcode = instruction[7:5]
  • operand = instruction[4:0]

AC.v - Accumulator

The accumulator stores the main working data value of the CPU. It receives ALU output when ld_ac is asserted.

ALU.v - Arithmetic Logic Unit

The ALU performs arithmetic, logic, and data-transfer operations based on the opcode. It also generates the zero flag based on whether the accumulator input is zero.

Controller.v - Control Unit

The controller is implemented as an 8-state finite state machine. It generates all datapath control signals, including memory read/write, instruction loading, accumulator loading, program-counter increment/loading, bus enable, and halt control.

CPU.v - Top-Level Processor

The top-level CPU connects the datapath modules and controller into a complete processor system. It exposes the following interface:

module CPU (
    input  clk,
    input  rst,
    output halt
);

Requirements

At least one Verilog simulator is required:

  • Icarus Verilog for iverilog and vvp
  • AMD/Xilinx Vivado Simulator for xvlog, xelab, and xsim

Python is also required for the automated test runner.

Optional development environment:

  • Nix with flakes enabled
  • The provided flake.nix defines a development shell containing Verilog, Python, and LaTeX-related tooling.

Getting Started

Clone the repository:

git clone <repository-url>
cd Verilog-Simple-Risc-Processor

If Nix is available, enter the development shell:

nix develop .#risc

Alternatively, install the required tools manually:

# Ubuntu/Debian example
sudo apt update
sudo apt install iverilog python3

Running Tests

The repository includes an automated Python test runner that can use either Icarus Verilog or Vivado Simulator.

Run all testbenches with simulator auto-detection:

python run_tests.py --src src --testbench testbench

Run all tests with Icarus Verilog:

python run_tests.py --src src --testbench testbench --sim icarus

Run all tests with Vivado Simulator:

python run_tests.py --src src --testbench testbench --sim vivado

Run selected tests only:

python run_tests.py --src src --testbench testbench --filter test_001 test_008

Use loose output comparison:

python run_tests.py --src src --testbench testbench --loose

For Vivado installations that are not available through PATH, specify the Vivado binary directory:

python run_tests.py --src src --testbench testbench --sim vivado --vivado-bin "C:/Xilinx/Vivado/2024.2/bin"

Waveform Simulation

The waveform-oriented CPU integration testbench is located at:

testbench/test_010/CPU_tb_wave.v

This testbench is intended for signal inspection and waveform debugging. It exposes internal CPU signals as top-level aliases and generates waveform output.

Example using Icarus Verilog:

iverilog -g2005 -o CPU_tb_wave.vvp src/*.v testbench/test_010/CPU_tb_wave.v
vvp CPU_tb_wave.vvp

Open the generated waveform file with a waveform viewer such as GTKWave, Surfer, or another compatible tool.

Note: test_010 does not include an expected.txt file, so the automated test runner treats it as a waveform-oriented test rather than a standard output-comparison test.


Verification Coverage

The verification suite includes both module-level and CPU-level tests.

Test Target Purpose
test_001 Program Counter Reset, increment, load, hold, priority, wrap-around
test_002 Address MUX Address selection, parameter override, stability
test_003 ALU Opcode behavior, zero flag, arithmetic and logic operations
test_004 Controller FSM state transitions and control signal generation
test_005 Instruction Register Reset, load, hold, opcode and operand extraction
test_006 Accumulator Reset, load, hold, boundary values
test_007 Memory Read, write, high impedance, conflict prevention
test_008 CPU Integration Basic program: LDA, ADD, STO, HLT
test_009 CPU Integration Extended instruction-flow verification
test_010 CPU Waveform Waveform inspection and full instruction demonstration

Documentation

The report/ directory contains the LaTeX source and compiled PDF report for the project. The report describes the design approach, implementation details, simulation results, RTL schematics, and waveform captures.

Main report files:

report/riscReport.tex
report/riscReport.pdf
report/chapters/
report/figures/

Limitations

This processor is designed as an educational RTL project and intentionally remains compact. Current limitations include:

  • Small instruction set
  • 5-bit address space limited to 32 memory locations
  • Fixed multi-cycle execution sequence
  • No pipelining
  • No interrupt support
  • No general-purpose register file
  • No separate instruction and data memories

License

This project is released under the MIT License. See the LICENSE file for details.


"The best way to understand a processor is to build one."

About

A simple RISC processor designed in Verilog HDL, demonstrating fundamental CPU architecture concepts such as instruction execution, ALU operations, register files, memory access, and control logic.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages