Extra Content: Building SoCs with LiteX
These three tutorials are supplementary material, independent of Projects 1-3. They explore LiteX, a Python-based framework for building RISC-V SoCs on FPGAs, using pre-built components (a CPU, a UART, a Wishbone bus) instead of writing them from scratch.
Where your projects build a processor and its peripherals from the gate level up, LiteX lets you assemble a working SoC from existing building blocks in minutes, then extend it with your own SystemVerilog. Seeing both approaches - build-everything vs. assemble-from-parts - is a useful contrast for understanding the design space of real hardware/software systems (see Design Space & Alternatives).
LiteX targets the same board and toolchain you already have installed:
- Board: Sipeed Tang Nano 9K (same as Projects 1-3).
- Toolchain: OSS CAD Suite - Yosys, nextpnr-himbaechel, openFPGALoader (same as Lab 2). LiteX drives these tools for you.
- Cross-compiler: the RISC-V GCC toolchain from Lab 2 (verify the exact flags needed - noted per tutorial below).
The tutorials
Tutorials 1-3 are the core sequence. Tutorial 4 is a further-optional add-on within already-optional material - skip it freely if you're short on time or already comfortable with custom instructions from Project 2.
| Tutorial | What you do | Builds on |
|---|---|---|
| 1 - LiteX in simulation | Install LiteX, boot a pre-built RISC-V SoC in Verilator-based simulation, then compile and run your own small C program in that same simulation. | Lab 2 (Verilator), Lab 5 (C compilation) |
| 2 - LiteX on real hardware | Repeat Tutorial 1's two programs, now synthesized and running on your physical Tang Nano 9K. | Tutorial 1, Lab 2 (FPGA bring-up) |
| 3 - A custom peripheral on the Wishbone bus | Write a small peripheral in SystemVerilog, wire it into LiteX's Wishbone bus, and drive it from a C driver - verified in simulation and on hardware. | Tutorials 1-2, Project 2 (bus/peripherals) |
| 4 - A custom instruction via VexRiscv's CFU (optional) | Add a custom RISC-V instruction to VexRiscv through its built-in CFU port - a second way to do what Project 2's CMAC does by hand, on a CPU you didn't write yourself. | Tutorials 1-2, Project 2 (custom instructions) |
Toolchain setup (do this once, before Tutorial 1)
All three tutorials assume this is done first:
LiteX auto-detects a RISC-V toolchain by trying a fixed list of common prefixes and silently using the first one it finds on your PATH - if more than one is installed, it may not pick the one you expect, with no warning. This environment variable pins it explicitly to the xPack toolchain you already have from Lab 2, so no second RISC-V GCC install is needed for this track. If you've activated OSS CAD Suite's environment/activate script per Lab 2, also double-check python3 still resolves to the environment where LiteX is installed and not to a Python bundled with OSS CAD Suite - some distributions ship their own, which can shadow the one with litex installed if it lands ahead of it on PATH.
A note on this material
These tutorials were validated hands-on, end to end, on real Tang Nano 9K hardware, following the same reference-implementation methodology used for the rest of this course's material - several corrections below came directly out of that pass, including one that would have blocked Tutorial 3 from ever reaching real hardware (a SystemVerilog pattern that simulates fine but fails synthesis). If a step still doesn't match what you see on your machine, that's useful feedback, not necessarily something you did wrong - let the instructor know.
Tutorial 4's opcode encoding was likewise resolved and validated against real hardware, not guessed - see the tutorial itself for the one detail worth remembering: its custom opcode (custom-1) is not the same as the course's own CMAC opcode (custom-0), despite the similar idea.