Skip to main content

C0-microSD Modes and Custom Bitstream

The C0-microSD doubles as an open FPGA development board. In addition to the Signaloid SoC coprocessor mode, it supports a bootloader mode, mode switching, and custom user bitstreams, taking advantage of the iCE40 warmboot capability to reconfigure the FPGA from multiple stored images.

Modes of operation

The C0-microSD has three distinct modes of operation, also called active configurations:

  1. Bootloader mode: flash custom bitstreams, update the C0-microSD firmware, and flash user data to non-volatile memory.
  2. Signaloid SoC mode: load and run C/C++ applications on the Signaloid SoC, optionally using UxHw technology.
  3. Custom user bitstream mode: load the latest custom user bitstream onto the device.

Modes 1 and 2 are used with a host device that communicates over the SD interface. Mode 3 is for using the C0-microSD as a standalone FPGA module.

The built-in Bootloader is always the first configuration to load. Following the boot order logic below, it either stays in Bootloader mode, switches to the Signaloid SoC configuration, or loads the Custom User Bitstream.

C0-microSD boot order logic

Identifying the active mode

When the C0-microSD is powered on and connected to a host:

  • Bootloader mode: the red LED is solid.
  • Signaloid SoC mode: the green LED is solid.

When powered on without a host present, the C0-microSD loads the Custom User Bitstream; LED behavior is then entirely determined by that bitstream.

C0-microSD in Bootloader modeC0-microSD in Signaloid SoC mode
Bootloader mode (solid red LED)Signaloid SoC mode (solid green LED)

Switching between modes

Switching between modes 1 and 2 requires writing to a predefined offset over the SD interface. The C0-microSD stores the new setting in its on-board SPI flash and enters the SWITCHING state; you must power-cycle the device for the change to take effect. Once in the SWITCHING state, the LED that was not solid begins to blink, indicating the mode the device will boot into next.

For the step-by-step procedure, see Switch Between Operation Modes. Programmatically, write the 4-byte ASCII word SBLD to BOOTLOADER_SWITCH_CONFIG_OFFSET.

Bootloader and addressing

In Bootloader mode, you communicate with the device through block read and write operations at the following flash address offsets:

Address spaceOffsetSizeOperationDescription
CONFIGURATION_ID_OFFSET0x0200004 bytesRActive configuration ID
CONFIGURATION_VERSION_OFFSET0x0200044 bytesRActive configuration version
CONFIGURATION_STATE_OFFSET0x0200084 bytesRActive configuration state
OTP_SECTOR_OFFSET0x022000512 bytesRNon-volatile memory OTP sector
BOOTLOADER_UNLOCK_OFFSET0x0600004 bytesWLock / unlock the bootloader
BOOTLOADER_BITSTREAM_OFFSET*0x080000512 KiBR/W**Bootloader bitstream region
SIGNALOID_CORE_BITSTREAM_OFFSET*0x100000512 KiBR/W**Signaloid SoC bitstream region
USER_BITSTREAM_OFFSET*0x200000512 KiBR/WCustom user bitstream region
USER_DATA_OFFSET*0x28000013 MiBR/WUser data region
BOOTLOADER_SWITCH_CONFIG_OFFSET0xF800004 bytesWSwitch operation mode

* Address space corresponds to on-board flash memory data. ** Address space must be unlocked before writing.

Key offsets:

  • CONFIGURATION_ID_OFFSET identifies the active configuration as a 4-byte ASCII word, SBLD for Bootloader and SSOC for Signaloid SoC.
  • CONFIGURATION_VERSION_OFFSET holds the version of that configuration, with the major version in its first two bytes and the minor version in its last two.
  • OTP_SECTOR_OFFSET exposes the one-time-programmable sector holding the device serial number and UUID.
  • BOOTLOADER_UNLOCK_OFFSET: the bootloader and Signaloid SoC bitstream regions are locked by default to prevent accidental overwrites that could render the device inoperable. Write the ASCII word UBLD to unlock, and write anything else to lock again. The unlock does not survive a power cycle, so unlock the regions again after the module powers up.
  • USER_DATA_OFFSET: a 13 MiB region for data or binaries. The Signaloid SoC initializes its memory by copying the first 128 KiB of this region before execution.
note

The SD interface mandates read and write support across the entire address space, which differs from the per-region operations above. For R regions, writes succeed but have no effect. For W regions, reads return invalid data. Any address space not listed above should be treated as not applicable (N/A): reads return invalid data and writes have no effect.

Write and erase semantics

The C0-microSD writes its flash in whole 4 KiB sectors. Writing a sector replaces all 4 KiB of it, so each write discards whatever the rest of that sector held.

Write each sector completely, starting at a 4 KiB-aligned offset and running from the first byte of the sector to the last. Two behaviors follow from that rule, and the module reports neither of them as an error.

  • The module discards a partial sector. When a transfer ends before the last byte of a sector, the module writes nothing at all.
  • The module does not preserve skipped bytes. Bytes that you leave out of the transfer do not keep the previous contents of the sector, so write every byte of every sector.

Most hosts meet this requirement without any effort on your part. A full-size SD host controller usually issues writes in whole aligned blocks of at least 4 KiB, so flashing from a computer behaves as you expect. A host that uses SD over SPI, typically a microcontroller, transfers 512 bytes at a time and must group eight of those transfers into each complete 4 KiB sector.

warning

Never remove power while a flash write is in progress. A sector caught part way through an erase or a program holds neither its old contents nor its new contents.

note

Flash writes reach the device only in Bootloader mode. In Signaloid SoC mode nothing writes the flash, from the host or from the device application, apart from the mode switch described above.

Custom user bitstream flow

Using the C0-microSD as a programmable FPGA SoM does not require switching modes, you only need the device in Bootloader mode. Once powered on without an SD host, the bootloader loads the latest custom user bitstream. In this configuration the C0-microSD offers six configurable I/O pins (by repurposing the microSD pads) plus five test-pad I/O pins.

To flash a bitstream to the custom user bitstream region, use the C0_microSD_toolkit.py script from the Signaloid-Compute-Module-Utilities repository. On a macOS host with the device at /dev/disk4:

sudo python3 C0_microSD_toolkit.py -t /dev/disk4 -b bitstream.bin

Flashing the custom user bitstream is the default operation of the script, so -b with no mode flag targets the custom user bitstream region. See Flash the C0-microSD for the full flashing reference.

Example RTL designs, along with build and flash instructions, are in the rtl-examples/ directory of the C0-microSD-Hardware repository.

Next steps