VHDL не может нарезать записи - PullRequest
       20

VHDL не может нарезать записи

0 голосов
/ 17 сентября 2018

Могу ли я не взять фрагмент массива записей? Я объявляю такую ​​запись:

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;

но это:

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

получает ошибку

"record type mytypes is used but not declared"

Так не разрешается ли брать фрагменты записей или мне нужно написать дополнительный код, чтобы включить его?

Я должен был сказать - Кварт II

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Стандарт VHDL изначально основан на LRM Ada'83, включая типы записей.И Ada, и VHDL имеют строгую типизацию и требуют (здесь в терминологии VHDL), что для расширенного имени, суффикс которого является именем элемента, объявленным в объявлении типа записи, префикс должен быть соответствующим (обозначает значение типа записи).См. IEEE 1076-2008:

8.3 Выбранные имена (параграфы 3 и 4)

Выбранное имя может обозначать элемент записи, объект, обозначенный значением доступа, илиименованный объект, объявление которого содержится в другом именованном объекте, в частности в библиотеке, пакете или защищенном типе.Кроме того, выбранное имя может обозначать все именованные объекты, объявления которых содержатся в библиотеке или пакете.

Для выбранного имени, которое используется для обозначения элемента записи, суффикс должен быть простым именем, обозначающим элемент объекта или значения записи.Префикс должен соответствовать типу этого объекта или значения.

Это означает, что

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

приводит к ошибке (обозначает обязательное требование, см. 1.3 Структура и терминологияэтот стандарт).

Расширенное имя здесь mt(0 to 1).one, the suffix is the element name one` и префикс mt (от 0 до 1), имя среза - это тип массива, элементы которого являются типом записи.(8.5, «Имя фрагмента обозначает одномерный массив, состоящий из последовательности последовательных элементов другого одномерного массива.»)

Оригинальный постер вопроса прокомментировал неприемлемый ответ, что рабочее решение былонайдено с использованием состояния генерации, которое выдает несколько одновременных операторов присваивания:

SOME_LABEL:
    for i in 1 downto 0 generate
        slv(i) <= mt(i).one;
    end generate;

Где суффикс выбранного имени mt(i) будет индексированным именем (8.4 "Индексированное имя обозначает элемент массива.").

Вы могли бы заметить, что это просто уклоняется от проблемы, не используя имя фрагмента.

Один из способов вырезать массив записей, извлекающих элемент из каждой, - использованиефункция подпрограммы, выражение, возвращающее значение (4. Подпрограммы и пакеты).Функция будет возвращать подэлемент one из элемента массива со значением типа mytypes, заданным параметром:

    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_vector, длина которого определяется длиной массива элементоввведите mytypes.

Различие между использованием функции и оператора генерирования включает предоставление выражения, которое позволяет параметру, который может быть именем среза, и позволяет возвращаемому значению включать подэлементы из нескольких элементов записи.В то время как функция требует объявления и / или определения подпрограммы, она используется в качестве выражения, которое может помочь потоку описания функций.Функцию можно использовать в нескольких вызовах функций, в то время как оператор генерирования является специфическим.Также генерирующая инструкция будет уточнена до блочной инструкции (14.5.3 Генерация операторов).Одно действительно полезное отличие состоит в том, что вызов функции может использоваться в операторе последовательного присваивания (например, в операторе процесса или подпрограмме).

Создание Минимального, Завершенного и Проверяемого примера с использованием объявленийнайдено в вопросе:

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;

ghdl -r mytypes_slices
mytypes_slices.vhdl: 49: 9: @ 0ms: (примечание к отчету): slv (от 1 до 0) = 01
mytypes_slices.vhdl: 52: 9: @ 0ms: (примечание к отчету): slv1 (от 1 до 0) = 01

Мы видим, что вызов функции также может быть гибким.Присвоение slv использует вызов функции, возвращаемое значение которой разделено на части (8.1 «Некоторые формы имени (индексированные и выбранные имена, имена фрагментов и имена атрибутов) включают префикс, который является именем или вызовом функции.»).Значение параметра типа массива также можно нарезать.Оба выражения предоставляют одно и то же значение.

Вы также можете заметить, что направление имен фрагментов соответствует объявленному направлению их соответствующих типов массивов.Вопрос OP содержит дополнительную ошибку:

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

Если префиксу разрешено быть срезом, mt(0 to 1) будет нулевым срезом (8,5 ". Срез является нулевым срезом , если дискретный диапазон является нулевым диапазоном. Это ошибка, если Направление дискретного диапазона не совпадает с направлением диапазона индексов массива, обозначаемого префиксом имени среза », 5.2 Скалярные типы, 5.2.1 пункты 3-6, 5.3.2.2 Ограничения индекса и дискретные диапазоны). Направление не соответствует направлению, указанному в объявлении mt.

0 голосов
/ 17 сентября 2018

Вы можете нарезать массивы записей

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

но вы не можете сделать это:

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

Вам нужно будет сделать это:

slv(0) <= mt(0).one;
slv(1) <= mt(1).one;

Кстати: если вы объявляете массив, используя downto, вы не можете разрезать его, используя to. Направление среза должно соответствовать направлению объявления.

...