FPGA programming or FPGA development process is the process of planning, designing and implementing a solution on FPGA. Small processors are, by far, the largest selling class of computers and form the basis of many embedded systems. The first single-chip microprocessors contained approximately 10,000 gates of logic and 10,000 bits of memory. Today, field programmable gate arrays (FPGAs) provide single chips approaching 10 million gates of logic and 10 million bits of memory.
Powerful tools exist to program these powerful chips. Unlike microprocessors, not only the memory bits, but also the logical gates are under your control as the programmer.
FPGA programming is actually (re)configuring FPGAs using Hardware Description Language (Verilog/VHDL) to connect these logic blocks and interconnects in a way that it can perform a specific functionality (adders, multipliers, processors, filters, dividers, etc.).
The amount and type of planning vary from application to application. But creating a requirements document that captures all specific requirements and creating a design document that explains how the proposed solution would be implemented can be very helpful to enumerate potential problems and plan around them. A little bit of time spent creating a quality design document will save tons of time in refactoring, debugging and bug fixing later.
Implementing a solution on FPGA includes building the design using one of the design entry methods such as schematics or HDL code such as Verilog or VHDL, Synthesizing the design (Synthesis, netlist generation, place and route etc..) in to output files that FPGAs can understand and program the output file to the physical FPGA device using programming tools.
Entering the design using schematics is not used in the industry widely anymore. So we will keep the discussion limited to design entry using HDL (Hardware Description Language), specifically Verilog in this article series.
Synthesis and programming are almost completely taken care of the vendor tools such as ISE and Vivado and Numato Lab configuration tools. All necessary steps to be taken by the user as part of design entry, synthesis and programming will be explained in subsequent sections.
2. What is the FPGA programming language?
FPGA programming language is commonly called Hardware Description Language because it is actually used to describe or design hardware. The two major Hardware Description Languages are Verilog HDL and VHDL.
Verilog –, standardized as IEEE 1364, is a hardware description language (HDL) used to model electronic systems. It is most commonly used in the design and verification of digital circuits at the register-transfer level of abstraction. It is also used in the verification of analog circuits and mixed-signal circuits, as well as in the design of genetic circuits.
“Verification” + “Logic”, which originally created by P. Moorby, P. Goel, C.-L. Huang, and D. Warmke in 1984 to model gates and perform simulation in a logic simulator. Verilog was acquired by Cadence in 1990 and became IEEE Standard 1364 in 1995. Now, Verilog is commonly used for designing and verification of digital circuits and analog or mixed signal circuits as well.
VHDL is VHSIC (Very High Speed Integrated Circuits) Hardware Description Language which was initially developed by US Defense Department to research and develop very high speed integrated circuits in the 1980s. VHDL became IEEE Standard 1076 in 1987. Now, VHDL is mostly used to model digital and analog mixed signal circuits such as FPGAs and ASICs. VHDL (VHSIC Hardware Description Language) is a hardware description language used in electronic design automation to describe digital and mixed-signal systems such as field-programmable gate arrays and integrated circuits. VHDL can also be used as a general purpose parallel programming language.
Verilog HDL is similar to C programming language such as case-sensitive, keywords, operators, etc. VHDL is similar to Ada programming language since it was initially built based on Ada. Although there are similarities in syntax between HDLs (Verilog, VHDL) and software programming languages (C, Ada), FPGA programming is completely different from Software programming.
Table 1: Step-by-step design process for microprocessors and FPGAs
|Architectural design||Architectural design|
|Choice of language
|Choice of language (Verilog, VHDL)
|Editing programs||Editing programs|
|Placing and routing programs
(.VO, .SDF, .TTF)
|Loading programs to ROM||Loading programs to FPGA|
|Debugging P programs||Debugging FPGA programs|
|Documenting programs||Documenting programs|
|Delivering programs||Delivering programs|
The architectural-design phase is surprisingly similar. Although people will argue design philosophies, it’s not unusual to perform a “first cut” at programming in a pseudo-language that can be translated into and refined as a specific language, say assembly, C++, or JAVA. I describe my first FPGA architectural design in a pseudo-C language then translate it to Verilog for an FPGA. Thus the ability to express yourself in C is a good start in learning Verilog. Architectural issues could fill a book; therefore we’ll focus on development issues.
Because you understand editing, compiling, assembling, linking, and loading in microprocessor programming, you can relate this to editing, compiling, synthesizing, placing, routing, and loading in FPGA programming.
Not only is Verilog syntax C-like, but, since it’s 100% ASCII, you can use any editor to prepare fpga.v files. Nothing new here.
The process of compiling a program for the microprocessor combines the edited files and builds a logically correct sequence of bits that are used to control the sequencing of logical gates. These gates write data onto buses, into latches and registers, out ports, and across channels. The gates have fixed relationships designed to accomplish fixed functions. The assembly-language instructions represent these functions. Thus microprocessor compilers either produce assembly-language programs that are then assembled into bit patterns or directly produce the bits to drive the gates and fill the registers and the memories.
The analogous operation in FPGA programming is the compilation of Verilog into register transfer logic (RTL) netlists. As the name implies, data is transferred into registers, subject to some clocking condition. At this stage FPGA programming departs from microprocessor programming in that an additional synthesis process is required to produce bits (or intermediate objects that can be converted to bits) that will control gates and fill registers and memories on an FPGA. This level is called gate-level logic, since it describes the logical gates of which the system will be composed. The output format is typically an Electronic Design Interchange Format (EDIF) file.
There’s a large difference between compiling and synthesizing, and you have to stretch some to encompass it. Whereas the compiler produces bits to control fixed-gate patterns (the microprocessor decoders, registers, arithmetic logic unit, and so on) the synthesizer defines gate patterns described by the logic of the program. That is, your program logic gets synthesized, or mapped into, logical gates, not into processor instructions that control multigate structures. This is absolutely amazing, and good FPGA programmers give thanks every day for living in the rare time in history (post 1990+) when you can design architectures with words and then synthesize your logic into (mostly silicon) gates that execute your logic. Not to get carried away, but it’s absolutely wonderful.
Linking was a latecomer to programming—maybe 1950. Previous computers and programs simply put bits into console switches, and thereby into registers. (Read about the development of linking in the sidebar.)
The bit-based outputs of the microprocessor compilation process typically don’t directly control gates but must be connected to other bit patterns. This is true because most programs run under the control of an operating system and must be connected, or linked, to the operating system. In fact, the location in memory of the actual compiled bits is usually unknown and not determined until linking and loading is completed. Further, there may be programs existing in a library that must also be linked to the compiled program before a useful product exists.
The synthesis process, as we have discussed, produces bit patterns, in an intermediate format. We compile Verilog to RTL netlists, then synthesize Verilog to EDIF, then place and route EDIF to produce HEX or TTF files that can be loaded into an FPGA. These bit patterns will end up controlling logic gates and filling memory and registers.
In the same way that C and other programs include objects defined in (possibly third-party) libraries, FPGA programs can include or import portions of systems from third-party intellectual property, in the form of FPGA-implementable programs or objects.
Also, in the same way that the linking and loading process of embedded systems design connects various system objects, subsystems, or super systems like the operating system, including library objects (and loads or places them into specific memory locations), the place and route function in FPGA design places the synthesized subsystems into FPGA locations and makes connections (microprocessor links ~ FPGA routes) between these subsystems, enabling their operation as an integrated system. The actual linking and loading of compiled bits is essentially a process of fitting, in one dimension, the bit patterns distributed over a set of available linear memory addresses. The FPGA place and route process fits, in two dimensions, the bit patterns (logic subsystems) over a two dimensional array of available logic gates, and routes buses between these logic subsystems as necessary.
The similarity in the processes is obvious.
Finally, just as embedded programs are often embedded in physical ROM, flash, or downloaded live, FPGA programs (compiled, synthesized, placed, and routed) must be embedded in the physical FPGAs. The actual programming file may be a .HEX or similar. Programmers typically download or burn the bits from these files into the hardware. If nonvolatile, this is a one-time proposition. If not, it’s a download-at-power-up proposition. Many variations exist with FPGAs as with microprocessor-based embedded systems, but in the end, in a functioning microprocessor-based product, the bits compiled, linked, and loaded must “get into” the physical memory to control the gates of the processor, and in an FPGA-based functioning product, the bits compiled, synthesized, placed, and routed, must “get into” the FPGA, to implement the gates of the system.
All experienced programmers know that complex programs, even subprograms, don’t run correctly the first time. When we first see how to solve a problem, we tend to be overjoyed, (it’s possible!) and then underestimate the time required to implement the solution. This is because our powers of abstraction, based on experience, enable us to see solutions without worrying about every nitty-gritty detail. But the hard truth is that the physical system in which we’re embedding our programs requires that every nitty-gritty detail must be handled before it will work. No doubt, you have had the experience of fixing a single bit (or flag) that caused a crashing program to suddenly run correctly. Hallelujah! It works. I can sleep now.
Anyway, things don’t work right out of the gate. We generally have to kick them and see what they do and where they expire. In embedded systems program development, we typically use debuggers, simulators, and emulators. These tools enable us to step through the program execution and observe the effects on flags, register contents, memory locations, and so on, and to try to match what we expect at a given place and time with what we see, in the simulator or emulator.