![]() |
![]() |
This section describes concurrent versions of sequential statements in the following form.
A concurrent procedure call, which is used in an architecture construct or a block statement, is equivalent to a process with a single sequential procedure call in it (see the following example). The syntax is the same as that of a sequential procedure call.
procedure_name [ ( [ name => ] expression
{ , [ name => ] expression } ) ] ;
The equivalent process reads all the in and inout parameters of the procedure. The following example shows a procedure declaration and a concurrent procedure call and its equivalent process.
procedure ADD(signal A, B: in BIT;
signal SUM: out BIT);
...
ADD(A, B, SUM); -- Concurrent procedure call
...
process(A, B) -- The equivalent process
begin
ADD(A, B, SUM); -- Sequential procedure call
end process;
Foundation Express implements procedure and function calls with logic unless you use the map_to_entity compiler directive. (See the Procedures and Functions as Design Components section of the Sequential Statements chapter.)
A common use for concurrent procedure calls is to obtain many copies of a procedure. For example, assume that a class of BIT_VECTOR signals must have just 1 bit with value '1' and the rest of the bits with value `0' (as in the following example). Suppose you have several signals of varying widths that you want monitored at the same time (as the second example following). One approach is to write a procedure to detect the error in a BIT_VECTOR signal, and then make a concurrent call to that procedure for each signal.
The following example shows a procedure, CHECK, that determines whether a given bit vector has exactly one element with value '1.' If this is not the case, CHECK sets its out parameter ERROR to TRUE, as the example shows.
procedure CHECK(signal A: in BIT_VECTOR;
signal ERROR: out Boolean) is
variable FOUND_ONE: BOOLEAN:= FALSE;
-- Set TRUE when a '1' is seen
begin
for I in A'range loop -- Loop across all bits in the vector
if A(I) = '1' then -- Found a '1'
if FOUND_ONE then -- Have we already found one?
ERROR <= TRUE; -- Found two '1's
return; -- Terminate procedure
end if;
FOUND_ONE := TRUE;
end if;
end loop;
ERROR <= not FOUND_ONE; -- Error will be TRUE if no '1' seen
end;
The following example shows the CHECK procedure called concurrently for four differently sized bit vector signals. The resulting circuit design is shown in the figure following the example.
BLK: block
signal S1: BIT_VECTOR(0 to 0);
signal S2: BIT_VECTOR(0 to 1);
signal S3: BIT_VECTOR(0 to 2);
signal S4: BIT_VECTOR(0 to 3);
signal E1, E2, E3, E4: BOOLEAN;
begin
CHECK(S1, E1); -- Concurrent procedure call
CHECK(S2, E2);
CHECK(S3, E3);
CHECK(S4, E4);
end block BLK;
A concurrent signal assignment is equivalent to a process containing a sequential assignment. Thus, each concurrent signal assignment defines a new driver for the assigned signal. This section discusses the three forms of concurrent signal assignment.
The syntax of the simplest form of the concurrent signal assignment follows.
target <= expression;
target is a signal that receives the value of an expression.
The following example shows the value of expressions A and B concurrently assigned to signal Z.
BLK: block
signal A, B, Z: BIT;
begin
Z <= A and B;
end block BLK;
The other two forms of concurrent signal assignment are conditional signal assignment and selected signal assignment.
The syntax of the conditional signal assignment follows.
target <= { expression when condition else }
expression;
target is a signal that receives the value of an expression. The expression used is the first one whose Boolean condition is TRUE.
When Foundation Express executes a conditional signal assignment statement, it tests each condition in the order written.
The following example shows a conditional signal assignment. The target is the signal Z, which is assigned from one of the signals A, B, or C. The signal depends on the value of the expressions ASSIGN_A and ASSIGN_B. The resulting design is shown in the figure following the example.
Note: The A assignment takes precedence over B, and B takes precedence over C, because the first TRUE condition controls the assignment.
Z <= A when ASSIGN_A = '1' else
B when ASSIGN_B = '1' else
C;
The following example shows a process equivalent to the example of the conditional signal assignment.
process(A, ASSIGN_A, B, ASSIGN_B, C)
begin
if ASSIGN_A = '1' then
Z <= A;
elsif ASSIGN_B = '1' then
Z <= B;
else
Z <= C;
end if;
end process;
The syntax of the selected signal assignment follows.
with choice_expression select
target <= { expression when choices, }
expression when choices;
target is a signal that receives the value of an expression. The expression selected is the first one whose choices include the value of choice_expression.
Each choice can be either of the following.
The value of each choice the target signal receives has to match the value or values of choice_expression.
If the value of choice_expression is a static range, each value in the range must be covered by one choice in the expression.
The final choice can be others, which matches all remaining (unchosen) values in the range of the choice_expression type. The others choice, if present, matches choice_expression only if none of the other choices match. You can use others as the final choice only if the value of choice_expression is a range.
The with...select statement evaluates choice_expression and compares that value to each choice value. The when clause with the matching choice value has its expression assigned to target.
The following restrictions are placed on choices.
The following example shows target Z assigned from A, B, C, or D. The assignment depends on the current value of CONTROL. The resulting design is shown in the figure following the example.
signal A, B, C, D, Z: BIT;
signal CONTROL: bit_vector(1 down to 0);
. . .
with CONTROL select
Z <= A when "00",
B when "01",
C when "10",
D when "11";
The following example shows a process equivalent to the previous example of selected signal assignment statement.
process(CONTROL, A, B, C, D)
begin
case CONTROL is
when 0 =>
Z <= A;
when 1 =>
Z <= B;
when 2 =>
Z <= C;
when 3 =>
Z <= D;
end case;
end process;