My adventure on trying to control a
- Colorlight 5A-75E v8.0 board
- Featuring a Lattice ECP5 FPGA
- Running a RISC-V SoC
- Built with LiteX
- Running custom firmware written in Rust 🦀
- Built with LiteX
- Running a RISC-V SoC
- Featuring a Lattice ECP5 FPGA
Everything with open-source tools!
soc.py
builds FPGA bitstream with LiteX containing a simple RISC-V SoC to run firmware.
build bitstream and generate needed files with:
python3 soc.py --build --cpu-type vexriscv --csr-svd "./litex-pac/5a-75e_6.0.svd"
notes:
5a-75e_6.0.svd
will be overwritten and used later for the litex pac (peripheral access crate).- you can use
--memory-x "../litex-pac/memory.x"
, however, I encountered many issues with the provided memory file, so I created my own one aroundregions.ld
(see #firmware).
flash fpga with:
python3 soc.py --load --no-compile-software
Firmware is built after SoC is also built, because it will depend on the memory regions defined at regions.ld
(generated by LiteX).
- firmware/memory.x: defines memory regions and interrupt handlers
- firmware/build.rs: when
memory.x
orregions.ld
change, we need to rebuild and put the linker script somewhere the linker can find it (with firmware/.cargo/config)
cd firmware
BUILD_DIR=../build/colorlight_5a_75e cargo build --release
When running cargo run
, by default, cargo will try to upload the generated .bin
via firmware/.cargo/flash.sh. However, if you want to simulate, you can change config.runner
to run firmware/.cargo/sim.sh.
DEVICE=/dev/ttyUSB0 cargo run
Make sure to adjust DEVICE
to your needs, since firmware .bin
is uploaded via UART.
When building the SoC, LiteX generates the svd
file for us. With this, we can use svd2rust
to create our PAC in order to access and manipulate the system. The PAC will use its build.rs
to do this automatically.
- Colorlight-5A-75E datasheet
- roby2014/risc-v-colorlight-5a-75e: similar example, but flashing C firmware
- pepijndevos blog post: helped a lot in this journey
- roby2014 blogpost #1: JTAG pin mapping for flashing bitstream
- roby2014 blogpost #2: UART pin mapping for flashing firmware