1

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?

4
  • IEEE Std 1076-2008 6.5.3 Interface type declarations "... The name of the given interface type denotes both an undefined base type and a subtype of the base type. The class (see 5.1) of the base type is not defined. ...". Where the (5.1) classes are Scalar, Composite, Access, File, and Protected. If the class is undefined you can't use the length or other attributes dependent on object class or index or slice an object value. You don't provide a minimal reproducible example and there are no declarations for slv_arr, unsigned_arr or signed_arr. Commented Nov 9 at 13:37
  • OTOH, can you use IEEE Std 1076-2019? Unspecified types from will allow you to do this. Going further, with 2019, you can use unspecified types as parameter types that are implicitly converted to type generics. I will try to circle back and provide a relevant example if you can use them. Commented Nov 10 at 0:29
  • I have added an example. I changed so that first arg is std-logic-vector. Commented Nov 10 at 8:43
  • 1
    @JimLewis Vivado and XSIM only support vhdl2019 interfaces and condititional analsys. Commented Nov 10 at 8:45

1 Answer 1

3

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) );
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.