Search code examples
for-loopvhdlalias

Use alias-like variable in for loops


Is it possible to create an alias variable/signal to improve readability of for loops in VHDL processes?

For instance, consider the following module which contains a process with inner for loops (code is for example purpose, I haven't test it):

library ieee;
use ieee.std_logic_1164.all;

entity MyModule is
  port (
    clk                 : in  std_logic;
    inData              : in  std_logic_vector(7 downto 0);
    outData             : out std_logic_vector(7 downto 0));
end MyModule;

architecture functional of MyModule is
  type sample_vector  is array (natural range <>) of std_logic_vector(9 downto 0);
  type data_t is record
    samples     : sample_vector(3 downto 0);
    -- other elements...
  end record data_t;
  type data_vector  is array (natural range <>) of data_t;
  signal data  : data_vector(1 downto 0);

begin  -- functional
  process (clk)
  begin  -- process
    if clk'event and clk = '1' then
      -- Set outData(N) to '1' if at least 1 of the last 10 values of inData(N) was '1'
      for d in data'RANGE loop
        for s in data(0).samples'RANGE loop
          data(d).samples(s)(9 downto 1) <= data(d).samples(s)(8 downto 0);
          data(d).samples(s)(0) <= inData(d * 4 + s);
          outData(d * 4 + s) <= '0';
          for b in data(d).samples(s)'RANGE loop
            if data(d).samples(s)(b) = '1' then
              outData(d * 4 + s) <= '1';
            end if;
          end loop;
        end loop;
      end loop;
    end if;
  end process;

end functional;

Having to use data(d).samples(s) every time I need to reference that signal is cumbersome, so I'd rather use an alias-like variable, something like that instead (inspired from generate syntax, idx part is just a bonus):

      -- Set outData(N) to '1' if at least 1 of the last 10 values of inData(N) was '1'
      for d in data'RANGE loop
        for s in data(0).samples'RANGE loop
          alias sample  : std_logic_vector(9 downto 0) is data(d).samples(s);
          constant idx  : integer := d * 4 + s;
        begin
          sample(9 downto 1) <= sample(8 downto 0);
          sample(0) <= inData(idx);
          outData(idx) <= '0';
          for b in sample'RANGE loop
            if sample(b) = '1' then
              outData(idx) <= '1';
            end if;
          end loop;
        end loop;
      end loop;

Of course, this does not work. So, is there any way to achieve something like that in VHDL, or do we always have to specify the full signal "path" each time?

I could replace the loop body with a procedure, but having to declare the procedure code in a (far away) different place of the file reduces readability even more. I could also use a for ... generate construct, but this will create 1 process for each iteration and prevent me from using common process variables inside the iteration.


Solution

  • As indicated in question comments, this can be achieve using process variables:

      process (clk)
        variable sample : std_logic_vector(9 downto 0);
        variable idx    : integer;
      begin  -- process
        if clk'event and clk = '1' then
          -- Set outData(N) to '1' if at least 1 of the last 10 values of inData(N) was '1'
          for d in data'RANGE loop
            for s in data(0).samples'RANGE loop
              -- Helpers
              sample := data(d).samples(s);
              idx := d * 4 + s;
    
              outData(idx) <= '0';
              for b in sample'RANGE loop
                if sample(b) = '1' then
                  outData(idx) <= '1';
                end if;
              end loop;
              sample(9 downto 1) <= sample(8 downto 0);
              sample(0) <= inData(idx);
    
              -- Do not forget to apply changes
              data(d).samples(s) <= sample;
            end loop;
          end loop;
        end if;
      end process;
    

    Of course, using process variables implies changing the operations order to get the same behavior.

    Since process variables are read and written in the loops, I was worried the synthesis tools would believe the result of iteration N was dependent on the result of iteration N-1, and make implements the iterations in series (instead of in parallel). However, after unrolling the loop (which is what synthesis tools do), it gets clear the synthesis tools will see sample and idx values are not re-used between iterations.