More VHDL Constructs


Purpose of this Lecture

  • Concurrrent Statements
  • Sequential Statements
  • More Examples

  • Statements

    Concurrent Statements

    Execute at the same time in parallel. The behavior of concurrent statemetns is independent of the order in which they are written. Here is an example: We can write the code in either ways the resutl of x and z are the same!
    
    	SIGNAL a, b, c, x, z : INTEGER;
    
    	x <= a + b;
    	z <= c + x;
    
    
    	z <= c + x;
    	x <= a + b;
    
    
    (This is where the delta time comes from.) The easiest way to visualize it is to think of the hardware these two statments imply. Try to think of a schematic that implements these two statements:
                         +-------+
    	      a -----|   |   |   x           +-------+
    		     |  -+-  |---------------|   |   |
    	      b -----|   |   |               |  -+-  |------ z
                         +-------+          +----|   |   |
    			  		|    +-------+
    	      c ------------------------+
    
    It really does not matter which box (adders) you draw first, we will get the same hardware! There are some things that you have done when writing traditional software, that may not make much sense in describing hardware. Consider the statement x <= x + y. In software, x and y are register locations. The statement just mentioned means we take the content of x add it to y and store the final result back in register x. So assigning to itself is OK in software. But this is not what you think you are specifying in concurrent hardware statements. As a concurrent state, the same line of code is describing an adder with no implied storage registers. Hence we are describing a hardware with feedback around combinational logic! This logic is thus asynchronous and may exibit different behavior depending on the delay of the hardware implementation.
                         +-------+
    	      y -----|   |   |   x   
    		     |  -+-  |----------+
    	      x --+--|   |   |          |
                      |  +-------+          |
    		  |	  		|
    	          +---------------------+
    
    So it is important to remember that we are describing hardware using VHDL.

    Sequential Statements

    Execute one at a time in sequence and is different from concurent statements. There are several VHDL language constructs that can only be used within the sequential part of the VHDL. They are the IF THEN, CASE, and FOR IN LOOP statements. These sequential statements can only be within the PROCESS block. We will see how these sequential statements interact later.

    PROCESS syntax

    As we have mentioned, all sequential statements are within the PROCESS block. Or in other word, all statements within PROCESS are sequential. The PROCESS block starts with the keyword PROCESS. It has an optional label and a sensitivity list. Following the PROCESS is the statement BEGIN. Every statement between BEGIN and the "END PROCESS label;" are sequential statements. An example is shown here:

        mux: PROCESS (a, b, sel)
        BEGIN
    	
    	 IF sel = '1' THEN z <= a;
    	 ELSE z <= b;
    	 END IF;
    
        END PROCESS mux;
    
    
    A process, unlike concurrent statements, does not excute continuously. It is invoked when one of the signals in its sensitivity list changes its value. In other word, when there is an event on any of the signals on the sensitivity list. While each proccess block executes the statements within the block sequentially, multiple processes interact with each other just like concurrent statements - concurrently. Each process executes when there is an event on one of the signals on its sensitivity list causing events to occurs on signals that it assigns to. From the VHDL language construct/syntax point of view, a process must be written within an architecture. However, VHDL allows multiple numbers of processes to be described within the same architecture. For example:
    
        ARCHITECTURE abc OF def IS
    	BEGIN
    
    	-- ------ concurrent processes
    	    p1: PROCESS
    	        BEGIN
    	          -- -- sequential statements
    	        END PROCESS p1;
    	    p2: PROCESS
    	        BEGIN
    	          -- -- sequential statements
    	        END PROCESS p2;
        END abc;
    
    

    OK, let us look at an example to clearify the concepts we have covered so far. Consider the following two statements:

    
        z <= a AND b;
        z <= c AND d;
    
    
    Assume z is of a resolving type, if these two statements are not within the PROCESS block, then these two are concurrent assignments. The hardware the describe has two AND gates driving the same output - z. If z is not a resolving data type, there will be an error flagged. However if these two statements are inside the PROCESS blk, these two statements have different behavior. Becasue a PROCESS (as a whole) is considered as a concurrent statement, A process only place one driver on a signal and the final value of the signal is determined by the last assignment within the process. In this case signal z will be assigned with c AND d. To ensure that the signal update is a clean transition, signals assigned to within a process are not actually updated with their new value until the process suspends. Therefore in this example, z will never get assigned with the value of a AND b at any time. let us look at a few more examples:
    No-problem Example:
    
    ...
    BEGIN
    	PROCESS
    	BEGIN
    	...
    	x <= a;		-- this assignment is executed before the next one.
    	y <= b;
    	...
    	END PROCESS;
    ...
    
    
    Scheduling Example:
    
    ...
    BEGIN
    	PROCESS
    	BEGIN
    	...
    	x <= a AFTER 10 NS; -- the value of a is scheduled for x after 10ns
    	y <= b AFTER 6 NS;   -- the value of b is scheduled for y after 6 ns
    	...
    	END PROCESS;
    ...
    
    -- first assignment b to y is executed
    -- then in 4 ns, assignment a to x is executed
    -- signal y receives the value of b 4 ns sooner than x, even though the 
    scheduling of the former was done after that of the latter.
     
    
    
    "Trouble" Example:
    
    x=`0`
    
    ...
    BEGIN
    	PROCESS
    	BEGIN
    	...
    	x <= `1`; 		-- `1` is scheduled for x after delta delay;
    	IF x=`1` THEN	-- this statement is executed immediately after
    					the execution of x<=`1` assignment;
    		action_1;
    	ELSE
    		action_2;
    	END IF
    	...
    	END PROCESS;
    ...
    
    
    -- Since these two statements (x<=... and IF) are executed during the 
    same simulation cycle (in zero time), the new `1` value of x is not 
    available for the IF. 
    
    -- Had x been a variable (x:=`1`), its new value, `1`, would be available 
    (action_1 would have been performed).
    
    

    More on timing delays

    Sequential statements assigning value to the same signal follow the rules listed here:

  • If the new transaction is BEFORE an already existing transaction, then the new transaction overwrites the existing transaction
  • If the new transaction is AFTER an already existing transaction, then the new transaction is appended to the existing transaction if the new transacton is of TRANSPORT type.
  • If the new transaction is AFTER an already existing transaction and is of the INERTIAL delay then: Here is an example:
    
    -- try to understand sequential assignment
    --
    ENTITY saving_all IS END saving_all;
    ARCHITECTURE sequential OF saving_all IS
      TYPE trit IS ('0', '1', 'Z');
      SIGNAL xt : trit := 'Z';
      SIGNAL yt : trit := 'Z';
      SIGNAL zt : trit := 'Z';
      SIGNAL wt : trit := 'Z';
      SIGNAL xi : trit := 'Z';
      SIGNAL yi : trit := 'Z';
      SIGNAL zi : trit := 'Z';
      SIGNAL wi : trit := 'Z';
      SIGNAL xr : trit := 'Z';
      SIGNAL yr : trit := 'Z';
      SIGNAL zr : trit := 'Z';
      SIGNAL wr : trit := 'Z';
    BEGIN
      p1:PROCESS
      BEGIN
        xt <= TRANSPORT '1' AFTER 5 NS;
        xt <= TRANSPORT '0' AFTER 8 NS;
        WAIT;
      END PROCESS p1;
    
      p2:PROCESS
      BEGIN
        yt <= TRANSPORT '1' AFTER 5 NS;
        yt <= TRANSPORT '0' AFTER 3 NS;
        WAIT;
      END PROCESS p2;
        
      p3:PROCESS
      BEGIN
        zt <=           '1' AFTER 5 NS;
        zt <= TRANSPORT '0' AFTER 8 NS;
        WAIT;
      END PROCESS p3;
    
      p4:PROCESS
      BEGIN
        wt <=           '1' AFTER 5 NS;
        wt <= TRANSPORT '0' AFTER 3 NS;
        WAIT;
      END PROCESS p4;
        
      p5:PROCESS
      BEGIN
        xi <=           '1' AFTER 5 NS;
        xi <=           '0' AFTER 8 NS;
        WAIT;
      END PROCESS p5;
    
      p6:PROCESS
      BEGIN
        yi <=           '1' AFTER 5 NS;
        yi <=           '0' AFTER 3 NS;
        WAIT;
      END PROCESS p6;
        
      p7:PROCESS
      BEGIN
        zi <= TRANSPORT '1' AFTER 5 NS;
        zi <=           '0' AFTER 8 NS;
        WAIT;
      END PROCESS p7;
    
      p8:PROCESS
      BEGIN
        wi <= TRANSPORT '1' AFTER 5 NS;
        wi <=           '0' AFTER 3 NS;
        WAIT;
      END PROCESS p8;
        
      p9:PROCESS
      BEGIN
        xr <=           '1' AFTER 5 NS;
        xr <=           '0' AFTER 10 NS;
        WAIT;
      END PROCESS p9;
    
      pa:PROCESS
      BEGIN
        yr <=           '1' AFTER 5 NS;
        yr <=           '0' AFTER 11 NS;
        WAIT;
      END PROCESS pa;
        
      pb:PROCESS
      BEGIN
        zr <=           '1' AFTER 5 NS;
        zr <= REJECT 2 NS INERTIAL '0' AFTER 8 NS;
        WAIT;
      END PROCESS pb;
    
      pc:PROCESS
      BEGIN
        wr <=           '1' AFTER 5 NS;
        wr <= REJECT 5 NS INERTIAL '0' AFTER 8 NS;
        WAIT;
      END PROCESS pc;
        
    END sequential;
    --
    --  TIME  |----SIGNAL NAMES------------------------------------|
    --        |                      
    --  (NS)  |    Xt  Yt  Zt  Wt  Xi  Yi  Zi  Wi  Xr  Yr  Zr  Wr
    --        |                 
    --    0   |   'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z'
    --    1   |   'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z'
    --    2   |   'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z' 'Z'
    --    3   |   'Z' '0' 'Z' '0' 'Z' '0' 'Z' '0' 'Z' 'Z' 'Z' 'Z'
    --    4   |   'Z' '0' 'Z' '0' 'Z' '0' 'Z' '0' 'Z' 'Z' 'Z' 'Z'
    --    5   |   '1' '0' '1' '0' 'Z' '0' 'Z' '0' 'Z' 'Z' '1' 'Z'
    --    6   |   '1' '0' '1' '0' 'Z' '0' 'Z' '0' 'Z' 'Z' '1' 'Z'
    --    7   |   '1' '0' '1' '0' 'Z' '0' 'Z' '0' 'Z' 'Z' '1' 'Z'
    --    8   |   '0' '0' '0' '0' '0' '0' '0' '0' 'Z' 'Z' '0' '0'
    --    9   |   '0' '0' '0' '0' '0' '0' '0' '0' 'Z' 'Z' '0' '0'
    --    10  |   '0' '0' '0' '0' '0' '0' '0' '0' '0' 'Z' '0' '0'
    --    11  |   '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0' '0'
    
    

    Sensitivity Lists

    Recall the first example we have given :

    --    mux: PROCESS (a, b)
        mux: PROCESS (a, b, sel)
    	BEGIN
    	     IF sel = '1' THEN z <= a;
    	     ELSE z <= b;
    	END IF;
        END PROCESS mux;
    
    This code describe the simple 2:1 MUX. If there is an event on a, b, or sel then the PROCESS is active (called). Depending on the value of sel z is assigned with the value of either a or b. If sel is missing from the sensitivity list, the behavior is changed. Since a PROCESS is active only when there is an event on the signals of the sensitivity lists, in this case only when a, or b has an event the value of z is assigned with a value. Therefore given a, b, and sel as follows, the z will change value only when a, b changes their value.
    
        sel   0001111100000000000001111100
        a     0111111111110000011111100000
        b     1000000000011111000001111111
    
        z     1000000000011111000001100000
    
    
    Convience yourself that the z value is as depicted. In this case z sometimes has the right result and sometimes has the wrong result. This type of error is very difficult to debug. Therefore as a good coding style, one should always include all signals read in the PROCESS on the sensitivity lists. This rule is also adapted by almost all of today's synthesis tool.
    Here are couple more excercises:
    EX. 1:
    
    In which part of a VHDL code do you have concurrent signal assignemnts?
    
    
    
    EX. 2:
    
    When is a signal updated with its new value as the result of having an
    assignmenet to it within a process?
    
    
    

    Sequential Statements

    As we have mentioned before there are three statements which can be used only in the sequential body of the VHDL code. They are IF THEN, CASE and FOR LOOP.

  • IF-THEN-ELSE
  • Here is a simple example of the syntax. Beware that the END IF must be seperated by a space.
        IF condition THEN
          -- sequential statements
        ELSE
          -- sequential statements
        END IF;
    
    You may have nested IF and ELSE as shown here:
        IF condition THEN
          -- sequential statements
        ELSIF condition THEN
          -- sequential statements
        ELSIF condition THEN
          -- sequential statements
        ELSE
          -- sequential statements
        END IF;
    
    In this structure only one of the branch is executed depending on the condition. Even there are several condition which are true in this structure only the first TRUE condition will be followed. After the execution of the sequential statements within the first true condition the statements after the END IF will be executed next. Therefore it is very import to write the order of IF and ELSIF according to your desired behavior. Here is an example:
    
        PROCESS (a, b, c, x)
        BEGIN
    	IF (x = "0000") THEN z <= a;
    	ELSEIF (x <= "101") THEN z <= b;
    	ELSE z <= c;
    	END IF;
        END PROCESS;
    
    
    In this example when x is "0000" z is assigned with value of a even though both conditions are satisfied. Here the second condition's syntax is correct. Recall the comparison of arrays, if two different length arrays are compared, they are aligned from the left. In IF and ELSEIF structure, there is a build in priority.
  • CASE
  • Here is an exmaple of the syntax:

        CASE object IS
    	WHEN value1 => 
    	    -- statemetns
    	WHEN value2 => 
    	    -- statemetns
    	WHEN value3 => 
    	    -- statemetns
    	WHEN value4 => 
    	    -- statemetns
    
            -- etc.
        END CASE;
    
    The case considers all of the possible values that an object can take and execute a different branch depending on the current value of the object. IThis is different from the IF THEN ELSEIF structure. You may also include range and operators such as To and |:
        PROCESS (a, b, c, x)
        BEGIN
    	CASE x IS
    	    WHEN 0 TO 4 => z <= b;
    	    WHEN 5 => z <= a;
    	    WHEN 6 | 9 | 12 =>  z <= c;
    	    WHEN OTHERS =>  z <= 0;
            END CASE;
        END PROCESS;
    
    
    There is also the OTHERS which covers alll left over values not included in the CASE which have not been specified.

    As we have mentioned that CASE is quite different from IF and ELSEIF structure. Only one condition can be true in the CASE structure. That is one may not specify two conditions that are both true. For example:

        PROCESS (a, b, c, x)
    	BEGIN
    		CASE x IS
    		    WHEN 0 TO 4 => z <= b;
    		    WHEN 3 => z <= a;
    		    WHEN 6 | 9 | 12 =>  z <= c;
    		    WHEN OTHERS => z <= 0;
    	        END CASE;
        END PROCESS;
    
    The second condition has been already specifiedaand cannot be included again. Another rule of the CASE structure is that one must specify all possible values of the object. In this case omitting OTHERS is not allowed.

    There are couple more things about CASE. First the object can be an expression instead of simple object such as a variable or signal. Second, all possible values in the CASE structure must be constants and they must be of the same type of the object.

  • FOR LOOP
  • Just like any loops in an procedural language, FOR LOOP structure allows the execution of a block of codes iteratively. The LOOP structure should have an index. The syntax is:

        FOR i IN 0 To 7 LOOP
    	-- statements
        END LOOP;
    
    In this example the LOOP will execute the statements 8 times. In VHDL, there is no need to declare the loop variable "i". It is implicitly declared! Most of the synthsis tools support the FOR LOOP construct when the range it iterate is fixed. Usually the LOOP body is unroled (unfolded) and logic described by the statements of the LOOP body is duplicated once for each iteration it specified. Therefore in the previous example the logic is duplicated 8 times. Of course once the logic is duplicated, optimization on these newly generated logic is performed. Here is an example which uses the LOOP statement. It loops for 16 times and assignment a value when it suspends. Remember all we have talked about so far on PROCESS and LOOP. Please read the code and think about the behavior it describes.
    ENTITY ex_loop IS
    PORT (a:   IN STD_LOGIC_VECTOR(0 TO 15);
          sel: INTEGER RANGE 0 TO 15;
          z:   OUT STD_LOGIC);
    END ex_loop;
    
    ARCHITECTURE rtl OF ex_loop IS
    BEGIN
        ex3 : PROCESS (a, sel)
        BEGIN
    	FOR i IN 0 TO 15 LOOP
    	    IF sel = i then
    	       z <= a(i);
    	    END IF;
    	END LOOP;
        END PROCESS ex3;
    END rtl;
    
    
    Now here is the exercise:

    EX.3 : What is the function of the peice of VHDL described above??

    Finally, can you write another piece of VHDL code which descibes the same hardware? (Hint: use CASE)

    How Multiple Processes Interact with Each other

    As we have already mentioned that statements within the PROCESS is executed sequentially. The value of a signal is updated only at the time when the PROCESS suspends. We have also mentioned that an Architecture body may have multiple processes. We say that each process can be treated as a single concurrent statement. Therefore when there are multiple processes, there are multple concurrent statements in the architecture. Let us look at an example again:

    
    example: PROCESS (a, b, m)
    BEGIN
        y <= a;
        m <= b;
        z <= m;
    
    

    In this example the signal m is first written then read. Let us assume that there is an event on the signal b. When it happneds the PROCESS becomes active and it is called because b is on the sensitivity list. Since the value of m is not updated until the process is suspended. Therefore if we start with values of (a, b, m) = (0, 0, 0) and b changes to 1 and creating an event. The final value of z after the PROCESS suspends is still 0 NOT 1 !! Of course the value of m at the end of the PROCESS is 1 since it is assigned with b. Convince yourself this is true. However, after the PROCESS suspends, there is an event on the signal m now. Therefore the PROCESS is called again and this time z is updated with the value of 1. Here is an example of the delta delay which we have mentioned before. Even though there is no delays associated with each signal the simulator must cycle twice to determine the final values of signals. We will return to this subject again later. For the time being we will discuss briefly the simulation cycle. At a given point of simulation time, there are two queues: one of signals to be updated and one of processes to be executed. When a signal is updated at a specific point in simulation time, all processes that are sensitive to that signal are placed on a "Process Execution" queue. Each process executes in turn, and signals that are assigned to in each process are not updated immediately the process suspends, but are placed on the "signal Update" queue. When all of the processes have executed, then the signals are updated. As a result of the signals being update, further processes may be placed on the process execution queue. One loop around this sequence is known as a "delta cycle".

    Now we have look at this delta time concept, let us revisit the simulation process here again. A given point of simulation time, there are two "queues" maintained by the simulator. One of the queue is used to keep track of alll signals to be updated and the other one contains the processes to be executed. When a signal is updated at a specific point in simulation time, all processes that are sensitive to the signal are placed on a "Process Execution" queue. Each process in the queue executes in turn. Signals assigned to in each process are not updated immediately the process usupends but are placed on the "Signal Update" queue. When all the processes have executed then the signals are updated. As a result of signals being updated, further processes may be placed on the process executon queue. One loop around this sequence is known as a "delta cycle". Let me stress again the importance of knowing that the multiple delta cycles we have discussed are heppening at the "same" simulation time. Therefore the full model of VHDL simulation consists of multiple delta cycles at each point of simualtion time. We execute at a single point of simulaiton time until there are no further signal assignements or process executions queud. After there is no more signal assignments, then the simualtion time advances to the next time (resolution) where there are either processes to be executed or signals to be updated. There are only two statements in VHDL that can cause time to advance. One is the signal assignement using the AFTER clause, where the signal assignment is put on a signal update queue at some time in the future instead of at the currrent time. We have seen many example so far on AFTER. The second way for time to advance is when a process is suspended until some time in the future. This can be done with a "WAIT FOR" statement. We will look at the WAIT statement in more detail later.

    More on PROCESS

    THE VHDL defines two styles of describing a PROCESS. One is done with sensitivity list and the other is done without a list but with WAIT statement. The one without the senstivity list suspends when it executes a WAIT statement while the one with the list suspends at the end of the PROCESS automatically. Examples:

    
        PROCESS (a, b)
        BEGIN
    	IF (a='1' OR b='1') THEN z <= '1';
    	ELSE z <= '0';
    	END IF;
        END PROCESS; -- suspends here
    
        PROCESS
        BEGIN
    	IF (a='1' OR b='1') THEN z <= '1';
    	ELSE z <= '0';
    	END IF;
    	WAIT ON a, b; -- suspends here
        END PROCESS;
       
    

    A PROCESS without a sensitivity list is defined to be an infinite loop. When the execution reaches the bottom (end of the process), it automatically starts to execute again from the begining. It suspends on on WAIT statements. The VHDL language defines that a process with a sensitivity list cannot contain WAIT statements. Therefore it is a shorthand way of writing a PROCESS with a signal WAIT statement at the bottom which waits for an event on one or more of the signals in the sensitivity list of its equivalent. The processes we have shown in the previous example are equivalent. However, for describing combinational logic you are recommended to use the form the contains the sensitivity list as it is accepted by all synthesis tools.

    WAIT statements

    There are four forms of WAIT statements.

  • WAIT FOR ;

    This causes the process to re-execute after a specific mount of time has passed. As we have used earlier, this can be useful in writing test benches to create stimulus where signals are required to change value over time.

    Example:
    
        stimulus: PROCESS
        BEGIN
    	sel <= '0';
    	bus_a <= "1111";
    	bus_b <= "0000";
    	WAIT FOR 10 ns;
    	sel <= '1';
    	WAIT FOR 10 ns;
    	-- .....
        END PROCESS stimulus;
    
    
  • WAIT ON ;

    The WAIT ON statement waits for an event on one or more of the signals in a list specified before re-executing.

    
        PROCESS
        BEGIN
    	IF (a='1' OR b='1') THEN z <= '1';
    	ELSE z <= '0';
    	END IF;
    	WAIT ON a, b;
        END PROCESS;
    
    
  • WAIT UNITL ;

    The WAIT UNTIL statement has a condition which returns either TRUE or FALSE. The statement waits for an event on one of the signals in the condition, and if as a result of the event the condition has become ture, then the process re-executes.

    
        PROCESS
        BEGIN
    	WAIT UNTIL clk='1';
    	q <= d;
        END PROCESS;
    
    
  • WAIT;

    Lastly, it is possible to just use WAIT to suspend a process forever. You may ask, what is the usage of this structure? Well, it can be used in a test bench to make sure your infinite loop feature of the processes from causing your stimulus to repeat once complete.

    
        stimulus: PROCESS
        BEGIN
    	 sel <= '0';
    	 bus_a <= "1111";
    	 bus_b <= "0000";
    	 WAIT FOR 10 ns;
    	 sel <= '1';
    	 WAIT;
        END PROCESS stimulus;
    
    

    Now let us look at an excercise.
    
    Ex.5. From where in a process does execution commence when a WAIT statement causes the PROCESS to be
    re-invoked?
    
    

    Variables

    We have mentoned several objects in VHDL. One of them is variables. Let us look at variables more closely. We look at variable now because variables are used in sequential part of the VHDL code. That is, a variable in VDL can only be declared and used within a PROCESS. Avariable is different from a signal in that it is assigned its value immediately. just as any procedure languages. This is very important to note. To distinguish the differnce between signals and variables, we use a different assignment symbol ":=" for variables instead of the "<=" used for signals. A variable can only be used in the PROCESS that it is declared. This is known as the "scope" of the variable in programming languages. A variable retains its value between calls to a PROCESS. That is when a PROCESS suspends it retain its variables' values. When the PROCESS is re-invoked it remembers the values created from the previous PROCESS call. So it is possible to imply the behavior of a memory element if required. To prevent any problems with describing combinational logic, always assign a value to your variable before you read its value as the following example:

    
        PROCESS (a, b, c)
    	VARIABLE m, n : INTEGER;
        BEGIN
    	m := a; 
    	n := b;
    	z <= m + n; -- z is assigned with a+b, if the first statement is not there then z = b+c
    	m := c;     -- this value of m is retained between calls to this process.
    	y <= m + n;
        END PROCESS;
    
    
    You will noticed in this example that we have freely assigned signals to variables and variables to signals. It is possible to do this if signals and variables are of a particular type. That is the rules about matching data types still needs to be observed.

    Now let us look at how a variabel is used in describing a design in VHDL. Because a variable is updated immediately, variable is commonly used to calculate an "intermediate" value within a process, which is then used later on in the process execution. Since all variables scope is only within the current PROCESS where the variable is declared, it is always necessary to assign the final values of variables to signals if they are used outside of the process. Therefore, we usually use variables when we want to perform complex calculations or we need to implement complex algorithms where it is easier to do them in steps. In these cases, values enter the PROCESS using signals, they are assigned to variables and usd for calculation and algorithm implementation. The final result is assigned back to signals to communicate to the outside. Here is an example where we calcuated the parity of the input data and output the reuslt.

    
           ....
           -- a is of type std_logic_vector(15 DOWNTO 0)
           -- z is the output of type std_logic;
           ....
    
            PROCESS (a)
    	VARIABLE tmp : std_logic;
    	    BEGIN
    	        tmp := '0'; 
    	        -- FOR i IN a'low TO a'high LOOP
    		FOR i IN 0 TO 15 LOOP
    		    tmp := tmp XOR a(i);
    		END LOOP;
    		odd <= tmp;
    	END PROCESS;
    
    
    Note that this design describes a combinational logic implementation of the parity generator. Remember what we said about FOR loop before that this design is unfolded and optimized by the tool when synthesiszed. Now draw the hardware in your mind described by the VHDL code above. In this example we used the ATTRIBUTE of an array. We will come back to that in more detail later.

    Now let us review the difference between signals and variables again with an exercise.

    Ex 6:
    
    Recall the example we had:
    
        PROCESS (a, b, c)
    	VARIABLE m, n : INTEGER;
        BEGIN
    	m := a; 
    	n := b;
    	z <= m + n; -- z is assigned with a+b, if the first statement is not there then z = b+c
    	m := c;     -- this value of m is retained between calls to this process.
    	y <= m + n;
        END PROCESS;
    
    Now if signals are used instead of variables for m and n we have:
    
        ENTITY ...
        PORT (a, b, c : IN INTEGER);
        ...
    
        ARCHITECTURE
           SIGNALS m, n : INTEGER;
        PROCESS (a, b, c, m, n)
        BEGIN
    	m <= a; 
    	n <= b;
    	z <= m + n; -- z is assigned with a+b, if the first statement is not there then z = b+c
    	m <= c;     -- this value of m is retained between calls to this process.
    	y <= m + n;
        END PROCESS;
    
    
    QUESTION: What are the final values of y and z in terms of a, b, c?
    
    


    Answers to excercises:

    Ex.1 : in the architecture body

    Ex.2 : When a process suspends

    Ex.3 : a 16 to 1 MUX

    Ex.4 :

    ENTITY ex_case IS
    PORT (a:   IN STD_LOGIC_VECTOR(0 TO 15);
          sel: INTEGER RANGE 0 TO 15;
          z:   OUT STD_LOGIC);
    END ex_loop;
    
    ARCHITECTURE rtl OF ex_loop IS
        BEGIN
    	ex3 : PROCESS (a, sel)
    	BEGIN
    	    CASE sel IS
    	        WHEN 0 => z <= a(0);
    	        WHEN 1 => z <= a(1);
    	        WHEN 2 => z <= a(2);
    	        WHEN 3 => z <= a(3);
    	        WHEN 4 => z <= a(4);
    	        WHEN 5 => z <= a(5);
    	        WHEN 6 => z <= a(6);
    	        WHEN 7 => z <= a(7);
    	        WHEN 8 => z <= a(8);
    	        WHEN 9 => z <= a(9);
    	        WHEN 10 => z <= a(10);
    	        WHEN 11 => z <= a(11);
    	        WHEN 12 => z <= a(12);
    	        WHEN 13 => z <= a(13);
    	        WHEN 14 => z <= a(14);
    	        WHEN 15 => z <= a(15);
    	    END CASE;
            END PROCESS ex3;
    END rtl;
    
    
    
    Ex.5:
    
    The line immediately below the WAIT statement.
    
    
    
    Ex 6:
    
    
    BOT y and z are c+b.