In a slight change from my previous plans, I want to talk about different ways of programming FPGAs.
This can often be a fiercely controversial subject, with many advocates of the different methods. But I don’t believe the subjects needs to be controversial. To begin with, lets overview the process of building some FPGA code:
- High level language (optional)
if this has been used, it typically compiles the following, or most people still code at this level directly:
tools provided by the FPGA manufacturers then allow:
- Mapping – breaks down the design into resource elements present on the FPGA
- Place and Route – places those elements on an FPGA, and determines routing
- Timing check – ensure the design meets certain performance criteria
- Bit stream generation – makes the actual FPGA programming file
The Place and Route/Timing check steps often occur iteratively. If timing checks fail, a different placement attempt is made.
Register Transfer Level
To a certain extent, these last steps are outside of a designers hands, algorithms provided by FPGA manufactures are used for all the steps – these algorithms can be guided, but they work with heuristic techniques such as simulated annealing.
FPGA designers have the biggest input with their code, which is usually at the Register Transfer Level (or RTL – to be explained shortly) or perhaps at a higher level.
What is meant by a RTL language is that the designer specifies the changes in the states of the internal connections of the design between clock ticks. We talked about clock ticks in a previous blog entry, but an internal connection in this case means just that – a single wire with in the FPGA – whether it changes to a 1 or 0.
This is incredibly low level, RTL languages do provide some abstractions for buses (collections of wires), and the ability to modularise code and simulate, but essentially it deals with the states of individual wires.
Today, the RTL approach is the one used for most designs, even the complicated designs used in financial applications. The two main languages are VHDL and Verilog. In terms of features, these languages offer pretty much the same thing, though the syntax is different.
Needless to say, controversy exists as to whether VHDL or Verilog is the best approach to use. In my own opinion, since they offer more or less the same tools to a designer, I prefer them equally. Any reasonably experienced FPGA designer should be able to switch between both approaches in any case.
Not used so often today, but still possible, is schematic capture where a CAD tool is used to draw a circuit diagram by hand. Essentially, its equivalent to an RTL.
RTL languages give a high level of control to a designer, making low level optimisations possible, and allowing precising timing of certain operations.
Higher level languages
However the problem with RTL is that the programming is a such a low level that things taken for granted by software programmers are not possible. For example, changing the number system of part of a calculation.
Since the way to carry out arithmetic operations changes depending on the number system used, changing the number system leads to large and painful re-writes of code when it is done.
There are a number of varied alternatives for higher level FPGA programming languages, however at this time, despite a number of initiatives and much hype, no genuine standards have been widely adopted by the industry.
Higher level languages have been tarnished with a bad reputation – often ambitious marketeers have promised these languages as a silver bullet to reskilling software programmers into hardware designers. This is clearly not the case and will never be in all likelihood. The paradigm between programming CPUs and FPGAs is too different. The resources, optimisation methods, design granularity etc are all worlds apart. The two need a different mentality and no tool will change that.
Nevertheless, I do believe a higher level approach has much to offer the FPGA designer in terms of their efficiency as engineers, can help alot to reduce design times, and generally make our lives easier.
Types of higher level language
As I’ve indicated, a number of higher level approaches to FPGA design have been proposed. Due to the conservative nature of the space, these have seldom had an impact.
Generally the approaches fit somewhere between being a fully featured language (Impulse C, Handel C) and very narrow domain specific tools. Somewhere in between sit the so called “stream compilers” (or example OpenCL). I’ve worked with and designed a few of these myself, and they are all equally valid approaches depending on the aim of the designer.
Luckily, no one has to be restricted into using a single approach, compiler or language on a design. Its possible to mix and match. In my opinion the best approach is to use an RTL where its really needed, for designing interfaces etc. Domain specific compilers can then be used for the computing blocks – taking the hard work out of defining number systems/data types, and rebalancing pipeline branches to the same length.
Also, by performing simulations and debugging at a high level, its possible to turn around changes much more quickly, than going through a full compilation cycle.
As the name domain specific compiler suggests, its rarely possible to use one for a whole design. There is so much hype and misinformation in this space, it is hard for the inexperienced to say whether one high level tool or another is appropriate for a particular purpose.
Since no standards are really defined in the space of high level compilers, I would even encourage designers to make their own. Scripting languages easily allow the mapping of a high level pipeline description into VHDL, and you can save yourself alot of time this way. It will be a tool you understand and can develop in the direction you need it.