Seyed Masoud Hosseini · Overview · Study log · Ideas · Transcript · RSS feed
FPGA & Verilog Design · Lecture 11 of 12 · 23:06
Part 11: RISC-V Softcore Processor
Study guide
What this lecture covers
This lecture answers how to run actual software on an FPGA rather than hand-designed logic, by building an existing open-source RISC-V processor (FemtoRV, by Bruno Levy) for the iCEstick and writing a small C program for it. It covers installing the required toolchain on a Raspberry Pi running Linux, configuring FemtoRV's board-specific settings, and understanding how the processor talks to hardware peripherals through memory-mapped I/O addresses.
By the end you can build and upload the FemtoRV system-on-a-chip to the iCEstick, write a C program using its header-provided macros to control the LEDs and print to a serial console, and compile and upload firmware with make main.prog. The lecture sets a challenge to enable and test the buttons as inputs, and previews building a custom hardware peripheral next.
Key ideas
- RISC-V: an open instruction set architecture with no licensing fees, making it practical to implement and modify CPU designs on an FPGA for learning purposes.
- FemtoRV: a small RISC-V implementation by Bruno Levy aimed at learning and tinkering, chosen here (using its "quark" variant) because it fits the iCEstick's limited logic cells, unlike larger designs such as PicoRV32.
- System-on-a-chip (SOC) top level: the processor core is instantiated inside a top-level Verilog module (
femtosoc.v) alongside program memory, RAM, and driver modules for peripherals like LEDs and buttons. - Board configuration defines: a config header (for example
rtl/configs/config_icestick.v) enables or disables peripherals and sets RAM size and program storage location, tailored to what fits on a given board. - Program vs data memory: firmware is stored in external SPI flash and executed from there, while general-purpose RAM lives in the FPGA's block RAM.
- Memory-mapped I/O: peripherals like the LEDs don't exist as real memory; writing to a specific address (computed from an I/O base address plus a per-device bit offset) is intercepted by hardware and drives the corresponding driver.
- Toolchain build: this workflow requires building Yosys, Icarus Verilog, Project IceStorm, and nextpnr from source (in addition to a RISC-V compiler), and the lecture recommends Linux (a Raspberry Pi) since the available guides target it.
Walkthrough
Project overview and choosing FemtoRV (0:33)
The lecture compares available open RISC-V implementations for the iCE40, explaining that Claire Wolf's PicoRV32 needs more lookup tables than the iCEstick has to spare, while Bruno Levy's FemtoRV is built specifically for small boards. It tours the FemtoRV repository structure: RTL Verilog for the processor and SOC, device driver modules, and processor variants, noting the "quark" version (no interrupts) is used here.
Setting up the Raspberry Pi and cloning the repository (2:47)
Working over SSH on a Raspberry Pi, the lecture updates package lists and clones Bruno Levy's learn-fpga repository, following its iCEstick-specific tutorial for the rest of the installation.
Building Yosys, IceStorm, and nextpnr from source (3:44)
Even with apio's tools already installed, the lecture rebuilds Yosys, Icarus Verilog, Verilator, Project IceStorm, and nextpnr from source and installs them system-wide, since apio's copies aren't necessarily on the system path. It also adds a udev rule so Linux can talk to the iCEstick's FTDI chip over USB.
Configuring FemtoRV for the iCEstick (8:14)
In rtl/configs/config_icestick.v, unused peripherals (an IR receiver/transmitter, an OLED screen, an LED matrix) are commented out to save logic cells and I/O pins, the quark processor variant is selected, RAM size is set based on what's left after reserving space for processor registers, and firmware is configured to run from SPI flash rather than being preloaded into block RAM.
Memory-mapped I/O and writing the blinky program (13:27)
After building and uploading the SOC with make icestick, the lecture examines FemtoRV's header files to see how I/O addresses are computed from an I/O base address plus a per-device bit offset (for example, the LED address is 0x400004). A main.c program using the provided header's macros writes values to that address to turn LEDs on and off, uses a delay function, and prints text and CPU frequency over a serial connection.
Compiling, uploading, and the buttons challenge (19:40)
make main.prog compiles the C program for RISC-V and uploads it to SPI flash, and a serial terminal (picocom) at 115200 baud shows the printed output while the first two LEDs blink. The challenge is to enable button inputs by editing the SOC's Verilog and PCF file (using the SB_IO directive, since the -pullup PCF option doesn't work in this flow) and writing a C test program to read them.
Before you watch
- Complete Part 10 ("Metastability and Clock Domain Crossing") to finish the series' introductory portion before this soft-processor detour.
- Access to a Linux machine (the lecture uses a Raspberry Pi) is effectively required, since the FemtoRV toolchain build targets Linux.
- Basic C programming familiarity is assumed for writing the firmware.
Check your understanding
- Why does the lecture choose FemtoRV's "quark" variant over a larger RISC-V implementation like PicoRV32?
- Where does FemtoRV's program memory live versus its RAM, and why are they stored differently?
- How is a memory-mapped I/O address like the LED driver's
0x400004computed from the I/O base address and bit offset? - Why does the lecture rebuild Yosys and the other tools from source even if apio already installed them?
- What change is needed to the PCF file and Verilog to enable button inputs, according to the challenge?
Chapters
- 0:00 Introduction
- 0:33 Project Overview
- 2:47 Getting Started
- 3:44 Installing Yosis
- 5:25 Installing Project Icestorm
- 6:44 Installing Next PNR
- 16:10 Blinky
- 22:24 Conclusion
From the YouTube description
A field-programmable gate array (FPGA) is an integrated circuit (IC) that lets you implement custom digital circuits. You can use an FPGA to create optimized digital logic for things like digital signal processing (DSP), machine learning, and cryptocurrency mining. Because of the FPGA’s flexibility, you can often implement entire processors using its digital logic. You can find FPGAs in consumer electronics, satellites, and in servers used to perform specialized calculations.
In this series, we will see how an FPGA works and demonstrate how to create custom digital logic using the Verilog hardware description language (HDL).
Previously, we looked at how setup and hold time violations can cause metastability. In this episode, we build a RISC-V softcore processor for our FPGA and write a simple C test program for it.
Note: you will need Linux to follow along! I did everything on a Raspberry Pi 4, but any Debian-based flavor (e.g. Ubuntu) should work.
The solution to the challenge at the end of the episode can be found here: https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-11-risc-v-softcore-processor/f0511ddb538f444cae08f7bc43a74dcc
All code examples and solutions for this series can be found here: https://github.com/ShawnHymel/introduction-to-fpga
Bruno Levy’s learn-fpga FemtoRV repository: https://github.com/BrunoLevy/learn-fpga
Lattice Technology Library (contains SB_IO description): https://github.com/ShawnHymel/introduction-to-fpga/raw/main/datasheets/SBTICETechnologyLibrary201504.pdf
RISC-V is an open source instruction set architecture (ISA) that can be used to design processors without paying a licensing fee. As a result, it is a great way to implement a softcore processor in an FPGA to learn about how CPUs work.
Rather than construct a RISC-V processor from scratch (which would take an entire college course or a full series), we will use an existing implementation. Specifically, we will use Bruno Levy’s FemtoRV system-on-a-chip (SOC) core.
We disable a few hardware peripherals, such as the OLED and LED matrix drivers, as we won’t use them in this episode. We then build the SOC and upload it to the iCEstick. From there, we write a simple C program that blinks the onboard LEDs, compile it, and upload it to program memory. A section of the SPI flash memory is set aside to be the program memory for the iCEstick version of FemtoRV.
Your challenge is to modify the design to enable the buttons module and write a C program to demonstrate correct button operation. Note that the `-pullup yes` parameter does not work in the PCF file for this build system, so you will need to rely on the SB_IO directive instead.
Product Links:
https://www.digikey.com/en/products/detail/lattice-semiconductor-corporation/ICE40HX1K-STICK-EVN/4289604
Related Videos:
https://www.youtube.com/watch?v=z8Oldd-nrfs
https://www.youtube.com/watch?v=5kNXX67mchE
https://www.youtube.com/watch?v=iwcxLQ6AB88
Related Project Links:
https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-11-risc-v-softcore-processor/f0511ddb538f444cae08f7bc43a74dcc
Related Articles:
https://www.digikey.com/en/pdf/r/renesas-electronics-america/powering-fpga-applications
https://www.digikey.com/en/videos/d/dsp/edge-machine-deep-learning-on-fpga
Learn more:
Maker.io - https://www.digikey.com/en/maker
Digi-Key’s Blog – TheCircuit https://www.digikey.com/en/blog
Connect with Digi-Key on Facebook https://www.facebook.com/digikey.electronics/
And follow us on Twitter https://twitter.com/digikey
← Part 10: Metastability and Clock Domain Crossing · Part 12: RISC-V Custom Peripheral →
