.. | ||
source | ||
system_pll | ||
.gitignore | ||
neorv32_dmem.ice40up_spram.vhd | ||
neorv32_imem.ice40up_spram.vhd | ||
neorv32_upduino_v3_top.vhd | ||
neorv32_upduino_v3.pdc | ||
neorv32_upduino_v3.rdf | ||
README.md |
NEORV32 Example Setup for the tinyVision.ai Inc. "UPduino v3.0" FPGA Board
This example setup turns the UPduino v3.0 board, which features a Lattice iCE40 UltraPlus FPGA, into a medium-scale NEORV32 microcontroller. The processor setup provides 64kB of data and instruction memory, an RTOS-capable CPU (privileged architecture) and a set of standard peripherals like UART, TWI and SPI.
- FPGA Board: 📚 tinyVision.ai Inc. UPduino v3 FPGA Board (GitHub), 💳 buy on Tindie
- FPGA: Lattice iCE40 UltraPlus 5k
iCE40UP5K-SG48I
- Toolchain: Lattice Radiant (tested with Radiant version 3.0.0), using Lattice Synthesis Engine (LSE)
- Top entity:
neorv32_upduino_v3_top.vhd
(instantiates NEORV32 top entity)
Processor Configuration
- CPU:
rv32imacu_Zicsr_Zicntr
(reduced CPU[m]instret
&[m]cycle
counter width!) - Memory: 64 kB instruction memory (internal IMEM), 64 kB data memory (internal DMEM), 4 kB bootloader ROM
- Peripherals:
GPIO
,MTIME
,UART0
,SPI
,TWI
,PWM
,WDT
,TRNG
- Clock: 24 MHz from on-chip HF oscillator (via PLL)
- Reset: via PLL "locked" signal; external "reset" via FPGA re-reconfiguration pin (
creset_n
) - Tested with processor version
1.6.1.6
- On-board FPGA bitstream flash storage can also be used to store/load NEORV32 application software (via the bootloader)
ℹ️ This setup uses optimized platform-specific memory modules for the internal data and instruction memories (DMEM & IMEM). Each memory uses two
UltraPlus SPRAM primitives (total memory size per memory = 2 x 32kB = 64kB). VHDL source file for platform-specific IMEM:
neorv32_imem.ice40up_spram.vhd
;
VHDL source file for platform-specific DMEM: neorv32_dmem.ice40up_spram.vhd
.
These platform-specific memories are used instead of the default platform-agnostic modules from the core's rtl/core/mem
folder.
Interface Signals
ℹ️ See neorv32_upduino_v3.pdc
for the FPGA pin mapping.
Top Entity Signal | FPGA Pin | Package Pin | Board Header Pin |
---|---|---|---|
flash_csn_o (spi_cs[0]) |
IOB_35B | 16 | J3-1 |
flash_sck_o |
IOB_34A | 15 | J3-2 |
flash_sdo_o |
IOB_32A | 14 | J3-3 |
flash_sdi_i |
IOB_33B | 17 | J3-4 |
gpio_i(0) |
IOB_3B_G6 | 44 | J3-9 |
gpio_i(1) |
IOB_8A | 4 | J3-10 |
gpio_i(2) |
IOB_9B | 3 | J3-11 |
gpio_i(3) |
IOB_4A | 48 | J3-12 |
gpio_o(0) (status LED) |
IOB_5B | 45 | J3-13 |
gpio_o(1) |
IOB_2A | 47 | J3-14 |
gpio_o(2) |
IOB_0A | 46 | J3-15 |
gpio_o(3) |
IOB_6A | 2 | J3-16 |
- | - | - | - |
reconfigure FPGA ("reset") | CRESET | 8 | J2-3 |
pwm_o(0) |
gpio_i(0) (red) |
RGB2 | 41 |
pwm_o(1) (green) |
RGB0 | 39 | J2-6 |
pwm_o(2) (blue) |
RGB1 | 40 | J2-7 |
twi_sda_io |
IOT_42B | 31 | J2-9 |
twi_scl_io |
IOT_45A_G1 | 37 | J2-10 |
spi_sdo_o |
IOT_44B | 34 | J2-11 |
spi_sck_o |
IOT_49A | 43 | J2-12 |
spi_csn_o (spi_cs[1]) |
IOT_48B | 36 | J2-13 |
spi_sdi_i |
IOT_51A | 42 | J2-14 |
uart_txd_o (UART0) |
IOT_50B | 38 | J2-15 |
uart_rxd_i (UART0) |
IOT_41A | 28 | J2-16 |
ℹ️ The TWI signals (twi_sda_io
and twi_scl_io
) and the reset input (rstn_i
) require an external pull-up resistor.
GPIO output 0 (gpio_o(0)
, also connected to the RGB drive) is used as output for a high-active status LED driven by the bootloader.
FPGA Utilization
Number of slice registers: 1754 out of 5280 (33%)
Number of I/O registers: 11 out of 117 (9%)
Number of LUT4s: 4882 out of 5280 (92%)
Number of DSPs: 0 out of 8 (0%)
Number of I2Cs: 0 out of 2 (0%)
Number of High Speed OSCs: 1 out of 1 (100%)
Number of Low Speed OSCs: 0 out of 1 (0%)
Number of RGB PWM: 0 out of 1 (0%)
Number of RGB Drivers: 1 out of 1 (100%)
Number of SCL FILTERs: 0 out of 2 (0%)
Number of SRAMs: 4 out of 4 (100%)
Number of WARMBOOTs: 0 out of 1 (0%)
Number of SPIs: 0 out of 2 (0%)
Number of EBRs: 15 out of 30 (50%)
Number of PLLs: 1 out of 1 (100%)
FPGA Setup
- start Lattice Radiant (in GUI mode)
- click on "open project" and select
neorv32_upduino_v3.rdf
from this folder - click the ▶️ button to synthesize, map, place and route the design and to generate a programming file
- when done open the programmer (for example via "Tools" -> "Programmer"); you will need a programmer configuration, which will be created in the next steps; alternatively,
you can use the pre-build configuration
source/impl_1.xcf
- in the programmer double click on the field under "Operation" (fast configuration should be the default) and select "External SPI Memory" as "Target Memory"
- select "SPI Serial Flash" under "SPI Flash Options / Family"
- select "WinBond" under "SPI Flash Options / Vendor"
- select "W25Q32" under "SPI Flash Options / Device"
- close the dialog by clicking "ok"
- click on "Program Device"