Generate Statement - VHDL Example

Generate statements are used to accomplish one of two goals:

  1. Replicating Logic in VHDL
  2. Turning on/off blocks of logic in VHDL

The generate keyword is always used in a combinational process or logic block. It should not be driven with a clock. If the digital designer wants to create replicated or expanded logic in VHDL, the generate statement with a for loop is the way to accomplish this task. Note that a for loop only serves to expand the logic. For a thorough understanding of how for loops work in VHDL read about for loops in digital design.

The second use case is very handy for debugging purposes, or for switching out different components without having to edit lots of code. The example below turns on an entire process just by switching g_DEBUG to 1. One interesting thing about generate statements used this way is that the same signal can be driven by multiple generate statements. The designer needs to ensure that these generate blocks are mutually exclusive, such that no two can be active at the same time. Otherwise there will be a problem with the same signal being driven by two sources.

Note that the example below uses a VHDL Generic

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity example_generate is
  generic (
    g_DEBUG      : natural := 1        -- 0 = no debug, 1 = print debug
end example_generate;

architecture behave of example_generate is

  signal r_VECTOR : std_logic_vector(15 downto 0) := (others => '0');

  signal w_VECTOR_MSB_1 : std_logic_vector(7 downto 0);
  signal w_VECTOR_MSB_2 : std_logic_vector(7 downto 0);

  signal w_VECTOR_TEST : std_logic_vector(15 downto 0);
  -- Demonstrates Use Case #1: Replicating Logic
  -- Stores just the most significant byte in a new signal
  g_GENERATE_FOR: for ii in 0 to 7 generate
    w_VECTOR_MSB_1(ii) <= r_VECTOR(ii+8);
  end generate g_GENERATE_FOR;
  -- This code has the same effect as above
  -- But the above is more compact, easier to read, and less error prone!
  w_VECTOR_MSB_2(0) <= r_VECTOR(8);
  w_VECTOR_MSB_2(1) <= r_VECTOR(9);
  w_VECTOR_MSB_2(2) <= r_VECTOR(10);
  w_VECTOR_MSB_2(3) <= r_VECTOR(11);
  w_VECTOR_MSB_2(4) <= r_VECTOR(12);
  w_VECTOR_MSB_2(5) <= r_VECTOR(13);
  w_VECTOR_MSB_2(6) <= r_VECTOR(14);
  w_VECTOR_MSB_2(7) <= r_VECTOR(15);

  -- Demonstrates Use Case #2: Turning on/off logic
  g_KEEP_DEBUG : if g_DEBUG = 1 generate

    p_TEST: process (r_VECTOR) is
      w_VECTOR_TEST <= r_VECTOR;
    end process p_TEST;
  end generate g_KEEP_DEBUG;

  -- Demonstrates Use Case #2: Turning on/off logic
  g_REMOVE_DEBUG : if g_DEBUG = 0 generate
    w_VECTOR_TEST <= (others => '0');
  end generate g_REMOVE_DEBUG;
  -- This process is NOT synthesizable.  Everything else in this example is.
  p_MAIN_TEST : process is
    r_VECTOR <= X"DEAD";
    wait for 100 ns;
    r_VECTOR <= X"BEEF";
    wait for 100 ns;
  end process;
end behave;

Modelsim simulation wave output

Help Me Make Great Content!     Support me on Patreon!     Buy a Go Board!