Стандарт 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
.