This page is the fourth in a series of five pages about becoming a professional FPGA designer. This time, I go through some skills that are less important to start off with. I start by explaining the point of doing this in the first place.
Why mention something unimportant?
It may seem a bit off to write a page about skills and at the same time say "nah, this isn't so important". But this series isn't about me telling you what to do. Rather, I try to explain why each topic is important (or not so important). So it makes sense to do the same for the less important topics as well.
Some practical skills are often useful but overrated. These are skills that you might need to acquire at some point in time, but there's also a chance you'll never need them. The reason a topic can be overrated is that it often appears in example designs for boards. Not because it's important, but because it's relatively easy to make a nice and impressive demo with a specific technique.
Just to be clear about it: All skills mentioned below are useful. It's just that they are often acquired as needed to work on a project, along with a whole lot of other technical topics specific to that project's requirements.
I2C and SPI
You can work your whole life as an FPGA designer without knowing anything about these two. But realistically, there's a good chance you'll meet them quite soon in your practical work.
I2C (IIC, Inter-Integrated Circuit), protocols very similar to it, and SPI (Serial Peripheral Interface) are by far the most common standards for transmitting data to and from an electrical component on a PCB. They are based upon a master / slave setting, where the master initiates a read or write operation, and the slave possibly responds to it. In most cases, the master is a processor or a relatively sophisticated component, and the slave is a simpler component with a peripheral function in the electronic design.
I2C and protocols derived from it have a very low data rate (usually around 100 kbit/s) and are mainly used for configuring the parameters of a component. For example, if the component is an A/D converter, I2C can be used to select which voltage reference the component will use, and if its output should be given as a signed or unsigned integer. The main advantage of this protocol is that the connection consists of only two wires: Clock (SCL) and data (SDA). There is also a connection to ground (GND), but this is usually done through the PCB's common ground and virtually never requires a separate wire.
The protocol is actually a bus, so each data exchange cycle includes a 7-bit address. Consequently, several components can be connected to this pair of wires in parallel. Each component needs to have a different address in this case.
The I2C standard was originally patented by Philips. Because it was so useful, a lot of strikingly similar variants are commonly used, for example SMBus, PMBus and DDC2. These standards adopt the main ideas of I2C, but have slightly different parameters (in particular data rates) and main usage scenarios. For example, all computer monitors sold today have a small flash memory, containing information about what graphics modes they support. The cable between the graphics card in the computer and the monitor has two wires that are connected to this flash memory. This allows the graphics card to read the data in this memory with the DDC2 protocol, which is effectively the same as I2C.
So if you understand I2C, you know how a lot of different components talk to each other.
Next, SPI. This protocol usually requires four wires between the master and slave components (SCLK, MOSI, MISO, SSn). Sometimes this protocol is used for configuring a component, just like I2C and its variants. However, the main use of SPI is for transmitting data at higher data rates. It's not unusual that components support an SCLK frequency of 20–50 MHz, so it's a practical protocol for transmitting application data. For example, an A/D converter for two audio channels generates 48,000 Hz × 2 × 16 bits = 1.536 Mbit/s. This data rate is easy-peasy for SPI. And indeed, there are several audio chips that use SPI for transmitting samples.
It's also worth mentioning that the connection between the FPGA and the flash memory from which it reads its bitstream is often QSPI. This interface is just like regular SPI, but with four data wires instead of one, making the data transfer faster.
So, to the concluding question: Should you learn I2C and SPI as part of becoming an FPGA designer? My take is that they have nothing to do with FPGA design by themselves. But if you work in a small team developing an electronic product, odds are that you'll need to configure one of the components with I2C. Or one of the components connected to the FPGA uses SPI for communication. Or maybe use the flash memory containing the FPGA's bitstream directly from your own logic.
There are many use cases for these two protocols, but the most important thing is to recognize them and their variants when they appear in datasheets. Often a component uses one of these protocols, but doesn't use its name explicitly. If you know the principles behind I2C, you can't miss it when the datasheet describes a similar interface. The same goes for SPI.
And if you sit in a job interview and claim to be an experienced FPGA designer, but you don't know anything about these two protocols, it may not be so impressive.
Plus, here's a suggestion for a project to gain some experience: It's quite easy to find a cheap temperature sensor or a different kind of simple component that uses I2C or one of its variants. Buy a component like this, connect it to your FPGA board with Dupont wires or some other hacky method. Then write everything needed to interact with it through I2C from scratch. If you have an oscilloscope, use it to monitor the signals. This could be your first do-it-yourself project.
Block design
Most FPGA design tools offer the possibility to connect logic design blocks with a graphical interface. In principle, using this interface is fairly equivalent to instantiating modules in Verilog. The wires graphically drawn are like port connections in Verilog. A block design tool often offers a few more capabilities, for example, automatically inserting small pieces of logic that ensure that the connections made in the GUI do what the user intended.
The block design method is at its best when all or most of the blocks are supplied by the FPGA's vendor (in the form of IP blocks). In particular, when a processor is involved, a block design is usually the natural way to connect it with IP blocks implementing peripheral functions: Interrupt controllers, DMA controllers, bus arbiters etc. There are also more "classic" peripherals, for example Ethernet controllers.
Aside from the obvious processor-related blocks, there is also a large selection of IP blocks that implement a wide range of functions commonly implemented in an FPGA. These range from FPGA elements like clock resources and logic adjacent to I/O pins, through simple arithmetic units, up to digital filters and even more complex logic. It looks like the idea was to make it possible to create an entire FPGA design using only a block design.
That said, I've never heard of anyone who built a sensibly useful FPGA project with these pre-made IP blocks only. Except for a project consisting of a processor and its peripherals only, but if you only want a processor, why are you using an FPGA? It's much more expensive and complicated.
But an entire block design can, and usually is, instantiated in a Verilog module, just like any other Verilog module or IP. Accordingly, the block design is usually part of a larger, Verilog-based, project. In this context, a block design containing only a processor and its peripherals makes sense: It's just a module inside a larger project.
So what does this mean in terms of skills that you should, or maybe shouldn't learn?
The simplest skill is to create block designs, add blocks and connect them. There are plenty of tutorials telling you what to click and when. As these tutorials are so easy to follow and complete, why not run through one or two of them? And if you do, don't bother understanding each step and each selection made throughout the process. The point is to get a feel for how block design is done. Dive into the details if and when that becomes relevant.
The next skill is including a block design in a project, and instantiating it in a Verilog module. That's also quite simple, and there are a lot of examples for it. It's not different from using any IP in your project. If you know how to use a FIFO IP in your Verilog project, you also know how to do the same with a block design.
The most significant skill is turning something you wrote in Verilog into a block that can be used in a block design. And even more significantly, make this block configurable with Vivado's own GUI (or whatever development suite you use). I wouldn't recommend learning how to do this unless there is a direct purpose for doing so. Most FPGA designers never need to do anything of this sort.
So what's the bottom line? As with any GUI tool, play with it a bit, and then progressively learn as much as you need to complete a task. In particular, don't expect to do everything with a block design, even if the set of available blocks can mislead you into thinking that's the way to go.
Working with processors inside the FPGA
Many projects, in particular standalone electronic products, have some software running in them, and hence involve a processor. This processor can be a block inside the FPGA or a separate physical component outside of it. The challenges are completely different in each case.
I'll start with the processor inside the FPGA scenario. This can be a "hard processor", such as those in AMD's Zynq family, which have an ARM processor built into the silicon. A "hard processor" is just like any other logic element inside the FPGA, comparable to arithmetic units, PLLs and block memories. Except that a processor block is relatively big and has a whole lot of pins.
If an FPGA doesn't have a "hard processor", it can still run software on a "soft processor". For example, AMD's Microblaze and Altera's Nios processors. The difference is that the processor is implemented with the FPGA's regular logic elements (the "logic fabric"). This method is slower, takes more energy and consumes logic resources, but often it's good enough and a cost-effective choice.
Both "hard processors" and "soft processors" are in principle like any Verilog module that connects with the FPGA's logic just like any other IP. It's therefore quite natural to consider them part of the FPGA and hence consider the FPGA designer responsible for them.
Setting up the processor in the logic design is usually the relatively easy task, as there are lots of examples and templates for it. But it rarely ends there. The processor needs to have certain peripherals, and these should be available to the software at known addresses in the processor's memory space. The peripherals often have interrupt request outputs that need to be properly connected to the processor and configured correctly.
The software team usually expects that someone else takes care of the piece of software that runs when the processor powers up or gets a reset signal. This software consists of routines that, among other things, write to the processor's own hardware registers in order to make it work as configured. This isn't as difficult as it may sound, as the development tools create C code for inclusion in the larger software project for this purpose. But who is responsible for generating these files and ensuring that they are in sync with the rest of the FPGA design? In a small development team, that's the FPGA designer.
And if that isn't enough, the FPGA designer may be required to create peripherals for the processor that implement logic specific to the developed product. Writing the drivers for this logic in C is usually more than welcome.
So — is this something to start learning as part of becoming an FPGA designer? If you want to work in the intersection between software and hardware, I would say possibly yes. If you're already a C programmer and like low-level programming, this can be for you. And in particular, if you don't mind reading the processor's very thick user's manual every now and then. This is where you find the answer to "How can I have two units of peripheral X and three of peripheral Y?"
What topics should you learn, then? I'd say gaining a basic understanding of how processors run software, how they access memory, how interrupts work, and how processors start off when they power up. Look at a processor's address map, see how the memory regions are divided into different segments (on-chip RAM, external RAM, internal registers, external bus access segments, etc.) and understand how that whole thing works.
I also suggest understanding the principles of the AMBA protocols (AXI3, AXI4, AXI4 Lite, etc.), in particular the VALID / READY handshake. If you'll ever design a peripheral, odds are you'll need to implement an AXI slave. And even if you work with a processor that doesn't use AXI natively (for example, Altera's processors), the principles will be the same.
You'll probably also be responsible for the software running on powerup and reset of the processor. Getting acquainted with how this software is created and how it relates to the processor's own hardware registers might therefore help. And it's easier if you write the driver routines for accessing any peripherals you might be required to design. For these reasons, you won't get very far without being good at programming in C. Even if you use AI to write the code for you, you need to understand exactly what this code does.
But above everything, be aware that you won't learn much by running through a long example project, where you've configured a processor and clicked, clicked, clicked and in the end something very impressive happened on your board. Everything valuable to learn has already been done for you, and you skipped the important parts while clicking your way to the final line. If there's anything valuable in such an example project, it's what happens after you're done: What did you understand from the example? What can you change in the project? What can you try out yourself?
Working with processors outside the FPGA
Quite often, the processor is a standalone component or part of a separate board in a project involving an FPGA. It's not unusual to have a fullblown PC, either a regular desktop or an industrial x86-based motherboard, as the central part of a product. In these settings, it's common to consider the FPGA as a peripheral. Even though the purpose of the FPGA varies from one project to another, the processor (or PC) is usually considered the center of the project, and the FPGA (and the electronics around it) a part controlled and managed by software.
As the processor is a separate physical part, there is usually a separate team taking care of everything about it, including the software. The FPGA designer's tasks related to the processor mainly consist of interfacing with it. If the processor is only expected to control the FPGA's behavior, it's possible that the communication consists only of commands, possibly by reading or writing registers. In this case, simpler protocols are often used, in particular I2C and SPI. I've already covered these two above. SPI may also be chosen for data exchange at relatively low data rates.
It's worth mentioning that I2C and SPI are commonly used only with embedded processors. These protocols are less common with project-specific peripherals when a PC motherboard is involved. Even though SMBus is often used to control fans and obtain temperature readings, it's less common to use protocols of this sort with your own peripherals.
With embedded processors (and DSPs), it also happens that the interface with the FPGA takes place through an interface specific to the processor (or a family of processors from a specific vendor). For example, the processor might have many physical pins connected to the FPGA for accessing it with an address / data bus interface. Implementing the logic interfacing with this bus requires an accurate understanding of the (not always cleverly designed) protocol defined by the processor's vendor. There are also timing requirements that need to be met. However, there is no point in preparing yourself for a task of this sort, as it doesn't differ from interfacing with any other external component having a complicated I/O protocol.
Interfacing with PCs and high-end embedded processors is usually done with the PCIe (PCI Express) interface. This is a robust and well-supported communication channel that allows a data rate of 200 MB/s (of payload data) at its simplest setting, but sky is the limit: New versions of the PCIe protocol come out at regular intervals, and the data rate gets higher with each new version. The actual data rate limit is often what the processor itself can handle.
The downside of PCIe is that it's a complicated protocol, intended primarily for computer peripheral chips. It's implicitly assumed that if you're implementing something for PCIe, you have allocated specific manpower for developing the logic interfacing with the computer, and a software team as well for developing the driver. This task becomes significantly easier if Xillybus is used, as this solution takes care of the complication on both sides.
So what skills should you learn to prepare yourself for a scenario with an external processor? First and foremost, it can help a lot if you're good at C programming, so you can write the driver routines for accessing the FPGA from the processor, or at least offer sample code. AI can write this code for you, but if you don't have an accurate understanding of what the code does, you might end up with a bug in C that looks as if it came from the FPGA.
Other than that, there isn't much I would recommend learning in advance. The required technical skills depend a lot on how the processor and FPGA are connected, which differs from one project to another.
Other interface standards
If you go through several available FPGA development boards, you'll see that some specific components and connectors tend to be present more commonly than others. This can be interpreted as an indication of what technologies are often used in an FPGA project. That's partly true, and I'll go through a few of them.
HDMI
An HDMI connector is often present on FPGA boards. The purpose is usually to allow the FPGA to generate video output for display on a computer monitor. The connector's wires often go directly to the FPGA, as it's capable of generating the required high-speed signals with the help of the I/O block's SERDES. On some boards, there's a separate component ("video encoder") between the FPGA and the HDMI connector.
This connector's ubiquity indeed reflects reality: Many FPGA projects involve some kind of video processing and output. Connecting the FPGA board to a computer monitor and experimenting with that arrangement can help in the future. In particular, learn the basics of VGA, how the screen is scanned horizontally and vertically, and the different standard display modes that exist. If the HDMI connector is connected directly to the FPGA, you may try to implement logic that generates the signals, but I'm not sure that's worth the effort. It's not a simple protocol to learn, and if it doesn't work, it's difficult to debug such a project: The data rate on the wires is very high, and the computer monitor won't tell you what's wrong when it refuses to respond to the FPGA's output. There are ready-made IP blocks for this purpose. I suggest using them, and instead focusing on generating video data.
And a little tip: You probably want to send RGB pixels to the monitor. In this case, follow the DVI protocol (which is related to VGA), and not HDMI. The signals of DVI and HDMI are interchangeable. But HDMI is a stricter protocol intended for standard high-definition TV, and has a narrow set of display modes. The pixels of the commonly used display modes are represented in YCbCr format, which is an unnecessary difficulty. The HDMI connector is used because the DVI connector and its cable are large and clumsy. But the signals to a computer monitor almost always follow the DVI standard, not HDMI.
If you try out a video output project, you'll soon discover that the FPGA's own block RAMs often aren't enough to fit an image frame. That brings me to the next topic.
DDR memories
The FPGA's own RAM is a relatively scarce resource. When the project requires handling megabytes and gigabytes, external memory is required. This is often the case in projects involving video, but also in other applications, such as coprocessing / hardware acceleration, network switching and more.
By far, the most commonly used external RAMs are DDR SDRAMs, which are the same type as those used in computers. This is why they often appear on FPGA development boards, sometimes as SODIMMs and more often directly soldered to the board. They have a low price and excellent bandwidth, but they are designed with computers in mind. Accordingly, they are bandwidth-efficient when the access requests are long bursts of contiguous address ranges. The less well-known fact about them is that they have really lousy performance when the access pattern is less disciplined: Even though they are called "Random Access Memory" (RAM), their bandwidth performance drops dramatically with other access patterns. For example, if one data element is required at a time, and each time from an address unrelated to the previous one, these memories perform extremely badly.
The interface protocol with DDR memories is very complicated, however there is rarely any need for FPGA designers to know much about it: Every reputable FPGA vendor supplies a reliable and fairly efficient DDR memory controller as a free IP core for use with its FPGAs. The FPGA designer is therefore only required to interface with this IP, using AXI4 or a similar protocol.
Are DDR memories a topic worth learning? I'd say there's a relatively good reason to do so, as they are used often in FPGA projects in various fields. A project that involves DDR memories and maybe generates video output can be a good exercise. It's also recommended to read through a DDR memory's datasheet in order to understand the memory's array structure and the need to select rows before accessing their data. It's also worth looking at the delay requirements between different operations (CAS, RAS, refresh, etc.) in order to grasp how they can reduce bandwidth efficiency. The most important thing to know about these memories is when they shouldn't be used.
SFP+ cage
A lot of development boards, in particular the vendor's official boards, have an SFP+ cage. This part stands out visually, as it's a relatively large metal part on the board's edge. This connector is present only when the FPGA has Multi-Gigabit Transceivers (MGTs, called GTX, GTH, GTY, etc. on AMD FPGAs). Inside the cage, a connector makes a direct connection to one or several of the FPGA's MGTs.
An MGT is a functional unit allowing bidirectional communication at Gigabit rates, usually 1 Gbit/s and above. This is the workhorse behind several well-known protocols, in particular PCIe, SuperSpeed USB, SATA, Gigabit / 10G Ethernet, and DisplayPort. There is a whole series of pages about MGTs on this website, starting with a page explaining MGTs in general.
The primary use of the SFP+ cage is to insert a fiber-optic module into it. This makes it possible to connect two FPGA boards with a fiber-optic cable, or to connect the FPGA board to another unit with a similar interface, for example, a fiber-optic network router. The fiber-optic module is usually not included in the FPGA development board kit, but these aren't very expensive. There are also cables allowing you to connect two SFP+ connectors directly, without fiber.
Does the fact that SFP+ cages are so common on FPGA boards mean you should become an MGT expert as soon as possible? I wouldn't say that. They appear on boards a lot, among other reasons because the component on the board is cheap and doesn't require additional components or a lot of connectivity. It is also an elegant way to connect two FPGA boards compared with the alternatives (which usually consist of four RF cables connected to each MGT).
And MGTs are not easy to work with: They are in some ways similar to digital radio channels. There are bit errors on the link, the transmitter's clock frequency is often not exactly the same as the receiver's clock, the receiver needs to find the beginning of data frames in the data channel, and the list goes on.
It's therefore common that MGTs are used together with an IP block that handles the communication protocol. In particular, practically all FPGAs with MGTs also have a hard IP block implementing the PCIe protocol. There are also IP cores for several other well-known protocols used with computers. For a connection between two FPGAs, Xillyp2p presents a simple interface.
So even though MGTs are everywhere, this topic isn't necessarily the first thing to learn.
Ethernet
A lot of FPGA development boards have an Ethernet connector. The reason behind it depends on the kind of FPGA.
The easiest case to explain is when the FPGA has a processor inside, for example, AMD's Zynq devices. On these boards, the Ethernet connector is almost always connected to the processor's dedicated pins for that purpose. This is just like the Ethernet connector on any board with an embedded processor.
What about boards with FPGAs without a processor? First thing, even such an FPGA can contain a "soft processor" (e.g. MicroBlaze or Nios). Such a processor can make the same good use of an Ethernet connector as any other. This isn't necessarily a common usage scenario, but for a long time FPGA vendors tried to promote the idea of using FPGAs in data centers. They really wanted to make a mental connection between FPGAs and computers. The Ethernet connector is part of that.
If there is no processor at all on the FPGA, the Ethernet connector can be used to communicate with a computer. TCP/IP is maybe the first thing that comes to mind, however this protocol is tailored for implementation in software. Implementing this protocol in logic is complicated and results in limited functionality. The protocol stack also needs to respond to ARP requests and preferably ICMP packets as well.
Therefore, the only practical way Ethernet is used for connecting an FPGA board (with no processor) to a computer is with broadcast packets: The FPGA board and the computer are connected point-to-point. The Ethernet frames transmitted on the cable all have the broadcast MAC address. This is often achieved by using broadcast UDP/IP packets. So this is miles away from the way we usually connect a computer to an Ethernet network.
Except for not being elegant, this solution has a significant drawback: The Ethernet protocol doesn't guarantee delivery of packets. If there is a bit error in an Ethernet packet, it's dropped silently. The computer's network card can also randomly drop a packet for no reason at all. This goes unnoticed in normal use.
Hence, if data loss isn't allowed, the FPGA must keep all data it transmits in a buffer in order to make retransmissions. A protocol with an error detection mechanism needs to be applied in order to request such retransmissions. Doing it right over Ethernet becomes really complicated.
Alternatively, the possibility of data loss is accepted. Or, as often happens in student and hobby projects, this possibility is ignored, because it doesn't happen when the system is tested. Which is good enough when the project isn't professional.
Bottom line: Definitely use the Ethernet connector if there's a processor running on your board, in particular if it runs Linux. But I wouldn't suggest getting deeper than so.
That's the end of the fourth page in this series, and this also concludes the discussion of professional skills. The next page takes a completely different direction: What kind of personality is preferred for this profession?