Editor’s Note: As advanced algorithms continue to emerge for smart product designs, developers often find themselves struggling to implement embedded systems able to meet the associated processing demands of these algorithms. FPGAs can deliver the required performance, but designing with FPGAs has long been considered limited to the purview of FPGA programming experts. Today, however, the availability of more powerful FPGAs and more effective development environments has made FPGA development broadly accessible. In this excerpt, Chapter 4 from the book Architecting High-Performance Embedded Systems, the author offers a comprehensive review of FPGA devices, implementation languages, and the FPGA development process as well as a detailed walkthrough of how to get started implementing FPGAs in your own design. The complete excerpt is presented in the following series of installments:
1: Hardware resources
2: Implementation languages (this article)
3: Development process
4: Building a project
Adapted from Architecting High-Performance Embedded Systems, by Jim Ledin.
FPGA implementation languages
Implementing a design for an FPGA ultimately comes down to using one or more software-programming-like languages to define the functionality of the device.
The traditional languages used for FPGA development are VHDL and Verilog.
Current-generation FPGA development tools generally support both of these languages together with the ability to define system configurations using block diagramming techniques. Some tool suites also support the definition of FPGA functionality using the traditional C and C++ programming languages.
VHSIC Hardware Description Language (VHDL), where VHSIC stands for Very High-Speed Integrated Circuit, has syntax reminiscent of the Ada programming language. VHDL was developed under the guidance of the US Department of Defense beginning in 1983.
Like Ada, VHDL tends to be quite verbose and rigidly structured. In programming language terms, VHDL is strongly typed. The language contains a predefined set of base data types, principally boolean, bit, bit_vector, character, string, integer, real, time, and array. All other data types are defined in terms of the base types.
A set of VHDL libraries has been defined by the Institute of Electrical and Electronics Engineers (IEEE) and formalized as the IEEE 1164 standard, Multivalue Logic System for VHDL Model Interoperability. These libraries define the set of logic values to be used in the VHDL language. This library includes a type named std_logic, which represents a 1-bit signal. The logical values within the std_logic type are represented by the character literals shown in the following table:
The “strong” 0 and 1 values in the preceding figure represent signals driven to the specified binary state. The “weak” signals represent signals driven on a bus with multiple drivers where any driver can assert itself on the bus, overriding the other drivers. The Z value represents a CMOS output in the high-impedance state, where rather than driving the bus to a 0 or 1 state, the output is instead effectively disconnected from the bus and does not drive it at all. The U state represents the default values for all signals. When performing circuit simulation, any signal in the U state will be detected, which likely indicates an uninitialized value is being used unintentionally. The X state is associated with wires that do not have any outputs driving them. The – state represents inputs that are unused, and therefore it does not matter what state they are in.
VHDL circuit designs generally begin by importing the IEEE 1164 libraries via the following statements:
We will use VHDL in our project example later in the chapter. This is not intended to represent a strong preference for VHDL over Verilog. Both hardware definition languages are fully capable of representing essentially any design that can be synthesized for an FPGA.
The Verilog Hardware Description Language (HDL) was introduced in 1984 and became standardized as IEEE 1364 in 2005. In 2009, the Verilog standard was combined with the SystemVerilog standard to produce IEEE Standard 1800-2009. SystemVerilog contains extensive facilities for performing system verification, in addition to the hardware design features present in Verilog.
Verilog was designed to resemble the C programming language, including similar operator precedence and the use of some of the same control flow keywords, including if, else, for, and while.
Verilog uses the concept of a wire to represent signal states. A signal value can take any of the values 0, 1, don’t care (x), or high impedance (z), and can have a strong or weak signal strength.
Both VHDL and Verilog define language subsets that can be used to design logic circuitry. These subsets are referred to as the synthesizable language subsets. Additional language features beyond the synthesizable subsets are available to support tasks such as circuit simulation. We’ll see an example of this later in this chapter.
Non-synthesizable language constructs tend to behave more like traditional software programming languages. For example, a non-synthesizable for loop iterates through a block of code sequentially the specified number of times, just like in a regular programming language. A synthesizable for loop, on the other hand, becomes effectively unrolled to generate a collection of replicated hardware constructs that execute in parallel representing each iteration of the loop.
At a level of abstraction above the text-based HDLs, modern FPGA development tool suites support the rapid configuration of system designs incorporating complex logic components such as microprocessors and sophisticated I/O devices using a block structure format. Figure 4.2 is an example of a portion of a block diagram for a Xilinx FPGA design incorporating a MicroBlaze soft processor:
click for full size image
Figure 4.2 – Block diagram containing a MicroBlaze soft microprocessor
The MicroBlaze processor is a processor core provided with the Xilinx Vivado tool suite for use in FPGA designs in processor families including the Artix-7.
While the use of block diagrams provides a visually intuitive way to organize the instantiation and interconnection of complex logic elements in an FPGA design, it is important to remember that behind the diagram, the development tool generates VHDL or Verilog code to define the components and their connections. The block diagram is simply a user interface for managing the configuration of these components.
After you develop a block diagram, you can examine the generated HDL code, which will be contained in files associated with the project. In the diagram of Figure 4.2, a file named design_1_microblaze_0_0_stub.vhdl is produced from the diagram. This file begins with the following VHDL code:
entity design_1_microblaze_0_0 is
Clk: in STD_LOGIC;
Reset: in STD_LOGIC;
Interrupt: in STD_LOGIC;
Interrupt_Address: in STD_LOGIC_VECTOR (0 to 31);
Interrupt_Ack: out STD_LOGIC_VECTOR (0 to 1);
Instr_Addr: out STD_LOGIC_VECTOR (0 to 31);
Instr: in STD_LOGIC_VECTOR (0 to 31);
This code begins with a reference to the IEEE 1164 standard library, then defines an interface to the MicroBlaze processor that exposes the signals you would expect on a microprocessor, including the system clock, reset, interrupt request, and interrupt vector inputs; interrupt acknowledge and instruction address outputs; and a bus for the instructions retrieved from memory.
This code makes use of the IEEE 1164 library data types for single-bit signals (STD_LOGIC) and for multi-bit bus signals (STD_LOGIC_VECTOR).
The code in the listing defines the interface to the MicroBlaze processor, but it does not contain the HDL definition of the processor itself. Complex HDL designs for components such as microprocessors are considered valuable Intellectual Property (IP) and the commercial entities that develop these designs often take steps to ensure they are not used without appropriate licensing. When vendors distribute IP for use by their customers, it may be provided in a compiled format that is opaque to end users. This allows users to incorporate the IP into their designs, but they cannot examine the HDL used to develop it. This is conceptually similar to software developers who release a library in compiled form but do not provide the source code.
A number of vendors offer software tools that translate traditional high-level programming languages, often C and C++, into HDL code for use in FPGA development. This approach may be attractive if you have a complex algorithm in C or C++ that you would like to accelerate in an FPGA implementation. These tools also allow software developers who are familiar with C/C++ to immediately begin implementing code for FPGA use without a need to learn one of the HDLs.
While FPGA development tools for these high-level languages are capable of significant optimization of the resulting FPGA implementation of the C/C++ code algorithm, there is still something of a disconnect in that the C/C++ execution model involves the sequential execution of statements while the native FPGA environment consists of parallel hardware components. The FPGA design resulting from C/C++ code typically resembles a collection of state machines that manage the sequential execution of the operations defined in the programming language statements. Depending on the availability of opportunities for parallel execution within the C/C++ code, an FPGA implementation may provide a significant performance enhancement compared to running the same code on a traditional processor.
In modern FPGA development tool suites, all of the methods of FPGA implementation described in this section (VHDL, Verilog, block diagrams, and C/C++) can be combined in a single design, if needed. Because of this, one team member may prefer to work in VHDL while another uses Verilog. There may be project management reasons for discouraging multi-HDL use within a single project, but the languages themselves function together in a single design without issue. One reason a project manager may wish to avoid the use of multiple HDLs is that the future sustainment of the effort will require the participation of developers with skills in both languages.
Similarly, it is possible to define a high-level architecture for a project in terms of a block diagram and then implement detailed subsystem functionality using the HDL of choice. In the same design, it is also possible to integrate HDL generated from a C/C++ algorithm. Embedded system architects and developers should carefully consider the implications and select the appropriate implementation method for each portion of an FPGA design.
The next section will introduce the steps in the standard FPGA development process.
Reprinted with permission from Packt Publishing. Copyright © 2021 Packt Publishing
|Jim Ledin is the CEO of Ledin Engineering, Inc. Jim is an expert in embedded software and hardware design, development, and testing. He is also accomplished in embedded system cybersecurity assessment and penetration testing. He has a B.S. degree in aerospace engineering from Iowa State University and an M.S. degree in electrical and computer engineering from Georgia Institute of Technology. Jim is a registered professional electrical engineer in California, a Certified Information System Security Professional (CISSP), a Certified Ethical Hacker (CEH), and a Certified Penetration Tester (CPT).|
- Embedded design with FPGAs: Hardware resources
- Open-source tools help simplify FPGA programming
- Implementing floating-point algorithms in FPGAs or ASICs
- Software tools migrate GPU code to FPGAs for AI applications
- FPGAs displace ASICs in Subaru Eyesight vision-based ADAS
- How flash-based FPGAs simplify functional safety requirements
- Reaping the benefits of instant-on FPGAs
- FPGA configuration using high-speed NOR flash
- How FPGA technology is evolving to meet new mid-range system requirements
For more Embedded, subscribe to Embedded’s weekly email newsletter.