This tutorial explains how to:
- Install MSYS2 on Windows
- Install MinGW64 build tools
- Install Python (MinGW64)
- Install pyserial
- Install xPack RISC-V Embedded GCC (required for RISC-V firmware compilation)
- Configure the Makefile to use the correct Python interpreter
- Build the firmware
- Flash the firmware using
make program - Install processing 4.4.10
- Use dataset form processing_gng_dataset folder
This documentation is intended for the fpga_gng/picotiny project.
Download from:
Install using default settings.
After installation, open MSYS2 MinGW64 terminal, not MSYS or UCRT64.
Run:
pacman -Syu
Close MSYS2 → reopen MinGW64 terminal → run again:
pacman -Syu
Install development tools:
pacman -S --needed base-devel
pacman -S --needed mingw-w64-x86_64-toolchain
Verify installation:
make --version
gcc --version
Install Python for MinGW64:
pacman -S mingw-w64-x86_64-python
Check:
/mingw64/bin/python --version
pacman -S mingw-w64-x86_64-python-pyserial
Test:
/mingw64/bin/python -c "import serial; print('OK')"
If it prints “OK”, pyserial is correctly installed.
Download from:
👉 https://xpack.github.io/riscv-none-embed-gcc/
Choose the Windows .zip release (not installer).
Example folder path after extraction:
C:\xpack-riscv-none-embed-gcc\bin
Add this folder to PATH inside MSYS2.
Edit your ~/.bashrc:
nano ~/.bashrc
Add:
export PATH="/c/xpack-riscv-none-embed-gcc/bin:$PATH"
Reload:
source ~/.bashrc
Check:
riscv-none-elf-gcc --version
You should see xPack GCC version info.
git clone https://github.com/yourname/fpga_gng.git
cd fpga_gng/picotiny
MSYS2 has two Python versions:
| Interpreter | Path | pyserial support |
|---|---|---|
| MSYS Python | /usr/bin/python |
❌ does NOT work |
| MinGW64 Python | /mingw64/bin/python |
✔ works |
Edit the Makefile:
Find:
PYTHON = python
Replace with:
PYTHON = /mingw64/bin/python
Or (recommended):
PYTHON ?= /mingw64/bin/python
install pyserial
pacman -S mingw-w64-x86_64-python-pyserial
Run:
make
The compiled bitstream will be generated in:
fw/fw-flash/build/fw-flash.v
Connect your RP2040/PicoTiny board via USB (COM port).
Run:
make program
If needed, override Python manually:
make PYTHON=/mingw64/bin/python program
Or directly:
/mingw64/bin/python sw/pico-programmer.py fw/fw-flash/build/fw-flash.v COM14
Change COM1 to your actual port.
you need to get neorv32 first, well currently i'm using v1.12.5
git clone https://github.com/tzf230201/fpga_gng.git
cd fpga_gng
git clone https://github.com/stnolting/neorv32.git
or use the same version as me, download zip version and extract, and rename the folder to neorv32
https://github.com/stnolting/neorv32/releases/tag/v1.12.5
and my reference for implementing neorv32 in tang nano 9k is form this
https://github.com/jimmyw/tang_nano_9k_neorv32
but it seemslike the code kind of old version, so several things is not compatible anymore, especially for bootloader.
so i decided to build a new one, i plan to have different direction with mr.jimmyw, i want to make it more arduino like.
btw i also want to give credit to this
https://github.com/grughuhler/picorv32_tang_nano_unified
for the original version of uart_upload.py, but, i modify the code based to be compatible with newer bootloader version.
many thanks.
to compile the firmware you can do this
cd gng_neorv32
cd fw
make exe
python3 uart_upload.py /dev/ttyUSB0 neorv32_exe.bin
let's get back to neorv32,
so neorv32 is an FPGA based CPU by Mr. Stephan Nolting i like it becuse it's super customable, you can make it only have 1 uart or 2 uart, how many pwm output, how many spi and so on.
for now i'm talk about implementing neorv32 in gowin fpga.
but the main problem is, all the code of neorv32 is in VHDL. so there is no non-volatile memory inside the design of CPU.
so, the only way to program this CPU is to embed it into HDL code.
or, boot from external memory, such as, spi flash, uSD card, and so on.
there is an option to boot via UART, but, right after the power loss, the instructions gone.
if we embed to hdl it's okay, the boot will still there even though power loss, but the problem is when we change the code, we need to sinthesize again and over again, this take so much time compare to compile via UART.
so for UART boot: adventage: faster, only compile and send via uart time consuming disadvantage: the code gone when power loss.
for HDL embed boot: advantange: the code still there when power loss disadventage: slower, time consuming to convert .bin to hdl + re-synthesis and re-"place and root" the hdl files.
so what is the best way for now?
we need an external memory for store the instruction.
fortunately, gowin FPGA came with user flash memory, we can use that to store code from UART.
but another problem is, how to make it boot from user flash if uart not exist.
so we modified the bootloader, you can see "erase" function, that didn't exist before, we need that to clean up the memory before overwrite newer firmware on it,
the most important things is
- base address
- page size
- uflash num pages.
these value is related to in uflash configuration in the top vhdl file. if we use another board, we have to change the size in boorloader main.c file
#define UFLASH_BASE_ADDR ((uint32_t)0x00000000u)
#define UFLASH_PAGE_SIZE ((uint32_t)2048u)
#define UFLASH_NUM_PAGES ((uint32_t)38u)
and file and in the top vhdl file.
UFLASH_BASE : std_logic_vector(31 downto 0) := x"00000000";
UFLASH_END : std_logic_vector(31 downto 0) := x"00013000" -- 38 pages * 2048 bytes
because of that, the uart_upload.py have to change, we need to add erase function.
anyway, about the firmware, we have to adjust the rom (imem) and ram (dmem) size in the makefile according to our settings in vhdl. because we are using uflash right now, in top vhdl file, imem side is 0, but rom size follow uflash size.
# Adjust processor IMEM size
USER_FLAGS += -Wl,--defsym,__neorv32_rom_size=72k
# Adjust processor DMEM size
USER_FLAGS += -Wl,--defsym,__neorv32_ram_size=16k

