VHDL configuration

Andrzej Wojciechowski

I have recently had a chance to briefly play with a feature of VHDL I have never used before – configuration. Here I’ve gathered my thoughts and findings in this topic. Partially as sort of ‘note to myself’ and hopefully in the future I will have time to get some more experience with this part of the VHDL language.

What is the VHDL configuration?

In essence, the configuration defines specific entities to be used as components declared in modules. In most cases the configuration declaration is not required for one of two reasons:

1. Instantiation of a design entity (also known as entity instantiation or direct instantiation)

Directly instantiating a design entity is in most cases a superior way of instantiating submodule. In contrast to other methods, it unambiguously declares which exact submodule is instantiated and in case the interface is changed, only two places needed to be changed: the interface declaration and instance mapping. Below is the example of such instantiation.

architecture top_entity_arch_name of Top_entity_name is
begin

Submodule_inst : entity work.Submodule_name(submodule_arch_name)
port map (
   i_clk          => i_clk,

   i_in           => i_in,
   o_out          => o_out
);

end top_entity_arch_name;

2. Component and Entity match with no ambiguity

VHDL configurations are only relevant for component instantiation. However, if the component name and interface directly and unambiguously matches witch one (and only one) entity with a single architecture in the project, then by default the entity will by bonded to the component. In my opinion in most cases it’s risky to do it this way. Below is the example of a described case.

architecture top_entity_arch_name of Top_entity_name is

component Submodule_name
port (
   i_clk          : in  std_logic;
   i_rst          : in  std_logic;

   i_in           : in  std_logic_vector(3 downto 0);
   o_out          : out std_logic_vector(3 downto 0)
);
end component;

begin

Submodule_inst : entity work.Submodule_name(submodule_arch_name)
port map (
   i_clk          => i_clk,
   i_rst          => i_rst,

   i_in           => i_in,
   o_out          => o_out
);

end top_entity_arch_name;

-----------------------------

entity Submodule_name is
port (
   i_clk          : in  std_logic;
   i_rst          : in  std_logic;

   i_in           : in  std_logic_vector(3 downto 0);
   o_out          : out std_logic_vector(3 downto 0)
);
end Submodule_name;

architecture submodule_arch_name of Submodule_name is
begin

process (i_clk, i_rst)
begin
   if rising_edge(i_clk) then
      if i_rst = '1' then
         o_out    <= (others => '0');
      else
         o_out    <= i_in;
      end if;
   end if;
end process;

end submodule_arch_name;

How to define a VHDL configuration?

There are multiple examples on the web on how to use configuration. Below I listed some of them. However, I found them to be oversimplified and still struggled to implement them for the first time. In my case I wanted to define a configuration for a component 3 level deep in a hierarchy (from a top-level entity). Eventually I found out that the correct syntax for a configuration is as follows:

configuration Top_entity_config of Top_entity is
   for Top_entity_arch_name -- of Top_entity
      for Level_1_submodule_instance_name : Level_1_submodule_name
         use entity work.Some_module_wrapper(Some_module_wrapper_arch_name);
         for Some_module_wrapper_arch_name -- of Some_module_wrapper
            for Level_2_submodule_instance_name : Level_2_submodule_name
               use entity work.Some_module(Some_module_arch_name);
               for Some_module_arch_name -- of Some_module
                  for Level_3_submodule_instance_name : Level_3_submodule_name
                     use entity work.Low_level_module(Low_level_module_arch_name);
                  end for; -- for Level_3_submodule_instance_name : Level_3_submodule_name
               end for; -- for Some_module_arch_name -- of Some_module
            end for; -- for Level_2_submodule_instance_name : Level_2_submodule_name
         end for; -- for Some_module_wrapper_arch_name -- of Some_module_wrapper
      end for; -- for Level_1_submodule_instance_name : Level_1_submodule_name
   end for; -- for Top_entity_arch_name -- of Top_entity
end configuration Top_entity_config;

The things I didn’t realize at the beginning are:

  • you have to define architecture for each entity, even if only one architecture exists
  • there are two for loops per each component-entity binding: one for component name (and optionally instance name) and one for architecture
  • even if the component instantiation is used deeper in the hierarchy, in order to use a configuration, all submodules referenced in a configuration must be instantiated using components
  • at least I couldn’t get it to work, but it seems that in Vivado the IPs from Xilinx can’t be referenced in configuration. I tried use entity work.gtwizard_ultrascale_0; as well as use entity xil_defaultlib.gtwizard_ultrascale_0; and both resulted in errors.

Hopefully I’ll have more occasions to play with configurations in the future. I think it might have some interesting uses, especially when used with other VHDL features, such as automatic differentiation between simulation and synthesis. But generally I confirmed my belief that direct instantiation is a better practice. In my case I eventually achieved my goal using entity instantiation combined with generate statements.

List of useful resources: