В. Стешенко, Г. Шишкин, А. Евстифеев, Ю. Седякин
Как уже отмечалось в предыдущих занятиях, возрастающая степень интеграции ПЛИС, новые концепции проектирования (система на кристалле) накладывают свой отпечаток на способы описания проекта на ПЛИС. Языки описания аппаратуры (Hardware Description Language), являются формальной записью, которая может быть использована на всех этапах разработки цифровых электронных систем. Это возможно вследствие того, что язык легко воспринимается как машиной, так и человеком. Он может использоваться на этапах проектирования, верификации, синтеза и тестирования аппаратуры так же, как и для передачи данных о проекте, модификации и сопровождения. Существует несколько разновидностей этих языков: AHDL, VHDL, VerilogHDL, Abel и др. Известны также случаи использования стандартных языков программирования, например Си, для описания структуры БИС.
Ряд языков описания аппаратуры (AHDL, Abel) предназначены для описания систем на ПЛИС, другие появились изначально как средство моделирования цифровых систем, а затем стали инструментом их описания.
Одним из наиболее универсальных языков описания аппаратуры является VHDL, первый стандарт которого был разработан в 19831987 годах при спонсорстве минобороны США. На этом языке возможно как поведенческое, так структурное и потоковое описание цифровых схем.
VHDL поддерживает три различных стиля для описания аппаратных архитектур.
Первый из них структурное описание (structural description), в котором архитектура представляется в виде иерархии связанных компонентов.
Второй потоковое описание (data-flow description), в котором архитектура представляется в виде множества параллельных регистровых операций, каждая из которых управляется вентильными сигналами. Потоковое описание соответствует стилю описания, используемому в языках регистровых передач.
И, наконец, поведенческое описание (behavioral description), в котором преобразование описывается последовательными программными предложениями, которые похожи на имеющиеся в любом современном языке программирования высокого уровня. Все три стиля могут совместно использоваться в одной архитектуре.
Структурное и потоковое описание используется в основном для проектирования цифровых схем, поведенческое только для моделирования, так как содержит конструкции, которые невозможно реализовать в виде схемы.
Наиболее важными в языке VHDL являются понятия параллелизма и иерархии.
ОБЪЕКТ ПРОЕКТА (entity) представляет собой описание компоненты проекта, имеющей четко заданные входы и выходы и выполняющей четко определенную функцию. Объект проекта может представлять всю проектируемую систему, некоторую подсистему, устройство, узел, стойку, плату, кристалл, макроячейку, логический элемент и т. п. В описании объекта проекта можно использовать компоненты, которые, в свою очередь, могут быть описаны как самостоятельные объекты проекта более низкого уровня. Таким образом, каждый компонент объекта проекта может быть связан с объектом проекта более низкого уровня. В результате такой декомпозиции пользователь строит иерархию объектов проекта, представляющих весь проект в целом и состоящую из нескольких уровней абстракций. Такая совокупность объектов проекта называется ИЕРАРХИЕЙ ПРОЕКТА (design hierarchy).
Каждый объект проекта состоит, как минимум, из двух различных типов описаний: описания интерфейса и одного или более архитектурных тел. Интерфейс описывается в ОБЪЯВЛЕНИИ ОБЪЕКТА ПРОЕКТА (entity declaration) и определяет только входы и выходы объекта проекта.
Для описания поведения объекта или его структуры служит АРХИТЕКТУРНОЕ ТЕЛО (architecture body). Чтобы задать, какие объекты проекта использованы для создания полного проекта, используется ОБЪЯВЛЕНИЕ КОНФИГУРАЦИИ (configuration declaration).
В языке VHDL предусмотрен механизм пакетов для часто используемых описаний, констант, типов, сигналов. Эти описания помещаются в ОБЪЯВЛЕНИИ ПАКЕТА (package declaration). Если пользователь использует нестандартные операции или функции, их интерфейсы описываются в объявлении пакета, а тела содержатся в ТЕЛЕ ПАКЕТА (package body).
Таким образом, при описании цифровых схем на языке VHDL, возможно использование пяти различных типов описаний: объявление объекта проекта, архитектурное тело, объявление конфигурации, объявление пакета и тело пакета. Каждое из описаний является самостоятельной конструкцией языка VHDL, может быть независимо проанализирована анализатором и поэтому получило название "МОДУЛЬ ПРОЕКТА" (design unit). Модули проекта, в свою очередь, можно разбить на две категории: ПЕРВИЧНЫЕ и ВТОРИЧНЫЕ. К первичным модулям относятся различного типа объявления. К вторичным отдельно анализируемые тела первичных модулей. Один или несколько модулей проекта могут быть помещены в один файл, называемый ФАЙЛОМ ПРОЕКТА (design file). Каждый проанализированный модуль проекта помещается в БИБЛИОТЕКУ ПРОЕКТА (design library) и становится БИБЛИОТЕЧНЫМ МОДУЛЕМ (library unit). Данная реализация позволяет создать любое число библиотек проекта. Каждая библиотека проекта в языке VHDL имеет логическое имя (идентификатор). Фактическое имя файла, содержащего эту библиотеку, может совпадать или не совпадать с логическим именем библиотеки проекта. Для ассоциирования логического имени библиотеки с соответствующим ей фактическим именем предусмотрен специальный механизм установки внешних ссылок.
Объекты данных (data object) являются хранилищами для значений определенного типа. Следует заметить, что все типы в VHDL конструируются из элементов, представляющих собой скалярные типы. Значения всех объектов в создаваемой модели, взятые все вместе, отражают текущее состояние моделирования. Описание на VHDL содержит объявления, которые создают объекты данных четырех классов: константы, переменные, сигналы и файлы.
Константы и переменные содержат одно значение данного типа. Значения переменных могут быть изменены назначением нового значения в предложении назначения переменной. Значение константы устанавливается до начала моделирования и не может после этого изменяться.
Сигнал имеет текущее значение подобно переменной. Он также имеет прошлую историю значений, на которые разработчик может пожелать сослаться, а также множество будущих значений, которые будут получены от формирователей сигналов. Новые значения для сигналов создаются предложениями назначения сигналов. Каждый объект в описании должен ассоциироваться с одним и только одним типом. Тип состоит из множества возможных значений и множества операций. Имеются операции двух видов. Некоторые операции являются предопределенными, это, к примеру, операторы "+", "-" для значений типа integer. Другие операции явно кодируются в VHDL; например, может быть написана функция подпрограмма Max, которая возвращает наибольший из двух целых аргументов. Тип объекта представляет информацию, которая окончательно определяется в момент записи модели. Эта информация способствует обнаружению несоответствий в тексте без обращения к моделированию. Например, легко обнаружить и отметить попытку назначения булевого значения (True или False) целой переменной. Новое значение, которое должно быть создано предложением назначения, определяется выражением в правой части. Выражения используются также и в других контекстах: например, как условие в предложении if. В состав выражения могут входить константы, переменные, сигналы, операторы и указатели функций. Когда имя объекта используется в выражении, при расчете значения выражения учитывается его текущее значение.
Рассмотрим некоторые примеры описания цифровых схем на VHDL.
Примером описания цифрового автомата является преобразователь параллельного кода в последовательный. Преобразователь кода представляет собой устройство, на вход которого подается n-битное число в параллельном коде "d", сигнал загрузки "load" и синхроимпульсы "clk". По сигналу загрузки происходит запись входного слова во внутренний регистр и последовательная выдача в течении n тактов этого входного слова в последовательном коде на выходе "о" синхроимпульсами "oclk". После окончания преобразования на выходе "e" появляется высокий уровень сигнала в течение одного такта. Такого рода преобразователи кода часто используются для управления синтезаторами частот 1104ПЛ1 и им подобными.
Описание этого устройства на языке VHDL приведено на врезке 1.
Врезка 1
library ieee; use ieee.std_logic_1164.all; entity Serial is port ( clk : in STD_LOGIC; load : in STD_LOGIC; reset : in STD_LOGIC; d : in STD_LOGIC_vector (3 downto 0); oclk : out STD_LOGIC; o : out STD_LOGIC; e : out STD_LOGIC ); end; architecture behavioral of Serial is type t1 is range 0 to 4; signal s : STD_LOGIC_vector (2 downto 0); signal i : t1; begin process (clk) begin if reset = "1" then i <=0; else if (clk'event and clk='1') then if (i = 0 and load = "1") then s(2 downto 0) <= d(3 downto 1); o <= d(0); i <= 4; end if; if (i > 1) then o <= s(0); s(1 downto 0) <= s(2 downto 1); i <= i - 1; end if; if (i = 1) then e <= "1"; i <= 0; else e <= "0"; end if; end if; end if; if i >0 then oclk <= not clk; else oclk <= "0"; end if; end process; end behavioral; |
По переднему фронту синхроимпульса "clk" при высоком уровне на входе загрузки происходит загрузка трех старших бит входного слова d[3..1] во временный регистр s[2..0]. Младший бит входного слова d[0] подается на выход "o". На выходе "oclk" появляются синхроимпульсы. На сигнале "i" собран внутренний счетчик, выдающий сигнал окончания преобразования "e". При поступлении последующих синхроимпульсов происходит выдача на выход "o" остальных бит входного слова, хранящихся в регистре s[2..0].
Моделирование этого устройства было проведено в системе проектирования OrCAD 9.0.
Для тестирования схемы использовался тест (врезка 2).
Врезка 2
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity test_serial is end test_serial; architecture tastbench of test_serial is component serial port ( clk : in std_logic; load : in std_logic; reset : in std_logic; d : in std_logic_vector(3 downto 0); oclk : out std_logic; o : out std_logic; e : out std_logic ); end component; signal clk : std_logic; signal load : std_logic := "0"; signal reset : std_logic; signal d : std_logic_vector(3 downto 0); signal oclk : std_logic; signal o : std_logic; signal e : std_logic; begin process begin for i in 0 to 50 loop clk <= "0"; wait for 5 ns; clk <= "1"; wait for 5 ns; end loop; end process; process begin reset <= "1"; wait for 10 ns; reset <= "0" ; load <= "1"; d <= «1010»;wait for 10 ns; load <= "0"; d <= «0000»;wait for 500 ns; end process; dut : serial port map ( clk => clk, load => load, reset => reset, d => d, oclk => oclk, o => o, e => e ); end testbench; |
Результаты моделирования представлены на рис. 1.
Рисунок 1
В качестве примера описания устройства ЦОС рассмотрим цифровой КИХ-фильтр.
Работа цифрового КИХ-фильтра описывается разностным уравнением
yn = A0xn + A1xn-1 + A2xn-2 + ...,
где yn реакция системы в момент времени n; xn входное воздействие; Ai весовой коэффициент i-ой входной переменной.
На VHDL описание фильтра имеет вид, показанный на врезке 3.
Врезка 3
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity f is port ( din: in std_logic_vector(7 downto 0); sout:out std_logic_vector(15 downto 0); r: in std_logic; c: in std_logic ); end f; architecture behavior of is constant h00 : std_logic_vector(7 downto 0) := «00000000»; constant h01 : std_logic_vector(7 downto 0) := «00000001»; constant h02 : std_logic_vector(7 downto 0) := «00000100»; constant h03 : std_logic_vector(7 downto 0) := «00001111»; constant h04 : std_logic_vector(7 downto 0) := «00100100»; constant h05 : std_logic_vector(7 downto 0) := «01000010»; constant h06 : std_logic_vector(7 downto 0) := «01100100»; constant h07 : std_logic_vector(7 downto 0) := «01111100»; constant h08 : std_logic_vector(7 downto 0) := «01111111»; constant h09 : std_logic_vector(7 downto 0) := «01101010»; constant h10 : std_logic_vector(7 downto 0) := «01000010»; constant h11 : std_logic_vector(7 downto 0) := «00100011»; constant h12 : std_logic_vector(7 downto 0) := «11101100»; constant h13 : std_logic_vector(7 downto 0) := «11010110»; constant h14 : std_logic_vector(7 downto 0) := «11010101»; constant h15 : std_logic_vector(7 downto 0) := «11100011»; constant h16 : std_logic_vector(7 downto 0) := «11110111»; constant h17 : std_logic_vector(7 downto 0) := «00001010»; constant h18 : std_logic_vector(7 downto 0) := «00010100»; constant h19 : std_logic_vector(7 downto 0) := «00010011»; constant h20 : std_logic_vector(7 downto 0) := «00001100»; constant h21 : std_logic_vector(7 downto 0) := «00000010»; constant h22 : std_logic_vector(7 downto 0) := «11111000»; constant h23 : std_logic_vector(7 downto 0) := «11110101»; signal x00, x01, x02, x03,x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23 : std_logic_vector(7 downto 0); signal m00, m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23 : std_logic_vector(15 downto 0); begin m00 <= (signed(x00)*signd(h00)); m01 <= (signed(x01)*signd(h01)); m02 <= (signed(x02)*signd(h02)); m03 <= (signed(x03)*signd(h03)); m04 <= (signed(x04)*signd(h04)); m05 <= (signed(x05)*signd(h05)); m06 <= (signed(x06)*signd(h06)); m07 <= (signed(x07)*signd(h07)); m08 <= (signed(x08)*signd(h08)); m09 <= (signed(x09)*signd(h09)); m10 <= (signed(x10)*signd(h10)); m11 <= (signed(x11)*signd(h11)); m12 <= (signed(x12)*signd(h12)); m13 <= (signed(x13)*signd(h13)); m14 <= (signed(x14)*signd(h14)); m15 <= (signed(x15)*signd(h15)); m16 <= (signed(x16)*signd(h16)); m17 <= (signed(x17)*signd(h17)); m18 <= (signed(x18)*signd(h18)); m19 <= (signed(x19)*signd(h19)); m20 <= (signed(x20)*signd(h20)); m21 <= (signed(x21)*signd(h21)); m22 <= (signed(x22)*signd(h22)); m23 <= (signed(x23)*signd(h23)); sout <= (signed(m00)+signed(m01)+signed(m02)+signed(m03) +signed(m04)+signed(m05)+signed(m06)+signed(m07) +signed(m08)+signed(m09)+signed(m10)+signed(m11) +signed(m12)+signed(m13)+signed(m14)+signed(m15) +signed(m16)+signed(m17)+signed(m18)+signed(m19) +signed(m20)+signed(m21)+signed(m22)+signed(m23)); process(c,r) begin if r='1' then x00 <= (others => "0"); x01 <= (others => "0"); x02 <= (others => "0"); x03 <= (others => "0"); x04 <= (others => "0"); x05 <= (others => "0"); x06 <= (others => "0"); x07 <= (others => "0"); x08 <= (others => "0"); x09 <= (others => "0"); x10 <= (others => "0"); x11 <= (others => "0"); x12 <= (others => "0"); x13 <= (others => "0"); x14 <= (others => "0"); x15 <= (others => "0"); x16 <= (others => "0"); x17 <= (others => "0"); x18 <= (others => "0"); x19 <= (others => "0"); x20 <= (others => "0"); x21 <= (others => "0"); x22 <= (others => "0"); x23 <= (others => "0"); elsif (c'event andc='1') then x00(7 downto 0) <= din(7 downto 0); x01(7 downto 0) <= x00(7 downto 0); x02(7 downto 0) <= x01(7 downto 0); x03(7 downto 0) <= x02(7 downto 0); x04(7 downto 0) <= x03(7 downto 0); x05(7 downto 0) <= x04(7 downto 0); x06(7 downto 0) <= x05(7 downto 0); x07(7 downto 0) <= x06(7 downto 0); x08(7 downto 0) <= x07(7 downto 0); x09(7 downto 0) <= x08(7 downto 0); x10(7 downto 0) <= x09(7 downto 0); x11(7 downto 0) <= x10(7 downto 0); x12(7 downto 0) <= x11(7 downto 0); x13(7 downto 0) <= x12(7 downto 0); x14(7 downto 0) <= x13(7 downto 0); x15(7 downto 0) <= x14(7 downto 0); x16(7 downto 0) <= x15(7 downto 0); x17(7 downto 0) <= x16(7 downto 0); x18(7 downto 0) <= x17(7 downto 0); x19(7 downto 0) <= x18(7 downto 0); x20(7 downto 0) <= x19(7 downto 0); x21(7 downto 0) <= x20(7 downto 0); x22(7 downto 0) <= x21(7 downto 0); x23(7 downto 0) <= x22(7 downto 0); end if; end process; end behavior; |
Входные данные считываются с входа din[7..0] в дополнительном коде по переднему фронту синхросигнала "c".
На сигналах x0 - x23 построен сдвиговый регистр, обеспечивающий задержку данных на 24 такта. Сигналы с регистров умножаются на весовые коэффициенты h0 е h23 и суммируются.
Для тестирования схемы использован тест, показанный на врезке 4.
Врезка 4
-Test bench shell library ieee; use ieee.std_logic_1164.all; entity test_f is end test_f; architecture testbench of test_f is component f port ( din : in std_logic_vecor(7 downto 0); sout : out std_logic_vector(15 downto 0); r: in std_logic; c : in std_logic ); end component; signal din : std_logic_vector(7 downto 0); signal sout : std_logic_vector(15 downto 0); signal r : std_logic; signal c : std_logic; begin process begin for i in 0 to 50 loop c <= "0"; wait for 5 ns; c <= "1"; wait for 5 ns; end loop; end process; process begin r <= "1"; wait for 10 ns; r <= "0"; din <= «00000001»; wait for 10 ns; din <= «00000000»; wait for 500 ns; end process; dut : f port map ( din => din, sout => sout, r => r, c => c ); end testbench; |
Тест моделирует подачу на цифровой фильтр аналога d-функции. На выходе фильтра его импульсная характеристика.
Результаты моделирования представлены на рис. 2.
Рисунок 2
В следующем занятии мы рассмотрим использование языка AHDL для описания проектов на ПЛИС ALTERA.
Тел. (095) 263-6736
E-mail: steshenk@sm.bmstu.ru
Ваш комментарий к статье | ||||