Sometimes, there is more than one way to do something in VHDL. OK, most of the time, you can do things in many ways in VHDL. Let's look at the situation where you want to assign different values to a signal, based on the value of another signal.
With / Select
The most specific way to do this is with as selected signal assignment. Based on several possible values of , you assign a value to . No redundancy in the code here. The official name for this VHDL with/select assignment is the selected signal assignment.
When / Else Assignment
The construct of a conditional signal assignment is a little more general. For each option, you have to give a condition. This means that you could write any boolean expression as a condition, which give you more freedom than equality checking. While this construct would give you more freedom, there is a bit more redundancy too. We had to write the equality check () on every line. If you use a signal with a long name, this will make your code bulkier. Also, the separator that's used in the selected signal assignment was a comma. In the conditional signal assignment, you need the keyword. More code for the same functionality. Official name for this VHDL when/else assignment is the conditional signal assignment
Combinational Process with Case Statement
The most generally usable construct is a process. Inside this process, you can write a case statement, or a cascade of if statements. There is even more redundancy here. You the skeleton code for a process (begin, end) and the sensitivity list. That's not a big effort, but while I was drafting this, I had put in the sensitivity list instead of . Easy to make a small misstake. You also need to specify what happens in the cases. Of course, you could do the same thing with a bunch of IF-statements, either consecutive or nested, but a case statement looks so much nicer.
While this last code snippet is the largest and perhaps most error-prone, it is probably also the most common. It uses two familiar and often-used constructs: the process and the case statements.
Hard to remember
The problem with the selected and conditional signal assignments is that there is no logic in their syntax. The meaning is almost identical, but the syntax is just different enough to throw you off. I know many engineers who permanenty have a copy of the Doulos Golden Reference Guide to VHDL lying on their desks. Which is good for Doulos, because their name gets mentioned all the time. But most people just memorize one way of getting the job done and stick with it.
Assignment Symbol in VHDL
VHDL assignments are used to assign values from one object to another. In VHDL there are two assignment symbols:<= Assignment of Signals := Assignment of Variables and Signal Initialization
Either of these assignment statements can be said out loud as the word "gets". So for example in the assignment: test <= input_1; You could say out loud, "The signal test gets (assigned the value from) input_1."
Note that there is an additional symbol used for component instantiations (=>) this is separate from an assignment.
Also note that <= is also a relational operator (less than or equal to). This is syntax dependent. If <= is used in any conditional statement (if, when, until) then it is a relational operator, otherwise it's an assignment.
One other note about signal initialization: Signal initialization is allowed in most FPGA fabrics using the := VHDL assignment operator. It is good practice to assign all signals in an FPGA to a known-value when the FPGA is initialized. You should avoid using a reset signal to initialize your FPGA, instead use the := signal assignment.library ieee; use ieee.std_logic_1164.all; entity ex_assignment is end ex_assignment; architecture behave of ex_assignment is signal r_TEST_SIGNAL : integer range 0 to 10 := 0; -- initializing a signal signal r_RESULT : integer range 0 to 10 := 0; -- initializing a signal begin -- Demonstrates both assignment operators -- This process is synthesizable p_ASSIGN_RESULT : process (r_TEST_SIGNAL) variable v_TEST_VARIABLE : integer := 0; begin v_TEST_VARIABLE := r_TEST_SIGNAL + 1; if r_TEST_SIGNAL < 5 then r_RESULT <= r_TEST_SIGNAL; else r_RESULT <= v_TEST_VARIABLE; end if; end process; -- This process is NOT synthesizable. Test code only! -- Provides inputs to code and prints debug statements to console. p_TEST_BENCH : process is begin r_TEST_SIGNAL <= 3; wait for 100 ns; report "Value of Result = " & integer'image(r_RESULT) severity note; r_TEST_SIGNAL <= 7; wait for 100 ns; report "Value of Result = " & integer'image(r_RESULT) severity note; wait; end process; end behave; ------------------------------------------------------------------------------- -- Console output of Example: -- # ** Note: Value of Result = 3 -- # Time: 100 ns Iteration: 0 Instance: /example_assignment -- # ** Note: Value of Result = 8 -- # Time: 200 ns Iteration: 0 Instance: /example_assignment -------------------------------------------------------------------------------