In Part 1 of this tutorial, we introduced FPGAs and went through a simple starter project on the Mojo FPGA from Embedded Micro. In part 2, we’ll cover a more complex project: implementing hardware PWM on the Mojo FPGA.
Pulse-Width Modulation (PWM) is widely used in embedded systems to control the brightness of LEDs, the speed of motors, and even for communication. If you’ve used the Arduino, you’ve certainly come across PWM when using the analogWrite() function. Before we can implement PWM on the Mojo, we should first take a look at how PWM works!
Microcontrollers and other embedded systems processors compute and perform tasks with digital signals. These signals only occur in one of two voltage states: a “high” voltage, usually 3.3V or 5V, and a “low” voltage, which is usually 0V. These two voltages encode binary 1’s and 0’s respectively, and can thus be used to perform an enormous variety of tasks.
But what if we want to output voltages at finer levels than just on or off? This is the motivating question in applications such as the ones mentioned above, where some variable output intensity is required. One solution is to connect the system to an external device called a Digital to Analog Converter (DAC), which takes digital signal inputs in the form of binary 1’s and 0’s from a main processor and outputs voltages in an almost-continuous range from 0V to the system “high” voltage. However, for most embedded system applications, a simpler method exists: PWM!
In a sense, PWM makes use of the fact that human senses and physical systems such as motors average rapidly changing inputs. The system generates a digital signal that pulses at a high frequency such that individual pulses are not distinguishable. In a given period of this waveform, the signal is high for some portion of the time and low for the rest — this portion of time in which the signal is high is called the duty or duty cycle of the signal. The average output effect, be it the brightness of an LED or the speed of a motor, depends on the duty of the PWM signal. Of course, as the name suggests, we can change the output effect by changing the duty (the pulse width) of the wave! The following diagram shows a comparison of different duty cycles and their corresponding waveforms.
Figure 1. Comparison of different duty cycles and their associated pulse waveforms. It is clear that the most “intense” output effect occurs at 100% duty cycle when the signal is constantly high.
Microcontroller ICs such as the ATMega chips found on Arduino boards have internal hardware dedicated to generating PWM signals upon command from the processor. The outputs of these circuits are connected to specific pins on the microcontroller IC that are dedicated as PWM output lines. However, this also means that only these pins can provide PWM signals. On an FPGA like the Mojo, however, we can configure internal hardware as we please, which means that we can create as many hardware PWM circuits as we would like!