| Package import | "zappem.net/pub/io/pico2ice" |
|---|---|
| Documentation | https://pkg.go.dev/zappem.net/pub/io/pico2ice |
| Sources | https://github.com/tinkerator/pico2ice |
The pico2-ice board features a RP2350B microcontroller and a iCE40UP5K FPGA. This package provides some APIs for setting up these devices.
Light up the pico2-ice onboard LEDs including the use of the
hello.bin FPGA bitstream logic.
SW1 button (on the pico2 board, this button is labeled
BOOTSEL). This is a little awkward to do in practice, but it
should only be needed the first time. The bootloader re-program
ready state is a single LED shows “white” (all three RGB LEDs lit)
and once you see that, you can let go of the SW1 button. The
board is now patiently waiting for the tinygo flash command
below.Perform the following:
$ git clone https://github.com/tinkerator/pico2ice.git
$ cd pico2ice/examples
$ ~/go/bin/tinygo flash -target=pico2-ice -scheduler tasks cram.go && ~/go/bin/tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
Hello, World!
FPGA program running (flashing FPGA Blue LED)
Blinking the RP Tricolor LEDs randomly
Once flashed, the RP2350B starts running and briefly flashes the Red
RP LED while the cram-load of the hello.bin FPGA bitstream is
injected into the FPGA. When this is successful, a Green LED
illuminates to indicate that the FPGA is programmed. The cram.go
program then lets the FPGA logic run causing it to rapidly flash its
Blue LED. After this, and indefinitely, the cram.go code randomly
flashes one color at a time of the RP2350B connected Tricolor LED.
Part of the pico2ice package is generated code. The input for this
generation is the collection of .pio files in the pio/ directory:
pio/clock.pio a 2-cycle clock output (pico2: 75 MHz)pio/spi.pio a simple SPI read and write transfer loop (pico2 6.25 MHz)To rebuild the pio.go file (assuming that you are in the
pico2ice/examples directory), do the following:
$ cd ../../
$ git clone https://github.com/tinkerator/pious.git
$ cd pious
$ go install examples/piocli.go
This downloads the pious package
sources and installs the built tool in ~/go/bin/piocli. Go back to
the pico2ice sources and run this tool:
$ cd ../pico2ice
$ ~/go/bin/piocli --src=pio/spi.pio,pio/clock.pio --name pico2ice --tinygo > pio.go
This shouldn’t cause the file to change, but you can review if it has with:
$ git diff pio.go
The examples/hello.bin file is an FPGA bitfile for the ice40 chip on
the pico2-ice board. It is built from a verilog file present in the
v/ directory.
To convert v/hello.v into a hello.bin file we use the yosys
toolchain. Specifically the tools yosys, nextpnr-ice40 and
icepack.
NOTE on Fedora, these tools are to be found in the yosys,
icestorm and nextpnr packages. On Debian, these tools are to be
found in the yosys, fpga-icestorm and nextpnr packages.
In the v/ working directory do the following to rebuild the
hello.bin file:
$ yosys -p "synth_ice40 -top top -json hello.json" hello.v
$ nextpnr-ice40 --up5k --package sg48 --json hello.json --pcf hello.pcf --asc hello.asc
$ icepack hello.asc hello.bin
hello.pcf file is a script to map the pins these
cram.go + hello.v (and comm.v) examples use. The full FPGA
pinout file is referenced in a comment in that hello.pcf file, and
conveniently here
too.If you want to replace the default build of this file with the one made above, you can do this:
$ cp hello.bin ../examples
A more ambitious verilog file is v/comm.v. This pays attention to
runtime attempts by the cram.go code to control the FPGA LED from
the RP2350B microcontroller program. Namely, its attempts to set the
FPGA LED with an SPI command from the microcontroller code. To build
and install this FPGA bitfile, cd v/ and run the following
commands:
$ yosys -p "synth_ice40 -top top -json hello.json" comm.v
$ nextpnr-ice40 --up5k --package sg48 --json hello.json --pcf hello.pcf --asc hello.asc
$ icepack hello.asc hello.bin
$ cp hello.bin ../examples
Then, from the ../examples directory, this command will generate
some output like this (9 wrote + read values will be displayed):
$ ~/go/bin/tinygo flash -target=pico2-ice -scheduler tasks cram.go && ~/go/bin/tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
Hello, World!
FPGA program running (flashing FPGA Blue LED)
Blinking the RP Tricolor LEDs randomly
wrote: 2 read: 0
wrote: 4 read: 2
wrote: 1 read: 4
wrote: 2 read: 1
wrote: 4 read: 2
wrote: 1 read: 4
wrote: 2 read: 1
wrote: 4 read: 2
wrote: 1 read: 4
and will cause the FPGA to mirror the last set microcontroller LED color. The 9 read values here should match the prior line’s write value. The 0 initially read value is just reflecting the fact that the reset value is 0 for the 3 bit FPGA LED setting.
hello.v logicTypically, to simulate logic, you have some test wrapper for that
logic. In the hello.v case we have included the hello_test.v
file. To perform that test, we use the Icarus
Verilog suite. Most
specifically, the iverilog and vvp tools. We can also use GTKWave
(the gtkwave tool).
NOTE on Fedora and Debian, these tools are to be found in the
iverilog and gtkwave packages.
To build the test binary (generate a.out) and run it do the
following:
$ iverilog hello_test.v hello.v
$ ./a.out
VCD info: dumpfile dump.vcd opened for output.
end of test
You can view this dump.vcd file with
GTKWave,
and also with the twave
tool. To only look at the top level signals with that text based tool
we can do the following:
$ ~/go/bin/twave --file dump.vcd --syms hello_test.top.clk,hello_test.reset,hello_test.red,hello_test.green,hello_test.blue
[] : [$version Icarus Verilog $end]
hello_test.green-+
hello_test.red-|-+
hello_test.blue-|-|-+
hello_test.reset-|-|-|-+
hello_test.top.clk-|-|-|-|-+
| | | | |
2025-11-08 15:29:26.000000000000 1 1 x x x
2025-11-08 15:29:26.000000010000 1 1 x 1 0
2025-11-08 15:29:26.000000020000 1 1 x 1 0
2025-11-08 15:29:26.000000030000 1 1 x 1 1
2025-11-08 15:29:26.000000040000 1 1 x 0 1
2025-11-08 15:29:26.000000050000 1 1 x 0 0
2025-11-08 15:29:26.000000060000 1 1 x 0 0
2025-11-08 15:29:26.000000070000 1 1 0 0 1
2025-11-08 15:29:26.000000080000 1 1 0 0 1
2025-11-08 15:29:26.000000090000 1 1 0 1 0
2025-11-08 15:29:26.000000100000 1 1 0 1 0
2025-11-08 15:29:26.000000110000 1 1 0 1 1
2025-11-08 15:29:26.000000120000 1 1 0 1 1
2025-11-08 15:29:26.000000130000 1 1 0 1 0
2025-11-08 15:29:26.000000140000 1 1 0 1 0
2025-11-08 15:29:26.000000150000 1 1 0 1 1
2025-11-08 15:29:26.000000160000 1 1 0 1 1
2025-11-08 15:29:26.000000170000 1 1 0 1 0
2025-11-08 15:29:26.000000180000 1 1 0 1 0
2025-11-08 15:29:26.000000190000 1 1 0 1 1
2025-11-08 15:29:26.000000200000 1 1 0 1 1
2025-11-08 15:29:26.000000210000 1 1 0 1 0
2025-11-08 15:29:26.000000220000 1 1 0 1 0
2025-11-08 15:29:26.000000230000 1 1 1 1 1
2025-11-08 15:29:26.000000240000 1 1 1 1 1
2025-11-08 15:29:26.000000250000 1 1 1 1 0
2025-11-08 15:29:26.000000260000 1 1 1 1 0
2025-11-08 15:29:26.000000270000 1 1 1 1 1
2025-11-08 15:29:26.000000280000 1 1 1 1 1
2025-11-08 15:29:26.000000290000 1 1 1 1 0
2025-11-08 15:29:26.000000300000 1 1 1 1 0
2025-11-08 15:29:26.000000310000 1 1 1 1 1
2025-11-08 15:29:26.000000320000 1 1 1 1 1
2025-11-08 15:29:26.000000330000 1 1 1 1 0
2025-11-08 15:29:26.000000340000 1 1 1 1 0
2025-11-08 15:29:26.000000350000 1 1 1 1 1
2025-11-08 15:29:26.000000360000 1 1 1 1 1
2025-11-08 15:29:26.000000370000 1 1 1 1 0
2025-11-08 15:29:26.000000380000 1 1 1 1 0
2025-11-08 15:29:26.000000390000 1 1 0 1 1
2025-11-08 15:29:26.000000400000 1 1 0 1 1
This list of bit values over time tracks the clock starting up, the logic reset and eventually the Blue LED starting to toggle on and off.
The default tinygo package might be very old, and not include
support for the pico2-ice board. To remedy this, you can install a
fresh compile of the tinygo dev branch.
On Fedora install some packages (the first expands to most of the needed dependencies):
$ sudo dnf install tinygo clang-devel
On Debian, any go version older than 1.22 will not build. In truth, I’ve not yet been able to build tinygo on a Debian system (have only tried Bookworm 12). My best guess is. Install a better go revision. Also, install these dependencies:
$ sudo apt install llvm-dev libclang-dev
Then:
$ git clone https://github.com/tinygo-org/tinygo.git
$ cd tinygo/
$ git checkout dev
$ git submodule update --init --recursive
$ make llvm-source
$ make gen-device
The final step depends on which Linux distribution version you have:
| Linux distribution | command |
|---|---|
| Fedora 41 | $ go install --tags llvm19 |
| Fedora 42 | $ go install --tags llvm20 |
| Fedora 43 | $ go get tinygo.org/x/go-llvm && go install --tags llvm21 |
| Debian 12 (bookworm) | ? $ go install --tags llvm20 |
Then, to verify that the program installed correctly:
$ ~/go/bin/tinygo
Nothing planned. Currently, the tinygo code cannot take advantage of
the dual core nature of the RP2350B chip because of tinygo bug
4974 there is also
some issue with
llvm21. At some
point those problems will be fixed and these instructions will drop
the use of the -scheduler tasks compilation flags.
This is a personal project aiming at exploring the capabilities of the pico2-ice board. As such, no support can be expected. That being said, if you find a bug, or want to request a feature, use the github pico2ice bug tracker.
See the LICENSE file: the same BSD 3-clause license as that used by golang itself.