Building ever-smarter technology, we perpetually require more sensors to collect increasing amounts of data for our decision-making machines. Power and bandwidth constraints require signals from individual sensors to be aggregated, fused and condensed locally by sensor hubs before being passed to a local application processor or transmitted to the cloud.
FPGAs are often used for sensor hubs because they handle multiple parallel data paths in real time extremely well and can be very low power. ADC parallel interfaces and simple serial shift register interfaces are straightforward to implement in FPGA logic. However, interfacing FPGAs with more complex serial devices—which are becoming more common as analog and digital circuitry are integrated—or serializing collected data is often less straightforward. Typically, serial interfaces are implemented in FPGA fabric as a state machine where a set of registers represents the state of the serial interface, and each clock cycle, logic executes depending on the inputs and state registers. For anything but the most trivial serial interface, the HDL code for these state machines quickly balloons into a forest of parallel if-elseif-else trees that are difficult to understand or maintain and take large amounts of FPGA fabric to implement. Iterating the behavior of these state machines requires recompiling the HDL and reprogramming the FPGA for each change which is frustratingly time consuming.
Custom soft cores offer an alternate solution. Soft cores, sometimes known as IP cores, are not new in FPGA development, and most FPGA design tools include a library of cores that can be imported for free or purchased. Often these soft cores take the form of microcontrollers such as the Cortex M1, Microblaze, lowRISC, etc., which execute a program from memory and enable applications to be implemented as a combination of HDL (Verilog, VHDL, etc.) and procedural microcode (assembly, C, C++, etc.).
While off-the-shelf soft core microprocessors are overkill and too resource intensive for implementing single serial interfaces, we can easily create our own custom soft cores when we need them that use fewer resources and are easier to program than a state machine. For the purpose of this article, a custom soft core is a microcontroller with an instruction set, registers, and peripheral interfaces created specifically to efficiently accomplish a given task. The soft core executes a program from memory on the FPGA, which makes program iteration rapid because the memory can be reprogrammed without resynthesizing or reconfiguring the whole FPGA fabric. We program the soft core procedurally in assembly, which mentally maps to serial interface protocols more easily than HDL. Sensor data is made available to the FPGA fabric through register interfaces, which we also define according to the needs of our application.
Having implemented custom soft cores many times in FPGA applications, I am presently developing an open-source example/template soft core that is posted on GitHub (https://github.com/DanielCasner/i2c_softcore). For this example, I am interfacing with a Linear Technology LTC2991 sensor that has internal configuration, status, and data registers, which must be set and read over I2C (which is notoriously difficult to implement in HDL). The soft core has 16-bit instructions defined specifically for this application and executes from block ram. The serial program is written in assembly and compiled by a Python script. I hope that this example will demonstrate how straightforward and beneficial creating custom soft cores can be.
While I have been discussing soft cores for FPGAs in this article, an interesting related trend in microprocessors is the inclusion of minion cores, sometimes also called programmable real-time units (PRUs) or programmable peripherals. While not fully customizable as in FPGA fabric, these cores are very similar to the soft cores discussed, as they have limited instruction sets optimized for serial interfaces and are intended to have simple programs that execute independently of the application to interface with sensors and other peripherals. By freeing the main processor core of direct interface requirements, they can improve performance and often simplify development. In the future, I would expect more and more MCUs to include minion cores among their peripherals.
As the amount of data to be processed and efficiently requirements increase, we should expect to see heterogeneous processing in FPGAs and microcontrollers increasing and be ready to shift our mental programming models to take advantage of the many different paradigms available.
This essay appears in Circuit Cellar 301.