Mastering VHDL Generate Statements: Build Reusable Debouncers with Ease
The VHDL generate statement allows designers to automatically replicate a block of code across multiple instances, each wired to distinct signals. Think of it as a compile‑time for loop that can create chained processes or module instances, dramatically reducing boilerplate and improving maintainability.
Unlike a traditional loop, which is confined to a process or subprogram, generate sits directly in the architecture region. When combined with generics, it becomes a powerful mechanism for crafting highly configurable, reusable VHDL components.
Generate Statement Syntax
[label :] for <constant_name> in <range> generate
[declarations_local_to_each_loop_iteration]
[begin]
<processes_and_instantiations>
end generate [label];
Optional elements are enclosed in brackets. You may omit the declarative region and begin keyword if no local objects are declared. The <range> follows the standard integer syntax using to or downto.
One‑Bit Switch Debouncer
Before diving into generate, let’s review a simple debouncer that cleans a single switch input. A generic timeout_cycles allows the module to adapt to any clock frequency. The debouncer suppresses transient glitches that occur when a mechanical switch transitions.
entity debouncer is
generic (
timeout_cycles : positive
);
port (
clk : in std_logic;
rst : in std_logic;
switch : in std_logic;
switch_debounced : out std_logic
);
end debouncer;
The implementation relies on an integer counter whose width is dictated by the generic. A shadow signal debounced is used internally to keep the output logic clean.
architecture rtl of debouncer is
signal debounced : std_logic;
signal counter : integer range 0 to timeout_cycles - 1;
begin
-- Copy internal signal to output
switch_debounced <= debounced;
DEBOUNCE_PROC : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= 0;
debounced <= switch;
else
if counter < timeout_cycles - 1 then
counter <= counter + 1;
elsif switch /= debounced then
counter <= 0;
debounced <= switch;
end if;
end if;
end if;
end process;
end architecture;
Simulation in ModelSim confirms that switch_debounced follows the input only after the specified timeout, effectively filtering out bouncing artifacts.

Download the full ModelSim project, including testbenches, by providing your email address below. All updates are sent from VHDLwhiz, and you can unsubscribe at any time.
Generate for Loop with Instantiations
To extend the debouncer to an array of switches, we use a generate statement to create multiple instances automatically.
entity debouncer_gen_inst is
generic (
switch_count : positive;
timeout_cycles : positive
);
port (
clk : in std_logic;
rst : in std_logic;
switches : in std_logic_vector(switch_count - 1 downto 0);
switches_debounced : out std_logic_vector(switch_count - 1 downto 0)
);
end debouncer_gen_inst;
The architecture uses a generate loop to instantiate debouncer for each switch bit. Each instance shares the same clock and reset but connects to a distinct vector element.
architecture rtl of debouncer_gen_inst is
begin
MY_GEN : for i in 0 to switch_count - 1 generate
DEBOUNCER : entity work.debouncer(rtl)
generic map (
timeout_cycles => timeout_cycles
)
port map (
clk => clk,
rst => rst,
switch => switches(i),
switch_debounced => switches_debounced(i)
);
end generate;
end architecture;
Labeling the generate block (e.g., MY_GEN) improves readability in the simulator hierarchy and synthesis reports, making debugging straightforward.

The testbench toggles only switch 3, so the waveform focuses on MY_GEN(3). Run this example in ModelSim to see the debouncing logic in action.
Generate for Loop Containing Processes
Alternatively, you can lift the debouncer logic into the generate block itself, eliminating separate component instantiations. This approach demonstrates that a generate loop can also create identical processes with local signals.
architecture rtl of debouncer_gen_proc is
begin
MY_GEN : for i in 0 to switch_count - 1 generate
signal debounced : std_logic;
signal counter : integer range 0 to timeout_cycles - 1;
begin
switches_debounced(i) <= debounced;
DEBOUNCE_PROC : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= 0;
debounced <= switches(i);
else
if counter < timeout_cycles - 1 then
counter <= counter + 1;
elsif switches(i) /= debounced then
counter <= 0;
debounced <= switches(i);
end if;
end if;
end if;
end process;
end generate;
end architecture;
The resulting behavior matches the module‑instantiation approach, but the code is self‑contained within the architecture. Both methods are valid; choose the one that best aligns with your design style.
All code samples, including the full ModelSim project, are available for download via the form below. Subscribe to VHDLwhiz for updates, and feel free to unsubscribe at any time.
Have a creative use for generate? Share your ideas in the comments below!
VHDL
- VHDL Procedure Example: Incrementing a Standard Logic Vector
- Mastering the C# Switch Statement: Syntax, Examples & Best Practices
- C# Break Statement: How & When to Use It
- Mastering the C++ Switch‑Case Statement: Syntax, Workflow, and Practical Examples
- Mastering the C Switch Statement: Syntax, Flow, and Practical Example
- Mastering the Java Switch Statement: Syntax, Usage, and Best Practices
- Mastering C++ Switch‑Case: Syntax, Usage, and Practical Examples
- Mastering C Conditional Statements: IF, IF-ELSE, and Nested IF-ELSE Explained
- Understanding Switch‑Case in C: Syntax, Examples, and Best Practices
- Java Switch‑Case Statement Explained: Syntax, Examples, and Best Practices