web analytics
Skip to content
Elektronaut Blog

Solving the iCE40 / FT4222HQ Boot Conflict

I’ve been working on a project using Lattice’s iCE40 Ultra FPGAs, and they’re a fascinating platform. The iCE40 series stands out for its low cost, though you do trade off with available FPGA resources. Crucially for open-source enthusiasts, they are fully supported by the excellent Yosys and NextPNR open-source toolchains — I’ll dedicate a future post to diving into those tools.

iCE40 Configuration: The Modes of Operation

The iCE40 Ultra offers several ways to load its configuration, giving developers flexibility:

  1. SPI Master Mode: The FPGA acts as the master and loads its configuration directly from an attached external SPI flash memory. This is ideal for standalone systems.

  2. SPI Slave Mode: The FPGA acts as a slave and receives its configuration from an external host, like an Application Processor (APU).

  3. One-Time Programmable (OTP) Memory: A permanent, non-volatile option.

The decision between SPI Master and SPI Slave mode is made by the state of the line (sometimes labeled ) at power up.

The Problem: A Boot Failure Mystery

Since my design was intended to be standalone (no APU) and required in-system reprogramming, booting from an external SPI flash in SPI Master Mode was the logical choice.

I designed a PCB incorporating the iCE40 Ultra, an SPI flash chip, and an FTDI FT4222HQ device. The FT4222HQ was there purely to provide an easy USB-to-SPI bridge for programming the flash chip.

To my immense frustration, the FPGA would not boot correctly from the newly programmed flash.

The Culprit: The FTDI FT4222HQ

After significant debugging, I found the component at fault was, surprisingly, the FTDI FT4222HQ.

The problem wasn’t its operation while programming; the issue arose when the USB cable was disconnected — the intended state for standalone operation. Here’s the critical behavior: when the FT4222HQ loses its USB connection (i.e., the line goes low), it forcefully pulls down the signal

A permanently low line forces the iCE40 into . Since there’s no APU present to send it configuration data, the boot process stalls indefinitely. This crucial behavior was not documented in the ‘s datasheet or application notes, but the evidence on the scope was undeniable.

The Solution: Isolate the SPI_SS Line

The fix required preventing the from influencing the line when it wasn’t actively needed for programming. The simplest, most effective solution was to use a single transistor to conditionally connect the ‘s signal to the FPGA’s pin.

By sacrificing one of the ‘s general-purpose I/O (GPIO) pins, we gain control over the connection:

  • The ‘s pin controls the transistor’s state.

  • We only enable the transistor (connecting to ) when we are actively programming the flash via USB.

  • When programming is finished and the USB is unplugged, the is disabled, disconnecting the problematic line and allowing the to correctly interpret the state for booting.

The final circuit that is shown below, worked perfectly

I simply needed to remember that the pin must be pulled low to enable control of the signal, but this inversion is easily managed within the during the programming sequence.

This experience highlights a key lesson in embedded development: never trust a control line to be idle when an external device is powered down—always consider the off-state behavior, especially for critical boot signals like . Happy debugging!

Konstantin Schauwecker