Параметры (generic) являются эффективным средством разработки масштабируемых модулей, т.е. модулей, для которых возможна быстрая смена разрядности, числа каналов, пределов счета и тому подобных численных характеристик, при сохранении алгоритмов работы. Параметр определяется с помощью ключевого слова generic в разделе entity.
Например:
generic (DATA_WIDTH : integer := 8);
Впоследствии при упоминании в тексте DATA_WIDTH вместо него будет подставлено значение 8.
Параметризованные модули являются достаточно привлекательными для разработки по многим причинам. Рассмотрим, например, реализацию регистров различной разрядности.
8-разрядный регистр.
libraryIEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity reg8 is
Port (clk : in STD_LOGIC;
d : in STD_LOGIC_VECTOR(7 downto 0);
q : out STD_LOGIC_VECTOR(7 downto 0));
end reg8;
architecture Behavioral of reg8 is
begin
process(clk)
begin
ifclk’event and clk = ‘1’ then
q <= d;
end if;
end process;
end Behavioral;
16-разрядныйрегистр.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity reg16 is
Port (clk : in STD_LOGIC;
d : in STD_LOGIC_VECTOR(15 downto 0);
q : out STD_LOGIC_VECTOR(15 downto 0));
end reg16;
architecture Behavioral of reg16 is
begin
process(clk)
begin
ifclk’event and clk = ‘1’ then
q <= d;
end if;
end process;
endBehavioral;
Из описания модулей можно видеть, что кроме имени, они различаются только разрядностью сигналов d и q. Нетрудно понять, что регистр любой разрядности будет описываться процедурным блоком, в котором будет находиться оператор q<= d;. Таким образом, для перехода к другой разрядности необходимо отредактировать только разрядность портов d и q.
Используем для управления разрядностью объявление параметра через generic.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entityreg_any is
generic (DATA_WIDTH : integer := 8);
Port (clk : in STD_LOGIC;
d : in STD_LOGIC_VECTOR(DATA_WIDTH - 1 downto 0);
q : out STD_LOGIC_VECTOR(DATA_WIDTH - 1 downto 0));
endreg_any;
architecture Behavioral of reg_any is
begin
process(clk)
begin
ifclk’event and clk = ‘1’ then
q <= d;
end if;
end process;
endBehavioral;
При объявлении портов теперь используется не прямое указание числа, а ссылка на определенный через generic параметр, названный DATA_WIDTH (буквально «ширина данных», или разрядность данных). Поскольку параметр в примере задан равным 8, выражение (DATA_WIDTH – 1 downto 0) эквивалентно (7 downto 0), что и требуется для 8-разрядного порта. Можно заметить, что редактирование единственной строки, где определен параметр, автоматически изменяет разрядности обоих сигналов – d и q, тогда как при ручном редактировании за приведением разрядности этих сигналов в соответствие друг другу необходимо следить отдельно. Представление требуемых величин в виде параметров особенно эффективно, если они используются в различных модулях – например, при разработке системы цифровой обработки сигналов, в которой каждый модуль производит очередное преобразование сигнала. При необходимости изменить разрядность обрабатываемых данных пришлось бы производить коррекции во всех модулях.
Для повышения читаемости исходного текста можно использоваться алиасы (alias). Алиас в буквальном переводе означает «прозвище», и служит в программировании для задания альтернативных имен уже существующим объектам. Алиас работает как глобальная подстановка, заменяющая один фрагмент текста другим, поэтому может применяться как для имен объектов, так и для зарезервированных слов VHDL. Например, после нижеследующего объявления:
aliasSLVisstd_logic_vector;
можно будет объявлять сигналы в следующем стиле.
signala : SLV(7 downto 0);
Употребление алиасов не следует делать чрезмерным, поскольку на определенном этапе читаемость текста ухудшится из-за обилия непривычных сокращений и замен.
Для повышения переносимости и масштабируемости модулей также могут быть полезны атрибуты. Они позволяют обращаться к отдельным характеристикам сигналов композитного типа. Например, если определить сигнал a :std_logic_vector(7 downto 0), то следующие атрибуты дадут такие результаты:
a’left - 7
a’right - 0
a’low - 0
a’high - 7
a’range – 7 downto 0
a’length - 8
a’ascending - FALSE
a’reverse_range – 0 to 7.
Атрибутыleft/rightиhigh/lowдаютвприведенномпримереодинаковыерезультаты. Разница состоит в том, что left и right возвращают значения, указанные в левой и правой частях объявления размера (7 downto 0), а high и low вернут наибольший и наименьший индекс.
Атрибуты range и reverse_range возвращают интервал изменения индексов в порядке объявления (range) или в обратном порядке (reverse_range).
Атрибут ascending возвращает логическое выражение, равное ИСТИНЕ, если интервал композитного типа объявлен в порядке возрастания индексов (т.е. 0 to 7). В приведенном примере этот атрибут вернет ЛОЖЬ, поскольку использовано объявление с ключевым словом downto.
Можно еще раз вернуться к примеру функции, рассмотренной в разделе 2.10.3:
function PAR_GEN (BV : in bit_vector)
return bit is
variable PAR : bit := ‘0’;
begin -- function
for i in BV’range loop
PAR := PAR xor BV(i) ;
end loop ;
return PAR ;
endfunctionPAR_GEN ;
В объявлении функции не указана разрядность входного сигнала. Вместо этого в теле функции используется атрибут ‘range. Это дает возможность вызывать такую функцию для сигналов различной разрядности, при этом вместо атрибута будет подставлена соответствующая строка (например, 7 downto 0). Такой подход делает функции более универсальными и позволяет обойтись меньшим объемом вспомогательных библиотек.
Приведенные выше атрибуты являются предопределенными. В синтезаторе XST можно также использовать атрибуты, определенные пользователем, или добавленные Xilinx при адаптации языка VHDL для проектирования ПЛИС. Например, следующая строка укажет синтезатору, что для блока RAM1 следует использовать реализацию в виде блочной памяти.
attribute RAM_STYLE of RAM1: entity is "BLOCK";
Подробный список атрибутов и правила их использования приведены в справочной системе САПР ISE.