FPGA Helper

A programming and communication interface for FPGAs

Public Chat
Similar projects worth following
This project is a combination of open source hardware and software that provide features commonly needed in FPGA designs, primarily: programming interface, USB communication, and analog signals. While there are solutions for all these features today, they are typically not available in a single solution and in many cases they are not open and may require closed source utilities that are only available for a limited number of platforms. This project is being designed to run on any operating system and being an open source project, the features of this project can be expanded over time to add additional utilities and support for more targets.

The goal of this project is to bring FPGA development one step closer to Adafruit easy.

This project is a combination of open source hardware and software that provide features commonly needed in FPGA designs, primarily: programming interface, USB communication, and analog signals.  This project is being designed to run on any operating system and being an open source project, the features of this project can be expanded over time to add additional utilities and support for more targets.


Since this project is intended to be used with any operating system, the initial target will be the Lattice iCE40 series since Project IceStorm is the only tool that runs on multiple operating systems.  IceStorm currently supports the iCE40 HX1K, HX8K, and UltraPlus.  The initial version of the FPGA-Helper board will be able to connect directly to the following boards:

Programming (SPI):

In order to provide "Adafruit easy" programming on multiple operating systems, the FPGA-Helper will allow for drag-n-drop programming using USB Flashing Format (UF2).  The initial version of the board has an SOIC 8 location that can be loaded with a larger flash device to allow for upgrading the size of the flash provided on the target board.

USB Communication (UART):

The FPGA-Helper will implement a standard USB-CDC virtual serial port that can be used for communication between the FPGA and a computer.

Analog I/O (I2C):

The FPGA-Helper will implement the seesaw protocol to give the FPGA access to additional peripherals in the programmer MCU.

  • 1 × NSR05F30NXT5G Discrete Semiconductors / Diodes and Rectifiers
  • 1 × FTSH-105-01-F-DV-K Connectors and Accessories / Board-to-Board and Card Edge Connectors
  • 1 × 61201021621 Electronic Components / Misc. Electronic Components
  • 1 × W25Q64JVSSIQ 64Mbit SPI Flash Memory
  • 1 × APA102-2020 Serial RGB LED

View all 11 components

  • Better bootloader

    greg02/13/2023 at 02:49 0 comments

    Received the Arduino MKR Vidor 4000 this week.  

    First order of business is upgrading the bootloader.  It is the same SAMD21 with the same LED pin as the MKR Zero so rebuilding the was very straightforward.  All I really needed to do was change the drive label.  Long term I probably need to get a new VID/PID for this board with the UF2 bootloader.  I didn't want to wire up my CMSIS-DAP debugger, so I used the .ino file generated by uf2-samdx1 along with the Arduino IDE to update the bootloader.

    Next, I wanted to start porting CircuitPython to allow me to access the FPGA with the JTAG library.  I ran into some issues building mpy-cross that I still need to work through.  

    I'm continuing to look at strategies for loading images into the FPGA.  If I were designing the board, I would probably connect the MCU up to the config flash in parallel, but I did not design this board so I am stuck with their connections.  Reviewing the schematic in more detail I see that they only connected the JTAG signals.  There are many of the I/O connected in parallel with the MCU I/O and to the header pins, so I could also use those as side channel to load images through a friendlier interface than JTAG.  I am wondering how large an image would be that only wires up MCU I/O to the SPI signals for the configuration flash.  If it is small enough, I can include it in the MCU code, so it can be loaded into the FPGA, then load the flash directly with a SPI interface.  It would be easier to implement UF2 loading through a SPI interface than it would be through JTAG.

    This begs the question.  Where does the FPGA loading code belong?  Should it be part of the MCU bootloader so that you can update both the MCU and FPGA images from the same bootloader? Or, does it belong in the MCU application?  The bootloader should be small, so I need to consider the code size.  It might be possible to fit an SVF processor in the bootloader, but I doubt there would be room for even the smallest FPGA image to use the SPI flash trick.

    It is also worth considering what the MCU application will be doing along with the FPGA.  The SAMD21 is not a power house.  It will probably function mostly as a USB interface to the FPGA.  It is reasonable to consider that the MCU application could contain both the FPGA update code and the FPGA interface code.  CircuitPython might not be the ideal choice with the limited memory available on the SAMD21.  It may force splitting the loading and interfacing code into separate images.

  • A minor detour

    greg02/04/2023 at 22:11 0 comments

    Last week I mentioned some libraries that would work well in this project, but I failed to mention that I was also considering CircuitPython.  CircuitPython has a JTAG library, but it does not directly support SVF, so I was leaning towards libxsvf.  That was before Chris Brown's blog "Profesional Video With Arduinos" reminded me that there is an Arduino board with an FPGA integrated.  The Arduino MKR Vidor 4000 has an ATSAMD21G18A with a Cyclone 10CL016.  The SAMD21 is already connected to the JTAG pins on the Cyclone 10LP, so this is an ideal development platform for processing SVF files.

    The SAMD21 is very well supported by CircuitPython, but it is a little light on memory, especially without the extra SPI flash.  We can probably make it fit if we limit the libraries to only what we need, or worst case we can go back to libxsvf in C.  Either way, we can make use of the UF2 bootloader.  The MKR Vidor is not supported by CircuitPython yet, but the MKR Zero is, and enough of the pins are the same that the bootloader is probably compatible.  Since the chip is already supported, and the pinouts are so similar, it will be straightforward to add MKR Vidor support to CircuitPython.

    So my minor detour is to use the MKR Vidor as a development platform, and to start development with CircuitPython.  I think it would be good to have both libxsvf and CircuitPython solutions available so this is really just another path to the same result, thus a detour. 

  • Choosing Libraries

    greg01/29/2023 at 03:16 0 comments

    In the previous log I stated my current goal.  To summarize the requirements:

    • An SVF player
    • Connects through USB CDC serial port
    • Drives JTAG pins
    • As portable as possible

    I've spent some time looking for JTAG libraries, and libxsvf looks like the best candidate by far.  

    To keep this portable, I don't want to use vendor USB libraries.  There are two options for an open USB stack I am considering.  The first is Ha Thach's TinyUSB.  I am a big fan of this project.  Ha has done an incredible job creating a portable USB stack that supports an impressive list of MCUs.  I have used this before on a few projects including Adafruit's TinyUF2.  

    The only other USB stack I can think of that might come close to supporting as many MCUs would be the one in the Zephyr project.  The Zephyr project is also quite impressive.  It is very professional and has great infrastructure tooling.  There is a little bit more of a learning curve to use Zephyr and it is probably overkill for this initial effort.

    I think I will start with TinyUSB, but I might port it to Zephyr later on to make it easier to add features like ethernet and SD cards.  The number of open-source peripheral libraries in Zephyr are its biggest strength, and very likely why it is gaining so much momentum.

  • Hello again

    greg01/24/2023 at 04:23 0 comments

    After a prolonged hiatus, I am returning to this project.

    I'm working with FPGAs again and remembering how frustrating the programmers are, and why I started this project.  My previous attempt was diverted to software efforts for some off-the-shelf MCU boards.  Last time I was spoiled by working with an FPGA (MachXO2) that supported SPI and I2C configuration ports, so I was able to avoid the pain of JTAG.  This time I am not so fortunate.  

    I want an easy to use programming tool that will run on almost anything, without complicated software and target a variety of devices.  Targeting a variety of devices can be simplified by using the SVF format which most FPGA tools know how to generate.  In order to simplify the use and installation, I will run the majority of the code on an MCU and communicate over USB with a virtual COM port.  Using a virtual COM port interface means you can use the default USB driver in the OS and possibly support multiple platforms without compiling apps on each.  

    To keep this accessible, I want to support the most cost effective MCUs available.  Right now that would be the Raspbery Pi Pico which is one of the few MCUs you can find in stock, and the dev boards only cost $4.  A bonus feature of the Pico RP2040 is the PIO programmable I/O, which may be helpful for accelerating the abomination of a serial protocol that is JTAG. NXP/Freescale FlexIO may also work for this, but those devices are harder to find at this time.

  • November Update

    greg11/25/2018 at 16:50 0 comments

    I haven't had much time and things are progressing slowly, but I have made some progress.  I was able to add support for the on board flash in circuitpython so that it can be used for the circuitpy drive storage.  The code is posted in my github repo:

    I added a new fpga_helper_express board in addition to the fpga_helper board to keep the option not to use the on board flash for circuitpython.  The reason I want to keep this option is because circuitpython will put a file system on the flash that is not compatible with the internal SPI loader in the FPGA, and it will be difficult to share a single flash device with both circuitpython and the FPGA.  When this circuit gets integrated on a board with the FPGA, I don't want to require two SPI flash devices.  I will need to modify circuitpython to put the binary image on the flash without the file system so the FPGA can load directly from it.  This work is TBD.

    Another option would be to have circuitpython push the image from flash into the FPGA.  The reason I am avoiding this is because many FPGA's from a variety of vendors can load from similar SPI flash that are straightforward to program.  If were to push the code into the FPGA using circuitpython, I would have to customize it for every different target, which I would rather not do.   

    FPGA's with integrated storage are different story, since there is no external SPI device to program.  The MachXO2/3 series from Lattice have internal non-volatile storage that can be loaded through JTAG, SPI or I2C.  Since the I2C signals are so easy to get to with the qwiic connector, I think I will work to add support to configure the MachXO2/3 using circuitpython.  Using the on board flash to cache the image in this case is not as much of a penalty if you are only using this board as a programmer and disconnect it when you are done.  You can program as many targets as you want with the single programmer.  The extra flash device is more of a burden if you are integrating it permanently.

  • September 30th Update

    greg10/01/2018 at 05:10 2 comments

    The board is up and running and software development is making good progress.

    The UF2 bootloader and CircuitPython are up and running on the board. 

    The dotstar LED and QWIIC I2C connector are both accessible through CircuitPython.  Here is a link to a video showing the board fading the LED and reading a Qwiic NFCPROM:

  • The obligatory blinking lights video

    greg09/05/2018 at 03:17 0 comments

  • It's alive!

    greg09/03/2018 at 05:25 0 comments

    I received the boards and they passed the smoke test.  Great job MacroFab!

    It didn't take too long to get the uf2-samdx1 bootloader running on it:

    I started working on circuitpython and seesaw ports, but those will take a bit more time.  For now I will focus on the basic uf2 interface to the SPI flash.

  • Did I mention CircuitPython?

    greg08/20/2018 at 00:26 0 comments

    As mentioned previously, UF2 was created to make it easier to work with CircuitPython.  The boards upon which this circuit is based were designed to run CircuitPython and one of the first steps for bringing up and checking out this board will be to port and run CircuitPython.  Having a board like this capable of running CircuitPython could almost justify the project on its own.  This will be on of the first CircuitPython boards with any of Qwiic, UEXT, and PMOD connection options, let alone all three.  CircuitPython also provides an easier way for FPGA developers create scripts and utilities in an environment that might be easier for them to work with than the native embedded C/C++.  

  • Power Considerations

    greg08/20/2018 at 00:12 0 comments

    The primary power input for the board will be +5V from the USB connector.  This will need to be regulated down to +3.3V for all the circuitry on the board.  In the case where the flash memory is populated on this board and it is connected to provide the image to the target FPGA, it should not be necessary to connect the USB cable and the board will draw power from the target board through the PMOD or UEXT connector.  To enable two different power sources, a diode is placed in-line with the USB power input and a Pch MOSFET is connected in-line with the PMOD/UEXT power pins.  The gate of the MOSFET is connected to a voltage divider from the USB power input so that the MOSFET is off when USB power is present, and enabled when only the PMOD/UEXT power is present.  The gate is also tied to PA28 on the MCU so that the controller can detect when USB power is present, and so that it can also override the signal to deliver power from USB to the PMOD or UEXT connectors for additional flexibility.

View all 13 project logs

View all 4 instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates