🛠 Deploying an IoT Node with Sapphire RV64: Network and Storage
Objectives
This tutorial aims to configure the Sapphire RV64 SoC for a typical industrial IoT use case: data acquisition via peripheral interfaces (SPI/I2C) and network transmission. We will illustrate how to exploit the configurable architecture to allocate necessary memory resources and interfaces, focusing on AXI4/APB3 bus integration and external memory management.
Required Hardware
- A compatible Efinix FPGA board (Titanium, Topaz, or Trion, T20 or higher).
- Efinity software version 2026.1 or newer.
- A compatible external memory module (DDR3, LPDDR4x, or HyperRAM) connected to the FPGA.
- Wiring for GPIO, SPI, and I2C interfaces according to your test schematic.
- A RISC-V development environment (RISC-V GCC compiler, OpenOCD).
Steps
- VexiiRiscv Core Configuration: In Efinity, instantiate the Sapphire RV64 IP block. Select the VexiiRiscv core. Enable the
RV64IMACFDextensions for floating-point support (sensor calculations) andZba_Zbc_Zbsfor bit-operation optimization. If your application requires a full OS, enable the SV39 MMU.
- Memory Allocation: Configure the on-chip RAM to 64 KB for the stack and critical variables. For storing logs or network buffers, connect the external memory. For example, if using HyperRAM (500 Mbps), configure the corresponding interface controller in the IP block. Ensure the L1 cache is enabled to reduce access latency.
- Bus Interconnection: Connect the core to peripherals via the AXI4 bus for high speeds (external memory) and APB3 for slow peripherals (UART, GPIO). Map memory addresses for I2C peripherals (up to 5 masters available) and SPI (3 masters).
- Bitstream Generation: Synthesize the design. Verify that timing is met, especially if targeting the maximum frequency of 400 MHz. Upload the bitstream to the FPGA.
- Software Development: Write the firmware in C. Use provided drivers to initialize SPI interfaces to read a sensor. Buffer data in external memory. Implement a lightweight TCP/IP stack (like lwIP) using the network interface (if available via GPIO/SPI Ethernet or external module) to transmit data.
Verification
Use the standard RISC-V debugger via OpenOCD. Place hardware breakpoints (up to 4 available) in the data acquisition routine. Verify via a logic analyzer that SPI/I2C signals are correct. Confirm that data is correctly written to external memory by reading the corresponding addresses via the debugger.
Further Reading
Explore the use of the shared L2 cache (64 to 512 KB) to accelerate memory access in multi-core mode (up to 4 cores). You can also test performance with double-precision floating-point extensions for embedded signal processing.
Other tutorials for this board
Code examples for this board
gpio_blink_riscv.inoC (RISC-V)uart_echo_riscv.inoC (RISC-V)spi_sensor_read.inoC (RISC-V)i2c_master_write.inoC (RISC-V)timer_interrupt_handler.inoC (RISC-V)i2c-bmp280-temperature-6.inoC