vhdl

attribute of generic type in vhdl


I am trying to write a generic function in vhdl for converting from vector to array.

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

package test is
   type slv_arr       is array (natural range <>) of std_logic_vector;
   type unsigned_arr  is array (natural range <>) of unsigned;
   type signed_arr    is array (natural range <>) of signed;
end package test;

package body test is
   function f_to_arr_g
     -- generic (type arg_type; type ret_type) 
     -- parameter (arg : arg_type; element_size : positive) return ret_type is 
     generic (type ret_type) 
     parameter (arg : std_logic_vector; element_size : positive) return ret_type is 
     -- Function Declaration Region
     constant c_ARG_LEN   : positive := arg'length;
     constant c_ARRAY_LEN : positive := c_ARG_LEN / element_size;
     variable v_return    : ret_type(c_ARRAY_LEN-1 downto 0)(element_size-1 downto 0);
   begin  -- start of function
     ---- Splitting
       for i in 0 to c_ARRAY_LEN-1 loop
         v_return(i) := arg(((i+1)*element_size)-1 downto i*element_size);
       end loop;
     ----
     return v_return;
   end function f_to_arr_g;
   function f_to_arr is new f_to_arr_g generic map (slv_arr);
end package body test;

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

use work.test.all;

entity f_to_arr_tb is
end entity f_to_arr_tb;

architecture tb of f_to_arr_tb is
   constant c_slv      : std_logic_vector(31 downto 0)   := x"AABBCCDD";
   constant c_expected : slv_arr(3 downto 0)(7 downto 0) := (x"AA", x"BB", x"CC", x"DD");
   signal   s_result : slv_arr(3 downto 0)(7 downto 0);
begin
  process
  begin
    s_result <= f_to_arr(c_slv);
    assert s_result = c_expected
      report "Test failed"
      severity error;
    wait;
  end process;

end architecture tb;

the problem is that the compiler does not accepting the "length" attribute and issuing this error

" prefix of attribute length should be a discrete or physical type or subtype"

Is there a way to do this or I should overload the function for each type?


Solution

  • The issue here, with VHDL 2008, is that VHDL 2008 generic types could be any type - be it scalar, physical or composite types (which could be an array or record type). How could the compiler cope if the designer did:

     function f_to_arr is new f_to_arr_g generic map (time);
    

    Here, there is no 'length attribute for an object of type time - so the whole function is meaningless.

    In VHDL 2019, anonymous generic types are added as a way to enforce some level of specification to the generic types, so that certain attributes are always available:

    function f_to_arr_g is
        generic ( type ret_type is array(natural range <>) of type is private)
        parameter ....
    

    Here, because you have specified that the generic type must be an array, then any of the types you have declared in the package are now acceptable, and you can even get hold of the element type by using the 'element attribute.

    But that doesnt help if you if you are stuck with 2008.

    In your case, the obvious answer is to simply remove generic types altogether, as I assume you are only interested in converting to the 3 array types. Because they are all ultimately arrays of std_logic, why not simply make the return type always a slv_arr ? and create separate conversion functions to the other 2 types, which should be simple to sepcify?

    function slv_arr_to_us( s : slv_arr) return unsigned_arr is
      variable r : unsigned_arr(s'range)(s(s'low)'range);
    begin
      for i in r'range loop
        r(i) := unsigned( s(i) );
      end if;
      
      return r;
    end function;
    
    ....
    
    my_us_arr <= slv_arr_to_us( f_to_arr( my_slv_arr, 32) );