Problem
Games cannot initialize because VBlank signal is not reaching the CPU correctly.
Symptoms
Games stuck in infinite loop waiting for VBlank
$2002 (PPUSTATUS) always reads VBlank=0
No VRAM/palette writes occur
Games never display graphics
Root Cause Analysis
✅ PPU Module Works Correctly
Isolated PPU test shows VBlank generates properly:
✅ Level 0.2: VBlank Signal Test - PASS
- VBlank SET at scanline 241
- VBlank CLEAR at scanline 261
- Triggers every frame correctly
❌ NES System Integration Broken
When integrated in nes_system.sv, VBlank signal fails to reach CPU:
[PPU] $2002 read: VBlank=0 status=$00 ← Always 0!
[PPU] $2002 read: VBlank=0 status=$00
[PPU] $2002 read: VBlank=0 status=$00
Technical Details
Clock Domain Crossing Issue
// nes_system.sv
assign cpu_clk = clk_div[2 ]; // ÷8 = 2.68 MHz
assign ppu_clk = clk_div[1 ]; // ÷4 = 5.37 MHz
// VBlank synchronizer (ppu_clk -> cpu_clk)
logic vblank_sync1, vblank_sync2, vblank_sync3;
always_ff @ (posedge cpu_clk) begin
vblank_sync1 <= vblank; // From PPU
vblank_sync2 <= vblank_sync1;
vblank_sync3 <= vblank_sync2;
end
// PPUSTATUS update
if (vblank_sync2 && ! vblank_sync3) begin
ppustatus[7 ] <= 1 ; // Set VBlank flag
end
Problem : Synchronizer not working - ppustatus[7] never gets set.
Test Evidence
Layered Test Results
Level
Test
Status
0.1
PPU clock/counters
✅ PASS
0.2
VBlank signal (isolated)
✅ PASS
0.3
Video output signals
✅ PASS
1.x
PPU registers
❌ BLOCKED
2.x
VRAM access
❌ BLOCKED
Game Behavior
All games stuck at initialization:
WAIT_VBLANK:
LDA $ 2002 ; Read PPUSTATUS
AND # $ 80 ; Check VBlank bit
BEQ WAIT_VBLANK ; Loop forever ← Stuck here!
Impact
Game compatibility: 0% (games cannot initialize)
PPU rendering: Broken (no VRAM data)
Previous 90% claim: Invalid (based on frame count, not actual functionality)
Proposed Fix
Debug VBlank signal propagation from PPU to CPU
Verify clock domain crossing logic
Check if vblank signal is stable across clock domains
Consider using proper CDC (Clock Domain Crossing) techniques
Add debug signals to trace VBlank path
Files Involved
src/main/rtl/nes_ppu.sv - VBlank generation (✅ works)
src/main/rtl/nes_system.sv - VBlank synchronization (❌ broken)
Lines 402-433 in nes_system.sv
Test Case
# Run VBlank test
cd src/test/rtl
verilator --cc --exe --build ../../main/rtl/nes_ppu.sv test_ppu_vblank.cpp -o Vtest_vblank
timeout 5 ./obj_dir/Vtest_vblank
Expected: ✅ PASS (PPU works)
# Run game
timeout 3 src/test/rtl/obj_dir_screenshot/Vnes_system games/DonkeyKong_mapper0.nes /dev/null 2>&1 | grep " 2002 read"
Expected: VBlank=1 at least once per frame
Actual: VBlank=0 always ❌
Priority
CRITICAL - Blocks all game functionality
References
Layered test plan: docs/NES_LAYERED_TEST_PLAN.md
Test code: src/test/rtl/test_ppu_vblank.cpp
Issue 游戏兼容性测试报告 - 四款游戏测试结果 #4 : Game compatibility report
Problem
Games cannot initialize because VBlank signal is not reaching the CPU correctly.
Symptoms
$2002(PPUSTATUS) always reads VBlank=0Root Cause Analysis
✅ PPU Module Works Correctly
Isolated PPU test shows VBlank generates properly:
❌ NES System Integration Broken
When integrated in
nes_system.sv, VBlank signal fails to reach CPU:Technical Details
Clock Domain Crossing Issue
Problem: Synchronizer not working -
ppustatus[7]never gets set.Test Evidence
Layered Test Results
Game Behavior
All games stuck at initialization:
Impact
Proposed Fix
vblanksignal is stable across clock domainsFiles Involved
src/main/rtl/nes_ppu.sv- VBlank generation (✅ works)src/main/rtl/nes_system.sv- VBlank synchronization (❌ broken)Test Case
Expected: ✅ PASS (PPU works)
Expected: VBlank=1 at least once per frame
Actual: VBlank=0 always ❌
Priority
CRITICAL - Blocks all game functionality
References
docs/NES_LAYERED_TEST_PLAN.mdsrc/test/rtl/test_ppu_vblank.cpp