A gentle introduction to programming FPGAs
Programming an FPGA is a cool and quite unique experience when it comes to programming. Here I want to introduce you to the different concepts needed so that you can get (admittedly quite rough) barrings on how to go about programming your own logic on these pretty cool class of chips.
Programming an FPGA
First of all we need to know what it actually means to "program" an FPGA, what needs to be specified and why. This is only an overview of the concepts, I'll go into the how possibly in a next article. So let's get to it then.
The structure of a modern FPGA
To some of you this may already be known, but to the others here is a short overview.
On a very high level, an FPGA is a chip that can turn into other chips. That means that an FPGA, when programmed correctly, will behave exactly like a Z80 CPU or like a Nvidia GPU or like the chips in an old Atari arcade. There are some caveats, but they should not bother you now. Without programming though, they are pretty much useless, providing nothing more than a JTAG interface to program them with. The cool thing about an FPGA is that you get to design your own logic. The logic is not emulated on the FPGA, but rather stitched together from what is baked into it at the foundry. Being able to design the logic itself is a rather large deal, as this was previously only possible by designing a whole ASIC. That is really expensive (you need about 30 so called "masks" for the fabrication process and each of those masks will set you back at least a few thousand Euros when using the cheapest methods available and will set you back the price of a decent Apartment using the more expensive processes, and remember that you need 30 of them.
Now there essentially have been something like FPGAs since the dawn of chips. The thing is that their general purpose nature means that they need a relatively large area to implement the same functionality as a comparable "hard" circuit.
Terminology
I want to introduce some Terms here that are somewhat peculiar. The first of these terms are "hard" and "soft" respectively. "Hard" means that a circuit is actually burnt into the silicon as is, meaning the circuit cannot be altered by programming it (this does not mean, that the circuit itself cant be configured or programmed (think of a CPU, it's circuits are hard wired and can be programmed none the less)). "Soft" on the other hand means that the circuit can be rewired by reprogramming and subsequently rewiring the FPGA. As the "soft" circuits could be circuits like CPUs, soft circuits can also be configured or programmed (as a CPU can be programmed without changing it's actual wiring).
Another term that I want to introduce you to is "IP". This in contrast does not mean Internet Protocol (as in IP address) but has more to do with Disney than with transistors. "IP" stands for "intellectual property" and has been coopted by electrical engineers to mean a block of circuitry that can be cleanly separated from other blocks of circuitry. Think of an "ip block" in a similar way that you think of a function in a traditional piece of computer software.
Mixing and matching Hardware
As FPGAs are (again simplified here) essentially digital devices, the circuits in them essentially only deal with high and low voltages. This means that as long as a wire is connected inside the FPGA, an ip block does not care about where the wire came from. There goes a saying that is especially true in this circumstance: Garbage in, garbage out. What I want to make clear here, is that as long as the signals encode the right thing ( they come from an HDMI or an Ethernet connection for example ) a specific circuit does not care if the signals where generated by a router on the other side of an office or a circuit on the same silicon die ( yes you do have to be careful of voltage levels, but when we assume that there are only high and low signals and that all high signals are on the same voltage level and all the low signals are on the same voltage level there really is no difference ).
This means that it does not matter where the ip block came from, as long as it gets the inputs it expects, it can be treated as a black box, in the same way software libraries can be treated as black boxes, if you call the functions correctly. As a consequence, there are many companies (like ARM for example) that spend all of their time, writing and designing these black boxes, that they licence to others, which is why the term IP has taken hold in the hardware world (and because that work has essentially been done exclusively by for profit companies with legal departments ).
Input and Output
One area, where the "every high and every low are equal" does not hold, is on the edge of the silicon, where it has to interface with the rest of the world. To do this, there are a multitude of input and output drivers to choose from for essentially every pin on the FPGA package, depending on what the FPGA is to be connected with. These pins need special setup, which is why I mention them here separately.
Hard circuits and IP blocks
So as I mentioned earlier, there are hard circuits and there are soft circuits. To map the behaviour of the hard circuits into the domain of files and formal hardware descriptions, FPGA vendors (Xilinx in this case) ship IP blocks together with their tools that mimic the behaviour of that circuit. With these descriptions the hardware can be simulated and when it is time to generate the image that is written to the FPGA, the tool can replace the description with the proper sequence of bits to connect the "hard" circuit on the FPGA with the "soft" circuits that are wired together on the FPGA.
There is an added benefit of having the behavioral description of "hard" IP blocks at hand. If the target FPGA does not have the specified hard circuit on it, it can be implemented using the FPGA itself. The thing to keep in mind, is that the blocks that are turned in to hard blocks usually are quite recourse intensive if implemented natively on the FPGA.
Blocks that are available on FPGAs as hard blocks are RAM, and single cycle multipliers.
Things that need to be defined in order to wire a circuit on an FPGA
First off you need a description of your circuit. This could be done using old fashioned circuit drawings, connecting logic gates together, or it
could be done using text files containing an equivalent description. As the tools exist to parse text files and the notion of compilers can be adopted
from conventional programs, the second approach has been taken in the case of FPGAs. The added benefit is, that it is actually possible to compile a
circuit from a rather high level description of it's behaviour. There are currently two languages that are commonly used to describe such circuits to
our compiler. VHDL
and Verilog
. Both languages are pretty similar and have many of the same features.
One "mistake" that is seemingly made often, is that because the languages can describe successive steps ( like say the instructions in a computer program ) it is written in that manner. I want remind you that even though it is called "programming", what you are actually doing is describing circuits. You are describing a machine and not writing it's operating manual.
Second you need to define how and where the electrical signals enter and exit the FPGA. You could be using an FPGA to drive a CCD chip of a camera. So your signals enter the chip through very many pins ( for a fairly simple CCD we could say that we need one pin per line of pixels on the CCD ) for the data of the CCD and a few pins for it's clock and exit through the pins that are wired to the connector of an HDMI jack ( even though there might be a transceiver on the board to change the voltages and provide a bit of power to the outgoing signals.
The third and more or less final thing that you need to describe, are the different constraints that the circuit needs to abide by. The HDMI output of the example in the previous paragraph needs to follow specific constraints like signal rise time or the duration of bit and other, mostly timing related specifications given by the HDMI standard. The same goes for the inputs to the FPGA ( in the above example specified by the manufacturers of CCD chip. As a result, there are a bunch of timing related things that have to work, so that the behaviour defined in the beginning actually manifest on in the logic. This of course means that the FPGA needs to be capable of adhering to the constraints. An FPGA that can be clocked at a maximum of 200MHz will not be able to drive an Ethernet adapter that requires changing voltage levels at roughly 1GHz. ( Which is why there are often special circuits on the same die as the FPGA that have an input that runs at FPGA frequency and can output signals that meet the physical requirements of e.g. Ethernet ).
So there you have it. If all of that is properly described, and ( this is a tricky part in itself ) these descriptions are in the correct places, then
all you should need to do is to hit compile
or for the console aficionados like me type make
and you should get a file that can turn a piece of
silicon into your very own, custom CPU ( or whatever else you can come up with ).
Hoped you found this interesting.