代码之家  ›  专栏  ›  技术社区  ›  Matthew Taylor

运算符没有函数声明

  •  0
  • Matthew Taylor  · 技术社区  · 6 年前

    我收到此错误消息:

    vhd:16:22:运算符“+”没有函数声明

    在这一行:

        Z <= unsigned(X) + resize(unsigned(Y),X'length);
    

    使用此代码:

    library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.numeric_std.all;
    
    entity MCVE is
    end entity MCVE;
    
    architecture MCVE of MCVE is
      signal X, Z : std_logic_vector(15 downto 0);
      signal Y    : std_logic_vector(7 downto 0);
    begin
    
      process    
      begin
        Z <= unsigned(X) + resize(unsigned(Y),X'length);
      end process;
    
    end architecture MCVE;
    

    https://www.edaplayground.com/x/2LBg

    我不明白为什么。

    2 回复  |  直到 6 年前
        1
  •  1
  •   user1155120    6 年前

    而giwrgos rizakos原创 question 关于调整大小,关于运算符和函数重载可见性的问题和答案由来已久(这里没有运算符“+”的函数声明)。

    在对这些问题和答案进行搜索之后,此答案尝试提供一个问题和答案对,该对可用于消除基于在解释流中提供权威参考的未来重复问题。

    问题从可见性开始:

    12.3能见度

    文本中给定位置出现标识符的含义由可见性规则定义,在重载声明的情况下,也由重载规则定义。本子条款中考虑的标识符包括除保留字或表示预定义属性的属性指示符以外的任何标识符。本子条款中考虑的地方是发生词法元素(如标识符)的地方。本子条款中考虑的重载声明是子程序和枚举文本的重载声明。

    对于每个标识符和文本中的每个位置,可见性规则确定一组声明(使用此标识符),这些声明定义了标识符出现的可能含义。当根据可见性规则,声明定义此事件的可能含义时,声明称为在文本中的给定位置可见。在确定这种声明的含义时出现了以下两种情况:

    可见性规则最多决定一个可能的含义。在这种情况下,可见性规则足以确定定义标识符出现的含义的声明,或者在没有这样的声明的情况下,足以确定出现在给定点上是不合法的。
    可见性规则决定了多个可能的含义。在这种情况下,如果且仅当给定上下文中的重载规则只接受一个可见声明或所有可见声明表示同一命名实体时,此时标识符的出现才是合法的。

    它涉及重载子程序:

    4.5.2操作员超载

    一个函数的声明,其标志是一个运算符符号,用来重载一个运算符。运算符符号的字符序列应为9.2中定义的运算符类中的运算符之一。

    一元运算符的子程序规范应具有单个参数,除非子程序规范是受保护类型的方法(见5.6.2)。在后一种情况下,子程序规范没有参数。二进制运算符的子程序规范应具有两个参数,除非子程序规范是受保护类型的方法,在这种情况下,子程序规范应具有单个参数。如果二进制运算符的子程序规范有两个参数,则对于此运算符的每次使用,第一个参数与左操作数关联,第二个参数与右操作数关联。

    运算符重载被定义为子程序并使用子程序重载规则:

    4.5子程序重载

    4.5.1概述

    如果且仅当两个形式参数列表具有相同数量的参数,并且如果在每个参数位置对应的参数具有相同的基类型,则称它们具有相同的参数类型配置文件。如果且仅当两个子程序都具有相同的参数类型配置文件,并且如果两者都是具有相同结果基类型的函数,或者两者都不是函数,则称两个子程序具有相同的参数和结果类型配置文件。

    作为一个segue子程序,可以用签名来描述为一个速记:

    4.5.3签名

    签名根据参数和结果类型配置文件区分重载子程序和重载枚举文本。签名可用于子程序实例化声明、属性名、实体指示符或别名声明。

    签名:= [ [键入标记{,键入标记}][ 返回 类型标记 ]

    (注意,首括号和末括号是签名语法的一部分,并不表示产品的整个右侧是可选的。)签名被认为与给定子程序的参数和结果类型配置文件匹配,前提是,以下所有条件均成立:

    保留字返回之前的类型标记数(如果有)与子程序的形式参数数匹配。
    在每个参数位置,由签名的类型标记表示的基类型与子程序相应形式参数的基类型相同。
    如果保留字返回存在,则子程序为函数,签名中保留字后面的类型标记的基类型与函数返回类型的基类型相同,或者保留字返回不存在,子程序为过程。

    下面是一个例子:

    Z <= unsigned(X) + resize(unsigned(Y),X'length);
    

    可以用签名来描述。

    z被声明为std_logic_vector类型。“+”的左操作数是x,它是主题类型转换为无符号(9.3.6中给出的规则,两种数组类型,相同的元素类型)。右操作数是使用 [unsigned, natural, return unsigned] 通过重载分辨率在包numeric\u std中找到:

    12.5过载解决的背景

    重载是为名称、子程序和枚举文本定义的。

    在考虑对完整上下文的可能解释时,所考虑的唯一规则是语法规则、范围和可见性规则以及以下形式规则:

    a)要求名称或表达式具有某种类型或与另一名称或表达式具有相同类型的任何规则。
    b)任何要求名称或表达式类型为某一类类型的规则;同样,任何要求某一类型为离散、整数、浮点、物理、通用或字符类型的规则。

    e)解决重载子程序调用的规则;通用表达式的隐式转换的规则;具有通用类型边界的离散范围的解释的规则;前缀表示子程序的扩展名的解释的规则;以及在子程序实例化声明中命名的子程序,以表示未实例化的子程序。

    通过use use子句使函数可见,并使数值形式的声明可见:

    12.4使用条款

    use子句实现了通过选择可见的声明的直接可见性。

    在未找到函数声明的示例上执行相同的重载解析。找不到“+”的函数声明 [unsigned, unsigned return std_logic_vector] 其中,返回值必须与上面的std_logic_vector(a)规则)类型匹配。

    正如马修·泰勒所指出的,你可以在右手边修改作业 表达 按类型转换为标准逻辑矢量:

    Z <= std_logic_vector(unsigned(X) + resize(unsigned(Y),X'length));
    

    而不需要resize函数调用的原因可以通过引用ieee包numeric-std中的“+”`[unsigned,unsigned return unsigned]的函数声明来权威地显示。 numeric_std-body.vhdl ,在 1076-2008 downloads.zip 这是-2008标准的一部分):

      -- Id: A.3R
      function "+" (L : UNRESOLVED_UNSIGNED; R : STD_ULOGIC)
        return UNRESOLVED_UNSIGNED
      is
        variable XR : UNRESOLVED_UNSIGNED(L'length-1 downto 0) := (others => '0');
      begin
        XR(0) := R;
        return (L + XR);
      end function "+";
    

    要解释该命令,需要在numeric_std.vhdl中声明unsigned(也可以在上述zip文件中找到):

       type UNRESOLVED_UNSIGNED is array (NATURAL range <>) of STD_ULOGIC;
    
    
        subtype UNSIGNED is (resolved) UNRESOLVED_UNSIGNED;
    

    它是提供元素解析函数名的unresolved_unsigned的子类型。标准中解释了分辨率函数:

    4.6分辨率函数

    解析函数是定义如何将给定信号的多个源的值解析为该信号的单个值的函数。解析函数通过在信号声明或信号子类型声明中包含解析函数的名称,与需要解析的信号相关联。具有相关分辨率函数的信号称为分辨率信号(见6.4.2.3)。

    子类型声明语法可能需要找到解析函数:

    6.3子类型声明

    子类型声明::=
    子类型标识符是子类型指示;

    子类型指示::=
    [分辨率显示]类型标记[约束]

    分辨率显示:=
    决议案 函数名(元素分辨率)

    元素分辨率::=数组元素分辨率记录分辨率

    解析的函数可以在std_logic_1164包声明中找到(在上述zip文件中,作为标准的一部分提供)。

    分辨率是一个模拟问题,见14.7模型的执行,特别是14.7.3信号值的传播及其子条款,其中分辨率应用于信号。

    (关于这里,你可以看到为什么会有很多不完整的答案,但并不排除未来的问题。在标准中寻找答案需要对主题的理解,它的主要受众是工具实现者和高级用户,其中vhdl语法和语义的定义非常简洁,允许它用作正式的表示法。)

        2
  •  2
  •   Matthew Taylor    6 年前

    错误信息非常清楚。运算符“+”没有可以添加两个 unsigned 一起返回 std_logic_vector 。在包裹里 numeric_std ,但是有一个operator“+”可以添加两个 未签名的 一起返回一个 未签名的 .

    所以,如果添加另一个类型转换以将添加的结果转换回 标准逻辑向量 编译器可以选择返回 未签名的 .

    Z <= std_logic_vector(unsigned(X) + unsigned(Y));
    

    超载 只有当函数、过程或运算符正好有一个匹配项时才有效。如果少于一个,编译器就没有可供选择的版本;如果多于一个,编译器就不知道该选择哪一个,并且存在一个需要解决的歧义。

    实际上,您不需要调整大小 Y :只要其中一个操作数的宽度与结果的宽度相同,“+”运算符就可以使用。

    https://www.edaplayground.com/x/4VJE