VHDL 中数组切片的使用
Use of Array Slices in VHDL
我正在尝试设计使用一些多维数组功能的可综合 VHDL 代码。 RTL 有一个 64 字深数组(称为 big_array_s,64 x 16 位)用于存储一些初始 LUT 值。还有一个 4 字深数组(small_array_s,4 x 16 位)用于设计。需要将大数组的一部分分配给小数组。以下代码片段对此进行了说明。
type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 64) of bit_vector(15 downto 0);
signal small_array_s : small_array;
signal big_array_s : big_array := init_array_func("test.dat");
init_array_func() 是一个 VHDL 函数,它使用来自“test.dat”ascii 文件的数据初始化 big_array_s。我卡住的部分是将 big_array_s 的一部分分配给 small_array_s。例如,
small_array_s <= big_array_s(0 to 3);
是我需要用 RTL 实现的。但是这种直接分配是不可能的,因为 LHS 和 RHS 是不同的数组类型。 我的问题是如何在 VHDL 中实现这种数组切片?
我可以使用的另一种方法是将 big_array 类型声明为 small_array 的数组。例如,
type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 15) of small_array;
signal small_array_s : small_array;
signal big_array_s : big_array;
在这种情况下,语句
small_array_s <= big_array_s(0);
会很顺利。但是考虑到综合支持,我对如何初始化数组big_array_s表示怀疑。
要进行数组切片,您可以使用生成语句一次复制一个 bit_vector(15 到 0)。
关于 3D 阵列,那么我使用 Xilinx Vivado 进行综合的经验很差。 Vivado 将其识别为 3D 数组,告诉您它不受支持并实现了一堆寄存器。
您的问题中没有声明多维 (3D) 数组类型。 big_array 的第二个声明有一个索引。
IEEE 标准 1976-2008
5.3.2 数组类型
5.3.2.1 一般
An array object is characterized by the number of indices (the dimensionality of the array); the type, position, and range of each index; and the type and possible constraints of the elements. The order of the indices is significant.
A one-dimensional array has a distinct element for each possible index value. A multidimensional array has a distinct element for each possible sequence of index values that can be formed by selecting one value for each index (in the given order). The possible values for a given index are all the values that belong to the corresponding range; this range of values is called the index range.
对于第一个方法,您可以声明子类型而不是独立类型。结果是它们是同一类型。
这样做没有风险,在 VHDL 中,赋值要求在右侧表达式中为左侧目标中的每个元素匹配一个元素。元素数量不匹配的代码可以分析和详细说明,但会导致 运行 时间错误报告边界不匹配(并且需要综合以遵守 VHDL 语义)。
创建工作 Minimal, Complete and Verifiable example 您的第一个代码段看起来像这样:
entity some_array is
end entity;
architecture fuu of some_array is
-- type small_array is array (0 to 3) of bit_vector(15 downto 0);
-- type big_array is array (0 to 64) of bit_vector(15 downto 0);
type some_array is array (natural range <>) of bit_vector(15 downto 0);
subtype small_array is some_array(0 to 3);
subtype big_array is some_array (0 to 64);
impure function init_array_func (init_file: in string) return
big_array is
use std.textio.all;
file big_array_file: text is in init_file;
variable file_line: line;
variable big_array_val: big_array;
begin
for i in big_array'range loop
readline (big_array_file, file_line);
read (file_line, big_array_val(i));
end loop;
return big_array_val;
end function;
function to_string (inp: bit_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: bit_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(bit'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
signal small_array_s : small_array;
signal big_array_s : big_array := init_array_func("test.dat");
begin
small_array_s <= big_array_s(0 to 3);
MONITOR:
process
begin
wait on small_array_s;
wait for 0 ns; -- not the default value;
for i in small_array_s'range loop
report "small_array_s(" & integer'image(i) & ") = " &
to_string(small_array_s(i));
end loop;
end process;
end architecture;
这给出了:
ghdl -r some_array
some_array.vhdl:47:13:@0ms:(report note): small_array_s(0) = 0000000000000000
some_array.vhdl:47:13:@0ms:(report
note): small_array_s(1) = 0000000000000001
some_array.vhdl:47:13:@0ms:(report note): small_array_s(2) = 0000000000000010
some_array.vhdl:47:13:@0ms:(report note): small_array_s(3) = 0000000000000011
其中正确显示了前四个值初始化为信号 big_array_s 已知 test.dat 内容。
这些函数与-2008 之前的VHDL 标准修订版兼容,并且是从其他示例中剪切、粘贴和编辑而来的。
请注意,init_array_func 函数需要一个 test.dat 文件,该文件包含至少 65 行有效值的 big_array 元素,这样的函数可以通过传递big_array 个元素(长度),返回 some_array 的任意子类型的值。
您还可以在具有相同维度(索引数)的数组类型与密切相关的元素类型之间进行显式类型转换:
9.3.6 类型转换
Explicit type conversions are allowed between closely related types. In particular, a type is closely related to itself. Other types are closely related only under the following conditions:
...
— Array types—Two array types are closely related if and only if the types have the same dimensionality and the element types are closely related
注意数组类型的元素类型必须遵守相同的要求,因为它是元素(子元素,这里是位类型)。
使用没有子类型声明的原始类型声明,唯一的其他更改是赋值:
small_array_s <= small_array(big_array_s(0 to 3));
其中类型转换操作数表达式big_array_s(0 to 3)与small_array_s同维且元素类型密切相关(都是bit_vector(15下到0 )).
并且通过这些更改,上面的代码分析、阐述和模拟了相同的结果。
请注意,类型转换还依赖于赋值语义,以确保赋值目标和右侧表达式的元素匹配:
14.7.3.4 信号更新
In order to update a signal during a given simulation cycle, the kernel process first determines the driving and effective values of that signal. The kernel process then updates the variable containing the driving value with the newly determined driving value. The kernel also updates the variable containing the current value of the signal with the newly determined effective value, as follows:
...
b) If S is a composite signal (including a slice of an array), the effective value of S is implicitly converted to the subtype of S. The subtype conversion checks that for each element of S there is a matching element in the effective value and vice versa. An error occurs if this check fails. The result of this subtype conversion is then assigned to the variable representing the current value of S.
关于子类型转换的一点意味着索引范围不必匹配,表达式和目标必须有匹配的元素。
我正在尝试设计使用一些多维数组功能的可综合 VHDL 代码。 RTL 有一个 64 字深数组(称为 big_array_s,64 x 16 位)用于存储一些初始 LUT 值。还有一个 4 字深数组(small_array_s,4 x 16 位)用于设计。需要将大数组的一部分分配给小数组。以下代码片段对此进行了说明。
type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 64) of bit_vector(15 downto 0);
signal small_array_s : small_array;
signal big_array_s : big_array := init_array_func("test.dat");
init_array_func() 是一个 VHDL 函数,它使用来自“test.dat”ascii 文件的数据初始化 big_array_s。我卡住的部分是将 big_array_s 的一部分分配给 small_array_s。例如,
small_array_s <= big_array_s(0 to 3);
是我需要用 RTL 实现的。但是这种直接分配是不可能的,因为 LHS 和 RHS 是不同的数组类型。 我的问题是如何在 VHDL 中实现这种数组切片?
我可以使用的另一种方法是将 big_array 类型声明为 small_array 的数组。例如,
type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 15) of small_array;
signal small_array_s : small_array;
signal big_array_s : big_array;
在这种情况下,语句
small_array_s <= big_array_s(0);
会很顺利。但是考虑到综合支持,我对如何初始化数组big_array_s表示怀疑。
要进行数组切片,您可以使用生成语句一次复制一个 bit_vector(15 到 0)。
关于 3D 阵列,那么我使用 Xilinx Vivado 进行综合的经验很差。 Vivado 将其识别为 3D 数组,告诉您它不受支持并实现了一堆寄存器。
您的问题中没有声明多维 (3D) 数组类型。 big_array 的第二个声明有一个索引。
IEEE 标准 1976-2008
5.3.2 数组类型
5.3.2.1 一般
An array object is characterized by the number of indices (the dimensionality of the array); the type, position, and range of each index; and the type and possible constraints of the elements. The order of the indices is significant.
A one-dimensional array has a distinct element for each possible index value. A multidimensional array has a distinct element for each possible sequence of index values that can be formed by selecting one value for each index (in the given order). The possible values for a given index are all the values that belong to the corresponding range; this range of values is called the index range.
对于第一个方法,您可以声明子类型而不是独立类型。结果是它们是同一类型。
这样做没有风险,在 VHDL 中,赋值要求在右侧表达式中为左侧目标中的每个元素匹配一个元素。元素数量不匹配的代码可以分析和详细说明,但会导致 运行 时间错误报告边界不匹配(并且需要综合以遵守 VHDL 语义)。
创建工作 Minimal, Complete and Verifiable example 您的第一个代码段看起来像这样:
entity some_array is
end entity;
architecture fuu of some_array is
-- type small_array is array (0 to 3) of bit_vector(15 downto 0);
-- type big_array is array (0 to 64) of bit_vector(15 downto 0);
type some_array is array (natural range <>) of bit_vector(15 downto 0);
subtype small_array is some_array(0 to 3);
subtype big_array is some_array (0 to 64);
impure function init_array_func (init_file: in string) return
big_array is
use std.textio.all;
file big_array_file: text is in init_file;
variable file_line: line;
variable big_array_val: big_array;
begin
for i in big_array'range loop
readline (big_array_file, file_line);
read (file_line, big_array_val(i));
end loop;
return big_array_val;
end function;
function to_string (inp: bit_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: bit_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(bit'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
signal small_array_s : small_array;
signal big_array_s : big_array := init_array_func("test.dat");
begin
small_array_s <= big_array_s(0 to 3);
MONITOR:
process
begin
wait on small_array_s;
wait for 0 ns; -- not the default value;
for i in small_array_s'range loop
report "small_array_s(" & integer'image(i) & ") = " &
to_string(small_array_s(i));
end loop;
end process;
end architecture;
这给出了:
ghdl -r some_array
some_array.vhdl:47:13:@0ms:(report note): small_array_s(0) = 0000000000000000
some_array.vhdl:47:13:@0ms:(report note): small_array_s(1) = 0000000000000001
some_array.vhdl:47:13:@0ms:(report note): small_array_s(2) = 0000000000000010
some_array.vhdl:47:13:@0ms:(report note): small_array_s(3) = 0000000000000011
其中正确显示了前四个值初始化为信号 big_array_s 已知 test.dat 内容。
这些函数与-2008 之前的VHDL 标准修订版兼容,并且是从其他示例中剪切、粘贴和编辑而来的。
请注意,init_array_func 函数需要一个 test.dat 文件,该文件包含至少 65 行有效值的 big_array 元素,这样的函数可以通过传递big_array 个元素(长度),返回 some_array 的任意子类型的值。
您还可以在具有相同维度(索引数)的数组类型与密切相关的元素类型之间进行显式类型转换:
9.3.6 类型转换
Explicit type conversions are allowed between closely related types. In particular, a type is closely related to itself. Other types are closely related only under the following conditions:
...
— Array types—Two array types are closely related if and only if the types have the same dimensionality and the element types are closely related
注意数组类型的元素类型必须遵守相同的要求,因为它是元素(子元素,这里是位类型)。
使用没有子类型声明的原始类型声明,唯一的其他更改是赋值:
small_array_s <= small_array(big_array_s(0 to 3));
其中类型转换操作数表达式big_array_s(0 to 3)与small_array_s同维且元素类型密切相关(都是bit_vector(15下到0 )).
并且通过这些更改,上面的代码分析、阐述和模拟了相同的结果。
请注意,类型转换还依赖于赋值语义,以确保赋值目标和右侧表达式的元素匹配:
14.7.3.4 信号更新
In order to update a signal during a given simulation cycle, the kernel process first determines the driving and effective values of that signal. The kernel process then updates the variable containing the driving value with the newly determined driving value. The kernel also updates the variable containing the current value of the signal with the newly determined effective value, as follows:
...
b) If S is a composite signal (including a slice of an array), the effective value of S is implicitly converted to the subtype of S. The subtype conversion checks that for each element of S there is a matching element in the effective value and vice versa. An error occurs if this check fails. The result of this subtype conversion is then assigned to the variable representing the current value of S.
关于子类型转换的一点意味着索引范围不必匹配,表达式和目标必须有匹配的元素。