Search code examples
loopsvhdlendianness

Is it possible to access the index in a for loop in vhdl ? error: indexed name prefix type natrual is not an array type


I want to write a small program that converts big endian to little endian. Therefore I need to use a for loop. Since I only want to do the switch every 8 bit (1 Byte) i need to use some kind of modulo. I am not a fan of using predefined methods and would like to write it as hardware near as possible. Therefore I wanted to access the iterator variable and check if the last three bits are zero. Thus, I know that 8 iterations are done. Saddy, I get the erro message:

Indexed name prefix type natural is not an array type

My code is the following:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity TOP is
    Port ( INPUT : in STD_LOGIC_VECTOR (32 downto 0);
           CLK : in STD_LOGIC;
           OUTPUT : out STD_LOGIC_VECTOR (32 downto 0));

end TOP;

architecture Behavioral of TOP is

begin
S: process(CLK)
begin
    if rising_edge(CLK) then
        for I in INPUT' range loop
            --every 8 bit
            if I(3 downto 0) = "000" then
                OUTPUT(OUTPUT'left -I*8 downto OUTPUT'left - (I+1)*8) <= INPUT((I+1)*7 downto I*7); 
            end if;
        end loop;
    end if;
end process S;
end Behavioral;

Solution

  • Now the obvious answer would be if I mod 8 = 0 then but you don't want to do that.

    What you are doing with the line if I(3 downto 0) = "000" then is mixing levels of abstraction : an integer, and a low level representation of an integer as a bag of bits. Or strictly speaking, an indexable type - i.e. an array.

    That is a bad idea because it makes assumptions about the representation fo an integer that may or may not be valid ... ironically, including endian-ness. So, VHDL won't let you do that.

    What you can do is explicitly "convert" to a representation of an integer, where you can be certain what bit corresponds to what, and perform the low level operations on that concrete representation, instead of the abstract Integer. (Assuming the computer you're using has that representation anyway, the "conversion" has no penalty in time or hardware resources).

    There are two standard such representations. in the numeric_std library, called signed and unsigned respectively. The 'signed' one is explicitly 2-s complement and the unsigned is straightforward - both are arrays of std_logic types, therefore indexable.

    use IEEE.numeric_std.all;
    

    And you can read the source of this package, so there are no assumptions to make. (Or you could write a different package embodying the conventions you need instead. But nobody does that...)

    So you could convert the loop variable to a 5-bit unsigned and index into that...

    if to_unsigned(I,5)(2 downto 0) = "000" then
    

    Note that the original comparison would ALWAYS return False because of the array length mismatch.

    Finally, synthesis tools aren't stupid; they safely make the obvious optimisation on mod power-of-2 anyway.