我有这个定义:
子类型sample_t被签名(SAMPLE_WIDTH-1 downto 0);现在在代码中我想将信号设置为sample_t的最大值除以2:
signal max_sample:sample_t;
…
在VHDL中, signed 是数组类型,而不是整数。核心语言只知道它是一个集合 std_logic 对象。它的解释只是按照定义运算符和类型转换的numeric_std库函数引入的约定 signed 。因此,整数特定属性不适用于数组类型。
signed
std_logic
你最后一次分裂尝试失败的原因是形成股息的汇总表达式还没有完全确定的范围 others 。聚合仍然只是一个中间临时的,无法从中获取长度 max_sample 。这可以防止除法运算符编译。
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 。然后你可以用更复杂的方式使用它:
integer
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位,包括符号。此外,出于实际原因,最好不要将整数类型用于合成后将在顶级端口上公开的信号。
sample_t_max
否则,您必须在数值类型中使用数组的限制。您的选择是如上所述诉诸于twiddling或者直接计算与整数子类型类似的最大值:
constant SAMPLE_T_MAX : integer := 2**(sample_t'length-1)-1; max_sample <= to_signed(SAMPLE_T_MAX, max_sample'length);
Kevin Thibedeau接受的答案不能轻易与实际问题相协调( 为什么这个错误? )。答案可以用VHDL标准来解释。
首先是 最小,完整和可验证的示例 可以为问题构建:
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段(部分):
具有其他选择的数组聚合的索引范围应该可以从上下文中确定。也就是说,具有其他选择的数组聚合应仅出现在以下某个上下文中: ... e)作为赋值语句中的值表达式,其中目标是声明的对象(或其成员),并且目标的子类型是完全约束的数组子类型或目标是切片名称
具有其他选择的数组聚合的索引范围应该可以从上下文中确定。也就是说,具有其他选择的数组聚合应仅出现在以下某个上下文中: ...
e)作为赋值语句中的值表达式,其中目标是声明的对象(或其成员),并且目标的子类型是完全约束的数组子类型或目标是切片名称
这就是第一个例子(注释掉)分析的原因。 sample_t是一个完全约束的子类型,参见5. Types,5.1 General的定义 完全受约束 ,第6段(部分):
据说复合子类型 完全受约束 如果: - 它是一个带索引约束的数组子类型,元素子类型不是复合子类型,也不是完全约束的复合类型,或者 ...
据说复合子类型 完全受约束 如果:
- 它是一个带索引约束的数组子类型,元素子类型不是复合子类型,也不是完全约束的复合类型,或者 ...
其中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)作为限定表达式的操作数,其类型标记表示完全约束的数组子类型
我们可以使用限定的表达式:
max_sample <= sample_t'(max_sample'LEFT => '0', others => '1')/2;
这成功地分析(编译)。
澄清分配给max_sample的值表达式是除以2的结果,它使用运算符重载并且其函数不返回约束子类型。 (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阵列聚合第7段中的规则。
限定表达式直接提供子类型。