VHDL泛型函数实现向量转数组时length属性编译错误排查
VHDL泛型函数实现向量转数组的问题解决
问题描述
我尝试编写VHDL泛型函数以实现向量到数组的转换,代码如下:
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;
编译器不接受'length属性,报出如下错误:
" prefix of attribute length should be a discrete or physical type or subtype"
请问是否有可行的解决方法,还是我必须为每种类型重载函数?
错误原因
错误根源在于ret_type(c_ARRAY_LEN-1 downto 0)(element_size-1 downto 0)的约束方式:ret_type是未约束的数组类型(比如slv_arr是array(natural range <>) of std_logic_vector),而std_logic_vector本身也是未约束类型,编译器无法识别'length属性的合法前缀类型。
解决方法
方法一:完善泛型函数模板
通过将输入类型和返回数组类型都设为泛型参数,让编译器能正确识别类型属性,同时确保返回数组的元素类型与输入类型匹配:
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; -- 声明泛型函数模板 generic function f_to_arr_g (type elem_type; type arr_type) (arg : elem_type; element_size : positive) return arr_type; -- 实例化不同类型的转换函数 function f_slv_to_arr is new f_to_arr_g generic map (elem_type => std_logic_vector, arr_type => slv_arr); function f_unsigned_to_arr is new f_to_arr_g generic map (elem_type => unsigned, arr_type => unsigned_arr); function f_signed_to_arr is new f_to_arr_g generic map (elem_type => signed, arr_type => signed_arr); end package test; package body test is generic function f_to_arr_g (type elem_type; type arr_type) (arg : elem_type; element_size : positive) return arr_type is constant arg_len : positive := arg'length; constant arr_len : positive := arg_len / element_size; -- 用输入类型约束返回数组的元素长度 variable ret_val : arr_type(arr_len - 1 downto 0)(element_size - 1 downto 0); begin for i in 0 to arr_len - 1 loop ret_val(i) := arg(((i + 1) * element_size) - 1 downto i * element_size); end loop; return ret_val; end function f_to_arr_g; 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 : slv_arr(3 downto 0)(7 downto 0) := (x"AA", x"BB", x"CC", x"DD"); signal s_result_slv : slv_arr(3 downto 0)(7 downto 0); constant c_unsigned : unsigned(31 downto 0) := to_unsigned(16#AABBCCDD#, 32); constant c_expected_unsigned : unsigned_arr(3 downto 0)(7 downto 0) := (to_unsigned(16#AA#,8), to_unsigned(16#BB#,8), to_unsigned(16#CC#,8), to_unsigned(16#DD#,8)); signal s_result_unsigned : unsigned_arr(3 downto 0)(7 downto 0); begin process begin s_result_slv <= f_slv_to_arr(c_slv, 8); assert s_result_slv = c_expected_slv report "SLV Test failed" severity error; s_result_unsigned <= f_unsigned_to_arr(c_unsigned, 8); assert s_result_unsigned = c_expected_unsigned report "Unsigned Test failed" severity error; wait; end process; end architecture tb;
方法二:重载函数实现
如果追求代码直观性,可以为每种目标类型单独编写转换函数,编译器会根据输入类型自动匹配重载函数:
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; function f_to_arr(arg : std_logic_vector; element_size : positive) return slv_arr; function f_to_arr(arg : unsigned; element_size : positive) return unsigned_arr; function f_to_arr(arg : signed; element_size : positive) return signed_arr; end package test; package body test is function f_to_arr(arg : std_logic_vector; element_size : positive) return slv_arr is constant arg_len : positive := arg'length; constant arr_len : positive := arg_len / element_size; variable ret_val : slv_arr(arr_len - 1 downto 0)(element_size - 1 downto 0); begin for i in 0 to arr_len - 1 loop ret_val(i) := arg(((i + 1) * element_size) - 1 downto i * element_size); end loop; return ret_val; end function f_to_arr; function f_to_arr(arg : unsigned; element_size : positive) return unsigned_arr is constant arg_len : positive := arg'length; constant arr_len : positive := arg_len / element_size; variable ret_val : unsigned_arr(arr_len - 1 downto 0)(element_size - 1 downto 0); begin for i in 0 to arr_len - 1 loop ret_val(i) := arg(((i + 1) * element_size) - 1 downto i * element_size); end loop; return ret_val; end function f_to_arr; function f_to_arr(arg : signed; element_size : positive) return signed_arr is constant arg_len : positive := arg'length; constant arr_len : positive := arg_len / element_size; variable ret_val : signed_arr(arr_len - 1 downto 0)(element_size - 1 downto 0); begin for i in 0 to arr_len - 1 loop ret_val(i) := arg(((i + 1) * element_size) - 1 downto i * element_size); end loop; return ret_val; end function f_to_arr; end package body test;
总结
两种方案均可行:泛型函数能减少代码重复,适合需要扩展多种类型的场景;重载函数逻辑直观,调试和维护更简单,可根据实际需求选择。
内容的提问来源于stack exchange,提问作者Ahmad Zaklouta
相关产品推荐
相关产品推荐

