It is verified using a self-checking Verilog testbench designed to validate the processor at both block and CPU levels.
The verification environment combines:
- Directed testing
- ALU corner-case testing
- Register-file testing
- Control-flow testing
- Reset testing
- Stall testing
- Randomized ALU testing
- Randomized program testing
- Assertion-based checking
- X/Z-state detection
- Instruction coverage
- Functional coverage
The current regression completed successfully with:
Total checks : 1,087,551
Passed : 1,087,551
Failed : 0
The verification environment is designed to verify:
- Correct ALU functionality.
- Correct arithmetic flag generation.
- Correct register-file behavior.
- Correct instruction decoding and execution.
- Correct Program Counter behavior.
- Correct JMP behavior.
- Correct NOP behavior.
- Correct HALT behavior.
- Correct RESET behavior.
- Correct STALL/enable behavior.
- Safe handling of reserved opcodes.
- Correct behavior across register combinations.
- Correct behavior under randomized workloads.
- Absence of unexpected X/Z values.
- Compliance with architectural expectations through assertions.
The verification flow can be represented as:
flowchart TB
TB["Testbench"]
DT["Directed Tests"]
RT["Random Tests"]
DUT["DUT<br/>Device Under Test"]
ALU["ALU"]
RF["Register File"]
CTRL["CPU Control"]
MODEL["Self-Checking Model"]
REPORT["PASS / FAIL Report"]
TB --> DT
TB --> RT
DT --> DUT
RT --> DUT
DUT --> ALU
DUT --> RF
DUT --> CTRL
ALU --> MODEL
RF --> MODEL
CTRL --> MODEL
MODEL --> REPORT
The testbench automatically compares expected behavior against actual DUT behavior.
The regression contains 41 directed tests.
Directed tests:
41 / 41 PASS
Directed tests are used for deterministic verification of important architectural behaviors.
The directed test groups include:
ALU corner cases
Register file
Default program
Program Counter
JMP
NOP
HALT
STALL
RESET
Reserved opcodes
Register combinations
The ALU is tested independently with a large set of deterministic and randomized vectors.
The verification environment tests boundary and representative 16-bit values, including:
0000
FFFF
AAAA
5555
8000
0001
These values exercise:
- Zero results
- Maximum unsigned values
- Alternating bit patterns
- Sign-bit behavior
- Single-bit behavior
The implemented ALU operations are tested:
ADD
SUB
AND
OR
XOR
NOT
SHL
SHR
SLT
EQ
MOV
Walking-1 patterns are applied to both ALU operands.
This exercises individual bit positions across the 16-bit datapath.
Walking-0 patterns are also applied to both operands.
This provides complementary bit-level coverage.
All shift amounts from 0 through 15 are tested.
SHL:
0–15 → 16 / 16 covered
SHR:
0–15 → 16 / 16 covered
The verification environment also confirms that upper unused shift-operand bits do not alter the intended shift amount.
The ALU status flags are explicitly verified.
The current processor uses:
CF — Carry
ZF — Zero
NF — Negative
VF — Overflow
The following conditions are tested:
Carry
Borrow
Zero
Negative
Overflow
ADD carry-out cases are explicitly generated and checked.
Regression result:
ADD carry cases : HIT
SUB cases where the first operand is smaller than the second are tested.
Regression result:
SUB borrow cases : HIT
Zero-result conditions are tested across ALU operations.
Regression result:
Zero result : HIT
Negative-result cases are explicitly covered.
Regression result:
Negative result : HIT
Signed overflow is tested for both:
ADD
SUB
Regression result:
ADD overflow : HIT
SUB overflow : HIT
The register file is tested independently.
The testbench verifies all 16 registers:
R0–R15
Verification includes:
Individual register writes
Write-enable behavior
Both read ports
Register combinations
Data patterns
Read-before-write behavior
Every register is written individually:
R0
R1
...
R15
The test confirms that writing one register does not unintentionally modify another.
Result:
RF: write R0..R15 individually, no collateral
PASS
The testbench verifies that:
we = 0
does not modify register contents.
Result:
RF: we=0 must not write
PASS
All 256 combinations of the two 4-bit register addresses are tested:
16 × 16 = 256
Result:
RF: both read ports, all 256 (a,b) pairs
PASS
The following patterns are applied:
0000
FFFF
AAAA
5555
The results are verified for every register.
The CPU-level testbench verifies the complete processor rather than individual blocks.
The following architectural behaviors are covered:
Sequential execution
JMP
NOP
HALT
STALL
RESET
Reserved opcodes
The Program Counter is tested under multiple execution conditions.
The testbench verifies:
0 → 1 → 2 → ... → 15
The testbench verifies:
15 → 0
The testbench verifies:
Forward jumps
Backward jumps
Jump to address 0
Self-loop
Jump chains
All valid targets from 1 through 15 are tested.
NOP must not modify architectural register or flag state.
The regression verifies:
NOP:
No register write
No flag side effect
Result:
NOP: no register / flag side effects
PASS
HALT is tested as a state-freezing operation.
The testbench verifies that HALT freezes:
PC
Registers
Flags
HALT is tested with both:
en = 1
en = 0
HALT at address zero is also tested.
Results:
HALT: PC/regs/flags frozen
PASS
HALT at address 0
PASS
STALL behavior is tested over multiple cycles.
The regression includes:
5 consecutive frozen cycles
STALL at normal instruction
STALL at JMP
Alternating enable states
The testbench confirms that processor state is preserved while execution is disabled.
Result:
STALL: 5 frozen cycles
PASS
STALL at JMP
PASS
STALL: alternating en
PASS
RESET is tested from multiple processor states.
Tests include:
RESET after 3 instructions
RESET after 8 instructions
RESET while HALTed
RESET held for 3 cycles
RESET with en = 0
RESET blocks write-back
The verified reset behavior includes:
PC → 0
Flags → 0
Results:
RESET after 3 instructions : PASS
RESET after 8 instructions : PASS
RESET while HALTed : PASS
RESET held 3 cycles : PASS
RESET with en=0 : PASS
RESET blocks write-back : PASS
The two reserved opcodes are:
1011
1100
Both are tested.
The testbench also varies their register fields to ensure they do not cause unintended state changes.
Results:
Reserved opcodes: safe NOP
PASS
Reserved opcodes:
all rd/rs patterns
PASS
The CPU is tested using every combination of:
rd
rs1
rs2
Each field contains 16 possible register addresses.
Therefore:
16 × 16 × 16 = 4096
combinations are tested for ADD.
The same exhaustive combination space is tested for SUB.
Results:
Exhaustive ADD : 4096 / 4096 PASS
Exhaustive SUB : 4096 / 4096 PASS
This provides complete register-address combination coverage for these operations.
Randomized testing is used to identify combinations that may not be explicitly represented by directed tests.
The current regression contains:
10,000 random ALU vectors
500 random programs
Total random tests:
10,500
Each random ALU vector generates random operands and an operation.
The testbench calculates the expected result and flags using a reference model.
The DUT result is then compared against the model.
The comparison includes:
Result
CF
ZF
NF
VF
Result:
Random ALU vectors
10,000 / 10,000 PASS
500 random programs are generated and executed.
The processor is compared against a behavioral reference model.
The random programs exercise:
ALU operations
Register combinations
JMP
NOP
HALT
RESET
STALL
The regression result:
Random programs vs model
PASS
This provides a higher-level verification layer because complete instruction sequences are tested rather than isolated ALU operations.
The randomized program tests use an expected-behavior model.
Conceptually:
flowchart TB
RP["Random Program"]
RM["Reference Model"]
DUT["DUT"]
CMP["Compare"]
PASS["PASS"]
FAIL["FAIL"]
RP --> RM
RP --> DUT
RM --> CMP
DUT --> CMP
CMP --> PASS
CMP --> FAIL
The model tracks expected:
Registers
PC
Flags
Control state
and compares them against the RTL implementation.
Eight architectural assertions are checked.
| ID | Assertion | Result |
|---|---|---|
| A0 | RESET → PC=0, flags=0 | PASS |
| A1 | !EN holds PC/flags/registers | PASS |
| A2 | HALT freezes PC | PASS |
| A3 | PC increments sequentially | PASS |
| A4 | JMP loads target | PASS |
| A5 | NOP/RSVD/JMP/HALT: no writes | PASS |
| A6 | ALU writes only RD | PASS |
| A7 | RESET blocks write-back | PASS |
A0:
1525 evaluations
0 failures
A1:
2425 evaluations
0 failures
A2:
4960 evaluations
0 failures
A3:
21389 evaluations
0 failures
A4:
3371 evaluations
0 failures
A5:
10613 evaluations
0 failures
A6:
19107 evaluations
0 failures
A7:
1525 evaluations
0 failures
All assertion checks passed.
The testbench performs explicit unknown-state checking.
The regression executed:
51,966 X/Z scans
Result:
X/Z failures : 0
This helps detect unintended:
X
Z
values propagating into important processor signals during simulation.
All implemented instructions were executed during the regression.
Instruction Coverage
====================
ADD : PASS
SUB : PASS
AND : PASS
OR : PASS
XOR : PASS
NOT : PASS
SHL : PASS
SHR : PASS
SLT : PASS
EQ : PASS
MOV : PASS
NOP : PASS
JMP : PASS
HALT : PASS
Coverage:
14 / 14 = 100%
Reserved opcode execution:
1011 / 1100
926 executions
The regression defines 112 functional coverage bins.
Result:
112 / 112 bins = 100%
Coverage includes:
Opcode coverage
Destination register coverage
RS1 coverage
RS2 coverage
Shift amount coverage
Arithmetic corner cases
Comparison outcomes
Control-flow instructions
RESET
STALL
HALT
NOP
Opcode Coverage
---------------
14 / 14 = 100%
Destination Registers
---------------------
16 / 16 = 100%
Source Register RS1
-------------------
16 / 16 = 100%
Source Register RS2
-------------------
16 / 16 = 100%
SHL Amounts
-----------
16 / 16 = 100%
SHR Amounts
-----------
16 / 16 = 100%
The following important cases were hit:
ADD carry : HIT
ADD overflow : HIT
SUB borrow : HIT
SUB overflow : HIT
Zero result : HIT
Negative result : HIT
Carry result : HIT
Overflow result : HIT
SLT true : HIT
SLT false : HIT
EQ true : HIT
EQ false : HIT
JMP : HIT
HALT : HIT
NOP : HIT
RESET : HIT
STALL : HIT
The complete regression produced:
============================================================
VERIFICATION SUMMARY
============================================================
Directed tests : 41
Passed : 41
Random ALU tests : 10,000
Random ALU failures : 0
Random program tests : 500
Random program failures : 0
Total random tests : 10,500
Clock cycles simulated : 33,670
Total checks : 1,087,551
Passed : 1,087,551
Failed : 0
Instruction coverage : 14 / 14
Functional coverage : 112 / 112
X/Z scans : 51,966
X/Z failures : 0
Assertions : A0–A7
Assertion failures : 0
Overall status : PASS
============================================================
| Verification Area | Coverage / Tests | Result |
|---|---|---|
| ALU boundary testing | Multiple vectors | PASS |
| ALU random testing | 10,000 | PASS |
| Register file | 16 registers | PASS |
| Register pairs | 256 combinations | PASS |
| ADD register combinations | 4,096 | PASS |
| SUB register combinations | 4,096 | PASS |
| Instruction coverage | 14 / 14 | 100% |
| Functional coverage | 112 / 112 | 100% |
| Shift coverage | 16 / 16 | 100% |
| Random programs | 500 | PASS |
| Assertions | A0–A7 | PASS |
| X/Z scans | 51,966 | PASS |
The current RTL passes the complete self-checking regression.
============================================================
STATUS : ALL TESTS PASSED
============================================================
Functional Coverage : 100%
Instruction Coverage: 100%
Assertion Failures : 0
X/Z Failures : 0
Test Failures : 0
============================================================
The verified baseline consists of:
41 directed tests
10,000 random ALU vectors
500 random programs
1,087,551 total checks
33,670 simulated clock cycles
with zero reported failures.
The constrained-random regression uses a recorded simulation seed.
Current verification run:
Seed = 12648430
Recording the seed allows the same randomized sequence to be reproduced during debugging or regression analysis.
For future regressions, the seed should be recorded alongside the generated verification report.
Verification outputs should be stored under:
results/
└── verification/
├── verification_report.txt
├── coverage_report.txt
└── regression_summary.txt
The self-checking testbench is maintained under the testbench directory using its existing filename.
The current verification baseline can be extended as the processor architecture evolves.
Potential future verification areas include:
- Formal property verification
- Larger instruction-memory configurations
- Data-memory verification
- LOAD/STORE verification
- Immediate instruction verification
- Branch instruction verification
- Pipeline verification
- Hazard verification
- Forwarding verification
- Interrupt verification
- FPGA hardware validation
- Gate-level simulation
- Post-synthesis verification
- Static timing analysis
- Power-aware verification
Future features should be added without weakening the current regression baseline.
The current regression should be treated as the functional baseline for future RTL changes.
Before accepting a functional modification, the regression should be rerun and the following conditions should remain satisfied:
Directed tests : 100% PASS
Random ALU tests : 100% PASS
Random programs : 100% PASS
Instruction coverage : 100%
Functional coverage : 100%
Assertions : 0 failures
X/Z checks : 0 failures
Any failure should be investigated before the corresponding RTL change is considered verified.
| Verification Metric | Result |
|---|---|
| Directed Tests | 41 / 41 PASS |
| Random ALU Tests | 10,000 PASS |
| Random Programs | 500 PASS |
| Total Checks | 1,087,551 PASS |
| Instruction Coverage | 14 / 14 = 100% |
| Functional Coverage | 112 / 112 = 100% |
| Assertions | 0 FAIL |
| X/Z Checks | 51,966 / 0 FAIL |
| STATUS | ALL TESTS PASSED |
This verification result establishes the current RTL as a stable functional baseline for subsequent repository cleanup, architectural extensions, synthesis, and implementation work.