Previous

Generate Statements

A generate statement creates zero or more copies of an enclosed set of concurrent statements. The two kinds of generate statements follow.

For...generate Statement

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.

  1. A new local integer variable is declared with the name identifier.

  2. Identifier is assigned the first value of range, and each concurrent statement is executed once.

  3. Identifier is assigned the next value in range, and each concurrent statement is executed once more.

  4. Step 3 is repeated until identifier is assigned the last value in range.

  5. Each concurrent statement is then executed for the last time, and execution continues with the statement following end generate. The loop identifier is deleted.

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.

If...generate Statement

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.


NOTE

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

Next