This page is the fifth and last in a series of pages about becoming a professional FPGA designer. Unlike the previous ones, it doesn't talk about technical matters. Instead, the focus is on us as human beings, and what characteristics make the life of an FPGA designer easier and better.
This actually matters
It may seem odd to talk about the personality and attitude of FPGA designers, in particular on a website focused on technical topics. However, in a guide intended for a to-be FPGA designer, I find it suitable to also discuss the human qualities and behaviors that make the difference between having everything under control and working in complete chaos.
There's a suitable personality for virtually every profession: It's hard to be a car sales agent if you're bad with people, and you won't be a good teacher if you don't like kids. Likewise, there are certain personality traits that help you as an FPGA engineer, and some that don't.
I'm not preaching and neither am I trying to put anyone off. I'm not coming with "you must work hard" either. On the contrary: The intention is to do things correctly, and reach goals with less effort.
On this page, I'll attempt to describe what it takes to be a successful FPGA designer, on top of having this or other professional knowledge, in order to live in peace with this profession. This page is about the engineer's personality. It won't come as a surprise that it's better to have self-disciplineand self-control, and to be the accurate type. A slight obsession with details doesn't hurt either.
But don't mix this with some idea about suffering in life or working yourself to death. It's the other way around: If you have the ability to work in a certain manner, you'll get it done quicker and easier. It will be fun and rewarding. Getting it right the first time is the ideal, and it's attainable.
On the other hand, if you feel that you don't fit into my descriptions of the ideal FPGA designer below, not even remotely, hmmm, how should I say it? Like, think about this whole idea one more time?
"It works" isn't good enough
In the software world, in particular websites and apps, the common practice is to jot something down, try it, fix whatever is wrong and try again. With AI, even the code-jotting phase is skipped, and a machine does both coding and testing, and eventually commits the result to the Git repository.
The underlying idea is: If the code passes the tests, the job is done. If there's still a bug, QA will find it or a user's complaint will soon arrive. In that case, a request to fix it will be issued as a matter of standard procedure. Then fix the bug. A whole lot of software teams are structured to work exactly like this.
Whether this practice is suitable for developing software or not is a separate discussion. What I want to state clearly is that it's deeply wrong for professional FPGA design. "It works" is by far not good enough for an FPGA project. Maybe for hobbyists, but definitely not for a project that goes into real-life production. It's tempting to fall into this trap, particularly when you're happy that something finally works after a long debugging session, and call it a day.
This might sound like puristic preaching, but it's the simple truth: The only way to get a reliable FPGA design is to prove to yourself, once and for all, that what you've designed is guaranteed to work. You don't finish a task when the design passes all tests, but only when you can convince yourself that it can't possibly fail.
I'll compare this with a mathematical theorem: You don't say it's correct because you tried it a few times with numbers, and it turned out correct every time. You consider the equation to be correct when you have a mathematical proof.
In practice, this means that every line in a Verilog file is treated like an equation in a mathematical derivation, and the same goes for the timing constraints and other related source files. This may sound a bit extreme, but being this careful pays off in the long run.
The same goes for the FPGA's connections to other electronic components: You don't assume that the electrical interface is fine just because it works. You prove to yourself that the requirements in the datasheets are met: Both those in the FPGA's datasheet and those in the other components'. Are the voltage levels correct? Does the FPGA design ensure that all timing requirements on both sides are met?
Does this mean that my designs are always free of bugs? Of course not. I'm human, and I make mistakes. Just as I might not get a mathematical proof 100% correct, even if I try to. I might forget to check corner cases, I might swap a plus with a minus and mess up in general.
But the nice thing about this rigorous approach is that the few bugs that I end up with are usually obvious, and are relatively easy to fix. And once they are fixed, the design just works. No bugs, no mysteries, no witchcraft. A solidly working piece of electronics.
It's the slow path to reaching the goal quickly.
Do people really work this rigorously?
Short answer: Definitely not. I know that in particular from my time as a freelancer. My first task, with every new client, was to stabilize the FPGA project. This was a bit like doctors stabilizing a patient in the emergency room. And the engineers responsible for the project often seemed to need some kind of stabilizing too, after a long time of stress and frustration.
The jot-and-then-debug attitude is unfortunately common in the FPGA industry as well. No wonder, as the simulator is often presented in Verilog courses in the same spirit as a debugger in the software world. The underlying suggestion is often to reach the desired result by trial and error. Simulate until it works on the computer, and then synthesize and fix it until it works on hardware as well.
To make things worse, there are managers who encourage this kind of work method. They are impatient to see results, and once they see something that appears to be OK, they expect you to move on to the next task. The schedule is pressing, and "we'll fix bugs later".
As a result of this approach, it's difficult, and sometimes impossible, to get a truly reliable FPGA design. This is compensated for with extensive regression tests in simulation as well as extensive tests with hardware. Some companies run temperature tests on every manufactured board before it leaves the production line, if it has an FPGA on it. Testing the hardware before delivery becomes its own department, with its own hardware and software, which has only one purpose: Making sure that the FPGA does what it really should.
Behind all this, there are very stressed FPGA engineers, who are behind schedule as they frantically chase bugs that mysteriously appear and disappear.
It's not always this bad. When the FPGA works at a relatively low frequency, when requirements are simple and when sporadic failures aren't such a big deal, the trial-and-error attitude can work fairly well.
Besides, in reality, most people working with FPGAs are somewhere in the middle of the scale: Not at the extreme of considering Verilog as mathematical equations, but with an elevated level of patience, self-discipline and respect for accuracy. That's how they manage to get the work done in this field.
Know what you're doing
If I've convinced you that trial and error isn't the way to go with FPGAs, it's clear that a more rigorous and accurate path is required. But that's not enough by itself. A rigorous attitude doesn't help if you don't understand exactly what you're doing.
For example, it's quite common to see asynchronous resets in Verilog code (I mentioned this on previous pages as well). This is a legitimate method for resetting logic, but only if it's applied correctly. In the vast majority of cases, this reset is used incorrectly, and therefore doesn't guarantee that the logic behaves as expected. But in reality, everything works fine. Usually. There's a separate page on this topic.
The reason for this incorrect use of asynchronous reset is probably that people copy-paste Verilog code from other sources into their own. The coding pattern is so familiar and obvious, that people don't stop to think what it actually means. And in this case, what it doesn't mean nor guarantee.
Knowing what you're doing is a prerequisite for being able to prove to yourself that your design is guaranteed to work. This means understanding exactly what each Verilog expression means, and how the synthesizer might interpret it. The same principle applies to timing constraints and other information that the development tools consume in relation to the FPGA design.
But as I've already admitted, most FPGA designers aren't rigorous enough to prove that the design works. Knowing the exact meaning of what you type is nevertheless a step in the right direction.
Think abstractly
If you've taken an academic course in computer science, you may have seen how abstract creatures are invented for the sake of describing software. For example, data structures that are always organized in a specific way, classes and objects, streams of data, and invariants that are maintained after each iteration of a loop, and so on. In computer science, imaginary creatures are invented all the time, so that we humans can look past the small details inside and instead relate to a simpler representation. This reduces the load on our brains, and makes it possible to understand complicated software designs. This is what we call abstraction.
On the opposite side of abstraction, we have the concrete way of thinking. Or shall I call it "story-telling"? With this attitude, a computer program is treated like a story. First we do this, and then we do that, and if this is true we do this, otherwise that. Just follow the sequence of events with a finger going through the code, and you understand everything.
Story-telling works fine for developing simple scripts, websites, mobile apps and other simple software. If the user presses this button, go to this screen or web page, and take it from there. The software progresses in one simple thread of execution, and can be understood in one thread of thought.
I'd like to demonstrate the difference between the two ways of thinking with an example. Let's look at this function, written in C, which calculates n!, the factorial of n:
unsigned int factorial(unsigned int n) {
if (n == 0)
return 1;
return n * factorial(n - 1);
}
This is the classic example of recursion. How do you understand the code above?
The story-telling way is to "try it out". It sounds something like this: "Suppose the function was called with n=3. It will call itself with n=2, then n=1, and then n=0. Now unroll: So it returns 1 for the n=0 call, then 1*1, then it returns 2*1, and finally 3*2, which is 6, and that's the correct answer. Great, it works". Maybe this thought process is done with a debugger, using single-step execution.
The other way is similar to a proof by mathematical induction. We assume that the function indeed returns the factorial of n and confirm that if it works for n-1, it also works for n. Finally, we confirm that it gives the correct value for n=0, and that the recursion always ends up at n=0. The sequence of execution is irrelevant, as the function is treated as an abstract creature that just fulfills its purpose.
And you may ask: Why complicate things? The story-telling explained it just fine. To this I answer: Yes, but it worked only because the example is simple.
And now I finally get to the point: If you're limited to story-telling for understanding software, it's going to be an obstacle for you as an FPGA designer. The first and obvious reason is that in an FPGA, everything happens at once. Very little in an FPGA can be described with "first this, then that".
The second, and more important, reason is that FPGA designs are often complex. Abstraction is often needed for you to be mentally capable of grasping what's going on. For example, it's a good habit to define a Verilog module so that its functionality can be described in a few sentences and without too many details. The interfaces to its ports should also be simple to describe. When it's possible to reduce a complicated logic block into a few simple ideas, there's a smaller chance of a human mistake. This principle applies to software as well, but it's not always as crucial.
The third reason for abstract thinking relates to the ability to prove correctness to yourself. With story-telling you cover only the scenarios you're capable of thinking about. A real proof covers everything.
When tackling complicated tasks, it may be necessary to invent new theoretical creatures before writing a single line of Verilog. For example, if you need a module that both inputs and outputs data packets, it may help to define N as the number of packets that are currently stored in its memory buffer. With this, you can prove that the buffer never gets full. It may not sound like much, but making this step towards mathematical thinking can help a lot. It may very well be that all logic in the module is somehow related to keeping this N within the correct limits.
The trick is to find the correct abstract creatures that really help get the logic right. This can mean not writing a single line of Verilog for a few days, and then suddenly having a short Verilog module written really quickly. Code conceived this way is often short, elegant, easy to understand and works on the first attempt and forever after.
This may however not work so well if your boss asks you what you're doing every day: For a few days there is nothing to show, and when you eventually come up with something, the response might be "all you have is this trivial module?"
So once again, being purely mathematical about FPGA design isn't necessarily the way for everyone. But I still suggest getting rid of the story-telling habit, if you have such.
Don't trust the tools
Or more precisely: The development tools won't stop you from making horrible mistakes. They may not even warn you.
No software compiler in the world will ever produce executable code that does something different from what the source code requests. If it does, report a bug. A synthesizer, on the other hand, may very well generate logic that doesn't fulfill the behavior requested by the Verilog code. If you're lucky, there will be a warning about it. If you're even luckier, you will notice this warning among the hundreds of other innocent messages and warnings the synthesizer spits out.
The other parts of the FPGA development suite can also play nasty tricks. The most obvious is that most of them will create a bitstream that you can load into the FPGA, even if the timing constraints aren't met. This means that the FPGA may work as the synthesizer meant it to, and it may not. Or maybe it will work a little and then not work. You will get a warning, or even a Critical Warning. But would a software compiler finish a compilation and give an executable that may not work?
There are endless other ways to mess up an FPGA design without the tools stopping you. This is somewhat of a cultural thing. It's as if someone intentionally wants it to be difficult to deal with FPGAs.
I've worked with several different FPGA vendors, and quite a few development tools for FPGAs. It's quite intriguing that they all have this same tendency to make things difficult, and that safety nets are something to wish for. It's not one specific, cheap and evil FPGA vendor. It's all of them.
On top of everything, it's not rare that FPGA development tools have bugs. If you're lucky, they crash while attempting to build the project, so at least this isn't a bug that makes your design malfunction. However, bugs that result in a flaw in the bitstream happen, even if not that often. It's worse when a new design suite is released. In the FPGA world, the latest out doesn't necessarily mean the best, to say the least.
Having said that, don't suspect the tools if your design doesn't work, especially not when you're new to this field. And if you think the tools failed you, find the smoking gun. Find the logic cell in the FPGA where it should have been one thing but turned out to be something else. Convince yourself that it's really the tools' fault it ended up this way. It's not enough that you feel that the tools are crazy. There is almost always a simpler explanation for what looks like that.
And in particular, if you change something unrelated in your Verilog code, and a bug disappears, it doesn't mean there's a bug in the tools. That behavior is more typical of poorly defined timing constraints and other similar mistakes.
The key to tackling this issue with the development tools is, at the risk of repeating myself, to know what you're doing. Specifically for this topic, to read the warnings and messages that the tools emit, and understand what they mean, or at least roughly what they are related to. It's a matter of experience to learn which warnings are harmless, always appear, and can and should be ignored. As for why the tools keep emitting many useless warnings, version after version — did I mention culture?
It's therefore a good habit to skim through all warnings every now and then, and see if something stands out. Do this even, and in particular, when everything works perfectly well. Not just because "it works" isn't good enough, but also as a way of learning which warnings are harmless.
And as a matter of fact, some warnings are an indication that you've done things right. For example, if a warning says that a register has been removed from the design because it has a constant value or is equivalent to another register. That's an opportunity to stop for a second and think about whether that makes sense in context. Quite often, such warnings help you realize interesting facts about your own code.
From requirement to design
When you're writing software, there is usually a rather straight line between the requirement and what you need to write. This is particularly true for simple software (websites and mobile apps, for example).
With FPGA design, it may not be that easy. The requirement for an FPGA often sounds more like "Here are the components, we want it to behave this way".
For example, the setup can be a board with a camera sensor, an FPGA and wires that go to a different unit. The task is to fetch the image from the camera sensor, perform some basic signal processing on the pixels, and send the output to the other unit, following your employer's specific format for transmitting video data.
You know everything about FIFOs, state machines, pipelines and RTL design. How do you create what you're asked for? Nobody is telling you "write a state machine". You're expected to create something that works.
If you're lucky, the requirements are similar to many previous projects. Copy the block diagram, imitate the logic, and maybe copy a few parts. But quite often, there's something about the requirements for your project that makes such imitation unreasonable.
That's when you become the FPGA architect as well. You decide how the task is divided into functional units, what each of them does, and how they interact with each other. The better you do this at the project's very beginning, the easier it will be to write and maintain the project. All too often, an existing project's block diagram is forced on a new project in the absence of something better. This shortcut comes at a cost.
So how do you become a good architect? Much of this comes from experience, and also from observing solutions chosen in other projects. I mentioned abstraction earlier: Understanding a design, whether it's your own or someone else's, in abstract terms helps you build the next project better. If you see Verilog modules as functional blocks performing a task you have a short name for, you have a palette to use for your own project. If you see how several wires connect two modules, and can give a name to how the modules interact through these wires, you are in a better position to decide on how the different parts of your new project interact. The better you are at recognizing the theoretical creatures in an existing design, the better you will be at building a new one.
If the FPGA architect part sounds difficult, let me share a small secret: It really is. I've done this a few times, and it takes a whole lot of both time and regret. Every small mistake at this initial stage has significant consequences.
But remember, that you probably won't need to design a project from scratch, and surely not as someone new to FPGAs. This task is usually given to the most senior FPGA engineer on the team. So you probably have some time before you take on the system architect's hat. And even if you're hired as the only FPGA engineer on the team, odds are that you'll maintain existing code, or develop a new project based on an existing one.
But it's never too early to start preparing for this task.
Summary
In many ways, the main topic of this page has been self-discipline in different forms. It's the ability to overcome what is often considered human behavior: To do things inaccurately and without thinking it through first (writing Verilog code and timing constraints in particular) and then fix the mistakes (simulation and debugging on hardware). To be happy that something works and to be eager to go on to the next task ("it works" isn't good enough). To explain things to yourself in a simple and natural (story-telling) way, instead of looking for the abstract ideas behind them. To skip small and boring details, such as the warnings that the tools emit.
Our human nature is unfortunately an enemy to us as FPGA designers. But note that I said nothing about working hard. Striving toward less work is not laziness if you get the job done. The goal is actually to work less, and yet get a better result. And it's possible if you do it right.
Neither is this about becoming a robot. It's about having self-control and accuracy in your work life, but definitely not working like a machine. We need our human brains. A robot can work many hours, but our brains get tired. Self-control sometimes means leaving the desk and getting some rest after a long and tedious day. Even when that bug is still there.
And to summarize this entire series of pages — as should be evident now, FPGA design isn't the simplest of professions, and I've listed quite a few reasons for that. If you don't like learning new things about electronics all the time, maybe this isn't for you. If you don't think you have the self-discipline to do things thoroughly and accurately, that's another reason to rethink.
And if I haven't managed to scare you so far, I'll welcome you to the club, and wish you the best of luck and skill. And more than anything, I hope you'll enjoy this choice as much as I do.