Enginursday: A New Approach to FPGAs!

For me, Field Programmable Gate Arrays (FPGAs) have been the penultimate frontier of electrical engineering design (the ultimate would be fabricating our own chips, but once again, that’s a topic for a different blog post). In discussing FPGAs with some of my SparkFun colleagues, we agree that they’re hard to casually tinker with. You don’t just “play around” with them. FPGAs are programmed in their own languages (usually Verilog or VHDL), using techniques based on synchronous hardware, and developed using software that’s extremely sophisticated. Getting into them usually involves a very steep learning curve.

I’ve been on teams that built FPGA based designs a couple of times before, but it’s not a world I’ve comfortably settled into – I get pulled back into regular software design before I’m really up to speed. The FPGA design suites are big, full of menus, pages, tabs and modes, all described in unfamiliar terminology, which takes time to get to know. A lot of my experience was clicking on the wrong option, then having to figure out how to backtrack.

Justin Rajewski, the Founder and CEO of Embedded Micro, came to us earlier this year with an announcement: they were introducing a new language to ease the transition into FPGA development. I was curious to take a closer look – could they lower the learning curve, and perhaps make it possible for a beginner to casually experiment with an FPGA?

Prologue

Embedded Micro successfully Kickstarted the Mojo development board in 2013, and it’s been revised a couple of times since then.

Mojo Photo

The Mojo Development Board

The board is currently on version 3, which has:

  • a Xilinx Spartan6 FPGA.
  • 8 user-configurable LEDs
  • 84 I/O Pins.
  • An Atmel AVR 32u4 microcontroller.
  • A flash memory chip to store the FPGA configuration data.

The XC6SLX9 FPGA is the heart of the board, and it has a bunch of goodies under the hood:

  • 9,152 logic blocks.
  • 16 DSP slices.
  • 576 kilobits of RAM.
  • 102 I/O pins.

Developing code for an FPGA is actually describing how the above pieces are configured and interconnected. This could range from a set of simple binary logic operations to a very sophisticated plan for a mathematical algorithm or communication interface. If you want to take a deeper look at the FPGA itself, here is the family datasheet.

In addition to the Mojo hardware, Embedded Micro wrote a series of tutorials that guide the beginner through using the Xilinx tools to develop Verilog code. But, as mentioned above, these tools are cumbersome, and daunting for the beginner.

Enter Lucid

To ease the transition onto the FPGA world, Embedded Micro has now introduced an IDE for the Mojo, and a new FPGA programming language called Lucid.

Mojo IDE Screenshot

The Mojo IDE

The IDE is greatly streamlined in comparison the the Xilinx tools. It’s a single window, with a multi-tab editor, and relatively few buttons and menus. One button builds the code, another loads it on to the board. Since it only supports the Mojo board, a lot of the options present in the Xilinx tools simply aren’t applicable.

Behind the scenes, the Mojo IDE still requires the installation of Xilinx WebpackISE, which is a huge download, and requires navigating a license manager. However, once it’s installed, you don’t need to open it. The Mojo IDE invokes the command line tools in the background (much the same way that the Arduino IDE invokes the GCC compiler).

Lucid itself uses syntax that’s a hybrid of Verilog and C++/Java, with curly braces to denote blocks of code, which will be familiar if you’ve used C++ or Java (as seen in Arduino or Processing). It also includes some higher-level conceptual blocks, such as flip-flips and state machines, which are very useful for FPGA design. Here’s a snippet of Lucid that implements a configurable binary counter.

module counter #(
    SIZE = 8 : SIZE > 0, // Width of the output
    DIV = 0  : DIV >= 0, // number of bits to use as divisor
    TOP = 0  : TOP >= 0, // max value, 0 = none

    // direction to count, use "up" or "down"
    DIRECTION = "up" : DIRECTION == "up" || DIRECTION == "down"  
)(
    input clk,
    input rst,
    output value[SIZE]
) {
    .clk(clk), .rst(rst) {
    dff ctr[SIZE+DIV];
}

const MAX_VALUE = c{TOP, DIVx{1}}; // value when maxed out

always {
    value = ctr.q[SIZE+DIV-1-:SIZE]; // set the output

    if (DIRECTION == "up") { // when this is an up counter
        ctr.d = ctr.q + 1; // increase
        if (TOP != 0 && ctr.q == MAX_VALUE) { // reached the top?
            ctr.d = 0; // reset
        }
    } else { // down counter
        ctr.d = ctr.q - 1; // decrease
        if (TOP != 0 && ctr.q == 0) { // reached the bottom?
            ctr.d = MAX_VALUE; // reset to top
            }
        }
    }
}

The IDE also lets you intermix Lucid and Verilog source files, which can be useful if you’ve already got a Verilog module that you want to include. When you press the “Build Project” button, the IDE translates the Lucid files into Verilog, then passes them to the Xilinx Verilog tools. Those intermediate Verilog files are also saved in the build tree, in case you want to export them to use in a Verilog workflow.

In Use

I’ve been playing with Lucid on the Mojo for about 10 days now. It’s been a slow process, but more productive than 10 days with a traditional FPGA design suite. I’m finding that with fewer menus, options and buttons, I’m a lot less likely to take a wrong turn and wind up in some mode I wasn’t expecting. This has allowed me to focus on troubleshooting my code, rather than the development environment.

I was hoping to have some sort of ambitious project to share for this blog post, but it’s not coming together as quickly as I was hoping. My divisibility by 3 checking hardware isn’t fully functional, and I’m still a ways from building an I2S port from scratch.

Working with the tools, I’ve also found a couple of little issues with the language and IDE. In each instance, Embedded Micro have been quick to respond. They guided me toward better Lucid practices, and updated the IDE with missing features.

Epilogue: Future Developments

Lucid is very new – it was released on April 13th! It’s still in its infancy, and has room to grow. As such, I asked Embedded Micro for a peek at their roadmap. There are some things we can expect to see:

  1. More Lucid tutorials, eventually augmenting the older Verilog tutorials.
  2. Several new hardware shields.
  3. Some extensions to the IDE, adding timing simulation, and interactive debug features. You’ll be able to configure part of the FPGA as timing debugger or logic analyzer.

A New Path Into FPGA Development

If you’re looking to jump from Arduino into FPGA programming, the Mojo has an extra advantage. The 32U4 microcontroller (the same chip as is found on the the Pro Micro) is Arduino-compatible. You can use the Arduino IDE to program the microcontroller, and add your own code that can interact with the FPGA.

Embedded Micro have released the source code for the loader firmware. It exposes some hooks to run additional user code, which are described in their Arduino IDE Tutorial.

My Final Thoughts

Knowing what I know now, if I had to start fresh, I’d probably take a different path through the materials Embedded Micro provides.

  1. I’d start by printing out the Lucid Language Reference. It’s got syntax examples that demonstrate the basic features of the language.
  2. With the guide in hand, I’d work through the basic tutorials. Their current tutorials are for combinatorial logic and synchronous logic.
  3. Before forging ahead on my own, I’d carefully study all of the pieces listed in the ‘project->add components’ menu. These are actually modules written in Lucid, some of which implement non-trivial hardware like multi-channel PWM, or UART serial ports. It turns out that several of these were items that I’d been reinventing on my own.

I’ve also spent enough time playing with Lucid to develop some debugging strategies. If you get stuck, try the following:

  • Check the build output in the lower pane of the IDE. In one instance, I was able to find an error I’d made assigning signals to pins in the constraints file…which directly leads us to the next item:
  • Route internal signals to pins, and observe them with an oscilloscope or logic analyzer. Sometimes, you need to open your own windows into the chip. This might be the equivalent of peppering an Arduino sketch with Serial.print() calls.
  • When things are misbehaving, consider a different approach. Sometimes my initial instinct for implementation isn’t right, and things can be done differently.
  • If you really need help with a Lucid project, reach out to Embedded Micro. They’ve been very helpful, and are eager to see people using the language.

comments | comment feed

Leave a Reply

Your email address will not be published. Required fields are marked *