riscv-pico · console bring-up

Pico VGA Bench Card

Six jumpers from an RP2040 running RISC-V Linux to a Serial Wombat PCB_0024 breakout, with values read off hw_config.h and the PIO source rather than the README.

PS/2 keyboard · verified 2026-09-11 OLED status panel · running VGA · working 2026-09-14, standalone

Six jumpers

The breakout is passive. A DE-15 socket on one end, labelled headers on the other, and the series resistors already fitted in two header columns, one for 3.3 V logic and one for 5 V. An ordinary VGA cable plugs in whole, so none of the conductor identification that a cut cable demands applies here.

Breakout headerSignalOn-board RPico GPIOPico pin
RRED270 ΩGP1824
GGREEN270 ΩGP1925
BBLUE270 ΩGP2026
HHSYNC68 ΩGP1722
VVSYNC68 ΩGP1621
GNDGROUND—GND23

Ground on physical pin 23 sits between HSYNC and Red in the header, so that tie is one short jumper rather than a reach across the board.

Use the outer header column The board has two header columns carrying the same five signals. The inner column, nearest the resistors, is sized for 5 V logic. The outer column is the 3.3 V input and is the one the Pico wants. Ground is the separate two-pin header at the top. The five round pads along the top edge are spare DE-15 pins 15, 12, 11, 9 and 4 and stay unconnected, since pin 9 can carry 5 V from a monitor. Leave the solder jumpers on the back open: bridging them ties red, green and blue together for one-wire black and white.

The fitted values check out against the spec. The 3.3 V column carries 270 Ω on the colour lines and 68 Ω on the syncs. A 0.7 V peak into a 75 Ω terminated input from a 3.3 V pin needs (3.3 × 75 / 0.7) − 75 = 279 Ω, so 270 Ω sits a touch bright of nominal. The inner 5 V column uses 470 Ω, against 461 Ω from the same formula.

The chain, end to end

PICO HEADER PCB_0024 BREAKOUT DISPLAY resistors fitted here GP18 · pin 24 270Ω R GP19 · pin 25 270Ω G GP20 · pin 26 270Ω B GP17 · pin 22 68Ω HSYNC GP16 · pin 21 68Ω VSYNC GND · pin 23 GND DE-15 uncut cable monitor outer header column = 3.3 V input
Six jumpers in on the left, one ordinary cable out on the right. The resistors live on the breakout rather than beside the Pico, which is the trade the board makes: slightly more wire carrying a sharp edge, in exchange for no soldering and no cable dissection.

Keep the bundle off the left edge

RP2040 PSRAM GP10–14 pins 14–19 20 MHz · fragile VGA GP16–20 pins 21–26 62.5 MHz · aggressor PS/2 · pins 31–32 OLED · pins 27, 34 out this way never across the board
PSRAM and VGA sit on opposite edges but at the same height, near the bottom of the header. That is the one place the two bundles can meet, so the VGA breakout goes outward to the right and never arcs back over the board.

Only the three colour lines run at 62.5 MHz, and those are exactly the lines the breakout puts a series resistor on, into a 75 Ω terminated input. That is a well-damped line rather than a ringing stub. The syncs are unterminated but run at 31 kHz and 60 Hz. For comparison the PS/2 clock is around 15 kHz and caused no trouble at all.

So one breadboard is worth attempting. The failure mode is loud and shows up on the first boot, and the second board is a five-minute fallback rather than a rebuild.

Bring-up order

  1. Use the outer 3.3 V header column. The inner column is sized for 5 V and gives a dim picture.
  2. Six jumpers from the labelled headers to GP18, GP19, GP20, GP17, GP16 and a ground.
  3. Keep the bundle out to the right edge, away from GP10 to GP14 on the left. One breadboard to start with.
  4. Read the boot log before looking at the monitor. If initPSRAM() reports −1 or −2, VGA has upset the PSRAM bus. That is the decision point for splitting onto a second breadboard or dropping PSRAM_SPI_SPEED_MHZ, and it is a noise problem, not a dead chip.
  5. Then check for lock. If the monitor refuses to sync, the OLED panel still tells you the machine is alive, so check sync polarity against vga.c before suspecting the wiring. 640×480 at 60 Hz wants both sync polarities negative.
  6. If the colours come up wrong, swap two jumpers. Only the syncs have to be correct to get a picture at all.

Why green and blue have no config line

Only VGA_R_PIN exists in hw_config.h. Green and blue are not configurable. rgb_program_init() takes the red pin as a base and hard-wires pin, pin+1 and pin+2 as one consecutive PIO output group, so moving red moves the other two with it. One bit per channel gives eight colours at 320×240, which is 640×480 line-doubled.

The 62.5 MHz figure is not a guess either. The PIO clock divider is system frequency over 62500, and the RP2040 here runs overclocked at 400 MHz.

None of this needs a firmware change. CONSOLE_VGA has been enabled since the boards-v4 release, so the PIO program and its two DMA channels have been driving those pins into open air for weeks. Attaching the cable turns on no new code path.

Fallback: cutting a cable

Kept in case the board disappoints, or a second display is wanted later. None of this is needed for the PCB_0024 path.

Connector identification, the long way
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 FRONT FACE OF THE MALE PLUG schematic, not to scale — confirm against the numbers moulded on your shell
Red Green Blue Sync Ground Snip and tape off
Ten of fifteen pins are in use. Drawn from the front of the male plug, which is the orientation that matters, because the female-socket view is its mirror image.
DE-15SignalGoes to
1 2 3R G B270 Ω each, then GP18 / GP19 / GP20
13 14HSYNC VSYNCGP17 / GP16, no resistor required
5 6 7 8 10GROUNDSOne bus. 6, 7 and 8 are the R/G/B coax shields
4 9 11 12 15UNUSEDSnip and tape off, DDC included

Without the DDC pair on 12 and 15 the monitor cannot read an EDID and falls back to default timings, which is exactly what you want here.

The mirror trap, again Reading a connector diagram in the wrong view is what nearly went wrong on the keyboard. Here it is far less dangerous, because nothing in this cable carries power toward the Pico, so a mirrored reading costs you a wrong colour or no lock, never a dead pad. The self-check is the same idea as the dead-pin check on the mini-DIN: each colour pin should buzz to a coax centre, and pins 6, 7 and 8 to those same coaxes' shields. If that correspondence does not hold, you are reading the connector backwards.

Nine probes, not a hundred and fifty

Work backwards from the connector instead of sweeping every wire against every pin. Put one meter lead on a DE-15 pin and sweep the conductors until one buzzes, then move to the next pin. You only care about 1, 2, 3, 6, 7, 8, 10, 13 and 14.

Colour means nothing here. VGA cable colours are no more standardised than the keyboard's were, and that cable turned out to use red for data rather than power.

Perfboard construction

The same approach that worked for the keyboard, with three changes that matter more on this cable.

  • Strain relief is not optional. A VGA cable has real mass and will lever pads off the board. Zip-tie or hot-glue the jacket where it enters the perfboard.
  • Ground bus down one side. Land all five grounds on it, and keep each coax centre beside its own shield as far along as possible.
  • Resistors stay off the breakout, in the breadboard row beside GP18, GP19 and GP20. If there is no room there, solder each one inline into its jumper instead: trim one lead to plug into the breadboard, solder the other to the wire, heatshrink the joint. That keeps the resistor at the driver and costs no breadboard rows.