代码之家  ›  专栏  ›  技术社区  ›  CJC

VHDL:使用聚合其他对象为多个数据类型赋值

  •  1
  • CJC  · 技术社区  · 8 年前

    考虑到我有一种

    type sFoo is record 
        A : std_logic;
        B : std_logic_vector(2 downto 0);
        C : std_logic;
    end record;
    

    我有向量形式的sFoo,sFoo\u向量

    type sFoo_Vector is array (natural range <>) of sFoo;
    

    和空常量cNull\u Foo

    constant cNull_Foo: sFoo := (A => '0', B => (others => '0'), C => '0');
    

    此外,我在sBar中创建了sFoos记录

    type sBar is record 
        A   : sFoo; 
        B   : sFoo;
        C   : sFoo;
    end record; 
    

    我可以初始化一个常量,如:

    constant Var1 : sBar := (others => cNull_Foo);
    

    但是,如果我创建另一个记录sBaz,其中包含sFoo和sFoo\u向量,是否可以使用其他聚合来初始化多个数据类型(即sFoo和sFoo\u向量)?

    type sBaz is record 
        A   : sFoo; 
        B   : sFoo;
        C   : sFoo;
        D   : sFoo_Vector;
    end record;
    
    constant Var2 : sBaz := (others => ???)
    
    1 回复  |  直到 8 年前
        1
  •  3
  •   user1155120 user1155120    8 年前

    处理一堆片段是有风险的。

    如果sBaz D受到约束:

    D   : sFoo_Vector (0 to 3);
    

    初始值可以是

    (D => (others =>  cNull_Foo), others => cNull_Foo);
    

    在元素D的子类型指示中提供记录约束,而不限制类型定义:

    constant Var2 : sBaz (D (3 downto 0)) := (D =>  (3 downto 0 => cNull_Foo), others => cNull_Foo);
    

    根据ghdl,D元素关联不能 others D不是3到0,而是没有完全约束。

    IEEE标准1076-2008

    9.3.3.2记录骨料

    如果聚合的类型是记录类型,则作为选项给出的元素名称应表示该记录类型的元素。如果选择 其他 作为记录聚合的选择,它应至少表示一个元素。与多个选项或选项关联的元素 其他 ,仅当指定的元素都是相同类型时才允许。元素关联的表达式应具有关联记录元素的类型。

    没有帮助,我们可以把注意力集中在D上。

    9.3.3.3阵列聚合

    具有 其他 选择应根据上下文确定。即,使用 其他 选择只能出现在以下情况之一:

    ...
    f) 作为定义 常量的初始值 或变量 对象 ,其中该对象被声明为 完全约束数组子类型
    ...

    6.4对象
    6.4.1概述

    此外,以下是对象,但不是命名实体:

    ..
    另一个对象的元素或切片(参见8.3、8.4和8.5)

    8.3选定名称

    所选名称用于表示一个命名实体,其声明显示在另一个命名实体的声明中或设计库中。

    ...
    所选名称可以表示记录的元素、由访问值指定的对象或其声明包含在另一个命名实体中的命名实体,特别是在库、包或受保护类型中。。。

    因此,记录的元素是一个对象。它不是名称实体,而是使用选定的名称。命名实体是记录类型的对象。

    到目前为止,D元素定义了数组类型的对象的初始值。它有 完全约束数组子类型 ?

    9.4.2局部静态初级

    ...本地静态数组子类型是 完全约束数组子类型 通过对无约束数组类型施加局部静态数组约束而形成。无约束数组类型的每个索引位置应有一个局部静态索引子类型,每个数组子元素(如有)的每个索引位置应有一个局部静态索引子类型。局部静态记录约束是在每个记录元素约束中具有局部静态约束的记录约束。本地静态记录子类型是一种完全受约束的记录类型,其元素都是本地静态子类型,或者是一种完全受约束的记录子类型,通过对未受约束的记录类型施加本地静态记录约束而形成。对于每个数组子元素(如果有)的每个索引位置,无约束记录类型应具有本地静态索引子类型。。。。

    这看起来几乎令人信服。 除了

    6.4.2对象声明
    6.4.2.1概述

    对象声明声明指定类型的对象。这样的对象称为 显式声明的对象 .

    object\u声明::=
    常量\u声明
    |signal\u声明
    |变量\u声明
    |file\u声明

    对象声明称为 单对象声明 如果其标识符列表具有单个标识符;它被称为 多对象声明 如果标识符列表有两个或多个标识符。。。。

    常量声明是完全受约束记录子类型的单个对象声明。9.3.3.3数组聚合中没有提到这一点。

    如果您查看IEEE Std 610.12-1990 IEEE软件工程术语表,其对象定义将在1987年标准时生效:

    对象 (1) 用于修饰或说明汇编或编译过程的结果。 另请参见“ 目标代码;对象模块;目标程序。
    (2) 程序常量或变量。
    (3) 数据和操作该数据的服务的封装。 另请参见: **面向对象设计。

    您可以看到(3)属于受保护类型的对象。

    如果我们查看术语表(LRM附录I,信息性):

    对象: (A) 具有给定类型值的命名实体。对象可以是常量、信号、变量或文件。(6.4.1)(B)信息模型中类的实例。对象也是类的每个超类的实例。(17.2.1)

    我们看到了对象是命名实体的区别。(A)定义仅在本标准的早期版本中使用。“实体”在1993年修订版中变成了“命名实体”,并在4.3对象中表示元素不是命名实体(如上面的2008年6.4.1对象所示)。

    对于9.3.3.3数组聚合f),作为数组子类型的记录元素不是常量对象。

    完整的示例如下所示:

    library ieee;
    use ieee.std_logic_1164.all;
    
    package foobat is
        type sFoo is record 
            A : std_logic;
            B : std_logic_vector(2 downto 0);
            C : std_logic;
        end record;
    
        type sFoo_Vector is array (natural range <>) of sFoo;
    
        constant cNull_Foo: sFoo := (A => '0', B => (others => '0'), C => '0');
    
        type sBar is record 
            A   : sFoo; 
            B   : sFoo;
            C   : sFoo;
        end record; 
    
        constant Var1 : sBar := (others => cNull_Foo);
    
        type sBaz is record 
            A   : sFoo;
            B   : sFoo;
            C   : sFoo;
            D   : sFoo_Vector;
        end record;
    
        constant Var2 : sBaz (D (3 downto 0)) :=
                (D =>  (3 downto 0 => cNull_Foo), others => cNull_Foo);
    
        --  fully constrained type declaration:
    
        -- type sBaz is record
        --     A   : sFoo;
        --     B   : sFoo;
        --     C   : sFoo;
        --     D   : sFoo_Vector (0 to 3);
        -- end record;
        --
        -- constant Var2 : sBaz :=
        --       (D => (others =>  cNull_Foo), others => cNull_Foo);
    
    end package;