I’ve been an EE and digital logic designer for over 30 years. For the past 25 years I’ve been using FPGAs almost exclusively for designs I create for a variety of professional applications. For the uninitiated, FPGAs are field-programmable gate arrays, which essentially means they are reconfigurable hardware chips. My work is enjoyable and satisfying, but recently I’ve wanted to explore fun projects that are quite different from the day job. I also wanted to bring my FPGA skills to the maker movement: FPGAs are rarely used there, largely because working with them is considered difficult compared with the relative simplicity of an Arduino.
Searching for ideas, I looked at Make, Hackaday, and other sites that are focused on the maker community. The huge number of projects built aroundthe WS2812B programmable color LEDs [PDF] soon caught my attention. These popular LEDs come in strings that can be cut to whatever length is needed, and they require just a single-wire serial data connection to control all the lights in a string individually. Multiple strings can be stacked to create large—albeit low-resolution—two-dimensional displays. But they can be challenging to control when dealing with hundreds or even thousands of LEDs. This looked like a perfect application for an FPGA.
WS2812B LEDs use a 24-bit number to set their color. The cleverness of these devices is that each LED in a string can accept a whole stream of 24-bit color values over its data connection, strip off the first value (which it uses for itself) and then pass the rest of the numbers to the next LED along the string, which in turn strips off a value for itself and so on.
The trickiness of these devices is that the timing for the serial bit stream must be precise. Zeroes are represented by sending a 5-volt signal for 400 nanoseconds, followed by a 0-V signal for 850 ns. Ones are represented by sending 5 V for 800 ns, followed by 0 V for 450 ns. This precise timing can be challenging for microcontrollers such as the Arduino, especially when trying to control multiple long strings.
Meeting these timing requirements is trivial for an FPGA, but it’s harder to program an FPGA to display something interesting. Conversely, generating interesting patterns is a job for which microcontrollers are very well suited. So I set out to build an FPGA-based board that could operate as a bridge between a microcontroller and long WS2812B strings.
WS2812B controller boards already exist on the market, such as the US $25 Fadecandy, so my goal was to create an FPGA that could be cost competitive but offer the ability to control substantially more strings and LEDs. I also wanted it to be easy to use, so that most microcontroller boards could be hooked up to it using basic hardware connections and without the need for complex software. As most microcontrollers support simple protocols such as SPI or serial UART (and often both), I chose these as interfaces to the boards.
First, I had to settle on how my FPGA should be programmed to drive the LEDs. Many inexpensive FPGAs have sufficient RAM and thousands of flip-flops that can be used to build circuits to drive pixel strings. I had some FPGA boards with Spartan6 or CycloneIV parts on them, making them perfect prototyping platforms. Without putting too much thought into it, I programmed an FPGA so that a portion of its RAM could be accessed in “simple dual port mode.” In this mode, the RAM has separate read and write interfaces that can be accessed independently and simultaneously. I connected the RAM to a “string engine,” which converts the color-value bits stored in the RAM into the carefully timed pulses needed to communicate with an LED strip. This simple circuit would be easy to replicate within the FPGA, one circuit per string.
I should have thought about it a bit more. I got it designed and operational, but I couldn’t fit many strings in the FPGA. In a nutshell, the resources required to route data between the microcontroller and the individual circuit RAMs consumed too much of my FPGA’s silicon.
After a couple of more iterations, though, I hit on a solution. Rather than using individual string RAMs, I stored the color values for all the strings in a common RAM that’s attached to a new “string feeder” subcircuit. This string feeder is responsible for doling out data to each string engine in sequence, and it can do this fast enough to keep up with all the attached strings.
I labeled this iteration of the FPGA design the “ezPixel” and set about building a final board design. An Intel MAX10M08 FPGA is the heart of the board, and it is connected to 3.3- to 5-V level translators that convert the chip’s lower voltage to the 5 V required to control the LED strips. The complete board is 25 by 76 millimeters.
As designed, the ezPixel board can drive up to 32 strings of WS2812Bs, for up to 9,216 LEDs in total. WS2812B strings typically have 30, 60, or 144 LEDs per meter, allowing for a wide variety of display shapes and sizes. I wanted to unveil the ezPixel at the World Maker Faire this past October in New York City, so I built a demonstration display that could actually fit in my booth, using 32 strings that were 2 meters long with 120 pixels each. A laptop PC generated the display patterns and connected to ezPixel via a USB/serial connection. The result was certainly eye catching, even in the busy environment of the Maker Faire.
After the event, I added a serial flash memory chip to the design to store display content. This will allow ezPixel to run as a standalone display controller if desired. I’m now hoping to produce the boards for other makers, with a crowdfunding campaign slated for early 2018 (at which time I will publish the design open source and make details available at my site, MakerLogic.com).
This article appears in the January 2018 print issue as “The ezPixel Lights It Up.”