Синтаксис VHDL очень похож на язык Ада. Дело в том, что компания Intermetrics, которой Пентагон поручил специфицировать VHDL, имела большой опыт работы с языком Ада. — КиберПедия 

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

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

Синтаксис VHDL очень похож на язык Ада. Дело в том, что компания Intermetrics, которой Пентагон поручил специфицировать VHDL, имела большой опыт работы с языком Ада.

2022-11-27 33
Синтаксис VHDL очень похож на язык Ада. Дело в том, что компания Intermetrics, которой Пентагон поручил специфицировать VHDL, имела большой опыт работы с языком Ада. 0.00 из 5.00 0 оценок
Заказать работу

ВВЕДЕНИЕ

...товарищи, а в каком ключе докладывать.

Язык VHDL был разработан в 1983 г. по заказу МО США для формального описания логических схем на всех этапах разработки электронных систем. Аббревиатура VHDL (Very High Speed Integrated Circuit Hardware Description Language) переводится как язык описания высокоскоростных интегрированных схем.

Синтаксис VHDL очень похож на язык Ада. Дело в том, что компания Intermetrics, которой Пентагон поручил специфицировать VHDL, имела большой опыт работы с языком Ада.

Международный стандарт - IEEE Std 1076-2002 IEEE Standard VHDL Language Reference Manual.

Отечественный стандарт - ГОСТ Р 50754-95 Язык описания аппаратуры цифровых систем VНDL. Описание языка.

И т.д. и т.п. Ничего интересного? Тогда ответьте на вопрос и проверьте себя - можно ли VHDL-выражение 1 заменить выражением 2 и наоборот:

1. y <= x;

2. if x = '0' then y <= '0'; else y <= '1'; end if;

Ответ: Честно говоря, для правильного ответа необходимо знать, какой тип данных у объектов х и у. Дело в том, что если мы имеем дело с типом BIT, то выражения вполне идентичны. А теперь посмотрим, что будет, если объекты х и у имеют тип std_logic? Если Вы уже догадались в чем дело, то Вы вполне владеете основами VHDL (или выше того) и можете пропустить дальнейшие рассуждения.

Итак, в VHDL есть несколько типов данных, два из них мы упомянули выше: bit и std_logic. Их множества значений таково:

· bit: {'0', '1'};

· std_logic: { 'U','X','0','1','Z','W','L','H','- ', }

Как видите, объекты типа std_logic могут принимать девять различных значений, а объекты типа bit только два. Теперь рассмотрим такой код:

· signal x, y: std_logic;

· if x = 'U' then y <= 'U';

· elsif x = 'X' then y <= 'X';

· elsif x = '0' then y <= '0';

· elsif x = '1' then y <= '1';

· elsif x = 'Z' then y <= 'Z';

· elsif x = 'W' then y <= 'W';

· elsif x = 'L' then y <= 'L';

· elsif x = 'H' then y <= 'H';

· elsif x = '- ' then y <= '- ';

· end if;

Вышеприведенный VHDL код теперь идентичен выражению 1 для типа std_logic. Надеюсь теперь понятен смысл задачки, решенной нами. Ну вообще-то они не совсем идентичны, если мы будем синтезировать эти выражения. Тут все будет зависеть от способов оптимизации и прочего, но об этом позже. А сейчас перейдем к более подробному рассмотрению языка VHDL.

КЛАССЫ И ОБЪЕКТЫ

... а вы товарищ из буржуев будете? Или пролетарий?

В отличие от приплюснутого Си в VHDL не предусмотрена возможность создавать новые классы, они уже встроены и их всего три:

Constant - константа.

2. variable - переменная;

3. signal - сигнал;

Значение первых двух классов я думаю понятно без комментариев. Третий класс - сигнал, введен для описания цифровых схем и обладает многими свойствам реальных сигналов в цифровой технике: скорость распространения, способы взаимодействия с другими сигналами и пр.

Прежде чем использовать какой либо объект, его нужно объявить членом какого-нибудь класса. Например, объявляются три объекта х, у и gnd:

· constant gnd: bit:='0';

· variable y: bit;

· signal z: bit;

Да и еще, переменным можно задавать начальное значение при объявлении:

· variable y: bit:='1';

КОММЕНТАРИИ

... прокомментируйте вашу позицию, а то непонятно...

Комментарии отделяются от основного VHDL-кода двойным штрихом и действуют до конца строки:

· -------------------------------

· -- Пример комментариев --

· -------------------------------

· --

· -- Управление индикаторами сигналов LINK

· nLEDL1 <= GND when nLINKA ='0' else TRI; -- канал А

· nLEDL2 <= GND when nLINKB ='0' else TRI; -- канал В

· --

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

· -------------------------------

· -- Пример бесполезных

· -- комментариев

· -------------------------------

· --

· x <= '0'; -- Приравниваем сигнал х нулю.

· --

ТИПЫ ДАННЫХ

... гуляют тут разные типы, прохода от них нет.

Про типы обычно долго и нудно ведут пояснения и рассуждения. Мы этого делать не будем, просто покажем их объявления в библиотеке std с нашими комментариями:

· type boolean is (false,true); -- логический тип

· type bit is ('0', '1'); -- битовый тип

· type character is (-- символьный тип

nul, soh, stx, etx, eot, enq, ack, bel,
bs, ht, lf, vt, ff, cr, so, si,
dle, dc1, dc2, dc3, dc4, nak, syn, etb,
can, em, sub, esc, fsp, gsp, rsp, usp,

' ', '!', '"', '#', '$', '%', '&', ''',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',

'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\', ']', '^', '_',

'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', del,

c128, c129, c130, c131, c132, c133, c134, c135,
c136, c137, c138, c139, c140, c141, c142, c143,
c144, c145, c146, c147, c148, c149, c150, c151,
c152, c153, c154, c155, c156, c157, c158, c159,

-- the character code for 160 is there (NBSP),
-- but prints as no char

' ', ' Ў ', ' ў ', ' Ј ', '¤', ' Ґ ', '¦', '§',
' Ё ', '©', ' Є ', '«', '', '­', '®', ' Ї ',
'°', '±', ' І ', ' і ', ' ґ ', 'µ', '¶', '·',
' ё ', '№', ' є ', '»', ' ј ', ' Ѕ ', ' ѕ ', ' ї ',

' А ', ' Б ', ' В ', ' Г ', ' Д ', ' Е ', ' Ж ', ' З ',
' И ', ' Й ', ' К ', ' Л ', ' М ', ' Н ', ' О ', ' П ',
' Р ', ' С ', ' Т ', ' У ', ' Ф ', ' Х ', ' Ц ', ' Ч ',
' Ш ', ' Щ ', ' Ъ ', ' Ы ', ' Ь ', ' Э ', ' Ю ', ' Я ',

' а ', ' б ', ' в ', ' г ', ' д ', ' е ', ' ж ', ' з ',
' и ', ' й ', ' к ', ' л ', ' м ', ' н ', ' о ', ' п ',
' р ', ' с ', ' т ', ' у ', ' ф ', ' х ', ' ц ', ' ч ',
' ш ', ' щ ', ' ъ ', ' ы ', ' ь ', ' э ', ' ю ', ' я ');

· type severity_level is (note, warning, error, failure); -- перечислимый тип

· type integer is range -2147483647 to 2147483647; -- целый тип

· type real is range -1.0E308 to 1.0E308; -- вещественный тип

· type time is range -2147483648 to 2147483647; -- целый тип

По аналогии пользователь может создавать свои типы данных, например, определим перечислимый тип - день недели:

· type day_t is (mon, tue, wen, thu, fri, sat, sun);

· signal day: day_t;

· day <= mon;

Сразу нужно отметить, что приведенный выше перечислимый тип вполне синтезируемый, но на кристалле он будет уже работать в виде ноликов и единичек. Синтезатор просто переведет данное множество значений в цифровое. Какое будет множество? А все зависит от настроек, например такое: {"000", "001",...,"110"}, а может такое: {"0000001", "0000010",...,"1000000"}

На рисунке 4 показаны пояснения к символу 'Z'. В принципе это простой высокий импеданс. Этот символ подходит как для моделирования, так и для синтеза, но следует отметить, что в ПЛИС такой сигнал можно реализовать только на выходных каскадах микросхемы.

Теперь давайте посмотрим на слабые сигналы (рисунки 5, 6, 7). Думаю понятно, почему они слабые, просто их можно "поддавить". При моделировании используются в основном как нагрузка на открытом коллекторе (или его имитации).

Вот пример на VHDL открытого коллектора с нагрузкой (на рисунке 8 приведена схемная реализация данного кода):

· out <= '0' when in = '1' else 'H';

Причем некоторые ПЛИС содержат такие резисторы в своих выходных каскадах, а некоторые синтезаторы даже подключат их, встретив такой VHDL-код. В крайнем случае, это можно сделать вручную через настройки выходов, правда, сопротивление таких резисторов порядка 50 кОм.

И наконец, загадочный символ '-', который используется только при моделировании и означает, что Вам плевать какое значение имеет сигнал. Автор никогда его не использовал, но может, есть такие ситуации, когда его использование целесообразно. Пример такого использования показан на рисунке 9.

А теперь давайте разберемся, причем здесь std_ulogic, когда мы хотели подробно говорить об std_logic. А все очень просто - буква 'u' в std_ulogic означает unresolved, что означает неразрешенный. Следовательно, std_logic является разрешенным подтипом, что, кстати, следует из его объявления в библиотеке std_logic_1164:

· subtype std_logic is resolved std_ulogic;

И далее объявляется вектор:

· type std_logic_vector is array (natural range <>) of std_logic;

Как видите, подтип std_logic образуется из типа std_ulogic c помощью разрешающей функции resolved, которая также объявлена и определена в библиотеке std_logic_1164. Для разрешения данных типа std_logic, функция resolved использует разрешающую таблицу, VHDL-код которой приведен ниже:

type stdlogic_table is array(std_ulogic, std_ulogic) of std_ulogic; constant resolution_table: stdlogic_table:= (

-- ---------------------------------------------------------

-- | U X 0   1 Z W L H -   | |
-- ---------------------------------------------------------

   ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'), -- | U |

   ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'), -- | X |

   ('U', 'X', '0', 'X', '0', '0', '0', '0', 'X'), -- | 0 |

   ('U', 'X', 'X', '1', '1', '1', '1', '1', 'X'), -- | 1 |

   ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X'), -- | Z |

   ('U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X'), -- | W |

   ('U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X'), -- | L |

   ('U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X'), -- | H |

   ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X') -- | - |

);

Данная таблица определяет, какой сигнал получится в итоге "столкновения" двух сигналов типа std_logic. Например, приходят сигналы '0' и 'H', смотрим, что в месте пересечения соответствующих строки и столбца получается '0'. И это не удивительно, если вспомнить, что сигнал '0' - сильный (рисунок 2), а 'H' - слабый (рисунок 5). Аналогично можно разрешить ситуацию и с другими сигналами.

Кроме того, в библиотеке std_logic_1164 переопределены операторы and, or, nand, nor, xor, xnor и not для типов std_ulogic и std_logic. И в той же библиотеке определены несколько полезных функций.

А теперь о главном. В отличие от библиотеки STD, библиотеку std_logic_1164 нужно подключать с помощью следующих VHDL инструкций:

· library ieee;

· use ieee.std_logic_1164.all;

· .......

· -- Дальше можно делать объявления std_logic

· signal a, b: std_logic;

· signal c: std_logic_vector(7 downto 0);

· shared variable d: std_logic_vector(7 downto 0):="01010101";

О МАССИВАХ В ЯЗЫКЕ VHDL

... Районы, кварталы, жилые массивы...

В разделах "ТИПЫ ДАННЫХ" и "ПОДРОБНО О STD_LOGIC" мы уже встречались с массивами. Как известно, массив — именованный набор однотипных переменных, доступ к которым осуществляется по индексу. Массивы могут быть одномерными и многомерными, что определяется количеством индексов. При использовании массивов в VHDL, разработчику следует учитывать, что синтезаторы обычно не поддерживают многомерные массивы, за исключением массивов векторов. Массив не может состоять из файлов.

ОПЕРАЦИИ В ЯЗЫКЕ VHDL

... операция: действие, воздействие, деятельность, сделка, поход, кампания, дело, дельце...

ОПЕРАТОРЫ VHDL

- а кто такие опсосы?
- это операторы сотовой связи.

Как и данные, операторы в языке VHDL могут быть синтезируемыми и нет. Кроме того, операторы принято делить на последовательные и параллельные, простые и составные. Как говорилось выше, мы не пытаемся написать учебник по VHDL и не будем подробно рассматривать каждый оператор. Приведем только несколько примеров.

Последовательные операторы в VHDL (не надо путать с последовательной логикой) определяют алгоритмы выполнения подпрограмм и процессов. Они выполняются в том порядке, в каком расположены в VHDL-коде, отсюда и название такое. Одно важное замечание: все последовательные операторы могут использоваться только в теле процесса, функции или процедуры. К последовательным операторам языка VHDL относятся следующие операторы:

· assert (последовательный);

· case;

· exit;

· if;

· loop;

· next;

· null;

· report;

· return;

· wait;

· последовательные операторы присваивания.

Примеры использования последовательных операторов:

· -- Использование операторов loop, next, exit, if, присваивание

· -- Несинтезируемый фрагмент VHDL-кода подсчитывает кол-во несовпадающих бит в двух массивах

· neq:= 0;

· L1: for i in 0 to 31 loop

· next L1 when mem1(i) = mem2(i);

· for j in 7 downto 0 loop

· crash:= 1;

· exit L1 when (mem1(i)(j) = 'X' or mem2(i)(j) = 'X');

· crash:= 0;

· if (mem1(i)(j) /= mem2(i)(j)) then neq:= neq+1;

· end loop;

· end loop L1;

· -- Использование операторов wait, case, if

· -- Синтезируемый фрагмент VHDL-кода управляет состояниями сфетофора

· process begin

· wait until clk;

· if (trig = '1') then

· case state is

· when red => state <= green;

· when green => state <= yellow;

· when yellow => state <= red;

· end case;

· end if;

· end process;

Параллельные операторы в VHDL используются для определения блоков и процессов, которые описывают общее поведение или структуру проекта. Параллельные операторы VHDL, как следует из названия, выполняются (или не выполняются) параллельно друг другу и независимо от расположения в VHDL-коде. К таким операторам относятся:

· assert (параллельный);

· block;

· generate;

· process;

· применение компонентов (port map...);

· параллельные операторы присваивания.

Примеры использования оператора block:

· -- Пример защелки с использованием охранного выражения

· L1: block (LE = '1')

· begin

· Q <= guarded D; -- Выполнится только при LE = '1'

· end block L1;

· -- Пример простых блоков

· BLOCK1: block

· signal Q: std_logic;-- Этот сигнал Q виден только в BLOCK1

· begin

· Q <= A and B;

· end block BLOCK1;

· -----------------------------------

· BLOCK2: block

· signal Q: std_logic;-- Этот сигнал Q виден только в BLOCK2

· begin

· Q <= C and D;

· end block BLOCK2;

· -- Пример вложенных блоков

· BLOCK1: block

· signal Q: std_logic;-- Этот сигнал Q виден в BLOCK1 и в BLOCK2

· begin

· Q <= A and B;

· -----------------------------------

· BLOCK2: block

· signal Q1: std_logic;-- Этот сигнал Q1 виден только в BLOCK2

· begin

· Q1 <= Q and C;

· end block BLOCK2;

· -----------------------------------

· end block BLOCK1;

Следует отметить, что охранные блоки не синтезируются ни одним из известных автору синтезатором. Другие виды блоков нормально синтезируются, но и без них можно вполне обходиться. Во всяком случае, автор, кроме как в примерах, больше нигде не встречал применение блоков. Хотя на вкус и цвет...

ИНТЕРФЕЙС

... да вот фейс-то у меня не подходящий.

Ну чтож, вот мы и подошли к какому-то началу. Как говорится интерфейс он и в Африке интерфейс. То есть это те же входные и выходные сигналы, а также какие-нибудь передаваемые в архитектуру параметры, оформленные по правилам языка VHDL. В общем виде объявление интерфейса выглядит следующим образом:

· entity NAME_ENTITY is

· ----------------------------

· generic (

· -- Здесь указываются параметры);

· port (

· -- Здесь указываются порты);

· -- Область объявлений

· begin --ставится, если далее следуют параллельные операторы интерфейса

· -- Параллельные операторы (обычно assert), вызовы подпрограмм

· end NAME_ENTITY;

Приведем пример общего случая VHDL интерфейса, при этом не забываем объявлять библиотеки, если необходимо:

· library ieee;

· use ieee.std_logic_1164.all;

· entity ADDER_N is

· ----------------------------

· generic (

· -- Задаем разрядность сумматора

· N: natural:= 4);

· ----------------------------

· port (

· a, b: in std_logic_vector(0 to N-1); -- Операнды

· s: out std_logic_vector(0 to N-1); -- Сумма

· c: out std_logic -- Перенос

· );

· ----------------------------

· constant GND: std_logic:= '0';

· constant VCC: std_logic:= '1';

· constant TRI: std_logic:= 'Z';

· ----------------------------

· begin

· ----------------------------

· assert N > 1

· report "N is too small"

· severity error;

· ----------------------------

· end ADDER_N;

АРХИТЕКТУРА

... после программы ВРЕМЯ - архитектор перестройки.

ПРОЦЕССЫ

... процесс пошел.

Давайте продолжим развивать наш VHDL-проект. Пусть наше устройство будет программируемым, и сигналами разрешения/запрещения индикации ошибки будет управлять внешний процессор через управляющий регистр RegUpr. Итак, нам нужен регистр. Давайте напишем VHDL-интерфейс нашего регистра.

· ---------------------------------

· -- VHDL-интерфейс регистра

· ---------------------------------

· library ieee;

· use ieee.std_logic_1164.all;

· ---------------------------------

· entity RegUpr is

· port (

· wr, cs: in std_logic;

· addr: in std_logic_vector(1 downto 0);

· datain: in std_logic_vector(7 downto 0);

· en1, en2: out std_logic

· );

· end RegUpr;

· ---------------------------------

Теперь нам нужно сделать так, чтобы регистр реагировал на определенную комбинацию сигналов rw, cs и addr. В языке VHDL добиться этого можно несколькими способами. Один из способов это организовать процесс. В общем виде VHDL-процесс записывается так:

· LABEL: process (лист чувствительности)

· -- область деклараций

· begin

· --VHDL операторы

· end process;

Язык VHDL допускает процессы без меток, а также отсутствие листа чувствительности при наличии в теле процесса хотябы одного оператора wait. C учетом вышесказанного, напишем архитектуру регистра на VHDL:

· -----------------------------------

· -- VHDL-архитектура регистра

· -----------------------------------

· architecture arch of RegUpr is

· signal regupr: std_logic_vector(7 downto 0);

· begin

· -------------------------------

· -- VHDL-процесс регистра

· -------------------------------

· process (wr, cs, addr)

· begin

· if (cs = '1' and wr = '0') then

· case addr is

· when "01" => regupr <= datain;

· when others => null;

· end case;

· end if;

· end process;

· en1 <= regupr(0);

· en2 <= regupr(1);

· end arch;

Все хорошо, но смущает сигнал выбора устройства. Конечно без него никак, потому как адресная шина процессора наверняка больше, чем наши два разряда. Но есть вопрос, кто его формирует. Конечно, многие современные процессоры могут сами формировать несколько CS для разных областей адресного пространства, но мы в учебных целях будем считать, что дешифрация адреса возложена на периферию. Итак, нам нужен дешифратор адреса. Пусть адрес стробируется сигналом ALE. Тогда нам надо как-то ловить этот строб. Вот таким вот путем мы и подошли к атрибутам VHDL, которые и рассмотрим в следующем разделе.

АТРИБУТЫ

... а компьютер считался атрибутом буржуазного общества.

Атрибуты - это различные характеристики объектов VHDL. Они делятся на предопределенные и пользовательские. Мы рассмотрим и те и другие, хотя использование пользовательских атрибутов очень обременительно и мало что дает, но может кому-то и понравится.

Предопределенные атрибуты делятся на три группы - атрибуты сигналов, атрибуты массивов и атрибуты типов. Давайте мы их так и будем рассматривать. В таблице 1 приведены атрибуты сигналов, в таблице 2 - массивов, в таблице 3 - типов данных.

Таблица 1

Атрибут Описание
S'active TRUE, если было присвоение, но текущее значение еще прежнее
S'delayed(t) Значение сигнала, существовавшее на время t перед вычислением данного атрибута
S'event TRUE, если происходит изменение сигнала
S'last_active Время от последнего присвоения значения сигналу до момента вычисления атрибута
S'last_event Время от последнего изменения сигнала до момента вычисления атрибута
S'last_value Последнее присвоенное сигналу значение
S'stable(t) TRUE, если не происходило изменение сигнала в течение времени t
S'transaction TRUE, если происходит очередное присвоение значения сигналу
S'quiet FALSE, если было присвоение, но текущее значение еще прежнее

 

Таблица 2

Атрибут Описание
A'left(N) Левая граница N-го индекса массива А
A'right(N) Правая граница N-го индекса массива А
A'high(N) Верхняя граница N-го индекса массива А
A'low(N) Нижняя граница N-го индекса массива А
A'range(N) Диапазон N-го индекса массива А
A'reverse_range(N) Обратный диапазон N-го индекса массива А
A'length(N) Длина диапазона N-го индекса массива А

 

Таблица 3

Атрибут Описание
T'base Базовый тип данных
T'left Левая граница значений T
T'right Правая граница значений T
T'high Верхняя граница значений T
T'low Нижняя граница значений T
T'pos(X) Позиция значения Х в наборе значений Т
T'val(N) Значение элемента в позиции N набора значений Т
T'succ(X) Значение в наборе значений T, на одну позицию большее X
T'pred(X) Значение в наборе значений T, на одну позицию меньшее X
T'succ(X) Значение в наборе значений T, на одну позицию вправо от X
T'pred(X) Значение в наборе значений T, на одну позицию влево от X

 

Несколько слов о пользовательских атрибутах в языке VHDL. Раньше было модно назначать пины микросхемы прямо в VHDL-коде через пользовательские атрибуты, и компилятор брал эти значения и минуя синтезатор передавал их разводчику. Но сейчас такое почти нигде не практикуется. Во первых Вы можете не знать на этапе написания VHDL-кода, какую микросхему примените, во вторых сам компилятор может не знать, каким разводчиком Вы воспользуетесь, потому что серьезные разработчики практически не пользуются программами "все в одном флаконе", да и нет сейчас таких фирм, чтобы сами все делали, все равно синтезаторы от одной фирмы, компиляторы от другой, разводчики от третьей, а симуляторы от четвертой, все это в одну оболочку собрали и обозвали, к примеру, КВАРТУС II.

Но в качестве примера такие атрибуты подойдут в самый раз:

· entity example is

· port (res, clk: in std_logic;

· data_in: in std_logic_vector(3 downto 1);

· data_out: out std_logic_vector(3 downto 1)

· );

· attribute pinnum: string;-- Определили атрибут pinnum

· attribute pinnum of res signal is "5";-- Здесь и далее назначаем пины

· attribute pinnum of clk signal is "9";

· attribute pinnum of data_in signal is "11, 12, 13";

· attribute pinnum of data_out signal is "18, 20, 64";

· end example;

ПОДПРОГРАММЫ VHDL

...

В VHDL используется два вида подпрограмм - это функции и процедуры. В библиотеке std_logic_1164 описаны различные функции, в том числе и rising_edge()/falling_edge() определение которых выглядит так:

· function rising_edge (signal s: std_ulogic) return boolean is

· begin

· return (s'event and s = '1');

· end;

· function falling_edge (signal s: std_ulogic) return boolean is

· begin

· return (s'event and s = '0');

· end;

А так как мы используем библиотеку std_logic_1164, то спокойно можем задействовать эти функции. Теперь давайте напишем наш дешифратор 16-ти разрядного адреса:

· library ieee;

· use ieee.std_logic_1164.all;

· ---------------------------------

· entity dec is

· port (res, ale: in std_logic;

· addr: in std_logic_vector(15 downto 2);

· cs: out std_logic);

· end dec;

· ---------------------------------

· architecture dec_arch of dec is

· begin

· process (res, ale)

· begin

· if (res = '1') then

· cs <= '0';

· elsif rising_edge(ale) then

· if (addr = "11000011110000") then -- Это наше адресное пространство

· cs <= '1';

· else

· cs <= '0';

· end if;

· end if;

· end process;

· end dec_arch;

У нас получился работоспособный дешифратор адреса, а теперь приведем пример ошибки, которую часто допускают начинающие разработчики:

· architecture dec_arch of dec is

· signal addr_valid: std_logic_vector(15 downto 2);

· begin

· process (res, ale)

· begin

· if (res = '1') then

· addr_valid <= "00000000000000";

· elsif rising_edge(ale) then

· addr_valid <= addr;

· end if;

· if (addr_valid = "11000011110000") then -- Это наше адресное пространство

· cs <= '1';

· else

· cs <= '0';

· end if;

· end process;

· end dec_arch;

Для начинающих и поясним. Ошибка не в VHDL-коде, такой код пропустит любой САПР без запинки. Но дело в том, что в момент переключения по стробу addr_valid будет принимать всевозможные "случайные" значения, так называемый "дребезг". И есть шанс, что в какой-то момент addr_valid примет значение "11_0000_1111_0000", тогда cs примет валидное значение и неизвестно что будет с нашей схемой обработки ошибки. Подобные ошибки очень коварны, они не всегда о себе дают знать, моделирование может не выявить их, даже в железе может все работать нормально. Но изменение температурного режима, переход на другой тип микросхемы и т. п. может сразу привести к негативному результату.

Давайте продолжим развивать наш проект. Было бы расточительным, если бы наш дешифратор адреса выбирал бы только одно устройство. Пускай он еще выбирает внешнее статическое ОЗУ 32х8, согласно рисунку 15.

Давайте перепишем наш дешифратор:

· library ieee;

· use ieee.std_logic_1164.all;

· ---------------------------------

· entity dec is

· port (res, ale, cs: in std_logic;

· addr: in std_logic_vector(15 downto 5);

· cs_er, cs_ram: out std_logic);

· end dec;

· ---------------------------------

· architecture dec_arch of dec is

· begin

· process (res, ale)

· signal s_cs_ram, s_cs_er: std_logic;

· begin

· if (res = '1') then

· s_cs_ram <= '0';

· s_cs_er <= '0';

· elsif rising_edge(ale) then

· if (addr = "00000000000") then -- Адресное пространство ОЗУ

· s_cs_ram <= '1';

· s_cs_er <= '0';

· elsif (addr = "00000000001") then -- Адресное пространство устройства

· s_cs_ram <= '0';

· s_cs_er <= '1';

· else

· s_cs_ram <= '0';

· s_cs_er <= '0';

· end if;

· end if;

· end process;

· cs_ram <= s_cs_ram and cs;

· cs_er <= s_cs_er and cs;

· end dec_arch;

На рисунке 16 показано, как данный VHDL-код был воспринят квартусом. Обратите внимание, что код elsif rising_edge(ale) then реализован в виде входов синхронизации триггеров, на которые заводится сигнал ale, чего мы в принципе и хотели.

Сделаем соответствующие изменения в нашем устройстве, подключив дешифратор:

· library ieee;

· use ieee.std_logic_1164.all;

· ---------------------------------

· entity ERR_LED is

· port (

· -- Сигналы управления и шины процессора

· res, wr, oe, cs, ale: in std_logic;

· addr: in std_logic_vector(15 downto 0);

· data: in std_logic_vector(7 downto 0);

· -- Сигналы управления ОЗУ

· cs_ram, wr_ram, oe_ram: out std_logic;

· -- Сигналы управления индикацией

· ERR1, ERR2: in std_logic;

· LED: out std_logiс

· );

· constant GND: std_logic:='0';

· constant TRI: std_logic:='Z';

· end ERR_LED;

· ---------------------------------

· architecture led_arch of ERR_LED is

· signal serror, en1, en2, s_cs_er: std_logic;

· signal addr_h: std_logic_vector(15 downto 5);

· signal addr_l: std_logic_vector(1 downto 0);

· begin

· addr_h <= addr(15 downto 5);

· addr_l <= addr(1 downto 0);

· C0: entity WORK.dec(dec_arch) port map(res => res, ale => ale, cs => cs, addr => addr_h, cs_er => s_cs_er, cs_ram => cs_ram);

· C1: entity WORK.RegUpr(arch) port map(wr => wr, cs => s_cs_er, en1 => en1, en2 => en2, datain => data, addr => addr_l);

· C2: entity WORK.NAND2X3(bbb) port map(a => ERR1, b => en1, c => ERR2, d => en2, q => serror);

· LED <= GND when serror = '1' else TRI;

· wr_ram <= wr;

· oe_ram <= oe;

· end led_arch;

Для того чтобы смоделировать работу ПЛИС в схеме, показанной на рисунке 15, нам нужно иметь модели процессора и ОЗУ. Но если модель ОЗУ мы легко можем написать на VHDL сами, то модель процессора написать достаточно долго и трудно, если у Вас есть деньги, то модель можно купить у производителя. Но по большому счету, чтобы проверить работу ПЛИС, нам необязательно иметь модель процессора, достаточно имитировать его сигналы в соответствии с временными диаграммами, взятыми из DATASHEET. Реальным DATASHEET мы пользоваться не будем, а воспользуемся упрощенными временными диаграммами (рисунки 17, 18).

БИБЛИОТЕКИ VHDL

... библиотека - учреждение, собирающее и хранящее произведения печати и письменности для общественного пользования

Как и в языках программирования, в VHDL имеется возможность подключать различные библиотеки с заранее написанным кодом. Библиотеки могут быть скомпилированными для определенного САПР или быть в исходных кодах. Мы уже использовали библиотеки STD (встроенная в VHDL), IEEE (конкретно std_logic_1164), а также все нами написанное по умолчанию компилируется в библиотеку WORK. Кроме того, многие САПР подключают свои библиотеки примитивов и у нас тут не все гладко. Многие САПР возмутятся, что мы определили элемент NAND2, так как в их библиотеке примитивов уже есть такое определение. Тут можно просто переименовать NAND2 в MY_NAND2 или задействовать готовый элемент.

Мы можем создавать свои библиотеки, чем и займемся в этом разделе. У нас конечно не очень много VHDL-кода и вообще говоря создавать библиотеку для нашего проекта нецелесообразно, так как все прекрасно и удобно размещается в одном файле. Но чтобы разобраться, что к чему, давайте создадим VHDL-библиотеку. В общем виде VHDL-библиотека выглядит так:

· package package_name is

· -- Объявления типов и подтипов

· -- Объявления сигналов и констант

· -- Объявления функций, процедур и компонентов

· end package_name;

· ----------------------------------------

· package body package_name is

· -- Определения функций

· -- Определения процедур

· end package_name;

ТЕСТИРОВАНИЕ

...

ЗАКЛЮЧЕНИЕ

...

Вот мы и закончили наш проект. Кому интересно, тот может скачать архив написанного нами VHDL-проекта. Еще раз следует отметить, что все изложенное здесь не является учебником по VHDL, а лишь является пособием. Полученный проект является небольшим кусочком реального большого проекта, который успешно работает на объектах нашей Родины. Но для написания большого проекта, целесообразно разбить его на несколько функциональных узлов. Очень часто такие узлы на VHDL описывают разные люди, а затем эти узлы объединяются в одно устройство.

Следует отметить еще один момент. При написании этой странички, в VHDL-код могла закрасться ошибка. Автор будет очень признателен если Вы сообщите об этом по адресу [email protected].

ПРИЛОЖЕНИЕ А

...

Таблица 4

abs disconnect label port srl
access downto library postponed subtype
after   linkage procedure  
alias else literal process then
all elsif loop protected to
and end   pure transport
architecture entity map   type
array exit mod range  
assert     record unaffected
attribute file nand register units
  for new reject until
begin function next rem use
block   nor report  
body generate not return variable
buffer generic null rol  
bus group   ror wait
  guarded of   when
case   on select while
component if open severiti with
configuration impure or shared  
costant in others signal xnor
  inertial out sla xor
  inout   sll  
  is package sra  

 

 

Список литературы для изучения vhdl

 

Бибило П.Н., "Основы Языка VHDL"

Описывается применение языка VHDL на алгоритмическом и логическом уровнях проектирования цифровых систем. Язык VHDL является международным стандартом в системах автоматизации проектирования и преджназначен для спецификации, моделирования и синтеза цифровых систем на основе заказных и и программируемых пользователями сверхбольших интегральных схем.

Книга предназначена для первоначального ознакомления с языком VHDL и может быть полезна студентам, аспирантам и специалистам, занимающимся разработкой электронной аппарратуры с помощью САПР.

Зотов В.Ю., "Проектирование встраиваемых микропроцессорных систем на основе ПЛИС фирмы XILINX"

Книга предназначеня для самостоятельного изучения методики сквозного проектирования встраиваемых микропроцессорных систем на базе программируемых логических интегральных схем (ПЛИС) фирмы XILINX. Представлено подробное описание характеристик, архитектуры и системы комманд микропроцессорных ядер семейства PicoBlaze и MicroBlaze, применяемых в качестве основы встраеваемых систем. Рассмотренны этапы проектирования 8-разрядных микропроцессорных систем, реализумых на базе ПЛИС с архитектурой FPGA, с использованием ядер семейства PicoBlaze, и их выполнение в рамках САПР серии XILINX ISE (Integrated Software Environment) версии 7.1i. Дана развернутая характеристика основных этапов разработки 32-разрядных встраеваемых систем, выполняемых на основе микропроцессорных ядер семейства MicroBlaze. Рассмотрен процесс осуществления этих этапов с помощью комплекса средств автоматизированного проектирования встраеваемых микропроцессорных систем Xilinx Embedded Development Kit (EDK). Приведены исходные тексты VDL-описаний микропроцессорных ядер семейств PicoBlaze.

Материал, изложенный в книге, также может быть использован в процессе самострятельного освоения средства проектирования 32-разрядных встраиваемых микропроцессорных систем Xilinx EDK версии 7.1i.

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


Поделиться с друзьями:

Адаптации растений и животных к жизни в горах: Большое значение для жизни организмов в горах имеют степень расчленения, крутизна и экспозиционные различия склонов...

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.516 с.