Due to a need to add an FPGA to the control stack that I have been developing (please see the previous 4 or 5 blog entries), I have started to plan the implementation of a PID feedback loop on the Spartan 6 Xilinx FPGA that comes with the Mojo development board from Embedded Micro.
Mojo FPGA dev board
The Mojo is a very nice development platform for those of us who are new to the world of FPGA’s, and consists of a Spartan 6 FPGA along with an Atmega chip that simplifies the process of writing new configurations to the FPGA. The Atmega, once it is done uploading the new bitstream to the FPGA, is then available for work as a regular microcontroller, thereby providing Arduino-like functionality.
One of the primary benefits of the Mojo as a development platform is the software that comes along with it — in particular the IDE and the Loader. These give a nice soft learning curve for new users, and hide away the complexity of communicating with the FPGA in a way that allows the developer to concentrate on the details of the Verilog description of the FPGA configuration.
Despite the fact that the IDE is so simple to use, I decided to follow a route that uses the full development environment provided by Xilinx, and installed the ISE package. Although I recommend that you do the same, you should be aware that installation of this requires an enormous, multi-GB, download, from a relatively slow server. Even on a good connection, this may still take several hours.
The system that I intend to control with the PID loop is the same as used in a previous post — an LED pointed at a photoresistor. Using an FPGA to control such a simple system is clearly overkill, however the purpose of this project is educational, not practical.
As someone very new to FPGA development, I need to start with a relatively bite-sized piece of the puzzle, and so I have decided to begin by implementing a module that characterises the response of the system. In other words, to develop a system that will scan the brightness of the LED from zero to its maximum value, and record the read-back from the photoresistor circuit. If this is done carefully, then it can be included as one state of the state machine that will be used to implement the full system later on.
The LED brightness will be controlled by a 10-bit 3.3 V PWM output from pin #50 of the Mojo dev board. The 50 MHz clock speed of the Mojo will therefore result in a 50/1024 = 48.8 kHz PWM signal.
The photoresistor voltage drop will be measured between 0 and 3.3 V by the ADC provided by the Atmega. As explained here, each sample from the ADC is 10-bits wide.
The operation of the FPGA will be controlled by Serial input (thanks, again, to the microcontroller).
On reception of the relevant Serial input, the FPGA will begin scanning the PWM duty cycle from 0 to 100% using the smallest steps possible. At each step, the FPGA will take several samples of the ADC input from the photoresistor, storing the average in block RAM. Once the scan is complete, the FPGA will then transition back to its idle state.
This suggests that the FPGA should be configured as a state machine with two states: idle & scanning.
The width of the PWM and ADC signals implies that the RAM needs a 10-bit width (for the ADC value) and a 10-bit depth (for the PWM signals), resulting in a memory size of 2^20 bits — 1 Mb (128 kB).
The fact that the scan is over every single possible PWM duty cycle means that there is no need to store the PWM duty cycle alongside its associated ADC input, since the memory can be addressed with the appropriate PWM value stated as a binary integer between 0 and 2^10 – 1.
Testing the setup
Once the system has been implemented, there is a question of how to confirm that it operates as expected. This is not only important for testing purposes, but is also a critical component of the final system, since the user will expect to be able to view various outputs of the system in a human-readable way.
FPGA’s, as digital devices, deal entirely in binary information, and do not care so much about the “type” of the data Serial communications, on the other hand, fully expect the data to be in the form of 8-bit ASCII characters, and will interpret all input as such, whether appropriate or not.
The question is how to best return data from the FPGA in a way that can be easily converted to human-readable integers. This remains an open-question for the moment…