vhdl can';t切片记录

vhdl can';t切片记录,vhdl,slice,record,Vhdl,Slice,Record,我可以不从记录数组中获取一个片段吗? 我声明这样的记录: type mytype is record one : std_logic; two : std_logic; end record; Type mytypes is array (natural range <>) of mytype; signal mt : mytypes(3 downto 0); signal slv : std_logic_vector (3 downto 0); 当我像这样使用它

我可以不从记录数组中获取一个片段吗? 我声明这样的记录:

type mytype is record
    one : std_logic;
    two : std_logic;
end record;
Type mytypes is array (natural range <>) of mytype;
signal mt : mytypes(3 downto 0);
signal slv : std_logic_vector (3 downto 0);
当我像这样使用它时,它是可以的:

slv(0) <= mt(0).one;
slv(1) <= mt(1).one;
那么,是不是不允许对记录进行切片,还是我需要编写一些额外的代码来启用它


我应该说-Quartus II

您可以对记录数组进行切片

signal mt, mt2 : mytype(0 to 3);
mt2(0 to 1) <= mt(0 to 1);
信号mt,mt2:mytype(0到3);

mt2(0到1)VHDL标准最初基于Ada的83 LRM,包括记录类型。Ada和VHDL都共享强类型,并要求(在VHDL术语中)对于后缀为记录类型声明中声明的元素名的扩展名,前缀应适当(表示记录类型的值)。参见IEEE 1076-2008:

8.3选定名称(第3和第4段)

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

对于用于表示记录元素的选定名称,后缀应为表示记录对象或值的元素的简单名称。前缀应适用于该对象或值的类型

这意味着

slv(0 to 1) <= mt(0 to 1).one;
其中,所选名称
mt(i)
的后缀将是索引名称(8.4“索引名称表示数组的元素”)

您可以注意到,这只是通过不使用切片名称来回避问题

从每个记录中提取元素的记录数组切片的一种方法是使用子程序函数,即返回值的表达式(4.子程序和包)。函数将从参数指定的mytypes类型的数组值的元素返回子元素
one

    function mytypes_ones (inp: mytypes) return std_logic_vector is
        variable retv:  std_logic_vector(inp'range);
    begin
        for i in inp'range loop
            retv(i) := inp(i).one;
        end loop;
        return retv;
    end function;
返回值是一个std_logic_向量值,其长度由类型为
mytypes
的元素数组的长度决定

使用函数和generate语句之间的区别包括提供一个表达式,该表达式允许一个可以是片名的参数,并允许返回值包含来自多个记录元素的子元素。虽然函数需要子程序声明和/或定义,但它的用法是作为一个表达式,可以帮助函数描述流。一个函数可以在多个函数调用中使用,而generate语句是特定的。此外,generate语句将详细描述为block语句(14.5.3 generate语句)。一个真正有用的区别是函数调用可以在顺序赋值语句中使用(例如,在进程语句或子程序中)

使用问题中的声明创建一个

library ieee;
use ieee.std_logic_1164.all;

entity mytypes_slices is
end entity;

architecture fum of mytypes_slices is
    type mytype is record
        one:        std_logic;
        two:        std_logic;
    end record;
    type mytypes is array (natural range <>) of mytype;
    signal mt:      mytypes (3 downto 0) := (
                        (one => '1', two => '0'),   -- mt(3)
                        (one => '1', two => '0'),   -- mt(2)
                        (one => '0', two => '0'),   -- mt(1)
                        (one => '1', two => '0')    -- mt(0)
                    );
    signal slv:     std_logic_vector (3 downto 0);
    signal slv1:    std_logic_vector (3 downto 0);

    function mytypes_ones (inp: mytypes) return std_logic_vector is
        variable retv:  std_logic_vector(inp'range);
    begin
        for i in inp'range loop
            retv(i) := inp(i).one;
        end loop;
        return retv;
    end function;

begin

    slv  (1 downto 0) <= mytypes_ones(mt)(1 downto 0); -- slice return value
    slv1 (1 downto 0) <= mytypes_ones(mt(1 downto 0)); -- slice parameter

MONITOR:
    process
    begin
        wait for 0 ns;  -- skip default values of slv, slv1, delta cycle delay
        report "slv(1 downto 0) = " & 
            character'value(std_ulogic'image(slv(1))) &
            character'value(std_ulogic'image(slv(0)));
        report "slv1(1 downto 0) = " & 
            character'value(std_ulogic'image(slv1(1))) &
            character'value(std_ulogic'image(slv1(0)));
        wait;
    end process;

end architecture;

如果允许前缀为切片
mt(0到1)
将为空切片(8.5“如果离散范围为空范围,则切片为空切片。如果离散范围的方向与切片名称前缀表示的数组索引范围的方向不同,则为错误”,5.2标量类型,5.2.1第3-6段,5.3.2.2索引约束和离散范围)。该方向与
mt

声明中的方向不匹配,我应该说“记录字段的切片数组”。谢谢,但这是一个不合逻辑和武断的限制。我希望有一些额外的代码,我可以写来启用它。而且错误消息也没有什么帮助。我浪费了很多时间试图弄清楚我是如何搞砸了声明的。对表示记录元素的选定名称后缀的限制可以追溯到Ada83 LRM,4.1.3选定组件。现在可能有点晚了,单方面宣布限制不合逻辑和武断是错误的。不过,我同意,Quartus错误消息没有太大帮助。您可以尝试先进行模拟,而不是直接进行合成,错误消息通常会更好。你搞砸的不是声明,而是赋值语句。只是玩弄一下,generate似乎解决了我的问题,它改变了数组的大小,而不必更改代码。如果我弄错了,我道歉。数组不是可变的,但我想用一个常数来设置它的大小,以后可能会更改。当然,我希望能够更改常量,而不必理会代码。如果我不能编写“slv(0到msb)”,谢谢。我已经复制了该函数以供将来参考。这就是我在问“是否需要编写附加代码以启用切片”时的想法。为了澄清这一点,我正在尝试“清理”一个代码示例,该示例最初对变量“1”和“2”使用了两个并行数组并使用硬编码数字。我想用一个常量替换数组大小,并使用一个记录将两个数组合并为一个(这里我可能会提到我主要是一名C/C++程序员)。方向错误是我的错,在复制错误的最小代码中,“to”比“downto”短。这里不需要感谢和道歉。本手册和指南旨在为将来有类似问题的读者提供高质量的问题和答案,作为搜索资源。如果你要编辑你的问题,让它更清楚,这里有潜力。过时的注释可由其所有者删除或标记为删除。
slv(0) <= mt(0).one;
slv(1) <= mt(1).one;
slv(0 to 1) <= mt(0 to 1).one;
SOME_LABEL:
    for i in 1 downto 0 generate
        slv(i) <= mt(i).one;
    end generate;
    function mytypes_ones (inp: mytypes) return std_logic_vector is
        variable retv:  std_logic_vector(inp'range);
    begin
        for i in inp'range loop
            retv(i) := inp(i).one;
        end loop;
        return retv;
    end function;
library ieee;
use ieee.std_logic_1164.all;

entity mytypes_slices is
end entity;

architecture fum of mytypes_slices is
    type mytype is record
        one:        std_logic;
        two:        std_logic;
    end record;
    type mytypes is array (natural range <>) of mytype;
    signal mt:      mytypes (3 downto 0) := (
                        (one => '1', two => '0'),   -- mt(3)
                        (one => '1', two => '0'),   -- mt(2)
                        (one => '0', two => '0'),   -- mt(1)
                        (one => '1', two => '0')    -- mt(0)
                    );
    signal slv:     std_logic_vector (3 downto 0);
    signal slv1:    std_logic_vector (3 downto 0);

    function mytypes_ones (inp: mytypes) return std_logic_vector is
        variable retv:  std_logic_vector(inp'range);
    begin
        for i in inp'range loop
            retv(i) := inp(i).one;
        end loop;
        return retv;
    end function;

begin

    slv  (1 downto 0) <= mytypes_ones(mt)(1 downto 0); -- slice return value
    slv1 (1 downto 0) <= mytypes_ones(mt(1 downto 0)); -- slice parameter

MONITOR:
    process
    begin
        wait for 0 ns;  -- skip default values of slv, slv1, delta cycle delay
        report "slv(1 downto 0) = " & 
            character'value(std_ulogic'image(slv(1))) &
            character'value(std_ulogic'image(slv(0)));
        report "slv1(1 downto 0) = " & 
            character'value(std_ulogic'image(slv1(1))) &
            character'value(std_ulogic'image(slv1(0)));
        wait;
    end process;

end architecture;
slv(0 to 1) <= mt(0 to 1).one;