创建一个通用数组,其元素在 VHDL 中的宽度增加
Creating a generic array whose elements have increasing width in VHDL
是否可以创建一个数组,其元素的宽度不断增加。例如,假设 X 是一个包含 10 个元素的数组;
X(0) 是 std_logic_vector(3 下降到 0)
X(1) 是 std_logic_vector(4 下降到 0)
...
X(9) 是 std_logic_vector(12 下降到 0)
不,VHDL 数组中的所有元素都是相同的,因此如果元素是 std_logic_vector
,它们将具有相同的宽度(长度)。
但在综合中,如果您声明具有最大所需长度的元素,然后根本不在某些元素上使用高位,那么任何像样的综合工具都会减少实现中的实际大小。
如果您的问题仅与模拟有关,那么您可以声明一个指向std_logic_vector
的访问类型(指针)数组,然后指向的std_logic_vectors
可以有不同的长度。
没有按照您的要求解决您的问题的解决方案,但除了 Morten 的回答之外,我将尝试提供另一种解决方案。
我将使用您的示例:
X 是一个包含 10 个元素的数组,每个元素的长度从 4 增加到 13。
我的解决方案将所有向量放入一个一维向量中,并简化了对具有函数的位的访问。以下几行试图展示位的组织方式。
--bit 84 bit 19 bit 13 bit 8 bit 4 bit 0
[X(9)(12..0)]...[X(4)(7..0)][X(3)(6..0)][X(2)(5..0)][X(1)(4..0)][X(0)(3..0)]
循序渐进:
创建整数向量 (T_INTVEC) 或更多约束自然数向量 (T_NATVEC)。
type T_NATVEC is array (NATURAL range <>) of NATURAL;
创建此类型的实例并用您的数组长度填充它。
constant MY_BITS : T_NATVEC := (
0 => 4,
1 => 5,
[...]
9 => 13
);
或者用函数计算:
function generateVectorLengths return T_NATVEC is
constant Count : NATURAL := 10;
constant Startlength : NATURAL := 4;
variable Result : T_NATVEC(0 to Count - 1);
begin
for i in 0 to Count - 1 loop
Result(i) := StartLength + i;
end loop;
return Result;
end function;
constant MY_BITS : T_NATVEC := generateVectorLengths;
创建一些辅助函数来:
对所有向量长度求和
function isum(vec : T_NATVEC) return NATURAL is
variable Result : NATURAL := 0;
begin
for i in vec'range loop
Result := Result + vec(i);
end loop;
return Result;
end function;
获取嵌入向量的上限
function low(VectorBits : T_POSVEC; index : NATURAL) return NATURAL is
variable pos : NATURAL := 0;
begin
for i in VectorBits'low to index - 1 loop
pos := pos + VectorBits(i);
end loop;
return pos;
end function;
获取嵌入向量的下界
function high(VectorBits : T_POSVEC; index : NATURAL) return NATURAL is
variable pos : NATURAL := 0;
begin
for i in lenvec'low to index loop
pos := pos + VectorBits(i);
end loop;
return pos - 1;
end function;
获取整个嵌入向量
function getSubvector(vector : STD_LOGIC_VECTOR; VectorBits : T_POSVEC; index : NATURAL) return STD_LOGIC_VECTOR is
begin
return vector(high(VectorBit, index) downto low(VectorBit, index));
end function;
给大向量分配一个子向量
procedure assignSubVector(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant VectorBits : T_POSVEC; constant index : NATURAL) is
begin
for i in slv'range loop
slm(high(VectorBit, index) downto low(VectorBit, index)) <= slv;
end loop;
end procedure;
所以现在你可以使用这个函数来创建一个一维向量,如下所示:
signal Vector_1 : STD_LOGIC_VECTOR(isum(MY_BITS) - 1 downto 0) := (others => 'Z');
-- initialize this vector with 'Z'; this is needed for simulation!
您可以将此向量与高低函数或 forlast 辅助函数一起使用(参见函数 getSubvector
)。
signal Vector_X3 : STD_LOGIC_VECTOR(MY_BITS(3) - 1 downto 0);
...
Vector_X3 <= getSubvector(My_Vector, MY_BITS, 3);
最后可以用assignSubVector
给大的赋值向量:
signal Vector_X4 : STD_LOGIC_VECTOR(MY_BITS(4) - 1 downto 0);
...
assignSubvector(My_Vector, Vector_X4, MY_BITS, 4);
如果您发现这些用于向量和矩阵的位移动和扭曲函数很有趣,这里是 complete file :)。
是否可以创建一个数组,其元素的宽度不断增加。例如,假设 X 是一个包含 10 个元素的数组;
X(0) 是 std_logic_vector(3 下降到 0)
X(1) 是 std_logic_vector(4 下降到 0)
...
X(9) 是 std_logic_vector(12 下降到 0)
不,VHDL 数组中的所有元素都是相同的,因此如果元素是 std_logic_vector
,它们将具有相同的宽度(长度)。
但在综合中,如果您声明具有最大所需长度的元素,然后根本不在某些元素上使用高位,那么任何像样的综合工具都会减少实现中的实际大小。
如果您的问题仅与模拟有关,那么您可以声明一个指向std_logic_vector
的访问类型(指针)数组,然后指向的std_logic_vectors
可以有不同的长度。
没有按照您的要求解决您的问题的解决方案,但除了 Morten 的回答之外,我将尝试提供另一种解决方案。
我将使用您的示例: X 是一个包含 10 个元素的数组,每个元素的长度从 4 增加到 13。
我的解决方案将所有向量放入一个一维向量中,并简化了对具有函数的位的访问。以下几行试图展示位的组织方式。
--bit 84 bit 19 bit 13 bit 8 bit 4 bit 0
[X(9)(12..0)]...[X(4)(7..0)][X(3)(6..0)][X(2)(5..0)][X(1)(4..0)][X(0)(3..0)]
循序渐进:
创建整数向量 (T_INTVEC) 或更多约束自然数向量 (T_NATVEC)。
type T_NATVEC is array (NATURAL range <>) of NATURAL;
创建此类型的实例并用您的数组长度填充它。
constant MY_BITS : T_NATVEC := ( 0 => 4, 1 => 5, [...] 9 => 13 );
或者用函数计算:
function generateVectorLengths return T_NATVEC is constant Count : NATURAL := 10; constant Startlength : NATURAL := 4; variable Result : T_NATVEC(0 to Count - 1); begin for i in 0 to Count - 1 loop Result(i) := StartLength + i; end loop; return Result; end function; constant MY_BITS : T_NATVEC := generateVectorLengths;
创建一些辅助函数来:
对所有向量长度求和
function isum(vec : T_NATVEC) return NATURAL is variable Result : NATURAL := 0; begin for i in vec'range loop Result := Result + vec(i); end loop; return Result; end function;
获取嵌入向量的上限
function low(VectorBits : T_POSVEC; index : NATURAL) return NATURAL is variable pos : NATURAL := 0; begin for i in VectorBits'low to index - 1 loop pos := pos + VectorBits(i); end loop; return pos; end function;
获取嵌入向量的下界
function high(VectorBits : T_POSVEC; index : NATURAL) return NATURAL is variable pos : NATURAL := 0; begin for i in lenvec'low to index loop pos := pos + VectorBits(i); end loop; return pos - 1; end function;
获取整个嵌入向量
function getSubvector(vector : STD_LOGIC_VECTOR; VectorBits : T_POSVEC; index : NATURAL) return STD_LOGIC_VECTOR is begin return vector(high(VectorBit, index) downto low(VectorBit, index)); end function;
给大向量分配一个子向量
procedure assignSubVector(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant VectorBits : T_POSVEC; constant index : NATURAL) is begin for i in slv'range loop slm(high(VectorBit, index) downto low(VectorBit, index)) <= slv; end loop; end procedure;
所以现在你可以使用这个函数来创建一个一维向量,如下所示:
signal Vector_1 : STD_LOGIC_VECTOR(isum(MY_BITS) - 1 downto 0) := (others => 'Z'); -- initialize this vector with 'Z'; this is needed for simulation!
您可以将此向量与高低函数或 forlast 辅助函数一起使用(参见函数
getSubvector
)。signal Vector_X3 : STD_LOGIC_VECTOR(MY_BITS(3) - 1 downto 0); ... Vector_X3 <= getSubvector(My_Vector, MY_BITS, 3);
最后可以用
assignSubVector
给大的赋值向量:signal Vector_X4 : STD_LOGIC_VECTOR(MY_BITS(4) - 1 downto 0); ... assignSubvector(My_Vector, Vector_X4, MY_BITS, 4);
如果您发现这些用于向量和矩阵的位移动和扭曲函数很有趣,这里是 complete file :)。