如何在 if 条件下使用导入的枚举?

How to use imported enum in if condition?

在一个过程中,我需要根据其中一个端口是否具有特定值来做一些事情。该值在单独的包文件中的类型定义中定义。

比较应该在 'if-statement' 中完成,以获得简短易读的代码。

因为我需要确保没有混淆,所以我不能使用use work.pkg.all,而是使用pkg_name.enum_name


    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    use work.all;
    
    use work.SAWTOOTH_INNER_pkg.all;  -- other pkg which is needed. 
    
    entity SAWTOOTH_entity is
        PORT(
            p_clk : in std_logic;
            p_event_enum_next : in SAWTOOTH_pkg.in_event_enum
        );
    end entity;

    architecture arch of SAWTOOTH_entity is
    
    begin
        process(p_clk)
        begin
            if rising_edge(p_clk) then              
                
                -- Throws error. Modelsim says 'no feasable entry for /='
                if (p_event_enum_next /= SAWTOOTH_pkg.event_enum_empty) then
                    -- do something
                end if;
                
                -- Does the same but compiles without errors. But it is much longer.
                case p_event_enum_next is
                    when  SAWTOOTH_pkg.event_enum_empty =>
                        -- do nothing
                    when others =>  
                        -- do something
                end case;
            end if;
        end process;        
    end architecture;

已编辑:更多信息:

确切错误:

** Error: C:\UsersDIAC\Desktop\ModelSimWS\Bug.vhd(25): (vcom-1581) No feasible entries for infix operator '/='.
** Error: C:\UsersDIAC\Desktop\ModelSimWS\Bug.vhd(25): Type error resolving infix expression "/=" as type std.STANDARD.BOOLEAN.

包裹: SAWTOOTH_INNER_PKG:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    use work.all;

    package SAWTOOTH_INNER_pkg is
            
            TYPE in_event_enum is (event_enum_empty, event_enum_START, event_enum_STOP, event_enum_REQ, event_enum_CONFIG);
            TYPE buffer_event_type is array (0 to 3) of in_event_enum;
            

                    
     end SAWTOOTH_INNER_pkg;

SAWTOOTH_PKG:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.all;

package SAWTOOTH_pkg is
    
    TYPE in_event_enum is (event_enum_empty, event_enum_CONFIG, event_enum_START, event_enum_STOP);
    TYPE buffer_event_type is array (0 to 3) of in_event_enum;

                
 end SAWTOOTH_pkg;


问题中声称的包 SAWTOOTH_pkg 声明存在缺陷,因为当问题文本说 SAWTOOTH_pkg 时,声明显示为 SAWTOOTH_INNER_pkg:

SAWTOOTH_PKG:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    use work.all;

    package SAWTOOTH_INNER_pkg is
            
            TYPE in_event_enum is (event_enum_empty, event_enum_START, event_enum_STOP, event_enum_REQ, event_enum_CONFIG);
            TYPE buffer_event_type is array (0 to 3) of in_event_enum;
            

                    
     end SAWTOOTH_INNER_pkg;

出于最小、完整和可验证示例的目的,这两个包除了包名称外可以相同,因此包 SAWTOOTH_pkg 的包名称应为 SAWTOOTH_pkg(在两个地方) 代替 SAWTOOTH_INNER_pkg.

预定义运算符是在类型声明之后立即隐式声明的。这意味着通过所选名称使类型声明可见不会使运算符声明可见。

IEEE 标准 1076-2008
9.2 运算符
9.2.3 关系运算符

The equality and inequality operators (= and /=) are defined for all types other than file types and protected types. The equality operator returns the value TRUE if the two operands are equal and returns the value FALSE otherwise. The inequality operator returns the value FALSE if the two operands are equal and returns the value TRUE otherwise.

该标准在 4.5 子程序重载、4.5.1 概述、4.5.2 运算符重载小节中包括一种提供重载子程序和运算符的机制(“指示符为运算符符号的函数的声明用于重载运算符。运算符符号的字符序列应为9.2."中定义的运算符类和4.5.3签名中的运算符之一。这些可用于重载新类型的运算符,例如 枚举类型 (5.2 标量类型 5.2.1 常规)in_event_enum.

12.5 重载决议的上下文

12.5 重载决议的上下文

Overloading is defined for names, subprograms, and enumeration literals.

For overloaded entities, overload resolution determines the actual meaning that an occurrence of an identifier or a character literal has whenever the visibility rules have determined that more than one meaning is acceptable at the place of this occurrence; overload resolution likewise determines the actual meaning of an occurrence of an operator or basic operation (see 5.1).

这里的实体指的是命名实体,而不是实体声明所声明的外部块。

所有这些都基于 12.3 可见性:

For each identifier and at each place in the text, the visibility rules determine a set of declarations (with this identifier) that define the possible meanings of an o ccurrence of the identifier. A declaration is said to be visible at a given place in the text when, according to the visibility rules, the declaration defines a possible meaning of this occurrence. The following two cases arise in determining the meaning of such a declaration:

— The visibility rules determine at most one possible meaning. In such a case, the visibility rules are sufficient to determine the declaration defining the meaning of the occurrence of the identifier, or in the absence of such a declaration, to determine that the occurrence is not legal at the given point.

— The visibility rules determine more than one possible meaning. In such a case, the occurrence of the identifier is legal at this point if and only if exactly one visible declaration is acceptable for the overloading rules in the given context or all visible declarations denote the same named entity.

vcom-1581 错误告诉我们未满足第一种情况没有运算符重载声明(由“/=”指定)可见 returns 一个布尔值并且参数基类型为 in_event_enum.

根据您的问题,我们可以通过禁止您使用的子句使包的声明直接可见,没有提供推理,或者我们可以通过选择使声明可见(这违反了问题要求“比较应该在 'if-statement' 中完成,以获得简短易读的代码。” 选定的名称可以用作函数调用的前缀,但不能用作运算符,并使用指示符作为函数调用可能满足也可能不满足要求。(它只是通过前缀、包围参数的圆括号和指定运算符符号的双引号来延长。)我们已经可以看到您尝试 'shorten' if 语句条件使用 use 子句 use work.all; 使在工作库中找到的包声明直接可见。通常使用这样的 use 子句会被高级 VHDL 用户认为是笨拙的,它实际上需要您扫描回使用子句来理解可见性是如何产生的

那么有没有办法让预定义不等运算符的隐式声明直接可见(避免函数调用的前缀)?

VHDL 支持使用别名(6.6 别名声明),其中 non-object 别名 在其声明中使用签名来提供信息以满足 12.3 的第一种情况上面提到的(在包 SAWTOOTH_pkg 中找到的每个类型声明,对 SAWTOOTH_pkg."/=" 的引用都会与第二种情况发生冲突)。

所以我们的别名声明可以像

architecture arch of SAWTOOTH_entity is
    alias "/=" is work.sawtooth_pkg."/="
        [work.sawtooth_pkg.in_event_enum,
         work.sawtooth_pkg.in_event_enum return boolean];
begin  
    process(p_clk)
    begin
        if rising_edge(p_clk) then              
            
            -- Throws error. Modelsim says 'no feasable entry for /='
            if (p_event_enum_next /= SAWTOOTH_pkg.event_enum_empty) then
                -- do something
            end if;
            

并且可以作为体系结构声明项制作,或者因为不等运算符仅在流程声明中使用,所以在流程声明部分。

在运算符指示符直接可见的情况下,二级设计实体(体系结构)进行分析(当问题提供最小、完整且可验证的示例时,同时提供两个包声明)。

还有声明范围的概念(12.2 声明范围)。如果禁止使用使包 SAWTOOTH_pkg 中的所有声明直接可见的 use 子句是由于包 SAWTOOTH_INNER_pkg 中出现相同的声明,您可以利用没有声明的内部声明区域来自包 SAWTOOTH_INNER_pkg 的依赖使用 use 子句使来自包 SAWTOOTH_pkg 的声明直接可见:

begin  
    process (p_clk)
        use work.SAWTOOTH_pkg.all;
    begin
        if rising_edge(p_clk) then              
            
            -- Throws error. Modelsim says 'no feasable entry for /='
            if p_event_enum_next /= event_enum_empty then
                -- do something
            end if;

这在这里也适用,这可能是也可能不是示例过于 最小化 的结果。一个过程语句是一个内部声明区域,它允许任何声明的出现也被所有 use 子句可见,其范围包括这个地方被内部声明区域中的 use 子句可见的声明隐藏(参见 12.4 Use 子句).

问题示例代码不排除通过在外部声明区域中隐藏声明来使用内部声明区域来划分可见性。

不依靠这两种方法使不等式运算符重载的声明直接可见将依赖于选定的名称并做不满足 if 语句的最短可读代码主观标准:

architecture arch of SAWTOOTH_entity is
    -- alias "/=" is work.sawtooth_pkg."/="
    --     [work.sawtooth_pkg.in_event_enum,
    --    work.sawtooth_pkg.in_event_enum return boolean];
begin  
    process (p_clk)
        -- use work.sawtooth_pkg.all;
    begin
        if rising_edge(p_clk) then              
            
            -- Throws error. Modelsim says 'no feasable entry for /='
            -- if p_event_enum_next /= sawtooth_pkg.event_enum_empty then
            --     -- do something
            -- end if;
            if sawtooth_pkg."/="(p_event_enum_next, 
                                 sawtooth_pkg.event_enum_empty) then
                -- do something
            end if;
            
            -- Does the same but compiles without errors. But it is much longer.
            case p_event_enum_next is
                when  SAWTOOTH_pkg.event_enum_empty =>
                    -- do nothing
                when others =>  
                    -- do something
            end case;
        end if;
    end process;        
end architecture;