[Disclaimer: The post is intended for Students or young professionals looking to know more about FPGAs]

When I first transitioned into FPGA design a decade ago, I felt a false sense of security. I looked at VHDL and saw familiar faces: if/then statements, case blocks, and the ever-present for loop. Coming from a C background, I assumed I was just learning a slightly more verbose programming language.

I was wrong. This is the “Syntax Trap.”

The most dangerous thing a software engineer can do when approaching an FPGA is to assume that similar syntax implies similar execution. In software, we live in a Sequential World. We write a story: First do this, then do that. Even when we talk about multi-threading or concurrency, we are usually just “time-slicing”—tricking a high-speed CPU into juggling multiple tasks by switching between them faster than the human eye can see.

In Hardware, the world is Inherently Parallel.

The Code Comparison: C vs. VHDL

When you write a loop in VHDL, you aren’t telling a processor to repeat an action. You are telling a synthesizer to unroll that logic and physically instantiate it across the silicon. If your loop has ten iterations, you aren’t running one piece of code ten times; you are creating ten different physical instances of that logic that exist—and execute—at the exact same moment.

To understand the weight of this difference, let’s look at the simple for loop. In C, this is a matter of time. In VHDL, it is a matter of space.

In C (Software):

// Sequential: The CPU flips bit 0, then 1, then 2...
for (int i = 0; i < 8; i++) {
    signals[i] = !signals[i];
}

In VHDL (Hardware):

-- Parallel: The synthesizer builds 8 physical NOT gates.
for i in 0 to 7 loop
    signals_out(i) <= not signals_in(i);
end loop;


The “Loop Unrolling” Secret

To a software engineer, both the pieces of code look the same. The VHDL code above looks like it takes 8 “steps.” To an FPGA Engineer, it looks like one massive row of gates.

When the synthesis tool sees that VHDL loop, it unrolls it. It doesn’t create a “looping” mechanism in the silicon; it literally copies and pastes the logic inside the loop 8 times.

FeatureSoftware for loopFPGA for loop
ExecutionSequential: One after another.Parallel: All at once.
ResourceOne CPU core used 8 times.8 NOT gates used 1 time.
TimeTakes 8 “units” of time.Takes 1 “unit” of time (propagation delay).
Mindset“How many times should I run this?”“How many copies of this circuit do I need?”

The code would synthesize into something like the following figures:

This is the key. An FPGA designer needs to visualize the digital circuit he/she is trying to implement.

This is not a unique case with a particular gate. it is with all the designs.

Lets take another example, what if you increment by one in C and in VHDL


The Comparison: Incrementing 8 Times

In C (Software):

// Result: A = 8
for (int i = 0; i < 8; i++) {
    A = A + 1;
}

  • What happens: The CPU performs 8 separate “Add” operations in a sequence. It takes the value of A, adds 1, stores it back, and repeats.
  • The Math: 0 –> 1 –> 2 –> 3 –> 4 –> 5 –> 6 –> 7 –> 8

In VHDL (Hardware):

-- Result: A = 1 (Wait, what?)
for i in 0 to 7 loop
    A <= A + 1;
end loop;

  • What happens: To a software dev, this looks like it should result in 8. But in VHDL, it results in 1.
  • The “Last Assignment Wins” Rule: Inside a process, signal assignments (<=) do not happen immediately.1 They are scheduled.
  • The Unrolling Reality: The synthesizer unrolls this loop into 8 parallel lines of code:
    1. A <= A + 1;
    2. A <= A + 1;
    3. …and so on.Because they all happen at the exact same time (parallelism!), they all see the same initial value of A. If A starts at 0, every single one of those 8 lines is trying to set A to 1. The compiler simply takes the last line it sees and discards the rest.2

Once again, even though the code looks nearly identical, the physical result of incrementing a signal in a loop is where software engineers usually get their first “broken” hardware.


How to actually get “8” in Hardware?

If you want that loop to actually increment the value by 8 in a single clock cycle, you have to use a Variable (:=) instead of a Signal (<=).

process(clk)
    variable temp_A : integer;
begin
    temp_A := A; -- Start with current signal value
    for i in 0 to 7 loop
        temp_A := temp_A + 1; -- Updates IMMEDIATELY (Blocking)
    end loop;
    A <= temp_A; -- Assign final result back to signal
end process;

The Circuit Design: What is inferred?

This is where the “hardware” mindset comes in. When you use a variable to increment 8 times in a loop, you aren’t telling the FPGA to “count fast.” You are telling it to build 8 physical adders chained together.

In Hardware: You use 8 Adders 1 time

In Software: You use 1 Adder 8 times

Now, we have to see what is wrong with eight adders chained together. That’s a topic for another post. If you found something interesting, tag along.

We’ve looked at two simple examples—inverters and adders—but the lesson applies to everything in the FPGA world. The “Syntax Trap” is thinking that VHDL is just another way to talk to a CPU.

It isn’t. VHDL is a way to build a machine.

Thanks for reading!

Also read: The Career Everyone Missed: FPGA Engineers in the Age of AI

Leave a comment

Trending