VHDL 初始化信号类型的最大值
VHDL initialize signal with maximum value of type
我有这样的定义:
subtype sample_t is signed(SAMPLE_WIDTH-1 downto 0);
现在在代码中我想将信号设置为 sample_t 除以 2 的最大值:
signal max_sample : sample_t;
max_sample <= to_signed(max_sample'<some attribute>/2,max_sample'LENGTH);
我查看了属性 sample_t'HIGH 和 sample_t'RIGHT 但这些似乎 return 数组的最高下标。
来自此列表:https://www.csee.umbc.edu/portal/help/VHDL/attribute.html
T'HIGH is the highest value of type T.
A'HIGH is the highest subscript of array A or constrained array type.
如何使用sample_t上的第一个定义?
评论者建议之一:
max_sample <= (max_sample'LEFT => '0', others => '1');
有效。但是这个:
max_sample <= (max_sample'LEFT => '0', others => '1')/2;
失败 "OTHERS is illegal aggregate choice for unconstrained target"。
为什么会出现这个错误?
在VHDL中,signed
是数组类型,不是整数。核心语言只知道它是 std_logic
个对象的集合。它作为数字的解释只是按照 numeric_std 库函数引入的约定,定义了 signed
的运算符和类型转换。因此,特定于整数的属性不适用于数组类型。
您最后一次除法尝试失败的原因是由于others
,形成被除数的聚合表达式还没有完全确定的范围。聚合仍然只是一个中间临时的,不能从 max_sample
中获取它的长度。这会阻止除法运算符编译。
如果您使用完全约束的范围,它将编译:
max_sample <= (max_sample'high => '0', max_sample'high-1 downto max_sample'low => '1') / 2;
或者如果您使用限定表达式:
max_sample <= sample_t'(max_sample'high => '0', others => '1') / 2;
另一种解决方案是子类型 integer
而不是使用 signed
。然后你可以以更完整的方式使用它:
constant SAMPLE_T_MAX : integer := 2**(SAMPLE_WIDTH-1)-1;
subtype sample_t is integer range -SAMPLE_T_MAX-1 to SAMPLE_T_MAX;
max_sample <= sample_t'high; -- Assuming that the "divide by 2" was just to avoid the sign bit
如果 sample_t_max
超过您的工具支持的最大整数大小(通常仍为 32 位,包括符号),这将不起作用。另外,出于实际原因,最好不要将整数类型用于合成后将暴露在顶层端口上的信号。
否则,您必须在对数字使用数组类型的限制范围内工作。您的选择是像上面那样使用位旋转或者直接计算类似于整数子类型的最大值:
constant SAMPLE_T_MAX : integer := 2**(sample_t'length-1)-1;
max_sample <= to_signed(SAMPLE_T_MAX, max_sample'length);
Kevin Thibedeau 接受的答案无法轻易与实际问题相协调(为什么会出现此错误?)。答案可以用VHDL标准来解释。
首先可以为问题构造一个Minimum, Complete, and Verifiable example:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
end entity;
architecture fum of foo is
constant SAMPLE_WIDTH: natural := 42; -- pick a number
subtype sample_t is signed(SAMPLE_WIDTH-1 downto 0);
signal max_sample : sample_t;
begin
-- max_sample <= (max_sample'LEFT => '0', others => '1'); -- analyzes
max_sample <= (max_sample'LEFT => '0', others => '1')/2; -- Doesn't analyze
end architecture;
因为我们在分析(编译)过程中处理语义规则,所以除了复制错误之外,示例不需要做任何事情。错误消息在 VHDL 中没有标准化,并且会因实现而异。
在聚合中使用其他选择的语义:
IEEE Std 1076-2008 9.3 聚合,9.3.3 数组聚合,第 7 段(部分):
The index range of an array aggregate that has an others choice shall be determinable from the context. That is, an array aggregate with an others choice shall appear only in one of the following contexts:
...
e) As a value expression in an assignment statement, where the target is a declared object (or member thereof), and either the subtype of the target is a fully constrained array subtype or the target is a slice name
这就是第一个例子(注释掉)分析的原因。 sample_t 是一个完全约束的子类型,参见 5. Types, 5.1 General the definition of fully constrained, para 6 (part):
A composite subtype is said to be fully constrained if:
-- It is an array subtype with an index constraint and the element subtype either is not a composite subtype or is a fully constrained composite type, or
...
其中 sample_t 元素基类型为 std_ulogic 且子类型具有索引约束。
回到第二个例子。
我们不满足规则 e),聚合不是赋值语句的值表达式,它是 IEEE 包中用于重载的“/”函数定义的除法运算符的操作数numeric_std:
-- Id: A.25
function "/" (L : UNRESOLVED_SIGNED; R : INTEGER) return UNRESOLVED_SIGNED;
-- Result subtype: UNRESOLVED_SIGNED(L'LENGTH-1 downto 0)
-- Result: Divides an UNRESOLVED_SIGNED vector, L, by an INTEGER, R.
-- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH.
(对于 numeric_std 的早期版本,参数和结果类型将是 SIGNED 而不是 UNRESOLVED_SIGNED,-2008 正式定义了如何定义复合类型驱动程序的解析函数。)
因为9.3.3第7段的规则是包容性的而不是排他性的,我们
需要找到一个允许我们使用聚合的规则,并且很容易识别:
i) As the operand of a qualified expression whose type mark denotes a fully constrained array subtype
我们可以使用限定表达式:
max_sample <= sample_t'(max_sample'LEFT => '0', others => '1')/2;
这样就分析(编译)成功了。
澄清分配给 max_sample 的值表达式是除以 2 的结果,它使用运算符重载并且谁的函数不是 return 约束子类型。 (UNRESOLVED_SIGNED 或 SIGNED 不受约束)。
存在包容性规则的原因是允许将值与聚合元素相关联的代码在分析时(编译时)确定。通过检查 VHDL 标准的先前修订版,您会发现包容性规则列表已得到扩展。
关于第二个例子的问题的答案:
max_sample <= (max_sample'LEFT => '0', others => '1')/2;
是在不知道上下文的子类型的情况下无法识别聚合的元素。
如果您要查看生成用于语义分析的抽象语法树的解析器的输出,赋值语句中右侧的表达式可以分层表示。 (11.6并发信号赋值语句,波形由一个或多个波形元素组成,见10.5.2简单信号赋值,10.5.2.1总则,一个波形元素可以包含一个值表达式,见10.5.2.2执行一个简单的赋值语句, 9. 表达式,9.1 通用 BNF。)
使用包含规则可以减少在分析期间遍历表达式层次结构和计算聚合(操作数)的子类型的需要,并且需要标准不需要的“/”函数的语义表征。您还可以构建无法在分析时通过表征轻松确定子类型的案例。结果是9.3.3 Array aggregates paragraph 7中找到的规则。
限定表达式直接提供子类型。
我有这样的定义:
subtype sample_t is signed(SAMPLE_WIDTH-1 downto 0);
现在在代码中我想将信号设置为 sample_t 除以 2 的最大值:
signal max_sample : sample_t;
max_sample <= to_signed(max_sample'<some attribute>/2,max_sample'LENGTH);
我查看了属性 sample_t'HIGH 和 sample_t'RIGHT 但这些似乎 return 数组的最高下标。
来自此列表:https://www.csee.umbc.edu/portal/help/VHDL/attribute.html
T'HIGH is the highest value of type T.
A'HIGH is the highest subscript of array A or constrained array type.
如何使用sample_t上的第一个定义?
评论者建议之一:
max_sample <= (max_sample'LEFT => '0', others => '1');
有效。但是这个:
max_sample <= (max_sample'LEFT => '0', others => '1')/2;
失败 "OTHERS is illegal aggregate choice for unconstrained target"。
为什么会出现这个错误?
在VHDL中,signed
是数组类型,不是整数。核心语言只知道它是 std_logic
个对象的集合。它作为数字的解释只是按照 numeric_std 库函数引入的约定,定义了 signed
的运算符和类型转换。因此,特定于整数的属性不适用于数组类型。
您最后一次除法尝试失败的原因是由于others
,形成被除数的聚合表达式还没有完全确定的范围。聚合仍然只是一个中间临时的,不能从 max_sample
中获取它的长度。这会阻止除法运算符编译。
如果您使用完全约束的范围,它将编译:
max_sample <= (max_sample'high => '0', max_sample'high-1 downto max_sample'low => '1') / 2;
或者如果您使用限定表达式:
max_sample <= sample_t'(max_sample'high => '0', others => '1') / 2;
另一种解决方案是子类型 integer
而不是使用 signed
。然后你可以以更完整的方式使用它:
constant SAMPLE_T_MAX : integer := 2**(SAMPLE_WIDTH-1)-1;
subtype sample_t is integer range -SAMPLE_T_MAX-1 to SAMPLE_T_MAX;
max_sample <= sample_t'high; -- Assuming that the "divide by 2" was just to avoid the sign bit
如果 sample_t_max
超过您的工具支持的最大整数大小(通常仍为 32 位,包括符号),这将不起作用。另外,出于实际原因,最好不要将整数类型用于合成后将暴露在顶层端口上的信号。
否则,您必须在对数字使用数组类型的限制范围内工作。您的选择是像上面那样使用位旋转或者直接计算类似于整数子类型的最大值:
constant SAMPLE_T_MAX : integer := 2**(sample_t'length-1)-1;
max_sample <= to_signed(SAMPLE_T_MAX, max_sample'length);
Kevin Thibedeau 接受的答案无法轻易与实际问题相协调(为什么会出现此错误?)。答案可以用VHDL标准来解释。
首先可以为问题构造一个Minimum, Complete, and Verifiable example:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
end entity;
architecture fum of foo is
constant SAMPLE_WIDTH: natural := 42; -- pick a number
subtype sample_t is signed(SAMPLE_WIDTH-1 downto 0);
signal max_sample : sample_t;
begin
-- max_sample <= (max_sample'LEFT => '0', others => '1'); -- analyzes
max_sample <= (max_sample'LEFT => '0', others => '1')/2; -- Doesn't analyze
end architecture;
因为我们在分析(编译)过程中处理语义规则,所以除了复制错误之外,示例不需要做任何事情。错误消息在 VHDL 中没有标准化,并且会因实现而异。
在聚合中使用其他选择的语义:
IEEE Std 1076-2008 9.3 聚合,9.3.3 数组聚合,第 7 段(部分):
The index range of an array aggregate that has an others choice shall be determinable from the context. That is, an array aggregate with an others choice shall appear only in one of the following contexts: ...
e) As a value expression in an assignment statement, where the target is a declared object (or member thereof), and either the subtype of the target is a fully constrained array subtype or the target is a slice name
这就是第一个例子(注释掉)分析的原因。 sample_t 是一个完全约束的子类型,参见 5. Types, 5.1 General the definition of fully constrained, para 6 (part):
A composite subtype is said to be fully constrained if:
-- It is an array subtype with an index constraint and the element subtype either is not a composite subtype or is a fully constrained composite type, or
...
其中 sample_t 元素基类型为 std_ulogic 且子类型具有索引约束。
回到第二个例子。
我们不满足规则 e),聚合不是赋值语句的值表达式,它是 IEEE 包中用于重载的“/”函数定义的除法运算符的操作数numeric_std:
-- Id: A.25
function "/" (L : UNRESOLVED_SIGNED; R : INTEGER) return UNRESOLVED_SIGNED;
-- Result subtype: UNRESOLVED_SIGNED(L'LENGTH-1 downto 0)
-- Result: Divides an UNRESOLVED_SIGNED vector, L, by an INTEGER, R.
-- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH.
(对于 numeric_std 的早期版本,参数和结果类型将是 SIGNED 而不是 UNRESOLVED_SIGNED,-2008 正式定义了如何定义复合类型驱动程序的解析函数。)
因为9.3.3第7段的规则是包容性的而不是排他性的,我们 需要找到一个允许我们使用聚合的规则,并且很容易识别:
i) As the operand of a qualified expression whose type mark denotes a fully constrained array subtype
我们可以使用限定表达式:
max_sample <= sample_t'(max_sample'LEFT => '0', others => '1')/2;
这样就分析(编译)成功了。
澄清分配给 max_sample 的值表达式是除以 2 的结果,它使用运算符重载并且谁的函数不是 return 约束子类型。 (UNRESOLVED_SIGNED 或 SIGNED 不受约束)。
存在包容性规则的原因是允许将值与聚合元素相关联的代码在分析时(编译时)确定。通过检查 VHDL 标准的先前修订版,您会发现包容性规则列表已得到扩展。
关于第二个例子的问题的答案:
max_sample <= (max_sample'LEFT => '0', others => '1')/2;
是在不知道上下文的子类型的情况下无法识别聚合的元素。
如果您要查看生成用于语义分析的抽象语法树的解析器的输出,赋值语句中右侧的表达式可以分层表示。 (11.6并发信号赋值语句,波形由一个或多个波形元素组成,见10.5.2简单信号赋值,10.5.2.1总则,一个波形元素可以包含一个值表达式,见10.5.2.2执行一个简单的赋值语句, 9. 表达式,9.1 通用 BNF。)
使用包含规则可以减少在分析期间遍历表达式层次结构和计算聚合(操作数)的子类型的需要,并且需要标准不需要的“/”函数的语义表征。您还可以构建无法在分析时通过表征轻松确定子类型的案例。结果是9.3.3 Array aggregates paragraph 7中找到的规则。
限定表达式直接提供子类型。