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 asuse 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:
- VHDL-2008 LRM
- Configurations: Part 1 and Configurations: Part 2 by Doulos
- “VHDL Design Units and Subprograms” by Department of Computer Science and Electrical Engineering UMBC
- “Configuration Declaration” by HDL Works
- “Configuration Declaration” by Peter Fabinski
- “Combine a vhdl and verilog configuration file” question on StackExchange