2

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 Answers2

2

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;
  • There were several typos in your [mcve]. I had to correct those before it would compile. Before reading this answer, I edited your question so that the [mcve] was compilable. One of the edits was making your `for` loop into a `generate` loop, because you can't have a `for` loop outside a process. After correcting your typos, I had no time to spend on answering the question. It seems like my changing of the `for` loop to a `generate` loop is not compatible with your answer. I suggest you edit my edits to put your `for` loop inside a process, otherwise this question and answer makes no sense. – Matthew Taylor Oct 22 '20 at 09:05
  • This answer will not compile. (i) the `generate` loop requires a label. (ii) `DUT_name` is not below this point in the hierachy. You need to say `^.DUT_name`. https://www.edaplayground.com/x/pWYc – Matthew Taylor Oct 22 '20 at 09:13
  • It's worth taking the time to sort these issues out with the question and answer, because it will be useful for future readers. – Matthew Taylor Oct 22 '20 at 09:15
  • Thank you Matthew, I did do this correctly in my system, but made a bad reproducible system. Hadn't seen the thing about ^. before though, I'll use that. Thanks a lot for your help! – Pepijn Ekelmans Oct 22 '20 at 10:24
0

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.

Jim Lewis
  • 3,601
  • 10
  • 20
  • This method was already referenced in my question. Is there a difference between your answer and this method? ```alias_signal <= <>```. The error I get for this is based in Questasim, and defined as: ```# ** Error: [location][line]: (vopt-1571) Index required for FOR GENERATE "gen_block".``` – Pepijn Ekelmans Oct 22 '20 at 07:20
  • Does not referencing the middle instance names absolve this issue? EDIT: I've tried this, and as expected, it could not find the the signal for that instance name. – Pepijn Ekelmans Oct 22 '20 at 07:20
  • Why are you tangling with the generate block if you are declaring the std_logic_vector signal outside of it in the architecture. This simply references that. Did you try it the way I wrote it? Your error message indicates you tried to reach into the generate block. – Jim Lewis Oct 23 '20 at 11:18
  • The way I wrote this, it references the declaration in the "architecture RTL of DUT_name". It does not bother to try to reach into the generate loop. If the design is as shown above and you tried it the way this shows (ie referencing the point of declaration), this will indeed work. – Jim Lewis Oct 23 '20 at 11:23