You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 01:40:57