VHDL instantiation

There are two ways to instantiate a module in VHDL: component instantiation and entity instantiation. Some people refer to the latter as direct instantiation.

Entity instantiation didn’t exist in the first revisions VHDL, but it has been available since VHDL’93. This is the method that I recommend unless you have specific reasons to use component instantiation.

To use the component instantiation method, you first have to declare the component in the declarative scope of where you want the module instance. That usually means in the VHDL file’s declarative region, but you can also define them in packages.

The listing below shows the syntax of the component declaration.

component_declaration ::=
  component identifier [ is ]
    [ local_generic_clause ]
    [ local_port_clause ]
  end component [ component_simple_name ] ;

While the component declaration resides in a declarative region, instantiations belong in the architecture. The Backus–Naur form notation below shows the combined instantiation syntax for all methods.

component_instantiation_statement ::=
  instantiation_label :
    instantiated_unit
      [ generic_map_aspect ]
      [ port_map_aspect ] ;

instantiated_unit ::=
  [ component ] component_name
  | entity entity_name [ ( architecture_identifier ) ]
  | configuration configuration_name

Note that there is a third method of instantiation: configuration. That’s an advanced VHDL feature which I will cover in a separate article.

Entity instantiation example

The VHDL code below shows an example of direct instantiation of a multiplexer module.

architecture str of top_tb is

  constant n : positive := 5;
  signal sel : positive range 1 to n - 1;
  signal din : std_logic_vector(n - 1 downto 0);
  signal q : std_logic;

begin

  MUX : entity work.mux(rtl)
    generic map (n => n)
    port map (
      sel => sel,
      din => din,
      q => q
    );

end architecture;

First, we give the instance a name. If there’s just one instance, I usually use the same name as the module’s entity, MUX, in this case. That makes it easy to find it in the simulator hierarchy view.

Then we use the entity keyword to show that we want to use direct instantiation. After that, we identify the module by library, entity, and architecture name.

Specifying the architecture name is optional, but I recommend always to do it. It may help you avoid annoying errors due to multiple architectures. If you don’t explicitly specify one, you will get the latest compiled architecture.

The example module above has a generic declaration. If your module doesn’t use generics, omit the generic map section.

Component instantiation example

The code below is an equivalent example using component instantiation.

architecture str of top_tb is

  constant n : positive := 5;
  signal sel : positive range 1 to n - 1;
  signal din : std_logic_vector(n - 1 downto 0);
  signal q : std_logic;

  component mux
  generic (n : positive);
  port (
    sel : in positive range 1 to n - 1;
    din : in std_logic_vector(n - 1 downto 0);
    q : out std_logic
  );
  end component mux;

begin

  MUX_1 : mux
    generic map (n => n)
    port map (
      sel => sel,
      din => din,
      q => q
    );

end architecture;

The component declaration is equal to the entity of the module that you want to instantiate. If you change your module’s entity, you have to update three places: in the module’s entity, in the component declaration, and the instantiation.

Furthermore, there is no way to specify which architecture to use. If you have two or more architectures for your module, it’s the last compiled one that becomes active. That could be the one at the bottom of your VHDL file or determined by compile order if you have multiple files.

And finally, because you have to give a name to the component, you can’t use the same name as a label for your instance. If the module’s name is mux, and you name the component mux, you would have to call your instance MUX_1 or something like that, as shown in the example above.

For those reasons, I consider component instantiation to be inferior to entity instantiation.

When to use component instantiation

I would say always use entity instantiation if you can; it’s neater and safer. But there are some situations where the synthesis tools force you to use component instantiation. For example, when instantiating something that isn’t VHDL in a VHDL file.

That could be a netlist, a hard macro, or a Verilog module. Xilinx Vivado only supports the component instantiation method for including Verilog files into VHDL projects.

Xilinx UG901 (Vivado):  Only component instantiation is supported when instantiating a Verilog module in VHDL. Direct entity instantiation is not supported.

The image above is an excerpt from Xilinx UG901 (v2020.1).

Another reason is if you want to use configuration constructs. Because of how the implementation design flow works in VHDL, configurations only work with component instantiation.

Positional association

All of the examples above use named association in the generic and port map. VHDL also supports positional association of entity to local signal names, as shown below.

MUX : entity work.mux(rtl)
  generic map (n)
  port map (sel, din, q);

Many style guides recommend only to use named association, and I have to agree with them. It’s easy to get into trouble if you make changes to the entity and forget to fix every single instance of the module. With named association, it will still work, or you get a compilation error.

Similar Posts

6 Comments

  1. Hi Jonas,
    until now, I only knew the “component instatiation” method, with the inconvenience of having to add the component declaration in addition to the instance declaration and modify both after changing the logic.
    With the entity instatiation method, you write fewer lines of code and avoid many errors and waste of time.
    Thanks for all your helpful articles.

    Giuseppe

      1. Jonas,
        I was trying to instantiate the block diagram entity in my top level, after generating the HDL wrapper, called “bd”. So I wrote:

           bd_i: entity work.bd(STRUCTURE)
              port map (
                 DDR_addr(14 downto 0)      => DDR_addr(14 downto 0),
                 DDR_ba(2 downto 0)         => DDR_ba(2 downto 0),
                 DDR_cas_n                  => DDR_cas_n,
                 DDR_ck_n                   => DDR_ck_n,
                 DDR_ck_p                   => DDR_ck_p,
                 DDR_cke                    => DDR_cke,
                 DDR_cs_n                   => DDR_cs_n,
                 DDR_dm(3 downto 0)         => DDR_dm(3 downto 0),
                 DDR_dq(31 downto 0)        => DDR_dq(31 downto 0),
                 DDR_dqs_n(3 downto 0)      => DDR_dqs_n(3 downto 0),
                 DDR_dqs_p(3 downto 0)      => DDR_dqs_p(3 downto 0),
                 DDR_odt                    => DDR_odt,
                 DDR_ras_n                  => DDR_ras_n,
                 DDR_reset_n                => DDR_reset_n,
                 DDR_we_n                   => DDR_we_n,
                 FIXED_IO_ddr_vrn           => FIXED_IO_ddr_vrn,
                 FIXED_IO_ddr_vrp           => FIXED_IO_ddr_vrp,
                 FIXED_IO_mio(53 downto 0)  => FIXED_IO_mio(53 downto 0),
                 FIXED_IO_ps_clk            => FIXED_IO_ps_clk,
                 FIXED_IO_ps_porb           => FIXED_IO_ps_porb,
                 FIXED_IO_ps_srstb          => FIXED_IO_ps_srstb,
                 PS_CLK_100M                => ss_ps_clk_100m,
                 rx                         => rx_ps,
                 tx                         => tx_ps
              );
        

        So I get the following error: “Cannot find in library . Please, ensure that the library was compiled, and that a library and a use clause are present in the VHDL file”.

        How could I resolve?
        Thanks for the reply

        Giuseppe

        1. This is one of those situations where you have to use component instantiation because the Xilinx processing systems isn’t a VHDL module. But you can do a workaround by right-clicking the block design in Vivado (in the Sources tab under Design Sources) and select Create HDL Wrapper. Vivado will create a VHDL wrapper which you can instantiate in your top VHDL file using entity instantiation. You will also have to include the wrapper VHDL file in your project.

        2. Aha, I was a bit too quick in reading your comment. You mentioned you have already created the wrapper. I think the problem here is that Vivado uses the “xil_defaultlib” library instead of “work”.

          Right-click the VHDL wrapper in the Sources tab and select Source Node Properties. There you can change the library it’s compiled into to “work”. Alternatively, you can change it to xil_defaultlib in your instantiation.

Leave a Reply

Your email address will not be published. Required fields are marked *