VHDL coding tips and tricks: VHDL: "Generate" Keyword with Examples

Tuesday, September 14, 2010

VHDL: "Generate" Keyword with Examples

    Generate statement is a concurrent statement used in VHDL to describe repetitive structures. You can use generate keyword in your design to instantiate multiple components in just few lines. It can be even combined with conditional statements such as if .. else or iteration statements such as for loops.

    In the first part of this post, I will combine the generate keyword with a for loop to implement a PISO using D flipflops. In fact, in an earlier post, I have done it using individual D flipflop instantiations. You can refer to that code from here, PISO in Gate level and Behavioral level Modeling.

PISO using Generate & for keywords:


--library declaration.
library ieee;
use ieee.std_logic_1164.all;

--parallel in serial out shift register
entity piso is
port(Clk : in std_logic;  --Clock signal
    parallel_in : in std_logic_vector(3 downto 0);  --4 bit parallel load
    load : in std_logic;  --active high for loading the register
    serial_out : out std_logic  --output bit. 
    );
end piso;

architecture gate_level of piso is

signal D,Q : std_logic_vector(3 downto 0) := "0000";

begin

serial_out <= Q(3);

--entity instantiation of the D flipflop using "generate".
F :  --label name
    for i in 0 to 3 generate   --D FF is instantiated 4 times.
    begin  --"begin" statement for "generate"
    ----usual port mapping. Entity instantiation with named association
        FDRSE_inst : entity work.FDRSE1 port map   
            (Clk => Clk,
            ce => '1',
            reset => '0',
            D => D(i),
            set => '0',
            Q => Q(i));  
    end generate F;  --end "generate" block.
--The D inputs of the flip flops are controlled with the load input.
--Two AND gates with a OR gate is used for this.
D(0) <= parallel_in(3) and load;
D(1) <= (parallel_in(2) and load) or (Q(0) and not(load));
D(2) <= (parallel_in(1) and load) or (Q(1) and not(load));
D(3) <= (parallel_in(0) and load) or (Q(2) and not(load));

end gate_level;

The FDRSE flip code can be copied from here: Synchronous D Flip-Flop with Testbench.

I believe that the code is self explanatory. The for loop is used to instantiate as many number of modules as we want to instantiate. To easily port map in a programmatic way, I declare a std_logic_vector for D and Q, and use the index "i" to connect bits of the individual signals to the ports of the individual flipflops.

Johnson Counter using Generate Statement:


    Next I want to show you how to combine generate statement with both if else conditional statement and for loop, to programmatically instantiate multiple components. For this I will be using the example of a Johnson counter.

library ieee;
use ieee.std_logic_1164.all;

entity johnson_counter is
port(clk : in std_logic;
    reset : in std_logic;
    count : out std_logic_vector(3 downto 0)
    );
end johnson_counter;

architecture Behavioral of johnson_counter is

signal D,Q : std_logic_vector(3 downto 0):="0000";
signal not_Q4 : std_logic:='0';

begin

--Q of the last flipflop is fed to the D of the first flop
not_Q4 <= not Q(3);
count <= Q;  --Q is assigned to output port

--generate the instantiation statements for the 4 fliflops
--F,F0 and F1 are label names for the generate statement.
--'generate' statements should have a 'begin' and an 'end'
F : for i in 0 to 3 generate
    begin
        F0 : if (i = 0) generate  --instantiate the "first" FF only.
            begin U1 : entity work.FDRSE1 port map --usual port mapping   
                (Clk => Clk,
                ce => '1',
                reset => reset,
                D => not_Q4,
                set => '0',
                Q => Q(0));     
            end generate F0;
        F1 : if (i > 0) generate --generating the rest of the three FF's.
            begin U2 : entity work.FDRSE1 port map   --usual port mapping
                (Clk => Clk,
                ce => '1',
                reset => reset,
                D => Q(i-1),
                set => '0',
                Q => Q(i));     
            end generate F1;
    end generate F;  
   
end Behavioral;

You can get the testbench for the Johnson counter from this post: 4 bit Johnson Counter with Testbench.
The FDRSE flip code can be copied from here: Synchronous D Flip-Flop with Testbench.

    As you can see from these examples, using "generate" keyword makes your code much more smaller and neat. They even help others to go through and understand your code faster.

    Make sure to visit the older posts linked in the above post to get the testbenches and see screenshots of the simulation waveform.

2 comments:

  1. Thanks by this tutorial !
    I need create this sequence of blocks in VHDL 1,2,3,4,4,5,6,7,8,9,10,11,12,13,13,14,15,,,,40,40,,j,...
    You know or have a idea of the correct way to do this sequence?
    Thanks again

    ReplyDelete
  2. if(valueYouWant = i) generate
    for j in 0 to howManyTimes generate
    ...

    ReplyDelete