What every software programmer needs to understand about hardware design
The most important article for a new digital designer
Every software developer who knows a language such as C or Java has the same problems when trying to start programming in VHDL or Verilog. They make assumptions about how code works. These assumptions are usually universal for all software languages. Unfortunately, those assumptions do not hold for hardware description languages. If you are new to hardware development but know a software language or two, read this first! This article gives examples of code and explains how the code works in a software world and in a hardware world to show you the difference.
Assumption #1: Serial vs. Parallel Logic
This is probably the most fundamental difference between hardware and software programming languages. Software designers have only ever seen serial code, yet they probably do not realize this fact. What is meant by serial code is that the lines of code are executed one at a time. For example, Line #2 can only execute after Line #1 is complete. VHDL and Verilog do not behave this way! They are known as parallel logic languages and all of the lines of code can and will execute all at the same time. This is known as concurrency. Here is an example demonstrating the difference between serial and parallel logic. Let’s say that a designer wants to light up an LED once every ten clocks.
Example Software Code:
while (1) { if (count == 9) { LED_on = 1; count = 0; } else { LED_on = 0; count = count + 1; } }
Equivalent VHDL Code:
P_INCREMENT : process (clock) begin if rising_edge(clock) then if (count < 9) then count <= count + 1; else count <= 0; end if; end if; end process P_INCREMENT; LED_on <= '1' when count = 9 else '0';
The important thing to realize here is that in the software code, each line executes, then the next line is allowed to execute. This is NOT true in VHDL and Verilog, and this is demonstrated by the last line that assigns the LED_on signal. That line is running concurrently with the VHDL process. It is always assigning either a ‘1’ or a ‘0’ to LED_on. If this were software, this line would only be reached once the preceding lines of code had been executed. A good digital designer needs to always remember that VHDL and Verilog are parallel languages.
Assumption #2: For Loops
This is a huge problem that new hardware developers have. They have seen for loops hundreds of times in C, so they think that they are the same in Verilog and VHDL. Let me be clear here: For loops do NOT behave the same way in hardware as in software. Until you understand how for loops work, you should not use them.
Example Software Code:
For (int i=0; i<10; i++) data[i] = data[i] + 1;
This code will take every value in the array “data” and increment it by 1. Here is equivalent code in VHDL:
P_INCREMENT : process (clock) begin if rising_edge(clock) then if (index < 10) then data[index] <= data[index] + 1; index <= index + 1; end if; end if; end process P_INCREMENT;
Starting to see a pattern here? Code written in C is almost always going to be less lines to do similar functionality as code in VHDL or Verilog. I’m going to be bold and say this: if you haven’t done at least 3 FPGA designs you should never be using for loops. So think about how the code you wrote in software could be rewritten to never use a for loop. Usually all you need is to add a counter signal (like index in the example above) to do the same thing that the for loop will do.
Assumption #3: Execution of Code is Immediate
This ties in to the serial vs. parallel logic discussion above but it is a common mistake that software developers often make. Software developers need to remember that a line of code is not immediately executed, with the value of the signal updated for use. An example below details this assumption with a state machine. The example below shows an initialization routine for some peripheral component, say an Analog to Digital converter. The FPGA needs to write in order to the ADC: 5, 6, 1, 0 on the data line. The state machine as described in software will allow the value of data to change as the states change. Unfortunately in the broken example of hardware code below this is not the case:
Example Software Code:
state = INITIALIZE; data = 5; state = LOAD_1; data = 6; state = LOAD_2; data = 1; state = DONE; data = 0;
NOT Equivalent Hardware Code: (Broken Code)
P_STATE_MACHINE : process (clock) begin if rising_edge(clock) then state <= INITIALIZE; data <= 5; state <= LOAD_1; data <= 6; state <= LOAD_2; data <= 1; state <= DONE; data <= 0; end if; end process P_STATE_MACHINE;
The hardware representation of this code is very broken! Since every line in a process executes concurrently, data will be always stuck at 0 and state will always be stuck at DONE. This code will never execute the state machine the way that it will in the software code. The code below is the correct way to write this state machine in VHDL:
Equivalent Hardware Code:
P_STATE_MACHINE : process (clock) begin if rising_edge(clock) then if (state == INITIALIZE) then data <= 5; state <= LOAD_1; elsif (state == LOAD_1) then data <= 6; state <= LOAD_2; elsif (state == LOAD_2) then data <= 1; state <= DONE; elsif (state == DONE) then data = 0; else state <= INITIALIZE; end if; end if; end process P_STATE_MACHINE;
The three examples above are three places that new software developers often have a hard time with when starting a new design in VHDL or Verilog. The three assumptions above should always be in the mind of a new digital designer. Questions about concurrency, for loops, and execution of code should always be considered. Once the examples above are thoroughly understood, the rest of the articles and examples on this web page can help turn you into a successful digital designer!
Shouldn’t line 14 in the last example read “data <= 0;" instead of "data = 0;" ?
yeah is just a mistake
> The hardware representation of this code is very broken! Since every line in a process executes concurrently, data will be always stuck at 0 and state will always be stuck at DONE.
What guarantees that it’ll be stuck at 0 and DONE? If everything runs concurrently, won’t it be a constant fight, with every section trying to set their desired values? Maybe I just don’t quite understand yet, so it’s on to the next lesson! 🙂