Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

Hardware-accelerated Nyancat animation on VGA display, implemented in Verilog RTL

License

Notifications You must be signed in to change notification settings

sysprog21/vga-nyancat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

27 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

VGA Nyancat

CI

Hardware-accelerated Nyancat (Pop-Tart Cat) animation on VGA display, implemented in Verilog RTL and simulated using Verilator. Features real-time hardware scaling, ROM-based animation storage, and a 2-stage rendering pipeline.

Note: This is an educational hardware design project demonstrating VGA timing, ROM-based graphics, and hardware animation techniques. The Nyancat character and animation are used under fair use for educational purposes.

Features

  • 12-frame animation cycling at ~11 fps (90ms per frame)
  • Real-time 8Γ— hardware scaling from 64Γ—64 source to 512Γ—512 display
  • Efficient storage using 4-bit character indices + 14-color palette (230Γ— compression)
  • Pipelined rendering with 2-stage ROM lookup for minimal latency
  • VESA-compliant timing at 640Γ—480 @ 72Hz (31.5 MHz pixel clock)
  • Automated data generation from upstream klange/nyancat source

Prerequisites

Ensure that you have the required dependencies installed:

Ubuntu/Debian:

sudo apt-get install libsdl2-dev verilator python3

macOS:

brew install sdl2 verilator python3

Building and Running

To build and run the interactive simulation:

make run

This will automatically:

  1. Download animation source via curl/wget (if needed)
  2. Generate animation data files
  3. Build the Verilator simulation
  4. Launch the interactive display

Interactive controls:

  • p key: Save current frame to test.png
  • ESC key: Reset animation
  • q key: Quit

Testing

To run automated tests and generate a test frame:

make check

This generates test.png containing a single animation frame.

Code Formatting

Format all Verilog and C++ source files:

make indent

This project follows the .verilog-style guidelines for consistent code formatting:

  • Verilog files formatted with verible-verilog-format
  • C++ files formatted with clang-format

Install verible from chipsalliance/verible releases.

How It Works

Data Generation Pipeline

This project automatically extracts animation data from the upstream klange/nyancat repository and converts it to hardware-friendly format:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Source Acquisition (Automated)                          β”‚
β”‚    make β†’ Download animation.c (52KB) via curl/wget        β”‚
β”‚         β†’ Save to build/animation.c                        β”‚
β”‚                                                            β”‚
β”‚ 2. Data Extraction (scripts/gen-nyancat.py)                β”‚
β”‚    Input:  animation.c (ASCII art frames)                  β”‚
β”‚    Parse:  Extract 12 frames of 64Γ—64 character data       β”‚
β”‚    Output: Character indices + color palette               β”‚
β”‚                                                            β”‚
β”‚ 3. Format Conversion                                       β”‚
β”‚    ASCII characters β†’ 4-bit indices (0-13)                 β”‚
β”‚    RGB888 colors    β†’ 6-bit VGA (RRGGBB)                   β”‚
β”‚                                                            β”‚
β”‚ 4. Hardware Files Generated                                β”‚
β”‚    build/nyancat-frames.hex: 49,152 lines (4-bit each)     β”‚
β”‚    build/nyancat-colors.hex: 14 colors in 6-bit format     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Character to Index Mapping:

The script maps each ASCII character from the animation to a 4-bit index:

Char Index Color RGB VGA 6-bit
, 0 Blue background (0,49,105) 000001
. 1 White stars (255,255,255) 111111
' 2 Black border (0,0,0) 000000
@ 3 Tan poptart (255,205,152) 111110
... ... ... ... ...
% 13 Pink cheeks (255,163,152) 111010

Conversion Process:

  1. Parse animation.c: Extract frame data using regex patterns
  2. Build color map: Map 14 unique ASCII characters to palette indices
  3. Convert frames: Transform each 64Γ—64 character grid to 4-bit indices
  4. Generate RGB to VGA: Convert 24-bit RGB to 6-bit VGA format (2R2G2B)

Result: 230Γ— compression (24KB vs 5.4MB for raw RGB888 storage)

System Architecture

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚      VGA Nyancat Top Module         β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚                 β”‚
                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
                   β”‚   VGA Sync Generator  β”‚      β”‚
                   β”‚   (vga-sync-gen.v)    β”‚      β”‚
                   β”‚                       β”‚      β”‚
                   β”‚  β€’ H/V counters       β”‚      β”‚
                   β”‚  β€’ Sync pulse gen     β”‚      β”‚
                   β”‚  β€’ Pixel coordinates  β”‚      β”‚
                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
                                β”‚                 β”‚
                     {x_px, y_px, activevideo}    β”‚
                                β”‚                 β”‚
                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
                   β”‚    Nyancat Animation Renderer       β”‚
                   β”‚         (nyancat.v)                 β”‚
                   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
                   β”‚  β”‚  Coordinate Transformation   β”‚   β”‚
                   β”‚  β”‚  β€’ Remove offset             β”‚   β”‚
                   β”‚  β”‚  β€’ Descale by 8              β”‚   β”‚
                   β”‚  β”‚  β€’ Calculate ROM address     β”‚   β”‚
                   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
                   β”‚             β”‚                       β”‚
                   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
                   β”‚  β”‚   2-Stage Pipeline           β”‚   β”‚
                   β”‚  β”‚                              β”‚   β”‚
                   β”‚  β”‚  Stage 1: frame_mem[addr]    β”‚   β”‚
                   β”‚  β”‚           β†’ char_idx         β”‚   β”‚
                   β”‚  β”‚                              β”‚   β”‚
                   β”‚  β”‚  Stage 2: color_mem[char_idx]β”‚   β”‚
                   β”‚  β”‚           β†’ color            β”‚   β”‚
                   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
                   β”‚             β”‚                       β”‚
                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                          rrggbb (6-bit color)
                                 β”‚
                                 β–Ό
                            VGA Display

Data Flow Pipeline

The rendering pipeline transforms pixel coordinates into colors through multiple stages:

Clock  Input            Stage 1              Stage 2              Stage 3           Output
Cycle  Coordinates      ROM Addressing       Char Lookup          Color Lookup
─────  ─────────────    ──────────────       ───────────────      ────────────      ──────
  N    (x_px, y_px) ──▢ Transform ────────▢ [pipeline reg] ───▢ [pipeline reg] ──▢ (blank)
                        addr calculated

 N+1   (x_px+1, y_px) ─▢ Transform ────────▢ frame_mem[addr] ──▢ [pipeline reg] ──▢ (blank)
                        addr calculated      char_idx fetched

 N+2   (x_px+2, y_px) ─▢ Transform ────────▢ frame_mem[addr] ──▢ color_mem[idx] ──▢ color(N)
                        addr calculated      char_idx fetched    color fetched        ↑
                                                                                      |
                                                            2-clock latency ───────────

Memory Organization

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Frame Memory (frame_mem): 49,152 Γ— 4 bits = 24 KB                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Frame 0 (4096 entries)  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚  [0..4095]               β”‚  64 Γ— 64 = 4096      β”‚                   β”‚
β”‚                          β”‚  4-bit char indices  β”‚                   β”‚
β”‚  Frame 1 (4096 entries)  β”‚  Values: 0-13        β”‚                   β”‚
β”‚  [4096..8191]            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚                                                                     β”‚
β”‚  ...                                                                β”‚
β”‚                                                                     β”‚
β”‚  Frame 11 (4096 entries) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚  [45056..49151]          β”‚  Last frame data     β”‚                   β”‚
β”‚                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚                                                                     β”‚
β”‚  ROM Address Calculation:                                           β”‚
β”‚    addr = (frame_index Γ— 4096) + (src_y Γ— 64) + src_x               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Color Palette (color_mem): 16 Γ— 6 bits = 12 bytes                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Index   Color         6-bit (RRGGBB)   RGB888                      β”‚
β”‚  ─────   ──────────    ──────────────   ───────────────────────     β”‚
β”‚    0     Dark Blue     000001           (  0,  49, 105)             β”‚
β”‚    1     White         111111           (255, 255, 255)             β”‚
β”‚    2     Black         000000           (  0,   0,   0)             β”‚
β”‚   ...    (10 more colors)                                           β”‚
β”‚   13     Light Pink    111010           (255, 163, 152)             β”‚
β”‚  14-15   (unused)                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

VGA Timing Diagram

One complete frame (640Γ—480 @ 72Hz):

Horizontal timing (per line, 832 pixels):
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚   FP   β”‚   SYNC   β”‚    BP     β”‚        ACTIVE            β”‚
  β”‚  24px  β”‚   40px   β”‚  128px    β”‚        640px             β”‚
  β”‚        β”‚ (hsync=0)β”‚           β”‚    (visible data)        β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  ◄──────────────────────────────────────────────────────────►
           832 pixels Γ— 31.5 MHz = 26.4 Β΅s per line

Vertical timing (per frame, 520 lines):
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚   FP   β”‚   SYNC   β”‚    BP     β”‚        ACTIVE            β”‚
  β”‚  9 ln  β”‚   3 ln   β”‚  28 ln    β”‚       480 ln             β”‚
  β”‚        β”‚ (vsync=0)β”‚           β”‚   (visible lines)        β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  ◄──────────────────────────────────────────────────────────►
         520 lines Γ— 26.4 Β΅s = 13.73 ms per frame (~72.8 Hz)

Active video region (where animation is rendered):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ 640 Γ— 480 VGA display                             β”‚
  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
  β”‚    β”‚                                 β”‚            β”‚
  β”‚    β”‚    512 Γ— 512 Nyancat            β”‚  ◄─ Centered horizontally
  β”‚ 64 β”‚    (8Γ— scaled from 64Γ—64)       β”‚  64        β”‚
  β”‚ px β”‚                                 β”‚  px        β”‚
  β”‚    β”‚                                 β”‚  margin    β”‚
  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚
  β”‚                                                   β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  Note: Bottom 32 lines of animation are clipped (512 > 480)

Command-Line Options

./obj_dir/Vvga_nyancat --save-png output.png  # Save a single frame and exit
./obj_dir/Vvga_nyancat --help                 # Show help message

Technical Details

Animation Data Storage

Parameter Value Details
Source frame size 64Γ—64 pixels Original animation resolution
Total frames 12 Complete animation loop
Storage format 4-bit indices Character codes (0-13)
Frame memory 49,152 Γ— 4 bits 24 KB total (12 Γ— 4096 entries)
Color palette 14 colors Γ— 6 bits 12 bytes (2R2G2B VGA format)
Total ROM ~24 KB 230Γ— smaller than raw RGB888 (5.4 MB)

VGA Display Timing

Parameter Value Calculation
Resolution 640Γ—480 @ 72Hz VESA standard timing
Pixel clock 31.5 MHz Standard VGA clock
Horizontal total 832 pixels/line FP(24) + SYNC(40) + BP(128) + ACTIVE(640)
Vertical total 520 lines/frame FP(9) + SYNC(3) + BP(28) + ACTIVE(480)
Line period 26.4 Β΅s 832 Γ· 31.5 MHz
Frame period 13.73 ms 520 Γ— 26.4 Β΅s
Refresh rate 72.8 Hz 1 Γ· 13.73 ms
Clocks/frame 432,640 832 Γ— 520

Animation Timing

Parameter Value Details
Frame duration 90 ms Target animation speed
Clocks/frame 2,835,000 90 ms Γ— 31.5 MHz
Animation rate ~11.1 fps 31.5 MHz Γ· 2,835,000
Total loop time 1.08 seconds 12 frames Γ— 90 ms

Hardware Implementation

Feature Implementation Benefit
Scaling 8Γ— nearest-neighbor Simple bit-shift (Γ·8 = >>3)
Pipeline stages 2 (frame ROM β†’ palette ROM) 2-clock latency, full throughput
Display area 512Γ—512 centered Symmetric margins (64px sides)
Coordinate transform Offset removal + descaling Minimal logic complexity
Frame sequencing 22-bit counter + 4-bit index Automatic wrap at 12 frames
ROM address calc Bit concatenation + OR Zero-delay, no multipliers
ROM reads Synchronous block RAM Synthesis-friendly implementation

Data Generation Automation

The build system automatically handles all data generation:

Makefile workflow:

make all
  ↓
1. Check if build/animation.c exists
  ↓ (if not)
2. Download animation.c (52KB) via curl or wget
   Source: https://raw.githubusercontent.com/klange/nyancat/...
  ↓
3. Run scripts/gen-nyancat.py build/animation.c build/
  ↓
4. Generate build/nyancat-frames.hex (49,152 lines)
  ↓
5. Generate build/nyancat-colors.hex (14 colors)
  ↓
6. Run Verilator to generate C++ files
  ↓
7. Compile C++ simulation binary
  ↓
Build complete (~4.7 seconds from clean state)

Available Make targets:

make all         # Build everything (default)
make build       # Same as 'all', explicit build target
make run         # Build and launch interactive simulation
make check       # Build and generate test.png
make clean       # Remove build artifacts (keep build/ directory)
make distclean   # Remove everything including build/ directory
make regen-data  # Force regeneration of animation data
make indent      # Format all Verilog and C++ source files

Manual data regeneration:

# Force regeneration using existing upstream source
make regen-data

# Clean everything and rebuild from scratch
make distclean && make all

# Generate from custom source file
python3 scripts/gen-nyancat.py /path/to/animation.c

Data file format:

nyancat-frames.hex - One hex digit per line (4 bits):

// Frame 0
0    ← Background pixel (char ',')
0
1    ← Star pixel (char '.')
...

nyancat-colors.hex - VGA 6-bit colors with comments:

01  //  0: ',' RGB(0,49,105)      ← Background
3f  //  1: '.' RGB(255,255,255)   ← Stars
00  //  2: ''' RGB(0,0,0)         ← Black
...

Project Structure

vga-nyancat/
β”œβ”€β”€ rtl/                              # Hardware RTL modules
β”‚   β”œβ”€β”€ vga-sync-gen.v               # VGA sync generator (640Γ—480@72Hz)
β”‚   β”‚                                 # β€’ Generates hsync/vsync pulses
β”‚   β”‚                                 # β€’ Outputs pixel coordinates
β”‚   β”‚                                 # β€’ Provides activevideo flag
β”‚   β”‚
β”‚   β”œβ”€β”€ nyancat.v                    # Nyancat animation renderer
β”‚   β”‚                                 # β€’ Frame sequencing (12 frames)
β”‚   β”‚                                 # β€’ Coordinate transformation
β”‚   β”‚                                 # β€’ 2-stage ROM pipeline
β”‚   β”‚                                 # β€’ ROM: 49,152Γ—4b + 16Γ—6b
β”‚   β”‚
β”‚   └── vga-nyancat.v                # Top-level integration
β”‚                                     # β€’ Connects sync gen to renderer
β”‚                                     # β€’ Reset polarity conversion
β”‚
β”œβ”€β”€ sim/                              # Simulation testbench
β”‚   └── main.cpp                     # Verilator + SDL2 wrapper
β”‚                                     # β€’ SDL2 framebuffer rendering
β”‚                                     # β€’ Standalone PNG encoder (no deps)
β”‚                                     # β€’ Interactive controls
β”‚
β”œβ”€β”€ scripts/                          # Data generation tools
β”‚   └── gen-nyancat.py               # Animation data extractor
β”‚                                     # β€’ Downloads klange/nyancat source
β”‚                                     # β€’ Parses ASCII art frames
β”‚                                     # β€’ Generates hex files
β”‚
β”œβ”€β”€ build/                            # Generated files (gitignored)
β”‚   β”œβ”€β”€ animation.c                  # Downloaded source (52KB)
β”‚   β”œβ”€β”€ nyancat-frames.hex           # Frame data (49,152 lines)
β”‚   β”œβ”€β”€ nyancat-colors.hex           # Color palette (14 colors)
β”‚   β”œβ”€β”€ Vvga_nyancat                 # Simulation binary
β”‚   └── test.png                     # Generated test image
β”‚
β”œβ”€β”€ Makefile                          # Build automation
β”‚                                     # β€’ Data generation
β”‚                                     # β€’ Verilator compilation
β”‚                                     # β€’ Test targets
β”‚
└── README.md                         # This file

Module Hierarchy

vga_nyancat (top)
    β”œβ”€β”€ vga_sync_gen
    β”‚   β”œβ”€β”€ Inputs:  px_clk, reset
    β”‚   └── Outputs: hsync, vsync, x_px[9:0], y_px[9:0], activevideo
    β”‚
    └── nyancat
        β”œβ”€β”€ Inputs:  px_clk, reset, x_px[9:0], y_px[9:0], activevideo
        └── Outputs: rrggbb[5:0]

License

VGA Nyancat is available under a permissive MIT-style license. Use of this source code is governed by a MIT license that can be found in the LICENSE file.

About

Hardware-accelerated Nyancat animation on VGA display, implemented in Verilog RTL

Topics

Resources

License

Stars

Watchers

Forks