【问题标题】:VHDL initialize signal with maximum value of typeVHDL用类型的最大值初始化信号
【发布时间】:2018-09-07 22:01:52
【问题描述】:

我有这个定义:

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 但它们似乎返回了数组的最高下标。

从此列表中: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 是不受约束的目标的非法聚合选择”而失败。

为什么会出现这个错误?

【问题讨论】:

  • 谢谢,如果您将评论添加为回复,我可以将问题标记为已回答。
  • @DinneBosman:你不需要除法,你可以简单地利用二进制数的位置特性。如果最大值是 (sign=0)11...1,那么(那个数字是奇数)一半落在 (sign=0)01...1 或 (sign=0)10...0 之间
  • 您也可以完全依赖 sample_t 声明,允许 max_sample 为常量 constant max_sample: sample_t := SHIFT_RIGHT(sample_t'(sample_t'LEFT =&gt; '0', others =&gt; '1'), 1);constant max_sample: sample_t := sample_t'(sample_t'LEFT =&gt; '0', others =&gt; '1')/2;
  • 注意:除以 2 与右移 1 相同...可能会提示您如何简化事情。

标签: vhdl fpga


【解决方案1】:

在 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);

【讨论】:

    【解决方案2】:

    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 段(部分):

    具有其他选择的数组聚合的索引范围应由上下文确定。也就是说,具有其他选择的数组聚合应仅出现在以下上下文之一中: ...

    e) 作为赋值语句中的值表达式,其中目标是声明的对象(或其成员),并且目标的子类型是完全约束的数组子类型或目标是切片名称

    这就是第一个示例(已注释掉)分析的原因。 sample_t 是一个完全约束的子类型,见 5. 类型,5.1 一般完全约束的定义,第 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 的结果,它使用运算符重载并且 who 的函数不返回受约束的子类型。 (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 段中的规则。

    限定表达式直接提供子类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 1970-01-01
      • 2021-11-25
      相关资源
      最近更新 更多