Generate Statement - VHDL Example
Generate statements are used to accomplish one of two goals:
- Replicating Logic in VHDL
- 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); begin -- 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 begin 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 begin r_VECTOR <= X"DEAD"; wait for 100 ns; r_VECTOR <= X"BEEF"; wait for 100 ns; wait; end process; end behave;