If you have a hierarchical design (so one block is built from others), you will have to instantiate and connect modules. Even if you have only one module and testbench dedicated for it, you will have to do that. In testbench used in previous post, I showed, how to instantiate a component, but there are more simpler ways to do that. Below you can find a few methods.
For my purposes, I will use module from previous post – Edge Detector:
library ieee; use ieee.std_logic_1164.all; entity EdgeDetector is port ( clk :in std_logic; d :in std_logic; edge :out std_logic ); end EdgeDetector; architecture EdgeDetector_rtl of EdgeDetector is signal reg1 :std_logic; signal reg2 :std_logic; begin reg: process(clk) begin if rising_edge(clk) then reg1 <= d; reg2 <= reg1; end if; end process; edge <= reg1 and (not reg2); end EdgeDetector_rtl;
During instantiating a component we have to map generics and ports of the component to local signals. We can do it in two ways. First one, seems faster and shorter, but I would not recommend it. Second needs more writing, but this is more readable and clearer method.
In first approach, important is order of the signals which are assigned to the instantiated component. In instantiation statement, signals have to be exactly in the same order as declared in a component which is being instantiated (when you look at the code, you won’t find there strong assignments of local signals to component ports).
UUT: EdgeDetector port map ( tb_clk, tb_d, tb_edge );
The second method unambiguously connects signals of testbech with ports of UUT block. It means that order of the signals doesn’t matter, because mapping is clearly described.
UUT: EdgeDetector port map ( clk => tb_clk, d => tb_d, edge => tb_edge );
Which method is better? I think, it is better to use second method, where all connections are shown and declared. Imagine what will happen, if you change order of the ports in the Edge Detector component, but you won’t do that in the block above. It will cause failures in your design…
Next part shows, that only not mapping can be done in many ways, but instantiating component as well. We can distinguish two method:
- component instantiation
- entity instantination
Method presented as first is called component instantiation. Before instantiating module you have to declare component in declarative part (lines 3 – 9).
architecture tb_ed_rtl of tb_ed is component EdgeDetector is port ( clk :in std_logic; d :in std_logic; edge :out std_logic ); end component; signal tb_clk :std_logic := '0'; signal tb_d :std_logic := '0'; signal tb_edge :std_logic := '0'; begin UUT: EdgeDetector port map ( clk => tb_clk, d => tb_d, edge => tb_edge ); end architecture;
Second option is called entity instantiation. You don’t have to declare component in declarative part. You just have to point out which entity and architecture you are going to use. This is much faster option with no useless code – component declaration.
architecture tb_ed_rtl of tb_ed is signal tb_clk :std_logic := '0'; signal tb_d :std_logic := '0'; signal tb_edge :std_logic := '0'; begin UUT: entity work.EdgeDetector(EdgeDetector_rtl) port map ( tb_clk, tb_d, tb_edge ); end architecture;
Which option is the best? It depends. Both are useful and can be used interchangeably. Below I wrote some main differences:
- Component instantiation works with configuration tool, which allows very easy to configure component, change its parameters etc. It is useful in bigger designs or in designs where you have many identical entities and theirs behavior depends on parameters.
- Component instantiation can be used where instantiated architecture is not yet ready and you have no sources. This method allows to compile the block and treat instantiated component as a black box.
- Entity instantiation doesn’t need any declarations, so it is much faster to instantiate component by this method. When you change ports in the component, compiler will adopt changes by itself. In component instantiation you will have to modify component declaration, so it creates places to make a mistake and takes more time.
In my opinion for small projects, where configuration is not used, it is better to use entity instantination. For bigger projects, where designer wants to control everything and some blocks are still under development, it is better to use component instantiation. Of course there are always exceptions. Not only size of the project is important, but its structure as well..
*** *** ***
All source codes used in that post you can find on gitlab.com.
*** *** ***