A complete single-cycle processor implementation in Verilog HDL based on the LEGv8 architecture (a simplified ARM-like instruction set). This project implements the fundamental datapath components of a 64-bit RISC processor, suitable for educational purposes and FPGA synthesis.
- Overview
- Architecture
- Module Descriptions
- Supported Instructions
- Instruction Format
- Control Signals
- Getting Started
- Simulation
- Project Structure
- License
This project implements a single-cycle datapath for the LEGv8 architecture, which is a 64-bit instruction set architecture used for educational purposes. The processor executes each instruction in a single clock cycle, making it simpler to understand compared to pipelined implementations.
- 64-bit data path with 32 general-purpose registers
- 32-bit fixed-width instructions following LEGv8 format
- Support for R-type, D-type, and CB-type instructions
- Fully synthesizable Verilog code targeting Intel Cyclone V FPGA
- Modular design with clear separation of concerns
File: datapath.v
The top-level module that integrates all components of the processor. It instantiates and connects:
- Program Counter
- Instruction Memory
- Register File
- ALU and ALU Control
- Main Control Unit
- Data Memory
- Sign Extender
- Various multiplexers and adders
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
clock |
Input | 1 | System clock |
reset |
Input | 1 | Asynchronous reset |
File: program_counter.v
A 64-bit register that holds the address of the current instruction being executed.
Features:
- Asynchronous reset to address 0
- Updates on positive clock edge
- Supports sequential execution (PC+4) and branch targets
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
AddressIn |
Input | 64 | Next PC value |
CLK |
Input | 1 | Clock signal |
Reset |
Input | 1 | Reset signal |
AddressOut |
Output | 64 | Current PC value |
File: instruction_memory.v
A read-only memory module that stores the program instructions.
Features:
- 1024 words × 32 bits capacity
- Word-aligned addressing (ignores 2 LSBs)
- Loads instructions from
instruction.memfile on initialization
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
ReadAddress |
Input | 64 | PC address |
Instruction |
Output | 32 | Fetched instruction |
File: Registers.v
A bank of 32 general-purpose 64-bit registers implementing the LEGv8 register model.
Features:
- 32 registers × 64 bits each
- Two simultaneous read ports
- One write port (synchronous, positive edge)
- Register X31 (XZR) is hardwired to zero
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
ReadRegister1 |
Input | 5 | First read register address |
ReadRegister2 |
Input | 5 | Second read register address |
WriteRegister |
Input | 5 | Write register address |
WriteData |
Input | 64 | Data to write |
RegWrite |
Input | 1 | Write enable |
CLK |
Input | 1 | Clock signal |
ReadData1 |
Output | 64 | First read data |
ReadData2 |
Output | 64 | Second read data |
File: alu.v
A 64-bit ALU that performs arithmetic and logical operations.
Supported Operations:
| ALUControl | Operation | Description |
|---|---|---|
0000 |
AND | Bitwise AND |
0001 |
OR | Bitwise OR |
0010 |
ADD | Addition |
0110 |
SUB | Subtraction |
0111 |
Pass B | Pass input B through |
1100 |
NOR | Bitwise NOR |
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
a |
Input | 64 | First operand |
b |
Input | 64 | Second operand |
ALUControl |
Input | 4 | Operation select |
result |
Output | 64 | Operation result |
zero |
Output | 1 | Zero flag (result == 0) |
Additional Components in alu.v:
- Adder: Simple 64-bit adder for PC+4 and branch calculations
- Shift Left 2: Shifts input left by 2 bits for branch offset calculation
File: alu_control.v
Generates the ALU control signal based on the ALUOp from the main control and the instruction opcode.
Control Logic:
| ALUOp | Instruction Type | ALU Action |
|---|---|---|
00 |
Load/Store | Add (address calculation) |
01 |
CBZ | Pass B (for zero comparison) |
10 |
R-type | Decode from opcode |
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
ALUOp |
Input | 2 | Operation type from main control |
Opcode |
Input | 11 | Instruction opcode field |
ALUControl |
Output | 4 | ALU operation select |
File: main_control.v
The central control unit that decodes instructions and generates control signals for the entire datapath.
Supported Instructions:
| Opcode | Instruction | Description |
|---|---|---|
11111000010 |
LDUR | Load Register (Unscaled) |
11111000000 |
STUR | Store Register (Unscaled) |
10110100xxx |
CBZ | Compare and Branch if Zero |
10001011000 |
ADD | Add |
11001011000 |
SUB | Subtract |
10001010000 |
AND | Bitwise AND |
10101010000 |
ORR | Bitwise OR |
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
Opcode |
Input | 11 | Instruction opcode |
Reg2Loc |
Output | 1 | Register 2 source select |
ALUSrc |
Output | 1 | ALU source B select |
MemtoReg |
Output | 1 | Write data source select |
RegWrite |
Output | 1 | Register write enable |
MemRead |
Output | 1 | Memory read enable |
MemWrite |
Output | 1 | Memory write enable |
Branch |
Output | 1 | Conditional branch |
UncondBranch |
Output | 1 | Unconditional branch |
ALUOp |
Output | 2 | ALU operation type |
File: data_memory.v
A read/write memory for storing and loading data during program execution.
Features:
- 1024 words × 64 bits capacity
- Synchronous write (positive edge)
- Asynchronous read
- Double-word aligned addressing
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
Address |
Input | 64 | Memory address |
WriteData |
Input | 64 | Data to write |
MemRead |
Input | 1 | Read enable |
MemWrite |
Input | 1 | Write enable |
CLK |
Input | 1 | Clock signal |
ReadData |
Output | 64 | Data read from memory |
File: sign_extender.v
Extends immediate values from different instruction formats to 64 bits.
Supported Formats:
| Instruction Type | Immediate Size | Extension |
|---|---|---|
| LDUR/STUR | 9-bit | Sign-extend to 64-bit |
| CBZ | 19-bit | Sign-extend to 64-bit |
| Default | 32-bit | Sign-extend to 64-bit |
Ports:
| Port | Direction | Width | Description |
|---|---|---|---|
Instruction |
Input | 33 | Instruction bits |
Extended |
Output | 64 | Sign-extended immediate |
File: mux.v
Generic multiplexer modules for data selection.
Available Modules:
mux2- 2-to-1 multiplexer (1-bit)mux3- 3-to-1 multiplexer (1-bit)mux4- 4-to-1 multiplexer (1-bit)
| Instruction | Format | Opcode | Operation |
|---|---|---|---|
| ADD | R-type | 10001011000 |
Rd = Rn + Rm |
| SUB | R-type | 11001011000 |
Rd = Rn - Rm |
| AND | R-type | 10001010000 |
Rd = Rn & Rm |
| ORR | R-type | 10101010000 |
Rd = Rn | Rm |
| LDUR | D-type | 11111000010 |
Rd = Memory[Rn + offset] |
| STUR | D-type | 11111000000 |
Memory[Rn + offset] = Rt |
| CBZ | CB-type | 10110100xxx |
if (Rt == 0) PC = PC + offset |
| 31-21 (11) | 20-16 (5) | 15-10 (6) | 9-5 (5) | 4-0 (5) |
| Opcode | Rm | Shamt | Rn | Rd |
| 31-21 (11) | 20-12 (9) | 11-10 (2) | 9-5 (5) | 4-0 (5) |
| Opcode | Address | Op2 | Rn | Rt |
| 31-24 (8) | 23-5 (19) | 4-0 (5) |
| Opcode | BR_Address | Rt |
| Instruction | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUOp |
|---|---|---|---|---|---|---|---|---|
| ADD/SUB/AND/ORR | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 10 |
| LDUR | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 00 |
| STUR | 1 | 1 | X | 0 | 0 | 1 | 0 | 00 |
| CBZ | 1 | 0 | X | 0 | 0 | 0 | 1 | 01 |
- Intel Quartus Prime (Lite or Standard Edition)
- ModelSim or Questa for simulation
- Basic understanding of Verilog HDL
-
Clone the repository:
git clone https://github.com/arian-fallahpour/verilog-hdl-datapath.git cd verilog-hdl-datapath -
Open the project in Quartus:
- Open Intel Quartus Prime
- File → Open Project → Select
cpu.qpf
-
Compile the project:
- Processing → Start Compilation
Edit the instruction.mem file to load your program:
// Example: ADD X1, X2, X3
10001011000000110000000001000001
// Example: LDUR X4, [X21, #0]
11111000010000000000101010100100
Each line represents a 32-bit instruction in binary format.
- In Quartus: Tools → Run Simulation Tool → RTL Simulation
- Add signals to the waveform viewer
- Run simulation with appropriate clock period
Create a testbench to verify functionality:
`timescale 1ns/1ps
module datapath_tb;
reg clock, reset;
datapath uut (
.clock(clock),
.reset(reset)
);
// Clock generation
always #5 clock = ~clock;
initial begin
clock = 0;
reset = 1;
#10 reset = 0;
#100 $finish;
end
endmoduleverilog-hdl-datapath/
│
├── datapath.v # Top-level datapath module
├── program_counter.v # Program Counter
├── instruction_memory.v # Instruction Memory (ROM)
├── Registers.v # Register File (32 × 64-bit)
├── alu.v # ALU, Adder, Shift Left 2
├── alu_control.v # ALU Control Unit
├── main_control.v # Main Control Unit
├── data_memory.v # Data Memory (RAM)
├── sign_extender.v # Sign Extension Unit
├── mux.v # Multiplexer modules
├── test_mux.v # MUX testbench
│
├── instruction.mem # Program instructions
├── cpu.qpf # Quartus Project File
├── cpu.qsf # Quartus Settings File
│
├── db/ # Quartus database files
├── incremental_db/ # Incremental compilation files
├── output_files/ # Compilation output
├── simulation/ # Simulation files
├── screenshots/ # Documentation images
│
└── README.md # This file
- Add pipelining (5-stage: IF, ID, EX, MEM, WB)
- Implement hazard detection and forwarding
- Add support for more instructions (B, BL, BR, etc.)
- Implement a cache hierarchy
- Add interrupt handling
- Patterson, D. A., & Hennessy, J. L. (2016). Computer Organization and Design: ARM Edition. Morgan Kaufmann.
- LEGv8 Reference Card
- Intel Quartus Prime Documentation
This project is open source and available for educational purposes.
Arian Fallahpour
- GitHub: @arian-fallahpour
- Course instructors and teaching assistants
- Open-source Verilog community
- Intel FPGA Academic Program