Язык vhdl для плис
VHDL с нуля.
VHDL с нуля. Выпуск первый — VHDL в картинках.
Статья предназначена для желающих освоить VHDL с нуля, но более опытное пользователи могут читать и вносить свои предложения. О языке буду рассказывать безотносительно какого-либо железа, так как особенности синтеза и реализации в железе написанного кода это отдельная тема, здесь же я хотел бы передать концепцию(идею) проектирования(да именно проектирования, а не программирования) цифровых устройств с использованием языка VHDL. В качестве среды для моделирования буду использовать ModelSim. Так как существует достаточное количество статей по VHDL, например тут, некоторые места не буду подробно рассматривать, а буду ссылаться. По поводу точности определений, для маньяков таких как я, любящих точные определения есть стандарт(тут), но читая его можно сломать мозг и как это не парадоксально, чтобы его читать уже нужно иметь представление о языке, как мне кажется. В данной статье я попытаюсь менее четко формулировать понятия, для того что бы сделать их более понятными, принимаются все предложения по их коррекции.
VHDL(Very high speed integrated circuits Hardware Description Language)- данный язык предназначен для описания проектируемых систем на схемотехническом уровне проектирования и замены классического подхода к схемотехническому проектированию на уровне отдельных элементов. Язык позволяет описывать цифровые ситемы на алгоритмическом уровне. При помощи специального программного обеспечения описание на языке VHDL преобразовывается в схему на уровне простейших элементов цифровой электроники. Описание на языке применятся VHDL как при проектировании
заказных СБИС так и при проектировании цифровых систем на базе специальных устройств ПЛИС(Программируемые логические интегральные схемы).
Теперь перейдем к основным понятиям языка(это моя трактовка):
Как же выглядит структура проекта. заглянем в замечательную книгу П.Н.Бибило Основы языка VHDL.
Что мы видим из рисунка: на одном уровне описывается интерфейс объекта проекта и архитектура объекта проекта, плюс если требуется к каждому интерфейсу можно подключить требующийся пакет. В свою очередь тело архитектуры состоит из параллельных операторов, среди которых может быть оператор процесса, содержащий последовательные операторы. Обратите внимание, что сигналы декларируются на уровне архитектуры, а переменные на уровне отдельных процессов и используются внутри их.
Всего имеется четыре класса типов: скалярный, составной, файловый и ссылочный(в стандарте за 200 год нашел еще пятый — защищенный тип, может потом рассмотрю). Вот они
Зелененьким светофором обозначил типы которые синтезируются, т.е. их смело можно использовать при написании программ для программирования ПЛИС. Пример объявления типов посмотри на основе предопределенных типов в пакете STANDART.
Достану несколько оттуда:
С остальными типами советую ознакомится из пакета. При синтезе используется пакет std_logic_1164. Он хорошо описан в статье, на которую я дал ссылку в начале. Единственное, не рассмотрено использование безразличного состояния, его применение я рассмотрю позже.
Еще один нюанс, необходимо понимать, что все типы при синтезе преобразовываются в типы std_logic(расширенный эквивалент bit) и std_logic_vector(расширенный эквивалент bit_vector).Т.е. все значения перечислимых типов будут закодированы двоичными комбинациями и целый тип так же будет закодирован двоичными комбинациями.
Способы задания значений.
В VHDL для задания числовых значений используются литералы. Вот они
Далее посмотрим декларации, которые нам могут понадобится в самом начале, более сложные будем рассматривать позже при рассмотрении последующих тем.
Операторы используемые в выражениях.
Я думаю здесь все понятно, объясню только оператор конкатенации(&) — он нужен для объединения нескольких битовых строк в одну.
1. Оператор присваивания значений переменной(:=) — A := B and C;
Что такое VHDL. Простейший пример создания логического элемента в ПЛИС
Вот вокруг говорят ПЛИС, ПЛИС… Понятно что это микросхема такая… А как в нее электрическую схему заталкивать? Для этого существует несколько способов, один из которых это описание схемы устройства на специальном языке описания аппаратуры. Таких языков существует несколько: Verilog, AHDL, VHDL и наверное еще есть, но мне не попадались. Эти три вроде самые распространенные. Вот о VHDL я и попробую рассказать.
Почему VHDL? Он как и Verilog поддерживается большинством производителей ПЛИС, в то время как AHDL разрабатывался сугубо для Альтеры. Ну и в свое время по VHDL мне удалось достать литературу на русском языке. ПЛИС достаточно сложные устройства и читать кроме даташита еще и описание языка на буржуйском — рвет мозг на мелкие кусочки.
Чем VHDL отличается от обычных языков программирования типа Си, Паскаля и т.д.? Самое главное отличие в том, что VHDL описывает параллельные процессы. Если код на Си или Паскале у нас выполняется по очереди команда за командой и надо изощряться с таймерами и прерываниями чтоб обработать разные куски кода «одновременно», то на VHDL разные блоки программы выполняются параллельно друг другу, но в тоже время в VHDL есть часть комманд, которые выполняются последоватеьно. Поэтому структура программы в корне отличается от привычной микроконтроллерной.
Структура программы
Процесс программирования на VHDL чем то напоминает создание принципиальной схемы устройства.
Шаг 1: Включение в код используемых библиотек.
Шаг 2: Описание точек входа и точек выхода устройства (аналогично входам и выходам принципиальной схемы всего устройства).
Шаг 3: Описание точек входа и выхода элементов входящих в устройство (аналогично назначению функций ногам контроллера и другой логике в схеме)
Шаг 4: Описание архитектуры элементов входящих в устройство (вроде подбора логики типа ИЛИ-НЕ, И-НЕ, вобщем описание того как выход элемента завязан с его входом)
Шаг 5: Описание архитектуры всего устройства (типа соединения проводниками всех элементов схемы)
Чтобы это все было не голословно, попробуем создать с помощью VHDL простой элемент, например 16-ти разрядный счетчик, который считает по переднему фронту импульса.
Что еще нам надо знать, чтобы переходить к созданию первой программы на VHDL?
Основные структуры данных, с которыми мы можем работать. В литературе они называются классами объектов. Их три:
— константы
— переменные
— сигналы
Константы имеют тот же смысл, что и в других языках и определяются ключевам словом «constant«:
Символы «—» означают комментарий
ВАЖНО: в VHDL нет разницы между строчными и прописными буквами в идентификаторах. То есть константы MyConst и mYcONST это на самом деле одна и таже константа.
Есть еще одно важное правило: идентификатор не должен оканчиваться подчеркиванием.
Переменные имеют практически тот же смысл, что и в других языках. Определяются ключевым словом «variable«:
Переменная i типа integer принимающая значения в диапазоне от 0 до 31. Описание диапазона позволяет точно определить разрядность переменной, что существенно экономит ресурсы кристалла. Присваивание переменной выполняется с помощью знака «:=».
Сигналы это очень важный класс в VHDL. Они похожи на переменные, НО физически имеют смысл проводников на печатной плате. Это значит, что сигнал всегда имеет некоторое значение.
Описываются сигналы с помощью ключевого слова «signal«:
Комментарии ( 24 )
Сейчас буду пинать ногами))
Вы говорили что сами изучали язык и ждете критику, я тоже сам изучал язык, буду критиковать, или пояснять.
Назначение одного сигнала можно выполнить только один раз.
назначение сигнала можно выполнять сколько угодно раз, главное чтобы это было в одном процессе, это связано с физической реализацией, т. к. процессы могут выполнятся одновременно, то и значение сигнала тоже может изменится одновременно, поскольку сигнал эквивалентен проводнику на плате, то это не возможно.
Назначение сигнала происходит при выходе из процесса.
Сигналы нужны для связи между процессами одной архитектуры, т. к. переменные (variable) видны только внутри процесса.
По чему вы учились? у меня это была книга «Основы языка VHDL» Бибило П.Н.
Основы VHDL. Пример проще простого.
Основы VHDL. Пример проще простого.
Сначала хотелось бы в вкратце описать процесс проектирования с использованием языка VHDL.
Этот процесс выглядит следующим образом:
1. Описание проекта на уровне алгоритма
* Выполняется поведенческое описание, абсолютно абстрактно, не привязываясь к какому либо железу, что кстати можно делать и на C
2. Моделирование работы поведенческого описания устройства
* Проверяем правильно ли работает придуманный нами алгоритм
3. Перерабатываем нашу поведенческую модель в синтезируемую и синтезируем схему
* Дело в том, что не все конструкции языка можно реализовать в виде железа. Простой пример это тип Real — вещественный тип, поведенческое описания с его использованием можно выполнить и промоделировать, но для реализации в железе придется написать устройство для работы с такими числами.
* При синтезе определенные конструкции языка реализуются в виде соответствующих им элементам цифровой электроники(мультиплексоры, логические элементы, дешифраторы и т.д.)
4. Проводим моделирование синтезированной модели
* На этом этапе можно уже оценить временные задержки в разрабатываемом устройстве, так как простейшие элементы обладают определенными задержками, да и можно оценить сколько логики требуется для реализации.
5. Проводим размещение и трассировку на кристалле нашего проекта
* В простейшем случае от нас потребуется связать конкретные Пины ПЛИС с портами(входами/выходами) нами разрабатываемого устройства.
* На этом этапе синтезируемая модель виртуально размещается в кристалле на базе имеющихся в составе ПЛИС элементов цифровой электроники и происходит организация внутренних связей.
6. Проводится моделирования работы размещенной в ПЛИС схемы, с учетом реальных задержек в элементах ПЛИС и задержек на линиях передачи.
* Здесь получаем достоверные временные характеристики нашего устройства проекта на ПЛИС.
* Получаем файл для программирования ПЛИС.
7. Программируем ПЛИС и радуемся жизни.
Примерно так выглядит в проектирование цифровых устройств с применением ПЛИС. Как видим ничего сложного тут нет.
Теперь предлагаю попробовать написать первый проект на VHDL.
VHDL на мой взгляд язык простой, но есть свои особенности. Язык тот имеет признаки высокоурожайного, но все таки не объектноориентированный, но это компенсируется большим количеством библиотек и пакетов( что то вроде библиотек в С).
Теперь рассмотрим основные понятия языка:
* Интерфейс — описывает наше с вами устройство, как черный ящик с входами и выходами, т.е. главная его задача показать какие входы и выходы есть у нашего устройства для связи с внешним миром.( Если взять человека, то можно его как кусок мяса с портами работающими на ввод — глаза, уши и.т.д, и на вывод — гортань, руки и т.д.)
* Архитектура — описывает поведение нашего устройства или раскрывает его внутреннюю структуру, т.е. в архитектуре описывается алгоритм функционирования нашего устройства. Стоит обратить внимание, что архитектура может быть описана в общем случае двумя вариантами: поведенческим стилем(описывается алгоритм работы устройства) и структурным стилем(описывается структура устройства).
Поведенческий стиль удобно использовать при описании элементов на низком уровне иерархии, а структурным на верхних уровнях иерархии, т.е. написать много маленьких устройств поведенческих стилем, а потом описать состоящие из них устройство структурным стилем, в виде связей между ними.
* Операторы языка — операторы в языке бывают последовательные, а бывают параллельные. Параллельные операторы вводятся для того, чтобы отобразить параллельность протекающих в железе процессов. Но любой параллельный оператор можно заменить оператором процесса с последовательными операторами внутри его, он как раз для этого и предназначен. По-этому я бы посоветовал, тем кто переходит с контроллеров и просто программирования, использовать оператор процесса с последовательными операторами, так как это более привычно для них.
Представим. что перед нами стоит задача описать цифровое устройство заданное следующей таблицей истинности(x — входные состояния, y — выходное состояние):
Применим сначала классический метод проектирования ЦУ, построим карту Карно, получим минимизированную функцию системы и построим схему.
В результате получим два поля 1 порядка и функцию системы Y = x1*x0 + x2’*x0′. Апострофами обозначил отрицание.
Построим схему:
Для человека плохо разбирающегося в цифровой электронике приведенный выше процесс довольно туманный.
Теперь рассмотрим проектирование той же системы, но на языке VHDL.
1. Исходя из таблицы истинности видим, что у нас 3 входных порта и один выходной. На основе этого можем описать интерфейс нашего устройства. Описывается он при помощи ключевого слова entity. Синтаксис объявления интерфейса имеет следующий вид:
entity ID is
[generic (
[port (
[
[begin
end [entity] ENTITYID;
Сразу так и не врубится, но посмотрим повнимательней.
[] — необязательная конструкция
<> — конструкция, которая может повторятся сколько угодно раз
| — альтернативные варианты
Пока нам требуется только знать, что все вход\выход порты описываются после ключевого слова port.
В нашем случае получится следующий вариант:
entity Sys is
port(X: in bit_vector(2 downto 0);
y: out bit);
end Sys;
Что получается — у нас один порт работающий на ввод(in) и один порт работающий на вывод(out), при этом тип выходного порта bit — грубо говоря это значит, что наш порт одноразрядный, а входной порт имеет тип bit_vector — это массив типа bit, запись вида bit_vector(2 downto 0) обозначает 3 разрядный порт, где каждый разряд это bit. Тип bit может, является перечислимым типом и принимает два значения (‘0′,’1’).
* На этом этапе получили черный ящик, с описанием его портов ввода/вывода.
2. На втором этапе опишем поведение нашего устройства, для этого требуется описать архитектуру. Смотрим на ее синтаксис:
architecture ID of ENTITYID is
[
begin
[
end [architecture] ARCHID;
Как видно архитектура должна принадлежать какому-то интерфейсу и ее тело состоит из параллельных операторов. Мы используем один параллельный оператор процесса и разместим там привычные нам последовательные операторы.
Если подумать, как можно реализовать таблицу истинности, то можно прийти к выводу, что лучше всего использовать оператор который выполнял какие либо действия в зависимости от состояния переменной, в С таким оператором является switch(), а в VHDL case. Это значит, что нам потребуется рассмотреть синтаксис оператора процесса и оператора case.
Оператор процесса:
[LABEL:] [postponed] process [(
[
begin
[
end [postponed] process [LABEL];
Если не вдаваться в подробности, то видно что внутри процесса расположены последовательные операторы, то что нам нужно. В скобках после ключевого слова process указывается список чувствительности, т.е. те сигнала при изменении которых процесс запускается или срабатывает, при синтезе этот список просто игнорируется, но он необходим для правильного выполнения моделирования.
Оператор case
[LABEL:] case expr is
<when choice [<| choice>] =>
end case [LABEL];
Видно, что проверяется значение сигнала или переменной — выражение expr, и в зависимости от его значения выполняется один из набора последовательных операторов.
Введение в язык описания аппаратуры: начало работы с VHDL для проектирования цифровых схем
В данной статье рассматривается VHDL, язык описания аппаратного обеспечения, и то, как он структурируется при описании цифровых схем. Мы также рассмотрим некоторые вводные примеры описаний схем и коснемся различий между типами данных » std_logic » и » bit «.
VHDL является одним из широко используемых языков описания аппаратуры (HDL, Hardware Description Language). VHDL означает язык описания аппаратуры VHSIC. В свою очередь, VHSIC означает высокоскоростная интегральная микросхема (Very-High-Speed Integrated Circuit).
Создание VHDL было инициировано Министерством обороны США в 1981 году. Сотрудничество таких компаний, как IBM и Texas Instruments, привело к выпуску первой версии VHDL в 1985 году. Xilinx, которая выпустила первую микросхему FPGA в 1984 году, вскоре поддержала VHDL в своих продуктах. С тех пор VHDL превратился в развитый язык в области проектирования, моделирования и синтеза цифровых схем.
В данной статье мы вкратце обсудим общую структуру кода VHDL при описании заданной схемы. С помощью некоторых вводных примеров мы также познакомимся с некоторыми широко используемыми типами данных, операторами и так далее.
Общая структура кода VHDL
Рассмотрим простую цифровую схему, показанную на рисунке 1.
Рисунок 1 – Простая цифровая схема
На этом рисунке показано, что есть два входных порта (a и b) и один выходной порт (out1). На рисунке показано, что входные и выходные порты имеют ширину один бит. Функциональность схемы – это выполнение логической операции И двух входов и вывод результата на выходной порт.
VHDL использует похожее описание; однако он имеет свой собственный синтаксис. Например, для описания входных и выходных портов этой схемы используются следующие строки кода:
Давайте по очереди разберемся, что это значит.
Строка 1. Первая строка указывает произвольное название для описываемой схемы. Слово « circuit_1 », которое находится между ключевыми словами « entity » и « is », определяет имя этого модуля.
Строки с 2 по 4. Эти строки определяют входные и выходные порты схемы. Сравнивая эти строки со схемой, изображенной на рисунке 1, мы видим, что порты схемы вместе со своими функциями перечислены после ключевого слова « port ». Например, в строке 3 говорится, что у нас есть порт под названием « b ». Этот порт является входом, как указано ключевым словом « in » после двоеточия.
Строка 5. Эта строка определяет конец оператора « entity ».
Следовательно, фрагмент кода entity определяет 1) название описываемой схемы и 2) порты схемы вместе со своими характеристиками, а именно: вход/выход и тип данных, которые должны передаваться этими портами. Фактически фрагмент кода entity описывает интерфейс модуля с окружающей его средой. Функции схемы, указанные в обсуждаемом операторе « entity », показаны на рисунке 1 зеленым цветом.
Строка 6. Эта строка дает название, « Behavioral », для архитектуры, которая будет описана в следующих строках. Это имя встречается между ключевыми словами « architecture » и « of ». Данная строка также связывает эту архитектуру с « circuit_1 ». Другими словами, эта архитектура будет описывать работу « circuit_1 ».
Строка 8. Указывает начало описания архитектуры.
Строка 9. Строка 9 использует синтаксис VHDL для описания работы схемы. Логическая операция И (AND) двух входов находится в круглых скобках, а результат присваивается выходному порту с помощью оператора присваивания « ».
Строка 10. Указывает конец описания архитектуры. Как упоминалось выше, эти строки кода описывают внутреннюю работу схемы, которая здесь представляет простой логический элемент И (на рисунке 1 показан синим цветом).
Объединив то, что мы обсудили ранее, мы закончим описание « Circuit_1 » в VHDL. Мы получим следующий код:
Однако нам еще нужно добавить еще несколько строк кода. Эти строки добавят библиотеку, содержащую некоторые важные определения, включая определения типов данных и операторов. Библиотека может состоять из нескольких пакетов (смотрите рисунок 2 ниже). Нам нужно сделать необходимый пакет(ы) данной библиотеки видимыми для проекта.
Поскольку в приведенном выше примере используется тип данных « std_logic », нам нужно добавить в код пакет « std_logic_1164 » из библиотеки « ieee ». Обратите внимание, что логические операторы для типа данных std_logic также определены в пакете « std_logic_1164 », иначе нам пришлось бы сделать соответствующий пакет видимым для кода. Окончательный код будет следующим:
Здесь мы добавляем две новые строки перед тем, что уже написали. Первая строка добавляет библиотеку « ieee », а вторая строка указывает, что требуется пакет « std_logic_1164 » из данной библиотеки. Поскольку « std_logic » является широко используемым типом данных, нам почти всегда нужно добавлять в VHDL код библиотеку « ieee » и пакет « std_logic_1164 ».
Рисунок 2 – Библиотека может состоять из нескольких пакетов
Для проверки приведенного выше VHDL кода мы можем использовать симулятор Xilinx ISE.
Теперь, когда мы познакомились с основными блоками кода VHDL, давайте рассмотрим один из самых важных типов данных VHDL, т.е. тип данных « std_logic ».
Тип данных « std_logic » (против « bit »)
Как упоминалось выше, тип данных « std_logic » может использоваться для представления однобитового сигнала. Интересно, что существует еще один тип данных VHDL, « bit », который может принимать логическую единицу или логический ноль.
Рисунок 3 – Схема инвертора с тремя состояниями
Когда на «включен» высокий логический уровень, «выход_данных» подключается либо к Vdd, либо к земле; однако, когда на «включен» низкий логический уровень, «выход данных» висит в воздухе, то есть он не имеет низкоимпедансного соединения с Vdd или землей, а вместо этого представляет для внешней схемы «высокий импеданс». Тип данных « std_logic » позволяет нам описывать цифровой сигнал в режиме с высоким импедансом, присвоив ему значение ‘ Z ‘.
Существует еще одно состояние, то есть к дополнение в высокому логическому уровню, низкому логическому уровню и высокому импедансу, которое может быть использовано при проектировании цифровых схем. Иногда нам неважно значение на конкретном входе. В этом случае представление значения сигнала с «неважным значением» может привести к более эффективному проектированию. Тип данных « std_logic » поддерживает состояние «неважное значение». Это позволяет улучшить аппаратную оптимизацию для таблиц поиска.
Тип данных « std_logic » также позволяет нам представить неинициализированный сигнал, присвоив ему значение ‘ U ‘. Это может быть полезно при моделировании фрагмента VHDL кода. Оказывается, что тип данных « std_logic » фактически может принимать девять значений:
Давайте посмотрим пример.
Пример 1
Напишем VHDL код для схемы на рисунке 4.
Рисунок 4 – Схема для примера 1
Основная процедура почти такая же, как в предыдущем примере. Код будет выглядеть следующим образом:
Строки 1 и 2. Эти строки добавляют в код необходимые библиотеку и пакет. Поскольку используется тип данных « std_logic », мы должны добавить пакет « std_logic_1164 ».
Строки 3-10. Эти строки определяют имя модуля вместе с его входными/выходными портами. Этот фрагмент кода соответствует частям зеленого цвета на рисунке 4.
Строки 11-17. Эта часть кода описывает работу схемы (т.е. части синего цвета на рисунке 4). Как вы могли заметить, на рисунке 4 есть один внутренний узел; он обозначен как « sig1 ». Мы используем оператор « port » из « entity » для определения входных/выходных портов, но как мы можем определить внутренние узлы схемы? Для этого мы используем ключевое слово « signal ».
В строке 12 вышеприведенного кода ключевое слово « signal » сообщает программному обеспечению, что в схеме есть узел, помеченный как « sig1 ». Подобно определению портов, мы используем ключевое слово « std_logic » после двоеточия, чтобы указать требуемый тип данных. Теперь мы можем присвоить значение этому узлу (строка 14) или использовать его значение (строка 15).
Пример 2
Напишем VHDL код для схемы на рисунке 5.
Рисунок 5 – Схема для примера 2
Данная схема представляет собой мультиплексор два-к-одному. Когда на « sel » высокий логический уровень, выход нижнего логического элемента И будет в низком логическом состоянии независимо от значения на « b ». Мы можем сказать, что логический элемент И предотвращает распространение « b » на « sig2 ». С другой стороны, поскольку на « sel » высокий логический уровень, выход верхнего логического элемента И будет соответствовать « a ». Или, что то же самое, « a » достигнет « sig3 ». Поскольку в этом случае « sig2 » равен логическому нулю, то на выходе логического элемента ИЛИ будет такое же состояние, как у « sig3 ». Следовательно, когда на « sel » высокий логический уровень, « out1 » будет таким же, как « a ».
Аналогичное обсуждение покажет, что, когда на « sel » низкий логический уровень, « out1 » будет принимать значение « b ». Следовательно, исходя из значения « sel », мы можем позволить значению на одном или другом входе достичь выхода. Это называется мультиплексированием, а схема называется мультиплексором.
Мы можем описать схему на рисунке 5, используя следующий код:
Резюме
В данной статье мы обсудили, что такое VHDL, как структурируется его код, и представили некоторые примеры того, как он используется для описания цифровых схем. Теперь вы должны лучше понимать следующие моменты: