A modular, educational RV32I RISC-V processor core implemented in VHDL for FPGA synthesis and simulation. Designed for learning computer architecture fundamentals with clean, parameterized RTL and comprehensive testbenches.
- Overview
- Features
- Architecture
- Project Structure
- Supported Instructions
- Getting Started
- Module Descriptions
- Simulation
- Technical Specifications
- Author
This project implements a single-cycle, non-pipelined RISC-V processor based on the RV32I base integer instruction set. The design prioritizes clarity and modularity over performance, making it ideal for:
- Educational purposes: Learning processor design and RISC-V ISA
- FPGA prototyping: Synthesizable for Xilinx FPGAs
- Architecture exploration: Easily extendable to pipelined versions
- Digital design coursework: Comprehensive testbenches included
Key Characteristics:
- 32-bit datapath with parameterized word width
- Harvard architecture (separate instruction and data memories)
- Memory-mapped I/O support ready
- External memory initialization via
.memfiles - Full Vivado project for one-click synthesis and simulation
- Complete RV32I Base ISA Subset: Arithmetic, logical, load/store, branch, and jump instructions
- 32 General-Purpose Registers: 32×32-bit register file with dual read ports
- Flexible Memory System: Parameterized instruction and data memories with file initialization
- Modular Design: 23 synthesizable VHDL modules with clear separation of concerns
- Comprehensive Verification: 17 dedicated testbenches for component-level testing
- Parameterized Components: Generic word width (W), memory depth, and address width
- VHDL Best Practices: Synchronous design, proper reset handling, type safety
- Educational Focus: Readable code over optimization, extensive comments
- FPGA-Ready: Synthesizable on Xilinx 7-series and later devices
┌──────────────────────────────────────────────────────────────┐
│ RV32I Processor Core │
└───────────────────────┬──────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ Control │ │ Datapath │ │ Memory │
│ Unit │ │ │ │ Subsystem│
└────┬────┘ └────┬─────┘ └────┬─────┘
│ │ │
┌────▼────────────────▼───────────────────▼──────┐
│ │
│ ┌──────────┐ ┌─────┐ ┌──────────────┐ │
│ │Controller│ │ ALU │ │Register File │ │
│ │ │ │ │ │ (32×32-bit) │ │
│ └──────────┘ └─────┘ └──────────────┘ │
│ │
│ ┌────────┐ ┌──────────┐ ┌──────────┐ │
│ │ PC │ │Instruction│ │ Data │ │
│ │ │ │ Memory │ │ Memory │ │
│ └────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Glue Logic (Muxes, Decoders, etc.) │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
Single-Cycle Architecture:
Clock Cycle N:
1. Fetch instruction from memory[PC]
2. Decode instruction → generate control signals
3. Read registers (if needed)
4. Execute ALU operation / compute address
5. Access data memory (load/store)
6. Write back to register file
7. Update PC (sequential or branch target)
Clock Cycle N+1: Repeat
No pipelining - Each instruction completes in one clock cycle.
Risc-V/
├── README.md # This file
├── .git/ # Version control
│
└── RISC-V/ # Vivado project root
├── RISC-V.xpr # Vivado project file
│
├── RISC-V.srcs/
│ ├── sources_1/new/ # RTL source files (23 VHDL modules)
│ │ ├── Controller.vhd # Instruction decoder & control unit
│ │ ├── ALU.vhd # Arithmetic logic unit
│ │ ├── Register_File.vhd # 32×32-bit register file
│ │ ├── Program_Counter.vhd # PC register
│ │ ├── Instruction_Memory.vhd # ROM for program storage
│ │ ├── Data_Memory.vhd # RAM for data storage
│ │ ├── DRAM.vhd # Generic memory primitive
│ │ ├── Extend_Immediate.vhd # Immediate sign extender
│ │ ├── Adder.vhd # 32-bit adder
│ │ ├── Register_*.vhd # Register variants (2 files)
│ │ ├── Mux_*.vhd # Multiplexers (4 files)
│ │ ├── Decoder_*.vhd # Decoders (3 files)
│ │ └── *.mem # Memory initialization files (4 files)
│ │
│ └── sim_1/new/ # Testbenches (17 VHDL files)
│ ├── TB_ALU.vhd
│ ├── TB_Controller.vhd
│ ├── TB_Register_File.vhd
│ ├── TB_Data_Memory.vhd
│ └── ... (13 more testbenches)
│
├── RISC-V.sim/ # Simulation artifacts
│ └── sim_1/behav/xsim/ # Vivado simulator scripts
│
├── RISC-V.runs/ # Synthesis/implementation runs
│ ├── synth_1/ # Synthesis outputs
│ └── impl_1/ # Implementation outputs
│
└── RISC-V.gen/ # Generated files
| Category | Count | Total Lines |
|---|---|---|
| RTL Modules | 23 | ~1,061 |
| Testbenches | 17 | ~850 |
| Memory Files | 4 | - |
The processor implements a functional subset of RV32I sufficient for basic programs:
ADD, SUB, AND, OR, XOR, SLL, SRL, SRA, SLT, SLTU
ADDI, SLTI, SLTIU, ANDI, ORI, XORI, SLLI, SRLI, SRAI
LW, LHU, LBU, JALR
SW, SH, SB
BEQ, BNE, BLT, BGE, BLTU, BGEU
LUI, AUIPC
JAL
R-Type:
┌───────┬────┬────┬───────┬────┬───────┐
│ funct7│ rs2│ rs1│ funct3│ rd │ opcode│
│ [6:0] │[4:0]│[4:0]│ [2:0] │[4:0]│ [6:0] │
└───────┴────┴────┴───────┴────┴───────┘
31:25 24:20 19:15 14:12 11:7 6:0
I-Type:
┌──────────────┬────┬───────┬────┬───────┐
│ imm[11:0] │ rs1│ funct3│ rd │ opcode│
│ [11:0] │[4:0]│ [2:0] │[4:0]│ [6:0] │
└──────────────┴────┴───────┴────┴───────┘
31:20 19:15 14:12 11:7 6:0
S-Type:
┌───────┬────┬────┬───────┬───────┬───────┐
│imm[11:5]│rs2│ rs1│ funct3│imm[4:0]│opcode│
└───────┴────┴────┴───────┴───────┴───────┘
31:25 24:20 19:15 14:12 11:7 6:0
Software:
- Xilinx Vivado: 2020.1 or later (tested up to 2023.2)
- Download: https://www.xilinx.com/support/download.html
- Free WebPACK edition is sufficient
- Operating System: Windows 10/11, Linux (RHEL/CentOS/Ubuntu)
Hardware (for FPGA deployment):
- Xilinx FPGA board (7-series or later)
- Examples: Basys 3, Arty A7, Nexys A7
# Clone repository
git clone <repository-url>
cd Risc-V
# Launch Vivado
vivado RISC-V/RISC-V.xpr-
Select Testbench:
- In Sources pane → Simulation Sources
- Choose a testbench (e.g.,
TB_ALU)
-
Run Behavioral Simulation:
- Flow Navigator → Simulation → Run Simulation → Run Behavioral Simulation
- Or click the simulation icon in toolbar
-
Observe Waveforms:
- Waveform window shows signal values
- Console displays assertion messages
-
Run Synthesis:
- Flow Navigator → Synthesis → Run Synthesis
- Wait for completion (~2-5 minutes)
-
Run Implementation:
- Flow Navigator → Implementation → Run Implementation
- Generates bitstream for FPGA programming
-
View Utilization:
- Reports → Utilization Report
- Check LUT/FF/BRAM usage
# Run specific testbench in batch mode
vivado -mode batch -source RISC-V/RISC-V.sim/sim_1/behav/xsim/TB_ALU.tcl
# Synthesize via TCL
vivado -mode batch -source synth_script.tcl- Purpose: Instruction decoder and control signal generator
- Inputs: 32-bit instruction word
- Outputs: Control signals for all datapath components
- Functionality:
- Decodes opcode (bits [6:0])
- Decodes funct3 (bits [14:12]) and funct7 (bits [31:25])
- Generates: ALU operation, register write enable, memory read/write, branch/jump control
- Supports all R/I/S/B/U/J instruction formats
Key Control Signals:
ALUSrc : Select ALU input (register or immediate)
MemtoReg : Select writeback source (ALU or memory)
RegWrite : Register file write enable
MemRead : Data memory read enable
MemWrite : Data memory write enable
Branch : Branch instruction flag
ALUOp : ALU operation selector- Operations: 10 functions
0: ADD (addition) 1: SUB (subtraction) 2: AND (bitwise AND) 3: OR (bitwise OR) 4: XOR (bitwise XOR) 5: SLL (shift left logical) 6: SRL (shift right logical) 7: SRA (shift right arithmetic) 8: SLT (set less than - signed) 9: SLTU (set less than - unsigned) - Inputs: Two 32-bit operands, 4-bit operation selector
- Outputs: 32-bit result, zero flag
- Features: Parameterized width via generic
W
- Structure: 32 registers (R0-R31)
- Ports:
- 2 read ports (simultaneous access)
- 1 write port (synchronous)
- Special Behavior:
- R0 is hardwired to zero (handled externally)
- Write occurs on rising clock edge when write_enable='1'
- Implementation: Uses VHDL GENERATE to instantiate 32 individual registers
- Function: Stores current instruction address
- Features:
- Synchronous update on rising clock edge
- Asynchronous reset to address 0
- Input from PC adder or branch target
- Parameterized:
RAM_DEPTH: Number of words (default 128)RAM_WIDTH: Bits per word (default 32)ADDR_WIDTH: Address bus width (default 7)MEMORY_FILE: Initialization file path
- Initialization: Loads from
.memfile using VHDL TEXTIO - Format: One 32-bit binary word per line
00010001001000100011001101000100 00100010001000100011001101000100 ...
- Type: Read-only memory (ROM-style)
- Implementation: Instantiates DRAM with write_enable='0'
- Usage: Stores program instructions
- File:
instruction_mem_init_file.mem
- Type: Read-write memory (RAM)
- Implementation: Instantiates DRAM with synchronous write
- Usage: Runtime data storage
- File:
data_mem_init_file.mem
- Function: Sign-extends immediate values
- Supports: I-type (12-bit), S-type (12-bit), B-type (13-bit), U-type (20-bit), J-type (21-bit)
- Algorithm: Replicates sign bit to fill 32 bits
- Type: Combinational 32-bit adder
- Usage: PC increment, branch target calculation
Mux_2to1.vhd: 2-input mux (generic width)Mux_4to1.vhd: 4-input muxMux_16to1.vhd: 16-input muxMux_32to1.vhd: 32-input mux (121 lines - for register file read)
Decoder_2to4.vhd: 2-bit to 4-bit one-hotDecoder_4to16.vhd: 4-bit to 16-bit one-hotDecoder_5to32.vhd: 5-bit to 32-bit one-hot (register write address)
All 17 testbenches located in RISC-V/RISC-V.srcs/sim_1/new/:
| Testbench | Component Under Test | Purpose |
|---|---|---|
TB_ALU.vhd |
ALU | Arithmetic/logic operations |
TB_Controller.vhd |
Controller | Instruction decoding |
TB_Register_File.vhd |
Register File | Register read/write |
TB_Program_Counter.vhd |
Program Counter | PC update logic |
TB_Instruction_Memory.vhd |
Instruction Memory | Program fetch |
TB_Data_Memory.vhd |
Data Memory | Load/store operations |
TB_DRAM.vhd |
DRAM | Generic memory primitive |
TB_Extend_Immediate.vhd |
Immediate Extender | Sign extension |
TB_Adder.vhd |
Adder | 32-bit addition |
TB_Register_Simple.vhd |
Simple Register | Basic register |
TB_Register_Write_Enable.vhd |
WE Register | Conditional write |
TB_Mux_2to1.vhd |
2:1 Mux | Multiplexer |
TB_Mux_4to1.vhd |
4:1 Mux | Multiplexer |
TB_Mux_16to1.vhd |
16:1 Mux | Multiplexer |
TB_Decoder_2to4.vhd |
2:4 Decoder | Decoder |
TB_Decoder_4to16.vhd |
4:16 Decoder | Decoder |
TB_Decoder_5to32.vhd |
5:32 Decoder | Decoder |
TB_ALU.vhd tests arithmetic operations:
-- Test vector: 0x12341234 + 0x43214321 = 0x55555555
in_A <= x"12341234";
in_B <= x"43214321";
alu_operation <= "0000"; -- ADD
wait for 10 ns;
assert (out_result = x"55555555")
report "ADD operation failed!"
severity error;Expected Output:
Time: 10 ns Iteration: 1 Instance: /tb_alu
Info: ALU ADD test passed
Time: 20 ns Iteration: 1 Instance: /tb_alu
Info: ALU SUB test passed
...
- After simulation starts, Vivado opens waveform viewer
- Add signals: Scope → tb_alu → Add to Wave Window
- Zoom: Fit, Zoom In/Out buttons
- Cursors: Click on waveform to measure timing
| Parameter | Value |
|---|---|
| ISA | RISC-V RV32I (base integer) |
| Word Size | 32 bits (parameterized) |
| Registers | 32 × 32-bit general purpose |
| Architecture | Single-cycle, non-pipelined |
| Memory Organization | Harvard (separate I-mem, D-mem) |
| Default I-Mem Size | 128 words (512 bytes) |
| Default D-Mem Size | 128 words (512 bytes) |
| Clock Domains | Single clock, synchronous design |
| Reset | Asynchronous active-high |
Note: Actual synthesis has not been completed for this design. The following are typical estimates for similar RV32I cores on Xilinx 7-series FPGAs. Your actual results will vary based on:
- Memory size configuration (default: 128 words I-mem + D-mem)
- FPGA family and speed grade
- Synthesis settings and optimizations
- Timing constraints
Expected Resource Usage (Xilinx Artix-7 XC7A35T):
| Resource | Estimated Range | Available | Notes |
|---|---|---|---|
| LUTs | 500-1500 | 20,800 | Depends on ALU implementation |
| Flip-Flops | 300-600 | 41,600 | Registers + control logic |
| BRAM | 2-8 blocks | 50 | Based on memory size |
| Max Frequency | 50-150 MHz | - | Depends on timing closure |
To get actual data, run synthesis in Vivado:
- Flow Navigator → Synthesis → Run Synthesis
- Open Synthesized Design → Reports → Utilization Report
- Implementation → Reports → Timing Summary
| Metric | Value |
|---|---|
| CPI (Cycles Per Instruction) | 1.0 (single-cycle design) |
| Theoretical Performance | Frequency × 1 instruction/cycle |
| Memory Latency | 1 clock cycle (synchronous) |
| Pipeline Depth | None (single-cycle) |
Memory files use binary text format (one 32-bit word per line):
Example: instruction_mem_init_file.mem
00000000000000000000000000000000 // NOP (or ADD x0, x0, x0)
00000000001000001000000010010011 // ADDI x1, x1, 2
00000000001000010000000100110011 // ADD x2, x2, x2
...
-
Write Assembly Code:
ADDI x1, x0, 5 # x1 = 5 ADDI x2, x0, 10 # x2 = 10 ADD x3, x1, x2 # x3 = x1 + x2 = 15 SW x3, 0(x0) # Store to memory[0]
-
Assemble to Binary:
- Use RISC-V assembler (e.g.,
riscv32-unknown-elf-as) - Convert to 32-bit binary format
- Use RISC-V assembler (e.g.,
-
Create
.memFile:00000000010100000000000010010011 00000000101000000000000100010011 00000000001000001000000110110011 00000000001100000010000000100011 -
Update Memory File Path:
-- In Instruction_Memory.vhd or DRAM instantiation MEMORY_FILE => "instruction_mem_init_file.mem"
-
Re-run Simulation
The following features are intentionally omitted to keep the design simple:
- Pipelining: No IF/ID/EX/MEM/WB stages
- Hazard Handling: No forwarding, stalls, or branch prediction
- CSRs: No Control and Status Registers
- Interrupts/Exceptions: No trap handling
- Privileged Modes: No M/S/U modes
- Memory Protection: No MMU or PMP
- Floating Point: No F/D extensions
- Multiplication/Division: No M extension
- Atomic Operations: No A extension
- Compressed Instructions: No C extension
- R0 Write Protection: Must be enforced externally
- Memory Size: Limited by FPGA BRAM availability
- Timing: May not meet timing at high frequencies without optimization
Potential extensions for advanced learning:
- 5-Stage Pipeline: Add IF, ID, EX, MEM, WB stages
- Hazard Detection: Data forwarding, stall logic
- Branch Prediction: Static or dynamic predictors
- M Extension: Hardware multiplier/divider
- CSR Support: System registers and instructions
- Interrupt Controller: External interrupt handling
- Cache Hierarchy: I-cache, D-cache
- UART Interface: Serial communication for I/O
- Debugger Support: JTAG, breakpoints
Contributions are welcome! Please follow these guidelines:
- File Issues: Report bugs or suggest features via issue tracker
- Pull Requests:
- Keep changes focused and atomic
- Include/update testbenches for modified modules
- Maintain VHDL coding style consistency
- Add comments for complex logic
- Testing: Ensure all testbenches pass before submitting
- Documentation: Update README for significant changes
- Indentation: 2 or 4 spaces (consistent)
- Naming:
- Signals:
snake_caseorcamelCase - Generics:
UPPERCASE - Components:
PascalCase
- Signals:
- Comments: Explain "why", not "what"
- Generics: Prefer parameterization over hardcoding
This project is licensed under the MIT License - see LICENSE file for details.
Copyright (c) 2024 Mehmet Arslan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software...
Mehmet Arslan
Hardware design engineer specializing in digital logic design, processor architecture, and FPGA development.
Technical Skills Demonstrated:
- RISC-V ISA implementation
- RTL design in VHDL
- FPGA synthesis and timing closure
- Modular hardware architecture
- Testbench development and verification
- Xilinx Vivado toolchain
- Computer architecture fundamentals
GitHub: @htmos6
- RISC-V Foundation: For the open RISC-V ISA specification
- Xilinx: For Vivado Design Suite and documentation
- Digital Design Resources:
- "Computer Organization and Design: RISC-V Edition" by Patterson & Hennessy
- RISC-V community tutorials and implementations
- Educational Institutions: For fostering open-source hardware education
- RISC-V ISA Specification
- RISC-V Assembly Programmer's Manual
- RISC-V Green Card - Quick reference
- RISC-V GNU Toolchain: https://github.com/riscv/riscv-gnu-toolchain
- RISC-V Online Assembler: https://riscvasm.lucasteske.dev/
- Vivado WebPACK (Free): https://www.xilinx.com/products/design-tools/vivado/vivado-webpack.html
Last Updated: January 2026 Version: 1.0 Project Status: Active Development