All your FPGA IO are belong to RP2040 PIO

PIO Assembly to Capture Key features of FPGA Verilog code

3 min readJun 16


PICO-ICE: both RP2040 and ICE40 FPGA

RP2040 MCU PIO has single clock cycle instruction sets and time delay syntax that make it easy to precisely control IO timing. It almost rivals FPGA in terms of IO control. It’s such a useful hardware feature, since RP2040 MCU is only a fraction of the cost and programming effort of a FPGA chip.

There are plenty of interesting examples (link) of using PIO, from driving NeoPixel to streaming VGA videos etc. In many cases, PIO assembly code captures key performance features that can only be expressed in Verilog/VHDL code on dedicated FPGA.

Here are some key features that PIO assembly code can do as well as FPGA Verilog code.

1. Control Timing

In FPGA, everything is driven from the main clock. To count down a fast main clock for LED toggling, one uses a counter

always @(posedge clk) begin
cnt <= cnt + 23'h1;

assign led_out = cnt[22];

So if the main clock clk runs at 125MHz, led_out toggles at about 7Hz.

In RP2040, you can divide down its 125MHz clock first, then use single clock instruction to toggle IO pin as well.

set pins, 1
set pins, 0

2. Sync. Parallel Processes

FPGA can have multiple simultaneous processes running and sync each other with “DONE” or strobe/flag signals. PIO can use IRQ flags to sync. among two PIOs: the main process can signal the waiting process with irq

irq 0
wait 1 irq 0

Now the waiting process can proceed once get synced with the main process. And the IO signals of these two processes will have determined timing relationship.

3. Detect Bit Pattern

Often a clocked-in bit sequence has some “header” to mark the beginning of a data packet, for example “10101” as a header. To detect that bit pattern in PIO:

set y, 21 // 10101 bit pattern as start of a packet
in pins, 1 // shift in one bit
mov x, isr
jmp x!=y, readloop // compare bit pattern




memento of electronics and fun exploration for my future self