SmolDVI (wren6991__smoldvi)
| Field | Value |
|---|---|
| Upstream | https://github.com/Wren6991/SmolDVI |
| Reviewed at | e8b8f87 (upstream date 2021-07-15), reviewed 2026-09-28 |
| License | CC0-1.0 (LICENSE.md) |
| HDL / framework | Verilog (12 .v files) |
| Toolchain | open (yosys + nextpnr-ice40 + icepack/icetime, via synth/{Icebreaker,Icestick,Icesugar,TinyFPGA_BX}.mk + synth/Makefile, driven by the Wren6991/fpgascripts submodule) |
| Programmer | board-specific, invoked from the per-board .mk (e.g. iCEBreaker prog target); not read in detail here |
| Target FPGA(s) | iCE40 UP5K (iCEBreaker, iCESugar), iCE40 HX1K (iCEstick), iCE40 LP8K (TinyFPGA BX) — not ECP5, no ULX3S target in this repo |
| Board revision(s) | n/a — repo does not target ULX3S |
| Activity | last commit 2021-07-15 (e8b8f87, “Port to TinyFPGA BX”); commit count / first commit unknown (shallow clone, repo not in .claude/memory/history.tsv) |
What the gateware does
A small, portable direct DVI/TMDS video-output core (top module smoldvi, hdl/smoldvi/smoldvi.v) that generates a pixel-doubled RGB666 640×480p60 (or configurable CEA-861D) DVI signal from an RGB pixel stream, using a minimal (“stateless”) TMDS encoder trick documented in hdl/smoldvi/smoldvi_tmds_encode.v (~20 LUTs/lane, at the cost of halving horizontal resolution and dropping the colour LSB — acceptable per the author for the iCE40 UP5K/HX1K this was built for). Per-board top-level example designs (hdl/fpga/smoldvi_fpga_*.v) drive a scrolling colour-gradient test pattern out to a DVI PMOD on iCEBreaker, iCEstick, iCESugar and TinyFPGA BX.
Structure
hdl/smoldvi/— the portable core:smoldvi.v(top: timing + TMDS encode + serialise),smoldvi_timing.v(CEA-861D-style H/V counters, sync/den generation),smoldvi_tmds_encode.v(the stateless TMDS trick),smoldvi_serialiser.v(10:2 gearbox + DDR output, not fully self-contained, see Reuse notes),smoldvi_fast_gearbox.v,smoldvi_clock_driver.v.hdl/fpga/— per-board top levels + PLLs (pll_12_126.v,pll_16_126.v) and.ffile lists.synth/— per-board Makefile fragments,.pcfpin constraints,synth/Makefile(shared rules).hdl/libfpga(git submodule, not fetched in this shallow clone —.gitmodulespoints athttps://github.com/Wren6991/libfpga.git) supplies the platformddr_outmodule and reset helpers used by the example top-levels.
How to build
Not run (read-only review; the hdl/libfpga submodule is also absent, so a build would fail as checked out). From Readme.md:
git clone --recursive https://github.com/Wren6991/SmolDVI.git smoldvi
cd smoldvi && . sourceme
cd synth && make -f Icebreaker.mk prog # also: Icestick.mk, Icesugar.mk, TinyFPGA_BX.mk
No ECP5/ULX3S Makefile exists in this repo.
Reusable blocks
| Block | Path | Top module | Language | Vendor primitives | License |
|---|---|---|---|---|---|
| Small DVI/TMDS core | hdl/smoldvi/*.v | smoldvi | Verilog | none in hdl/smoldvi/ itself — see below for the one platform-specific dependency | CC0-1.0 |
Reuse notes
- Top module ports (
hdl/smoldvi/smoldvi.v:18-35):clk_pix/rst_n_pix(pixel-rate domain),clk_bit/rst_n_bit(bit-rate domain, must be exactly 5×clk_pix, common root oscillator, reset deassertion synchronised to each domain’s clock — README, “Reusing” section),en,r/g/b(RGB_BITS-wide, 1–7 bits, default 6),rgb_rdy(pixel request/ready strobe),dvi_p[3:0]/dvi_n[3:0]({CK, D2, D1, D0}, TMDS channel order Blue/Green/Red like other DVI cores in this collection). Key parameters: the full CEA-861D H/V timing set (front porch, sync width, back porch, active) plusRGB_BITS. - The only platform-specific piece is
ddr_out(per the author, inReadme.md“Reusing”):smoldvi_serialiser.v:59-75instantiates a module calledddr_out(2:1 DDR output buffer, portsclk,rst_n,d_rise,d_fall,e,q) that is not itself in this repo — it comes from the unfetchedhdl/libfpgasubmodule and is compiled under`FPGA_ICE40to become aSB_IODDR primitive. Everything else inhdl/smoldvi/is plain, portable Verilog by the author’s own description. - Porting to ULX3S (ECP5): supply (1) an
EHXPLLLgeneratingclk_bit= 5× the desired pixel clock from the 25 MHz oscillator (e.g. 126 MHz for 25.2 MHz / 640×480p60, matching thepll_12_126/pll_16_126naming convention already used for the iCE40 boards) withclk_pixderived from it (in-fabric ring-counter divide-by-5, as the iCEBreaker top-level does athdl/fpga/smoldvi_fpga_icebreaker.v:54-64, or a second PLL output tap); (2) a`define FPGA_ECP5-styleddr_outimplementing the sameclk/rst_n/d_rise/d_fall/e/qport list aroundODDRX1F(one instance per TMDS lane, 4 total incl. clock) — the same primitive and DDR gearing already used bydanodus__ecp5_hdmi_audio_video’srtl/hdmi_serializer_ecp5.vin this collection, so that file is a good reference for the ECP5-specific half; (3) mapdvi_p/dvi_ntogpdi_dp[3:0]/gpdi_dn[3:0](ulx3s_v316.lpf,IO_TYPE=LVCMOS33D, ULX3S’s GPDI pins auto-generate the complementary leg from a single-ended drive, as used by the emardvga2dvid/danodushdmi_serializer_ecp5cores) instead of the SB_IO-based differential pads used on the iCE40 boards. - CC0-1.0 (public-domain-equivalent) license makes this one of the least encumbered DVI cores in the survey; RGB666 pixel-doubled 640×480p60 is small enough to be a good “just need a picture out” option compared to full hdl-util/hdmi-derived stacks when audio/HDMI infoframes aren’t needed.
Open questions
hdl/libfpga’s exactddr_out.vimplementation was not read (submodule not fetched in this shallow clone; not in.claude/memory/submodules.tsvallowlist). The port list quoted above comes from the call site insmoldvi_serialiser.v, not from the module’s own source.- Whether
smoldvi_clock_driver.v/smoldvi_fast_gearbox.valso assume any iCE40-specific behaviour (e.g. LUT-based shift register inference) was not checked line-by-line; the author’s “everything in hdl/smoldvi is portable” claim is unverified beyond the explicitddr_outcallout.