Altera deals with the SoC FPGA design challenge
With the major FPGA vendors marketing low cost FPGA devices with integrated hard processor cores, it finally seems that SoC class FPGA devices are going mainstream. But in order to deliver the all important FPGA flexibility, these devices have features that are new to both the FPGA designer and the software engineer, writes Stefano Zammattio, product marketing manager at Altera Europe.
The designer has to consider how to initialise and allocate resources between the FPGA and processor, and manage the complexity of connecting an infinitely variable set of processor peripherals.
You might say, ‘what I/O problem? FPGAs have plenty of I/O!’ However, the FPGAs now incorporate a powerful dual Cortex-A9 processor that needs a high performance memory system. If you didn’t need the processor you wouldn’t buy the device, so connecting a DDR2/3 memory to maximise performance is pretty much mandatory.
That takes up to 72 dedicated pins. Not only is there a powerful processor in there, but also a range of useful standard peripherals (e.g. USB, Ethernet, etc.) – there go even more pins! Add a raft of power and ground pins for good signal integrity and suddenly that ample BGA pincount you are looking at is starting to look a bit full! Fortunately these devices have a multiplexing capability for the hard peripherals, so you can simply choose to pin out only the peripherals you need.
Figure 1. The Altera SoC FPGA system showing processor dedicated and FPGA I/O pins (right)
The bitstream that programs the FPGA device contains information on how the I/O pins are configured. Essentially the SoC FPGA devices work in a similar way but there are two separate pin configuration processes – one for the FPGA I/O and one for the processor dedicated I/O (this also includes configuring the hard peripheral multiplexing, I/O pin and DDR controller settings).
DDR controller setup is required because high performance memory controllers need to be tuned for the particular device and circuit board layout to deliver optimum memory performance. The processor dedicated I/O and memory controller settings are made within the FPGA hardware development tools in a similar way as the FPGA pins. But how does all this configuration data get into the device if you’re not programming the FPGA?
A low cost microcontroller simply boots from on-chip ROM, whereas a high end processor boots from an external ROM (eg. X86 BIOS) and then loads a secondary bootloader. Like a microcontroller, the SoC FPGA devices have a hardwired on-chip boot ROM containing bootcode that brings up the processor, but the code also configures the I/O pins required to read data from either the FPGA, a Flash memory or SD card. This enables the system to load a secondary bootloader image into on-chip RAM.
The secondary bootloader binary code and the dedicated I/O pin configuration settings are built into a single image file; this image can also contain FPGA configuration data, and processor software (operating system (OS) bootloader, OS and/or applications). T
he image file is stored in the medium that will be the boot source for the processor. When the processor boots from the on-chip ROM it reads the status of external pins to select the boot source, loads the secondary bootloader into on-chip RAM and then runs it. This code sets up the processor and configures the external memory controller and dedicated peripheral I/O pins to allow user application code (which may be the bootloader for an OS) to be loaded into the DDR memory from the boot source.
At this stage the processor and all processor dedicated I/O are configured – so the OS bootloader (eg. U-Boot) could even load the OS binary code via a peripheral (e.g. over Ethernet).
Finally we have a fully configured chip and can boot an OS or application – but the FPGA may not be configured yet. Normally the OS/application initialises all the peripherals on startup but in this case they may not be there yet! One easy solution is to simply ensure that the FPGA is always configured before this happens but what if you need software to select from a set of different possible configurations? You may even want to re-configure the FPGA and change the peripheral set at anytime.
Building the FPGA based peripheral system is relatively straight forward; the FPGA vendors have IP libraries and GUI based design tools that allow you to easily connect peripheral IP to the hard processor. In this respect the design flow is exactly the same as using a soft core cpu like the Nios II processor. Naturally the hard processor system features cannot be changed, all you need to do is configure the dedicated pin multiplexing and connect peripheral IP in the GUI based tool.
The FPGA design tools deliver all the relevant hardware related data (base addresses, etc.) to the software development toolchain in the form of a header file, this header file can be used to generate pre-built applications that match each FPGA configuration and peripheral set. However if you are using an OS this can be problematic, as ideally you need peripheral drivers not hardwired applications.
Figure 2. Typical SoC FPGA boot process
Fortunately most OS’s support dynamic driver loading and unloading, hence it is possible to read a list of peripherals and have the OS load the appropriate drivers. If you re-configure the FPGA you simply unload the drivers and then re-load the ones contained in the new configuration. This may sound like a tricky task however most OS’s support this and Linux even has a feature, known as a device tree, that is actually intended specifically for storing peripheral related data in the Linux file system.
Each FPGA configuration would have a matching device tree file, hence (for Linux) all you would need to do is load in the correct device tree and Linux will then load up the correct driver set.
Due to the tightly coupled integration of processor and FPGA into a single device developing for these new devices is a little more complex than standard FPGAs, but the SoC FPGA device vendors have provided supporting tool flows and mechanisms that make it relatively straight forward to manage the new features required – even if you have never used a processor inside an FPGA before.