• Stars
    star
    289
  • Rank 143,419 (Top 3 %)
  • Language Verilog
  • License
    BSD 2-Clause "Sim...
  • Created almost 4 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An attempt to recreate the RP2040 PIO in an FPGA

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 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.

Simulation

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

cd fpga_pio/sim
make sim

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:

make sim TB=uart_tx

Synthesis

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

cd blackicemx
make prog

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.

Examples

Blink

.program blink
    set pindirs 1
again:
    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.

Hello

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

This example outputs a message repeatedly on the console.

Exec

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.

Pwm

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

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

Neopixels

.program ws2812
.side_set 1
.wrap_target
bitloop:
  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
do_one:
  jmp  bitloop   side 1 [1]; Continue driving high, for a long pulse
do_zero:
  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
outer:
    mov osr isr 
    set x 6
inner:
    out pins 4 [2]
    jmp x-- inner
    out pins 4
    jmp y-- outer
wrap_target:
    out pins 4
    jmp wrap_target

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

blackice mx stepper

I2S

.program i2s
.side_set 2
    pull noblock  side 3
    mov x osr     side 3
    set y 14      side 3 [1]
loop1:
    out pins 1    side 2 [3]
    jmp y-- loop1 side 3 [3]
    out pins 1    side 0 [3]
    set y 14      side 1 [3]
loop0:
    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.

More Repositories

1

tiny_usb_examples

Using the TinyFPGA BX USB code in user designs
Verilog
49
star
2

ulx3s_examples

Example Verilog code for Ulx3s
Verilog
39
star
3

LightwaveRF

C++
32
star
4

verilog_examples

Example code in Verilog for the Blackice II FPGA
C
26
star
5

blackicemxbook

25
star
6

tinyfpga_examples

Verilog example programs for TinyFPGA
Verilog
24
star
7

ulx3s_retro

Retro computing on the Ulx3s ECP5 FPGA board
24
star
8

saxonsoc-ulx3s-bin

The binaries for SaxonSoc Linux and other configurations
Verilog
17
star
9

ulx3s_bit_streams

Bit streams forthe Ulx3s ECP5 device
Forth
16
star
10

tinyfpga_bx_gaming

How to use the TinyFPGA BX as a game console
15
star
11

ulx3s_cores

Information on cores available on the Ulx3s ECP5 FPGA board
14
star
12

MuraxArduino

A version of f32c/arduino that works with the SpinalHDL Vexriscv Murax SoC
C
14
star
13

tiny_soc

Picorv32 SoC on the TinyFPGA BX, for games etc.
Verilog
12
star
14

tiny_ram_soc

Picorv32 SoC that uses only BRAM, not flash memory
Verilog
12
star
15

ulx3s_zx_spectrum

Minimal ZX Spectrum for Ulx3s ECP5 board
Verilog
12
star
16

ulx3s_zx81

ZX80/81 implementation for the Ulx3s
Verilog
11
star
17

atari_2600

TinyFPGA BX implementation of Atari 2600 for the FPGC LCD games console
Assembly
11
star
18

hdmi_examples

Ice40 open source HDMI examples on BlackIce II
Verilog
10
star
19

blackicemx_nmigen_examples

Example code for Blackice MX board written in nmigen
Python
10
star
20

ulx3s_mac128

Macintosh 128 on the Ulx3s ECP5 FPGA
Verilog
9
star
21

pico_ram_soc

A version of PicoSoc that runs from BRAM, with extra peripherals
Coq
9
star
22

ulx3s_68k

Experiments with the 68000 CPU on the Ulx3s ECP5 board
Verilog
8
star
23

ulx3s_sms

Sega Master System for Ulx3s ECP5 FPGA
Verilog
6
star
24

ulx4m_amaranth_examples

Amaranth HDL examples for the Ulx4m FPGA board
Python
6
star
25

spinal_synth

A version of tiny-synth, converted to SpinalHDL
Scala
6
star
26

atari_tia_soc

TinyFPGA BX RAM PicoSoc emulating Atari 2600 TIA
Verilog
6
star
27

ulx4m_examples

Verilog examples for the Ulx4M FPGA board
Verilog
6
star
28

blackicemx_zx81

ZX81 on the Blackice Mx ice40 FPGA board
Verilog
5
star
29

ulx3s_colecovision

ColecoVision console for the Ulx3s ECP5 board
Verilog
5
star
30

ulx3s_amstrad_cpc

The Amstrad CPC on the Ulx3s Ecp5 FPGA board
Verilog
5
star
31

fpga-computer-history

Recreating the history of computers on open source FPGAs
5
star
32

ulx3s_ql

Sinclair QL for the Ulx3s ECP5 board
Verilog
5
star
33

ulx3s_msx

MSX 8-bit computers on the Ulx3s ECP5 board
Verilog
5
star
34

SpinalULX3S

SpinalHDL ULX3S examples
Scala
5
star
35

ulx3s_altair_8800

Altair 8800 on the Ulx3s ECP5 FPGA board
Verilog
5
star
36

ulx3s_ay_3_8500

The AY-3-8500 Pong-on-a-chip for the Ulx3s ECP5 board
Verilog
4
star
37

SaxonArduino

SaxonArduino is an implementation of an Arduino board for open source FPGAs using SpinalHDL SaxonSoc
C
4
star
38

ulx3s_bbc_micro

Version of Ice40Beeb for Ulx3s ECP5 board
Verilog
4
star
39

fpga_roomba

Driving a Roomba from an FPGA
Python
4
star
40

ulx3s_vic_20

Minimal Commodore Vic 20 core for the Ulx3s ECP5 board
Verilog
4
star
41

ulx4m_bitstreams

Bitstreams for the Ulx4m ECP5 FPGA module
3
star
42

ulx3s_vhdl_examples

VHDL examples for the Ulx3s ECP5 FPGA
VHDL
3
star
43

blacksoc

A version of Clifford Wolf's icoSoC for the Blackice Mx
Coq
3
star
44

esp210_sketches

Arduino sketches for the ESP210 ESP8266 node.it devices
Arduino
3
star
45

ulx3s_cpm_z80

A port of the Ice40CPMZ80 project to the Ulx3s ECP5 board
Verilog
3
star
46

ulx3s_z80_template

Template for Z80 computer on the Ulx3s FPGA board
Verilog
3
star
47

ulx3s_z80_trs80

The TRS-80 Model 1 for the Ulx3s FPGA Ecp5 board, created from the Z80 template
Verilog
3
star
48

ulx3s_trs_80

TRS 80 Model 1 Verilog implementation for the Ulx3s ECP5 board
Assembly
3
star
49

HouseControl

Java
3
star
50

jupiter_ace

Jupiter Ace for the Ulx3s
Verilog
3
star
51

ulx3s_sg_1000

Sega SG-1000 console for the Ulx3s ECP5 board
Verilog
2
star
52

mystorm-rpi

Utilities to access the Blackice II FPGA board using the Raspberry Pi header
C
2
star
53

blackicemx_examples

Verilog
2
star
54

ulx3s_acorn_atom

Ulx3s port of Ice40Atom
Verilog
2
star
55

saxonsoc-fb

SaxonSoc linux framebuffer tools
C
2
star
56

ulx3s_pdp_11

Experiments with the PDP 11 instruction set on the Ulx3s Ecp5 FPGA board
2
star
57

Risc16

Verilog
2
star
58

soctalk

2
star
59

8bitworkshop

Examples from 8bitworkshop.com verilog compiler
2
star
60

silice_examples

Experiments with the Silice Hardware Description Language
Slice
2
star
61

qspi_periph

Prototyping nMigen QSPI peripheral interface for LogicDeck board
Python
1
star
62

pcremote

Arduino and python code for Harry's pcremote device
Arduino
1
star
63

pico_example_soc

A simple XIP PicoSoC example for Blackice Mx
Coq
1
star
64

spibox

Python
1
star
65

ulx3s_gamegear

Segs Game Gear for the Ulx3s ECP5 FPGA board
Verilog
1
star
66

saxonsoc-lib

Libraries of useful functions for SaxonSoc Linux and the lcc compiler
C
1
star
67

keyboard

Arduino
1
star
68

pico_xip_soc

Version of PicoSoC for the Blackice Mx with Execute-in-Place (XIP) and extra peripherals
C
1
star
69

MiteCPU-nmigen

MiteCPU converted to nmigen
Python
1
star
70

pico_sdram_soc

A version of PicoSoC for Blackice Mx, which uses XIP and SDRAM
Coq
1
star
71

ulx3s_atari_2600

Atari 2600 for the Ulx3s Ecp5 FPGA board
Assembly
1
star
72

evse

C++
1
star
73

SpinalBlackiceMx

Examples using SpinalHDL on the Blackice Mx ice40 board
Scala
1
star
74

rephone-client

HouseControl client for Seeedstudio RePhone
Arduino
1
star
75

respeaker-apps

Python apps for the Seeedstudio Respeaker
Python
1
star
76

blackicemx_altair_8800

Altair 8800 on the Blackice MX ice40 FPGA board
Verilog
1
star
77

binxt_verilog_examples

Verilog examples for the Blackice Nxt ice40 FPGA board
Verilog
1
star
78

yquest

Version of chibiakumas's Y-Quest game for 68k computers
Assembly
1
star
79

SpinalBlackice

A version of SpinalTemplateSbt with examples for the myStorm Blackice II board
Scala
1
star
80

esp8266-lua

Nodemcu Lua code for my devices
Lua
1
star
81

piglowd

A daemon for PiGlow
C
1
star