The datapath is a 16-bit RTL datapath responsible for fetching instructions, decoding register fields, reading operands, performing ALU operations, generating status flags, and writing results back to the register file.
The current implementation uses a simple non-pipelined execution model.
The major datapath elements are:
- Program Counter
- Instruction Memory
- Instruction Decoder / Control Logic
- Register File
- ALU
- Status Flags
- Write-back path
flowchart TB
PC["Program Counter<br/>4-bit"]
IM["Instruction Memory<br/>16 × 16"]
ID["Instruction Decode<br/>16-bit Instruction"]
RF["Register File<br/>16 × 16<br/>16 registers × 16-bit"]
ALU["ALU<br/>16-bit"]
RESULT["ALU Result<br/>16-bit"]
FLAGS["Status Flags<br/>CF / ZF / NF / VF"]
WB["Write-back"]
PC -->|Address| IM
IM -->|Instruction| ID
ID -->|Register Fields| RF
ID -->|ALU / Control Signals| ALU
RF -->|RS1| ALU
RF -->|RS2| ALU
ALU -->|Result| RESULT
ALU -->|Update| FLAGS
RESULT --> WB
WB -->|Write RD| RF
ID -.->|PC Control<br/>JMP / Sequential| PC
The Program Counter (PC) identifies the current instruction address.
The current implementation uses a 4-bit PC:
PC width = 4 bits
This provides 16 instruction addresses:
0 → 15
Normal sequential execution follows:
PC_next = PC + 1
subject to control conditions.
The PC can also be affected by:
- RESET
- JMP
- HALT
- STALL / disabled execution
Instruction fetching begins with the Program Counter.
flowchart
p["PC"] --> I["Instruction Memory"]
I --> II["16-bit Instruction"]
The instruction memory currently contains 16 entries, each 16 bits wide.
Therefore:
Address width = 4 bits
Data width = 16 bits
Depth = 16
The fetched instruction is then supplied to the instruction decoding logic.
The 16-bit instruction is divided into four fields:
15 12 11 8 7 4 3 0
+---------------+----------------+---------------+---------------+
| OPCODE | RD | RS2 | RS1 |
+---------------+----------------+---------------+---------------+
The decoder extracts:
opcode
rd
rs2
rs1
The opcode determines the operation.
The register fields determine which registers participate in the operation.
The register file contains:
16 registers
16-bit register width
4-bit register addressing
The datapath provides two source operands.
flowchart LR
RS1["RS1 Address<br/>4-bit"]
RS2["RS2 Address<br/>4-bit"]
RD["RD Address<br/>4-bit"]
WD["Write Data<br/>16-bit"]
WE["Write Enable"]
RF["Register File<br/>16 × 16"]
A["Operand A<br/>16-bit"]
B["Operand B<br/>16-bit"]
RS1 -->|Read Address| RF
RS2 -->|Read Address| RF
RF -->|Read Data| A
RF -->|Read Data| B
RD -->|Write Address| RF
WD -->|Write Data| RF
WE -->|Write Enable| RF
The source read paths provide operands to the ALU.
The write-back path returns an ALU result to the selected destination register.
For two-operand ALU instructions, the datapath obtains:
Operand A = R[RS1]
Operand B = R[RS2]
These operands are provided to the ALU.
For operations requiring only one source operand, the unused operand does not affect the intended operation.
Examples:
ADD:
A = R[RS1]
B = R[RS2]
SUB:
A = R[RS1]
B = R[RS2]
AND:
A = R[RS1]
B = R[RS2]
NOT:
A = R[RS1]
MOV:
A = R[RS1]
The ALU is the main computational block of the datapath.
It operates on 16-bit operands and supports the currently implemented arithmetic, logical, shift, comparison, and movement operations.
flowchart TB
A["Operand A<br/>16-bit"]
B["Operand B<br/>16-bit"]
CTRL["ALU Control"]
ALU["ALU<br/>16-bit"]
RESULT["Result<br/>16-bit"]
FLAGS["Status Flags<br/>CF / ZF / NF / VF"]
A --> ALU
B --> ALU
CTRL --> ALU
ALU --> RESULT
ALU --> FLAGS
Supported operations:
ADD
SUB
AND
OR
XOR
NOT
SHL
SHR
SLT
EQ
MOV
The ALU produces a 16-bit result.
For an arithmetic instruction:
R[RD] ← ALU_RESULT
For example:
ADD R2, R0, R1
produces:
ALU_RESULT = R0 + R1
and:
R2 ← ALU_RESULT
The verification environment checks the result for boundary values, walking-bit patterns, random operands, and exhaustive register combinations.
The ALU generates four status flags:
CF
ZF
NF
VF
Used to represent the carry/no-borrow behavior defined by the current ALU implementation.
Indicates a zero result:
ALU_RESULT == 16'h0000
Reflects the most significant bit of the result:
NF = ALU_RESULT[15]
Indicates signed arithmetic overflow for supported arithmetic operations.
The verification environment explicitly tests ADD and SUB overflow conditions.
Instructions that produce register results use the write-back path.
flowchart TB
ALU["ALU<br/>16-bit"]
WB["Write-back"]
RF["Register File<br/>16 × 16"]
RD["R[RD]"]
ALU -->|Result| WB
WB -->|Write Data| RF
RF -->|Updated Register| RD
The destination register is selected using the RD instruction field.
The control logic determines whether the current instruction is allowed to write a result.
Not every instruction performs a register write.
ADD
SUB
AND
OR
XOR
NOT
SHL
SHR
SLT
EQ
MOV
NOP
JMP
HALT
RESERVED
The verification environment explicitly checks that control-flow and no-operation instructions do not perform unintended writes.
Control-flow instructions modify the normal PC path.
Normal execution:
PC
|
v
PC + 1
|
v
Next instruction
JMP:
PC
|
v
JMP target
|
v
Target PC
HALT:
PC
|
v
HALT
|
v
PC remains frozen
RESET initializes the processor state.
The verified reset behavior includes:
PC → 0
Flags → 0
RESET also prevents the instruction currently being processed from performing an unintended write-back.
This behavior is explicitly checked by assertion A7.
The current processor includes an execution enable/stall mechanism.
When execution is disabled:
PC → Hold
Registers → Hold
Flags → Hold
Conceptually:
EN = 1
|
v
+----------------+
| Normal Execute |
+----------------+
EN = 0
|
v
+----------------+
| STALL |
| Hold State |
+----------------+
The verification environment tests multiple consecutive stall cycles, alternating enable states, and stalls around control-flow instructions.
NOP does not modify the register file or status flags.
The datapath effectively becomes:
Instruction
|
v
NOP
|
+----> No register write
|
+----> No flag update
|
v
Normal PC progression
HALT prevents normal execution from progressing.
When HALT is reached:
PC → Hold
Registers → Hold
Flags → Hold
The verification environment checks HALT with both enabled and disabled execution.
JMP replaces normal sequential PC progression with the jump target.
+----------------+
| PC |
+-------+--------+
|
v
Instruction
|
v
JMP
|
v
Jump Target
|
v
PC
The verification environment covers:
- Forward jumps
- Backward jumps
- Jump to address zero
- Self-loop
- Jump chains
- All valid jump targets
The complete datapath can be summarized as:
flowchart TB
PC["Program Counter<br/>4-bit"]
IM["Instruction Memory<br/>16 × 16"]
DEC["Instruction Decoder"]
RF["Register File<br/>16 × 16"]
OA["Operand A<br/>16-bit"]
OB["Operand B<br/>16-bit"]
ALU["ALU<br/>16-bit"]
RESULT["Result<br/>16-bit"]
FLAGS["Flags<br/>CF / ZF / NF / VF"]
WB["Register Writeback"]
PC -->|Address| IM
IM -->|Instruction| DEC
DEC -->|Control Signals| ALU
DEC -->|Register Fields| RF
RF -->|Operand A| OA
RF -->|Operand B| OB
OA --> ALU
OB --> ALU
ALU -->|Result| RESULT
ALU -->|Status| FLAGS
RESULT --> WB
WB -->|Write Data / RD| RF
The main architectural state elements are:
Program Counter
Register File
Status Flags
Halt State / Control State
The verification environment checks that these state elements change only when permitted by the current instruction and control inputs.
The current datapath has been tested using multiple verification methods.
Boundary values
Logic patterns
Walking-1 patterns
Walking-0 patterns
Shift amounts 0–15
Random ALU vectors
All 16 destination registers
All 16 source registers
All 256 source-register pairs
Multiple data patterns
Write-enable behavior
Asynchronous read behavior
Sequential execution
JMP
NOP
HALT
RESET
STALL
Reserved opcodes
Random programs
Total checks : 1,087,551
Passed : 1,087,551
Failed : 0
Instruction coverage:
14 / 14 = 100%
Functional coverage:
112 / 112 = 100%
X/Z checks:
51,966
Failures:
0
The current datapath provides a complete verified 16-bit execution path consisting of:
16-bit instruction
↓
Instruction decode
↓
16-bit register operands
↓
16-bit ALU
↓
16-bit result
↓
Register write-back
with associated:
Program Counter
Control Flow
Status Flags
RESET
STALL
HALT
The current implementation is intentionally simple and provides a stable RTL baseline for future processor enhancements.
Potential future datapath extensions include:
- Immediate operand paths
- Load/store datapath
- Larger memory interface
- Branch comparison hardware
- Pipeline registers
- Forwarding paths
- Hazard detection
- Multi-stage execution
- Interrupt/exception datapath