A set of VHDL statements that executes in sequence is called sequential statements in VHDL.
Sequential Statements in VHDL
The syntax of a sequential signal assignment is identical to that of the simple concurrent signal assignment except that the former is inside a process.
signal-name <= value-expression;
- Note that the concurrent conditional and selected signal assignment statements cannot be used inside the process.
- For a signal assignment with delay, the behavior of a sequential signal assignment statement is somewhat different from that of its concurrent counterpart.
- If a process has a sensitivity list, the execution of sequential statements is treated as a “single abstract evaluation,” and the actual value of an expression will not be assigned to a signal until the end of the process.
- Inside a process, a signal can be assigned multiple times. If all assignments are with & delays, only the last assignment takes effect. Because the signal is not updated until the end of the process, it never assumes any “intermediate” value.
process (a, b, c, d)
. . .
y <= a and c;
y <= a xor b;
y <= c or d;
— It is the same as
y <= c or d;
- It is a good idea to avoid assigning a signal multiple times, if there is no strong reason. The only exception is the assignment of a default value in the if and case statements.
- In above example, the result will be very different if the multiple assignments are the concurrent signal assignment statements.
The sequential statements in VHDL discussed in this article are:
An if statement selects a sequence of statements for execution based on the value of a condition. The condition can be any expression that evaluates to a boolean value.
if boolean-expr-1 then
elsif boolean-expr-2 then
elsif boolean-expr-3 then
end if ;
When an expression is evaluated as true, the statements in the corresponding branch will be executed and the remaining branches will be skipped. If none of the expressions is true and the else branch exists, the statements in the else branch will be executed.
The if statement description of an 4-to-1 multiplexer is shown in following example. Since the multiplexer is a combinational circuit, all input signals, including D and S are in the sensitivity list.
Note that the signals used in the Boolean expressions are also the input signals.
entity MUX41 is
port(D : in STD_LOGIC_VECTOR(3 downto 0);
S : in STD_LOGIC_VECTOR(1 downto 0);
Y : out STD_LOGIC);
architecture behavioral of multiplexer_4_1 is
if (S=”00″) then
Y <= D(3);
elsif (S=”01″) then
Y <= D(2);
elsif (S=”10″) then
Y <= D(1);
Y <= D(0);
case expression is
when choices => sequential-statements — branch #1
when choices => sequential-statements — branch #2
— Can have any number of branches.
[ when others => sequential-statements ] — last branch
The case statement selects one of the branches for execution based on the value of the expression.
The expression value must be of a discrete type or of a one-dimensional array type. Choices may be expressed as single values, as a range of values, by using | (vertical bar: represents an “or”), or by using the others clause.
All possible values of the expression must be covered in the case statement. “The others clause can be used as a choice to cover the “catch-all” values and, if present, must be the last branch in the case statement.
The case statement is also a sequential statement and it is, therefore, possible to have nested case statements. A model for a 4:1 multiplexer using a case statement is shown next.
entity MUX is
port (A, B, C, D: in BIT;
Sel: in BIT_VECTOR(0 to 1);
Z: out BIT);
architecture MUX_BEHAVIOR of MUX is
constant MUX_DELAY: TIME := 10 ns;
process (A, B, C, D, Sel)
variable TEMP: BIT;
case Sel is
when “00” => TEMP := A:
when “01” => TEMP := B;
when “10” => TEMP := C;
when “11” => TEMP := D;
Z <= TEMP after MUX_DELAY;
A loop statement is used to iterate through a set of sequential statements.
[ loop-label : ] iteration-scheme loop
end loop [ loop-label ] ;
There are three types of iteration schemes.
The first is the for iteration scheme that has the form
for identifier in range
FACTORIAL := 1;
for NUMBER in 2 to N loop
FACTORIAL := FACTORIAL * NUMBER;
- The body of the for loop is executed (N-1) times, with the loop identifier, NUMBER, being incremented by 1 at the end of each iteration. The object NUMBER is implicitly declared within the for loop to belong to the integer type whose values are in the range 2 to N.
- No explicit declaration for the loop identifier is, therefore, necessary. The loop identifier, also, cannot be assigned any value inside the for loop.
- If another variable with the same name exists outside the for loop, these two variables are treated separately and the variable used inside the for loop refers to the loop identifier.
The second form of the iteration scheme is the while scheme that has the form
Loop_wh: while a < 10 loop — This loop has a label, loop_wh.
var := var * 2;
- The statements within the body of the loop are executed sequentially and repeatedly as long as the loop condition, a < 10, is true. At this point, execution continues with the statement following the loop statement.
The third form of the iteration scheme is one where no iteration scheme is specified. In this form of loop statement, all statements in the loop body are repeatedly executed until some other action causes it to exit the loop.
These actions can be caused by an exit statement, a next statement, or a return statement.
L3: loop — This loop also has a label.
SUM := SUM* 10;
exit when SUM > 50;
end loop L3; — This loop label, if present, must be the same as the initial loop label.
In this example, the exit statement causes the execution to jump out of loop L3 when SUM becomes greater than 50. If the exit statement were not present, the loop would execute indefinitely.
The exit statement is a sequential statement that can be used only inside a loop. It causes execution to jump out of the innermost loop or the loop whose label is specified.
exit [ loop-label] [ when condition ];
If condition then exit[ loop-label];
If no loop label is specified, the innermost loop is exited. If the when clause is used, the specified loop is exited only if the given condition is true, otherwise, execution continues with the next statement.
An alternate form for loop L2 described in the previous section is
SUM := 1;
J := 0;
SUM := SUM* 10;
if (SUM > 50) then
exit L3; — “exit;” also would have been sufficient.
end loop L3;
- The ASSERT statement is a very useful statement for reporting textual strings to the designer. The ASSERT statement checks the value of a boolean expression for true or false.
- If the value is true, the statement does nothing. If the value is false, the ASSERT statement outputs a user specified text string to the standard output to the terminal.
- The designer can also specify a severity level with which to output the text string. The four levels are, in increasing level of severity, note, warning, error, and failure. The severity level gives the designer the ability to classify messages into proper categories.
- The ASSERT statement is currently ignored by synthesis tools. Because the ASSERT statement is used mainly for exception handling while writing a model, no hardware is built.
- The keyword ASSERT is followed by a boolean-valued expression called a condition. The condition determines whether the text expression specified by the REPORT clause is output or not.
If false, the text expression is output;
if true, the text expression is not output.
- There are two optional clauses in the ASSERT statement. The first is the REPORT clause. The REPORT clause gives the designer the ability to specify the value of a text expression to output.
- The second is the SEVERITY clause. The SEVERITY clause allows the designer to specify the severity level of the ASSERT statement.
- If the REPORT clause is not specified, the default value for the ASSERT statement is assertion violation. If the SEVERITY clause is not specified, the default value is error.
VARIABLE last_d_change : TIME := 0 ns;
VARIABLE last_d_value : std_logic := ‘X’;
VARIABLE last_clk_value : std_logic := ‘X’;
IF (last_d_value /= din) THEN — /= is
last_d_change := NOW; — not equal
last_d_value := din;
IF (last_clk_value /= clk) THEN
last_clk_value := clk;
IF (clk = ‘1’) THEN
ASSERT (NOW – last_d_change >= 20 ns)
REPORT “setup violation”
The example performs a data setup check between two signals that control a D flip-flop.
Most flip-flops require the din (data) input to be at a stable value a certain amount of time before a clock edge appears. This time is called the setup time and guarantees that the din value will be clocked into the flip-flop if the setup time is met.
The wait statement can also be used to suspend a process. It can be used to wait for a certain amount of time or to wait until a certain condition becomes true, or to wait until an event occurs on one or more signals.
There are three basic forms of the wait statement
wait on sensitivity clause;
wait until condition;
wait for time_out expression;
we can use statements like
wait on clock;
wait until clock=’1’;
wait for 20 ns;
Here is an example of a process statement that generates a clock with a different on-off period. Figure shows the generated waveform.
CLK <= ‘0’ ;
wait for 20 ns;
CLK <= ‘1’ ;
wait for 12 ns;
- This process does not have a sensitivity list since explicit wait statements are present inside the process. It is important to remember that a process never terminates. It is always either being executed or in a suspended state.
- All processes are executed once during the initialization phase of simulation until they get suspended. Therefore, a process with no sensitivity list and with no explicit wait statements will never suspend itself.
- A signal can represent not only a wire but also a place holder for a value, that is, it can be used to model a flip-flop. Here is such an example.
is a sequential statement that does not cause any action to take place and execution continues with the next statement.
One example of this statement’s use is in an if statement or in a case statement where for certain conditions, it may be useful or necessary to explicitly specify that no action needs to be performed.