GitHub - lawrie/fpga_pio: An attempt to recreate the RP2040 PIO in an FPGA

Mai 21, às 16:51


5 min de leitura


0 leituras

FPGA RP2040 PIO Introduction This is an attempt to recreate the Raspberry Pi RP2040 PIO interface in Verilog. PIO stands for Progammable I/O, and it is a peripheral that is part of the RP2040 SoC, which is...
GitHub - lawrie/fpga_pio: An attempt to recreate the RP2040 PIO in an FPGA



This is an attempt to recreate the Raspberry Pi RP2040 PIO interface in Verilog.

PIO stands for Progammable I/O, and it is a peripheral that is part of the RP2040 SoC, which is much more flexible than hardware implementations of specific protocols like SPI, I2C, UART etc. It can implement all these protocols and more at high speed and on any GPIO pins.

It runs in up to 8 special processors, known as State Machines, which are programmed in assembler using a machine language designed specifically for fast cycle-accurate I/O. These processors run independently of the main CPUs.

This implementation has been done from the specification, without access to any Raspberry Pi HDL. It is currently incomplete, but some programs run in simulation and on open source FPGA boards.

The current supported boards are the Blackice MX and the Ulx3s.

The current method of configuring and controlling PIO from a top-level module is different from that used on the RP2040 chip, and will probably be changed for closer compatibility.

For use by a SoC, e.g. a RISC-V SoC such as SaxonSoc, the appropriate peripheral bus interface would need to be added.

For use from a host processor, such as one running micropython, an SPI read/write memory interface could be added. This would be a lot slower than a bus interface but speed is not usually an issue for configuration and control. There are usually too few pins between a host processor and the fpga to implement a 32-bit (or even an 8-bit) bus interface.


To run a program in simulation, clone the repository and do:

That runs the tb.v testbench. You can see the results by opening waves.vcd using gtkwave.

You can run the other test programs in the sim directory, such as uart_tx.v, by:


To run the top.v Verilog file on the Blackice MX board, do:

For the Ulxs3 board use the ulx3s directory.

The current program flashes the red led approximately once per second.

You can select a different top-level module by, for example:

make clean prog TOP=hello

Current working top level modules include: blink, hello, wds812, exec, uart_tx.

Assembling programs

You can assemble program using the Adafuit pioasm assembler (used by CircuitPython), by:

cd asm
./compile square.asm square.mem

and then move square.mem to the src/top and/or the sim directory.

The compiler is currently incomplete and so the .mem files sometimes need modification, e.g when the "'side_set opt" option is used.



.program blink
 set pindirs 1
 set pins 1 [31] ; Drive pin high and then delay for 31 cycles
 nop [31]
 nop [31]
 nop [31]
 nop [31]
 set pins 0 [30] ; Drive pin low
 nop [31]
 nop [31]
 nop [31]
 nop [31]
 jmp again

This blinks every 320 cycles. so with a maximum clock divider of 64K -1 (0xFFFF), and a 25MHz FPGA clock, it blinks approximately every 1.2 seconds.


.program uart_tx
.side_set 1 opt
 pull block side 1
 set x 7 side 0 [7]
 out pins 1
 jmp x-- again [6]

This example outputs a message repeatedly on the console.


The exec examples needs no PIO program as it executes a SET PINS instruction immediately. The machine does not need to be enabled. The top/exec.v Verilog module uses immediate execution to blink the led approximately once per second.


.program pwm
.side_set 1 opt
 pull noblock side 0
 mov x osr
 mov y isr
 jmp x!=y noset
 jmp skip side 1
 jmp y-- countloop

The pwm example set the led off and then increases its brightness, repeatedly.


.program ws2812
.side_set 1
 out x 1 side 0 [1]; Side-set still takes place when instruction stalls
 jmp !x do_zero side 1 [1]; Branch on the bit we shifted out. Positive pulse
 jmp bitloop side 1 [1]; Continue driving high, for a long pulse
 nop side 0

ws2812 example

Stepper motor

This example shows driving a stepper motor with PIO.

You set the direction by pushing the required phase patterns as a set of 8 4-bit values, and then you push the required number of half steps.

To start again with a new set of steps, you execute an immediate jump to the start of the program.

.program stepper
 pull block
 mov isr osr
 pull block
 mov y osr
 mov osr isr 
 set x 6
 out pins 4 [2]
 jmp x-- inner
 out pins 4
 jmp y-- outer
 out pins 4
 jmp wrap_target

Here is is driving a stepper motor from a Blackice MX:

blackice mx stepper


.program i2s
.side_set 2
 pull noblock side 3
 mov x osr side 3
 set y 14 side 3 [1]
 out pins 1 side 2 [3]
 jmp y-- loop1 side 3 [3]
 out pins 1 side 0 [3]
 set y 14 side 1 [3]
 out pins 1 side 0 [3]
 jmp y-- loop0 side 1 [3]
 out pins 1 side 2 [3]

The I2S example (top/i2s.v) plays a wave file in 16-bit 44100Hz stereo, from BRAM to a Digilent I2S Pmod. It works better on the Ulx3s board, which has more BRAM.

Continue lendo


Motorola Razr Plus é o novo dobrável rival do Galaxy Z Flip
Após duas tentativas da Motorola em emplacar — novamente — telefones dobráveis, eis que temos aqui a terceira, e aparentemente bem-vinda, tentativa. Estamos falando do Motorola Razr Plus, um smartphone...

Hoje, às 15:20


Mentoring for the LGBTQ+ Community
Once unpublished, all posts by chetanan will become hidden and only accessible to themselves. If chetanan is not suspended, they can still re-publish their posts from their dashboard. Note: Once...

Hoje, às 15:13


IA: mais um arrependido / Déficit de TI / Apple: acusação grave · NewsletterOficial
Mais um pioneiro da IA se arrepende de seu trabalho: Yoshua Bengio teria priorizado segurança em vez de utilidade se soubesse o ritmo em que a tecnologia evoluiria – ele junta-se a Geoffr...

Hoje, às 14:37

Hacker News

The Analog Thing: Analog Computing for the Future
THE ANALOG THING (THAT) THE ANALOG THING (THAT) is a high-quality, low-cost, open-source, and not-for-profit cutting-edge analog computer. THAT allows modeling dynamic systems with great speed,...

Hoje, às 14:25


[DISCUSÃO/OPINIÕES] – Outsourcing! O que, para quem, por que sim, por que não! · dougg
Quero tentar trazer nesta minha primeira publicação, uma mistura de um breve esclarecimento sobre o que são empresas de outsourcing, como elas funcionam e ganham dinheiro, mas também, ven...

Hoje, às 13:58


Duvida: JavaScript - Desenvolver uma aplicação que vai ler um arquivo *.json · RafaelMesquita
Bom dia a todos Estou estudando javascript e me deparei com uma dificuldade e preciso de ajuda *Objetivo do estudo: *desenvolver uma aplicação que vai ler um arquivo *.json Conteudo do in...

Hoje, às 13:43


Automatize suas negociações com um robô de criptomoedas
Índice Como o robô de criptomoedas Bitsgap funciona?Qual a vantagem de utilizar um robô de criptomoedas?Bitsgap é confiável? O mercado de trading tem se tornado cada vez mais popular e as possibilidades de...

Hoje, às 13:13

Hacker News

Sketch of a Post-ORM
I’ve been writing a lot of database access code as of late. It’s frustrating that in 2023, my choices are still to either write all of the boilerplate by hand, or hand all database access over to some...

Hoje, às 13:11


14 chuveiros elétricos para o banho dos seus sonhos
Índice Chuveiro ou Ducha?Tipos de chuveiro elétrico9 fatores importantes para considerar na hora de comprar chuveiros elétricosMelhores chuveiros elétricosDuo Shower LorenzettiFit HydraAcqua Storm Ultra...

Hoje, às 11:00


Learn about the difference between var, let, and const keywords in JavaScript and when to use them.
var, let, and const: What's the Difference in JavaScript? JavaScript is a dynamic and flexible language that allows you to declare variables in different ways. You can use var, let, or const keywords to...

Hoje, às 10:21