A generate statement creates zero or more copies of an enclosed set of concurrent statements. The two kinds of generate statements follow.
The syntax follows.
label: for identifier in range generate
{ concurrent_statement }
end generate [ label ] ;
The required label names this statement (useful for nested generate statements).
The use of the identifier in this construct is similar to that of the for...loop statement.
Identifier is not declared elsewhere. It is automatically declared by the generate statement itself and is entirely local to the loop. A loop identifier overrides any other identifier with the same name but only within the loop.
The value of identifier can be read only inside its loop, but you cannot assign a value to a loop identifier. In addition, the value of identifier cannot be assigned to any parameter whose mode is out or inout.
Foundation Express requires that range must be a computable integer range, in either of these forms.
integer_expression to integer_expression
integer_expression downto integer_expression
Each integer_expression evaluates to an integer.
Each concurrent_statement can be any of the statements described in this chapter, including other generate statements.
A for...generate statement executes as follows.
The following example shows a code fragment that combines and interleaves two four-bit arrays A and B into an eight-bit array C. The resulting circuit is shown in the figure following the example.
signal A, B : bit_vector(3 downto 0);
signal C : bit_vector(7 downto 0);
signal X : bit;
. . .
GEN_LABEL: for I in 3 downto 0 generate
C(2*I + 1) <= A(I) nor X;
C(2*I) <= B(I) nor X;
end generate GEN_LABEL;
Figure 7.9 Circuit for for...generate Statement |
The most common use of the generate statement is to create multiple copies of components, processes, or blocks. The following example demonstrates this use with components. The example in the If...generate Statement section shows how to generate multiple copies of processes. The following example shows VHDL array attribute 'range used with the for...generate statement to instantiate a set of COMP components that connect corresponding elements of bit vectors A and B. The resulting circuits follow each of the examples.
component COMP
port (X : in bit;
Y : out bit);
end component;
. . .
signal A, B: BIT_VECTOR(0 to 7);
. . .
GEN: for I in A'range generate
U: COMP port map (X => A(I),
Y => B(I));
end generate GEN;
Figure 7.10 Circuit for for...generate Statement on an Entire Array |
Unconstrained arrays and array attributes are described in the Array Types section of the Data Types chapter. Array attributes are shown in an example of array attributes.
The syntax follows.
label: if expression generate
{ concurrent_statement }
end generate [ label ] ;
Label identifies (names) this statement. Expression is any expression that evaluates to a Boolean value. A concurrent_statement is any of the statements described in this chapter, including other generate statements.
Unlike the if statement described in the Sequential Statements chapter, the if...generate statement has no else or elsif branches.
You can use the if...generate statement to generate a regular structure that has different circuitry at its ends. Use a for...generate statement to iterate over the desired width of a design and a set of if...generate statements to define the beginning, middle, and ending sets of connections.
The following example shows a technology independent description of the following N-bit serial-to-parallel converter. Data is clocked into an N-bit buffer from right to left. On each clock cycle, each bit in an N-bit buffer is shifted up one bit, and the incoming DATA bit is moved into the low-order bit. The resulting circuit follows the example.
entity CONVERTER is
generic(N: INTEGER := 8);
port(CLK, DATA: in BIT;
CONVERT: buffer BIT_VECTOR(N-1 downto 0));
end CONVERTER;
architecture BEHAVIOR of CONVERTER is
signal S : BIT_VECTOR(CONVERT'range);
begin
G: for I in CONVERT'range generate
G1: -- Shift (N-1) data bit into high-order bit
if (I = CONVERT'left) generate
process begin
wait until (rising_edge);
CONVERT(I) <= S(I-1);
end process;
end generate G1;
G2: -- Shift middle bits up
if (I > CONVERT'right and
I < CONVERT'left) generate
S(I) <= S(I-1) and CONVERT(I);
process begin
wait until (rising_edge);
CONVERT(I) <= S(I-1);
end process;
end generate G2;
G3: -- Move DATA into low-order bit
if (I = CONVERT'right) generate
process begin
wait until (rising_edge);
CONVERT(I) <= DATA;
end process;
S(I) <= CONVERT(I);
end generate G3;
end generate G;
end BEHAVIOR;
Figure 7.11 Circuit for Typical Use of if...generate Statements |