Chapter 4 - Behavioral Descriptions

Section 3 - Sequential Statements

There are several statements that may only be used in the body of a process. These statements are called sequential statements because they are executed sequentially. That is, one after the other as they appear in the design from the top of the process body to the bottom. In this section we will examine some of these statements.

The first example illustrates the if statement and a common use of the VHDL attribute.

count: process (x)
  variable cnt : integer :=0 ;
begin
  if (x='1' and x'last_value='0') then
    cnt:=cnt+1;
  end if;
end process;
This if statement has two main parts, the condition and the statement body. A condition is any boolean expression (an expression that evaluates to TRUE and FALSE, such as expressions using relational operators). The condition in the example uses the attribute last_value, which is used to determine the last value that a signal had. Attributes can be used to obtain a lot of auxiliary information about signals. The value of an attribute for a particular signal is obtained by specifying the name of the signal, followed by a ' (called a tick) and the name of the attribute desired. Thus the condition in the example is true only if the current value of x is '1' and its previous value was '0'. Since this statement will only be executed when an event has occurred on x (i.e. x has just changed), this condition will be true when a rising edge occurs on x. This is because we know x just changed, we know it was a '0' and now it is a '1'. The statement body of the if statement is just a list of sequential statements that appear between the key words then and end if.

The execution of the if statement begins by evaluating the condition. If the condition evaluates to the value TRUE then the statements in the statement body will be executed. Otherwise, execution will continue after the end if and the statement body of the if statement is skipped. Thus, the assignment statement in this example is executed every time there is a rising edge on the signal x, counting the number of rising edges.

An example of another common form of the if statement is

...
if (inc='1') then
  cnt:=cnt+1;
else
  cnt:=cnt-1;
end if;
...
This form has two statement bodies. If the condition is TRUE, the first list of statements is executed (between the then and the else) and the second list of statements (between the else and the end if) is not. Otherwise, the second statement list is executed and the first is not. Thus, this example will increment cnt if inc is '1' and decrement it otherwise.

Another sequential statement is the case statement. The case statement allows one of several statement bodies to be selected for execution based on the value of an expression. The following is an example of a case statement.

...
cpu: process
constant NOP : integer := 0;
constant LDA : integer := 1;
constant ADDA : integer := 2;
...
variable op_code : integer;
variable A,op : bit_vector(7 downto 0);
...
begin
  case op_code is
    when NOP =>
      null;
    when LDA =>
      A:=op;
    when ADDA =>
      A:=A+op;
  end case;
end process;
...
This is a very small example of what a typical behavioral model of a CPU looks like. In addition to the case statement, this example contains two other new statements. The constant declaration is similar to a variable declaration except that a constant can not be modified. The other new statement is the null statement. This statement does nothing and is used where nothing should be done.

The case statement consists of two main parts, the expression (that appears between the key words case and is) and a set of alternatives (between the key words is and end case). Each alternative starts with the key word when, followed by a set of choices (these are the same as those described for the selected signal assignment statement in the section Signal Assignments), followed by a list of sequential statements. The execution of the case statement begins by determining the value of the expression at the top of the case statement. This expression is then compared to the choices of each alternative as they appear in the process from top to bottom. The list of statements of the first alternative that matches the case expression are the statements that will be executed. Only one of the alternatives will be executed (the first one that matches), and at least one of the alternatives must match the case expression. The special choice others may be used as in the selected signal assignment to match anything.

In the example, the constants are used to define the values of the op codes for the three instructions NOP, LDA, and ADDA. The op_code is assumed to be a variable containing the op code of the instruction being simulated, A is a variable representing a CPU register, and op is a variable containing the value of the instructions operand. The case statement is then used to execute one of the three sets of statements depending on the value of op_code. If the op_code is 0, the null statement will be executed. If the op_code is 1, the value of the instruction's operand is assigned to the register A. If op_code is 2, the value of the instruction's operand is added to the register A. If op_code is any other value, then the simulator will stop and report an error because at least one of the choices must match.

The last statement we will look at is the loop statement. We will explain just one form of the loop statement, often called a for statement. The for statement is used to execute a list of statements several times. The following example uses a loop statement to compute the even parity of a bit vector.

signal x : bit_vector (7 downto 0);
...
process (x)
  variable p : bit;
begin
  p:='0'
  for i in 7 downto 0 loop
    p:=p xor x(i);
  end loop;
end process;
The signal x is an 8 bit signal representing a byte. The variable p is used to compute the parity of this byte. The first part of the for loop i in 7 downto 0 is called the parameter specification. It specifies how many times the loop body will be executed and creates a temporary variable. It begins with the name of the temporary variable that will be created, in this case it is i. This is followed by the key word in and then a range of values as we have seen before. The body of the loop is executed once for every value in the range specified. The value of the temporary variable is assigned one of the values in the range each time the loop body is executed. In this example, the assignment will be executed first with i=7 then again with i=6, and again with i=5, and so on down to 0. This loop statement behaves the same as the following statements.
p:='0';
p:=p xor x(7);
p:=p xor x(6);
p:=p xor x(5);
p:=p xor x(4);
p:=p xor x(3);
p:=p xor x(2);
p:=p xor x(1);
p:=p xor x(0);
Notice how the temporary variable i was used in the statement body of the loop to operate on different elements of the vector x each time the body of the loop is executed. This is a very common use of the loop statement. Although this loop contains only one statement, there may be many statements in the loop body.

The previous section is Behavioral Descriptions - Using Variables.
The next section is Behavioral Descriptions - Signals and Processes.


Copyright 1995, Green Mountain Computing Systems.
Copying this document is strictly prohibited. Making any non-volatile or semi-permanent copies of this document is a violation of international copyright laws.