Finally got my little Verilog GPU project running on the Tang Nano 20K

Nov 04, 2026 Last reply: 1 minute ago 4 Replies
Jump to replies (4)

After months of evenings, my first real Verilog project is up and running. It's a small retro-style 3D renderer for the Tang Nano 20K, done entirely with the open-source flow: yosys with yosys-slang for synthesis, nextpnr with the himbaechel target, and apicula to actualy program the chip. No vendor tools involved, which was half the fun and half the pain. It's tile-based with deferred rendering, Gouraud shading, textures at 4, 8 or 16 bits per pixel through a CLUT, a Z-buffer, and semi-transparency. I also built a second bitstream that's more of a 2D video chip with tile planes, 128 sprites, a Mode 7 mode and a blitter. Both images live in flash and the host can swap between them while running. The demo scenes run at 30 to 50fps right now, and I think a v2 harness going over HSTX instead of SPI should push that toward 60. Repo is at fpt/tang-tiny-gpu on GitHub if anyone wants a look, and there's a video captured straight off the HDMI output. One heads-up if you want to run it yourself: you'll need a Pico or similar RP2040/RP2350 board sitting in front of the FPGA as an SPI bridge. The wiring notes are in docs/HARNESS.md, though fair warning they're written in Japanese.


I went down a similar path last year with a small sprite engine on the Nano 20K, all yosys and nextpnr, and the thing that ate most of my evenings was timing closure on the pixel pipeline. I kept failing at 74 MHz and eventually just dropped to 50 and hid the shortfall with a line buffer. If your frame rates wobble between scenes, I'd bet it's the fill rate peaking rather than the harness, since deferred tiles tend to spike when a lot of overlapping geometry lands on one tile.

The CLUT approach was the right call in my expirience too. I tried direct 16-bit framebuffers first and the internal BRAM just evaporated, whereas palette-indexed tiles left me room for two full plane buffers plus a font page. One thing on the Pico bridge: my early SPI setup capped out around 8 MHz reliably, and bumping the clock gave me corrupt lines til I shortened the jumpers and dropped the wire count. If you see garbage rows when the 2D blitter and the GPU bitstream swap, check the wiring length before blaming your Verilog. And no shame on the Japanese docs, mine are half pidgin English and half flowcharts my wife had to redraw.

Interesting to see someone else managing a depth buffer on that chip, becuase memory was the wall for me. The Nano 20K has a decent chunk of on-chip RAM but not enought that I could keep a full-resolution depth plane plus textures resident at the same time. I ended up dropping the depth plane entirely and having the host sort polygons back to front before streaming them over, wich freed up enough room for bigger textures at the cost of the occasional sorting glitch on intersecting faces. Worked fine for the kind of scenes I cared about, but I can see why you'd want the real thing for transparency. On the harness side, I also used a Pico as the bridge and found it was actually the bottleneck in my setup, not the renderer. Swapping bitstreams from flash while running is a neat trick, I never figured that out. And for anyone put off by the Japanese wiring notes, I ran the docs thru a browser translator and they were clear enough to follow, the pin table was the part that mattered.

Total beginner question here, I've only ever made an LED blink on one of these boards. The video looks like the old consoles I grew up with and I love it. When the chip needs a Pico sitting in front of it just to feed it data, does the little board do any of the actual picture work too, or is it purely a delivery boy for the files? Asking because I have a spare microcontroller lying around and wondering if this is something I could slowly build up to without buying much else.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required