VHDL 2008: Index in external names containing generated instances

932 views Asked by At

For a testbench, I'm trying to use external names to read signals within a DUT. It is not desired to export these signals outside of the DUT, so I concluded that using external names was the best option here.

Unfortunately, there are some for generate statements in the DUT, and this seems to make it quite difficult to assign signals outside of the DUT for some reason.

One of these generate systems will look like this:

   gen_block : for i in 0 to gen_loops generate
      entity_block : entity_name
         port map(
            signal_name          => signal_name
         );
   end generate;

My external name definition of the first generate can then be put in std_logic_vector signal alias_signal by doing this:

alias_signal(0) <= <<DUT_name.gen_block(0).entity_block.signal_name : std_logic>>

This works correctly. However, due to the large value of gen_loops, I would like to assign the external std_logic signals into std_logic_vectors, with index corresponding to the associated generate index.

The first thing I tried was this, by just leaving the indexes out and defining the external name as an std_logic_vector.

alias_signal <= <<DUT_name.gen_block.entity_block.signal_name : std_logic_vector>>

This is perfectly fine according to Sigasi, but once it's compiled in Questasim, I get this error for each line in which I do this:

# ** Error: [location][line]: (vopt-1571) Index required for FOR GENERATE "gen_block".

I assume this means that I have to use an index no matter what.

The next obvious step is to use a for loop with variable for_val to address every iteration of entity_block:

for for_val in 0 to gen_loops loop
   alias_signal(for_val) <= <<DUT_name.gen_block(for_val).entity_block.signal_name : std_logic>>
end loop;

Strangely, this produces an error in Sigasi, claiming that it "could not find a declaration corresponding to for_val". Somehow, within the external name, the value of for_val is getting lost, and the definition in the external name is somehow isolated from the rest of the code. Mind you, writing a number instead of for_val allows everything to work just fine, but due to the large value for gen_loops, this is a rather arduous task.

Is anyone able to see what I'm doing wrong? Do you maybe have a suggestion for a better method than this one? Is Sigasi being dumb, or is it me? Thanks in advance for your help :)

Minimal reproducible examples below: tb_name:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity tb_name is
end entity tb_name;

architecture RTL of tb_name is

   constant gen_loops  : integer                              := 10;
   signal alias_signal : std_logic_vector(gen_loops downto 0) := (others => '0');
   signal clk          : std_logic                            := '0';

begin

-- for loop approach
-- p_clk : process is
-- begin
--    loop
--       clk = '0'
--       wait for 1 ns;
--       clk = '1'
--       wait for 1 ns;
--    end loop;
-- end process p_clk;
--
-- p_alias : process(clk) is
-- begin
-- for for_val in 0 to gen_loops loop
--    alias_signal(for_val) <= << signal ^.DUT_block.gen_block(for_val).entity_block.signal_name : std_logic >> ;
-- end loop;
-- end process p_alias;

-- std_logic_vector approach
-- alias_signal <= <<signal ^.DUT_block.gen_block.entity_block.signal_name : std_logic_vector>>

-- working with index
alias_signal(0) <= << signal ^.DUT_block.gen_block(0).entity_block.signal_name : std_logic >> ;

   DUT_block : entity work.DUT_name 
      generic map (gen_loops)
   end entity DUT_block;

end architecture RTL;

DUT_name:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity DUT_name is
   generic(gen_loops : natural := 10);
end entity DUT_name;

architecture RTL of DUT_name is

   signal signal_name : std_logic_vector (gen_loops downto 0) := (others => '0');

begin

   gen_block : for i in 0 to gen_loops generate
   entity_block : entity work.entity_name
      port map(
         signal_name          => signal_name(i)
      );
   end generate;

end architecture RTL;

entity_name:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity entity_name is
   port(
      signal_name : out std_logic
   );
end entity entity_name;

architecture RTL of entity_name is

begin

   signal_name <= '1';

end architecture RTL;
2

There are 2 answers

4
Pepijn Ekelmans On BEST ANSWER

I have found the answer. External names need global static indexes, while the variables in for loops are non-static. Using a for generate statement instead of a for loop will solve the problem ;)

for for_val in 0 to gen_loops generate
   alias_signal(for_val) <= <<DUT_name.gen_block(for_val).entity_block.signal_name : std_logic>>
end generate;
4
Jim Lewis On

Why not just reference the array signal? By relative path it is:

alias signal_name is <<DUT_block.signal_name : std_logic_vector>> ; 

Note that you do not need to specify the index range of the std_logic_vector.

By an absolute path (which is what I commonly use) it is:

alias signal_name is <<.tb_name.DUT_block.signal_name : std_logic_vector>> ; 

Also keep in mind if you are putting these in your testbench, you have to put them after the instance of your DUT - in a process or block declarative region.