Введение
Сегодняшнюю жизнь невозможно представить без вычислительных устройств (ВУ), скрытых в бытовой технике, измерительных и медицинских приборах, управлении агрегатами транспортных средств, телекоммуникациях, чип-картах и т.п. В персональных компьютерах, которых сейчас в мире сотни миллионов штук, функции периферийных устройств исполняют различные специализированные ВУ. Если мысленно охватить всю электронику, используемую человеком, то в целом, на один универсальный микропроцессор приходятся многие десятки специализированных ВУ. Число новых применений ВУ стремительно возрастает, а сроки их разработки неуклонно сокращаются.
Основная часть специализированных ВУ реализована на микроконтроллерах. Но остается большое множество задач, требующих экстремальных характеристик быстродействия, пропускной способности, энергопотребления, для реализации которых необходима разработка заказных микросхем. В последнее время ядро микроконтроллера и необходимые сложные периферийные устройства выполняют в виде системы на кристалле (СНК). Возрастающий объем разработок специализированных ВУ и СНК требует освоения новых технологий их проектирования.
Проектирование ВУ представляет собой поэтапное преобразование технического описания ВУ с уточнением и детализацией описания на каждом новом этапе. Начальное описание специализированного ВУ включает в себя алгоритмы его функционирования, порядок взаимодействия с внешним миром, а также технические ограничения, такие как быстродействие, энергопотребление, габариты и т.п.
Традиционное проектирование ВУ основано на составлении на каждом этапе различных графических схем. В соответствии с названием этапа, различают схемы алгоритмов, схемы электрические структурные, функциональные и принципиальные. Черчение схем связано с высокой трудоемкостью, затратами времени, а главное - с трудностью выявления и исправления ошибок проектирования. Повсеместное внедрение САПР электронных схем обеспечивает уменьшение трудозатрат, повышение качества проектов, но не меняет в корне характер проектирования, как ручного составления схем.
Использование при разработке ВУ таких языков проектирования, как VHDL и Venlog, позволяет отказаться от составления схем на
большинстве этапов разработки ВУ. Технология проектирования ВУ с помощью VHDL предполагает описание исходных алгоритмов функционирования аппаратуры и ее интерфейса на языке VHDL и автоматическую трансляцию этого описания до уровня логических схем и далее - до уровня масок микросхем или прошивки программируемых логических интегральных схем (ПЛИС). При этом схемы ВУ в графическом виде практически не используются, а отсутствие ошибок в проекте автоматически контролируется средствами верификации. Как основное средство верификации, используется моделирование функционирования ВУ на VHDL-симуляторе на всех этапах проектирования. Разработка современных ВУ без использования языков VHDL и Verilog стала практически невозможной.
Язык VHDL - необычный язык, как для программистов, так и для разработчиков аппаратуры. Это связано с тем, что по своей природе VHDL - язык параллельного программирования. Начинающие программисты иногда путаются в основах программирования на VHDL, допускают трудно выявляемые ошибки, а их результирующие проекты ВУ нередко оказываются далекими от оптимальных. Кроме того, современная технология проектирования средств ВУ основана на ряде особенных требований, предъявляемых к проектам, описанным на VHDL. А большинство разработчиков аппаратуры, изучающих VHDL, с этими требованиями мало знакомо. Поэтому цель данной книги - помочь освоить VHDL, как современное средство проектирования ВУ.
Кратко о VHDL
Традиционно, разработка электрических схем является одним из этапов проектирования средств вычислительной техники. Эта ответственная работа связана с большими трудозатратами, контролем правильности и соответствия задуманному проекту, необходимостью четкого и емкого описания созданных схем, трудностями с их сопровождением и модернизацией. САПР вычислительной техники, как правило, имеют средства ввода и редактирования схем. Однако два десятилетия назад при разработке СБИС стали отказываться от схемного проектирования.
Язык Very high speed integrated circuits Hardware Description Language (VHDL) был разработан в 1983 г. по заказу Министерства обороны США с целью формального описания логических схем для всех этапов разработки электронных систем. Он является стандартным языком с 1987 г. Стандартом 1993 г. закреплены многие его усовершенствования [1]. Наряду с языком Verilog он является базовым языком при разработке аппаратуры современных вычислительных систем.
В чем преимущества VHDL над схемным проектированием?
Проектирование больших вычислительных устройств (ВУ). С помощью VHDL проще и быстрее ввести и проверить большой проект. Десятью строками VHDL можно описать как 1, так и 100000 триггеров. Микросхему с интеграцией более 10000 вентилей разработать только с помощью электрических схем практически невозможно по причине громоздкости схем.
Проект на VHDL — объединение структуры ВУ и алгоритма его функционирования. Для ВУ, описанного на VHDL, необязательно выполнять проверку правильности его функционирования, например, путем его макетирования. Чтобы определить, правильно ли ВУ выполняет заданный алгоритм, достаточно его VHDL-программу запустить на исполнение в симуляторе VHDL. Соответствующие САПР
преобразуют VHDL-описание в комплект документации для изготовления работоспособного устройства.
Проект на VHDL — самодокументированный, т.е. он не требует дополнительного технического описания или представления в виде схем. Нечеткость и небрежность описания исключаются, так как проект на VHDL несложно проверить.
Высокая надежность проекта. Синтаксический анализ, моделирование и компиляция в логическую схему быстро выявляют ошибки проекта.
Проект на VHDL — универсальный проект. Разработанный однажды вычислительный блок может быть использован во многих других проектах. При этом многие структурные и функциональные параметры блока могут быть настраиваемыми (параметры разрядности, объема памяти, элементная база, состав блока и структура межсоединений).
Проект на VHDL — портативный проект. Разработанный для одной элементной базы, проект ВУ без труда переносится на другую элементную базу, напр. СБИС с различной технологией.
Проект на VHDL — долгоживущий проект. Электрическая схема всегда разрабатывается под конкретную элементную базу и интерфейс. Так как элементная база сменяется через 2-5 лет, за этот же период устаревают и электрические схемы, использующие её. Проект ВУ на VHDL может быть повторно использован через несколько лет. Хорошее техническое решение (напр., изобретение), описанное на VHDL, может быть востребованным в течение десятилетий.
VHDL - универсальное средство описания ВУ на уровнях:
-
алгоритмическом,
-
структурном,
□ регистровых передач (RTL) и потоков данных (dataflow), и логическом,
□ аналоговых схем.
Ход проектирования с использованием VHDL
На рис. 1 показана схема разработки проекта ВУ, предназначенного для исполнения в программируемой логической интегральной схеме (ПЛИС).
Вначале ВУ описывается в виде своей поведенческой модели, на которой отрабатывается задуманный алгоритм функционирования ВУ. Затем эта модель вручную перерабатывается в синтезируемую модель ВУ, описанную на уровне регистровых передач. Такая модель, будучи странслированной компилятором-синтезатором, дает проектную документацию в виде файла описания схемы ВУ на уровне вентилей (EDIF-файл). При этом автоматически выполняется логическая оптимизация ВУ. Одновременно этот файл автоматически преобразуется в VHDL-модель ВУ на уровне вентилей.
Проект ВУ в виде Electronic Distribution International Format (ЕБПГ)-файла принимается, как исходные данные, всеми САПР изготовления ПЛИС и СБИС. Эти САПР выполняют замену вентилей на библиотечные компоненты, их размещение на площади кристалла, трассировку межсоединений, проектирование масок, проверку соответствия проектным нормам и т.п. В результате, записываются файлы проектной документации изготовления кристалла и его логи-
ческой модели, учитывающей задержки, как в вентилях, так и в межсоединениях. Эта модель также представляется на VHDL.
Стоимость ошибок при проектировании СБИС очень высока, особенно на ранних этапах. Поэтому все этапы проектирования - алгоритмический, структурный, логический, технологический - сопровождаются моделированием ВУ с помощью, так называемого, испытательного стенда (testbench). Этот стенд представляет собой VHDL-модель, составными частями которой являются модель тестируемого ВУ и модели генератора тестовых сигналов и логического анализатора, проверяющих правильность функционирования ВУ. Причем на всех этапах может использоваться один и тот же испытательный стенд и те же тестовые файлы.
VHDL используется в современных САПР
Исторически сложилось, что в микроэлектронной индустрии наибольшее распространение получил язык Verilog. Полтора десятилетия назад этот язык выиграл конкурентную борьбу с другими языками задания ВУ, благодаря небольшим вычислительным ресурсам, требуемым от прежних рабочих станций и достаточно точным результатам моделирования СБИС. VHDL - более универсальный и гибкий язык, но он проигрывал в быстродействии языку Verilog, особенно при моделировании на уровне вентилей и транзисторов. VHDL получил широкое распространение в университетах и исследовательских учреждениях, так как это строгий, стройный, универсальный и расширяемый язык. Так, например, появились пакеты VHDL для аналогового моделирования, моделирования многозначной логики. Кроме того, симуляторы VHDL были гораздо дешевле симуляторов Verilog.
Все современные САПР микроэлектроники имеют компиляторы как с Verilog, так и с VHDL. Программист, освоивший VHDL, без особого труда может перейти к программированию на языке Verilog. Но программисту, знающему Verilog, перейти к VHDL труднее.
Важнейшими качествами VHDL в САПР выступают следующие:
Гибкость. Проект, описанный на VHDL, может быть легко настроен под конкретные задачи потребителя.
Универсальный язык. VHDL - общепринятый язык для всех основных фирм - изготовителей микросхем ПЛИС, ПЛМ, заказных
СБИС, как стандартный язык для задания сложных проектов. Проектирование с VHDL - устойчивая тенденция в инженерной технологии. Существуют компиляторы, транслирующие VHDL-программы в эквивалентные им Verilog-программы.
Моделирование с учетом задержек. Фирмы-изготовители микросхем в своих САПР обеспечивают генерацию моделей результатов размещения и трассировки, описанных на VHDL.
Стандартное подключение блоков. Конструкции языка, такие как entity, port map, configuration, обеспечивают надежную и быструю стыковку блоков, разработанных разными фирмами и разработчиками, в различном сочетании.
Стандартное тестирование. На всех этапах разработки выполняется тестирование по одной методике одними и теми же тестами.
VHDL — стандарт будущего. Все новые САПР основаны на технологии трансляции описания ВУ на языке описания аппаратуры. Использование VHDL - гарантия того, что через 5 и 10 лет найдется САПР, поддерживающая старые разработки.
Технология разработки систем на кристалле
Согласно известному закону Мора, количество транзисторов на кристалле СБИС с каждым годом увеличивается приблизительно на 60 %. С определенного момента времени то оборудование, которое размещалось на одной печатной плате, стало возможным поместить на одном кристалле (рис. 2). Причем это становится выгодным, благодаря уменьшению общей стоимости, числа необходимых микросхем, энергопотребления, повышению надежности ВУ.
Таким образом, на одном кристалле размещается не только конкретное функциональное устройство, например, центральный процессор, но и другие устройства, такие как АЦП, ОЗУ, ПЗУ, блоки цифровой обработки сигналов, интерфейсные узлы и т.п., дополняющие его до законченной системы блоков. Поэтому такое ВУ при-
нято называть System On the Chip (SOC) - системой на кристалле (CHK) [2].
СНК - это, как правило, заказная СБИС. Чтобы разработка СНК себя окупила, необходимо реализовать десятки и сотни тысяч СБИС. Проект ВУ, реализованный на ПЛИС, может быть выгодным при партиях, как в десятки, так и в десятки тысяч экземпляров, благодаря дешевизне разработки и производства такой ВУ. Разработка такого ВУ длится, как минимум, в 2 раза быстрее, чем проектирование СБИС. Это обусловило бурное распространение ПЛИС в качестве элементной базы СНК.
Наиболее трудоемкими и ответственными этапами разработки СНК выступают этапы структурного проектирования и верификации соответствия ВУ заданным алгоритмам функционирования. Поэтому эффективность САПР микросхем и производительность разработчиков, выполняющих проектирование на уровне регистровых передач, постоянно растет приблизительно на 20 % в год. Но, начиная с середины 90-х годов, производительность разработчиков стала заметно отставать от роста сложности СНК (рис. 3).
Первым направлением улучшения технологии разработки СНК, ориентированным на уменьшение зазора между ростом производительности проектирования на уровне регистровых передач и ростом сложности СНК, является применение крупных библиотечных вычислительных модулей (Intellectual Property Cores). Эти модули должны быть надежно повторяемыми и настраиваемыми под решаемые задачи в ряде проектов СНК. Повторное применение таких модулей (IP Core reuse), которые можно назвать вычислительными заготовками за их функциональную и технологическую адаптируемость, позволяет уменьшить трудозатраты и сроки проектирования СНК.
Второе направление - это разработка САПР совместного проектирования аппаратно-программного обеспечения (Hardware - Software Codesign). Архитектура СНК, как правило, включает в себя микропроцессорное ядро с периферийными устройствами в различном сочетании. Обычно процесс разработки ВУ с такой архитектурой состоит из трех последовательных этапов: проектирования электрической схемы аппаратуры, разработки матобеспечения микропроцессора и стыковки матобеспечения с аппаратурой.
Для ускорения проектирования разрабатывают САПР, которая не только служит для совместного выполнения этих этапов, но и обеспечивает моделирование работы СНК и ее верификацию в комплексе.
Наибольшее ускорение разработки СНК может дать внедрение САПР непосредственного отображения алгоритмов в аппаратуру, т.е. САПР системного проектирования. Например, такая САПР может включать в себя трансляцию программы с языка высокого уровня, таком как C++, с автоматическим разделением вычислительных задач между микропроцессорным ядром и спецпроцессорами и другими периферийными устройствами.
Для более плавного перехода от алгоритма функционирования системы, описанного на языке C++, к аппаратно-программному описанию всё чаще применяется язык System-C. Особенность этого подмножества языка C++ в том, что его функции имеют взаимно однозначное соответствие с конструкциями языков VHDL и Verilog, описывающими аппаратуру.
Вычислительные заготовки
В крупных фирмах, долгие годы занимающихся разработкой СБИС, а теперь и СНК, наработаны большие библиотеки стандартных модулей, таких как: ОЗУ, АЛУ, периферийные устройства. В новых проектах СНК некоторые блоки приходится разрабатывать заново, а остальные - обычно берутся из библиотеки. При этом если модуль неясно описан, не имеет удобного интерфейса, документации, комментариев, испытательного стенда с надежными тестами, то он повторно применяться не будет.
Если такой модуль изначально оформлен в виде вычислительной заготовки, то он будет без лишних проблем вставляться в любой новый проект. Более того, лицензию на него можно предлагать другим фирмам-разработчикам СНК. Рисунки 2, 4 иллюстрируют суть вычислительной заготовки (IP core).
14
1. VHDL и технология систем на кристалле
Гибкие заготовки обычно подстраиваются к условиям нового проекта в широких пределах и независимы от его технологии (серия ПЛИС, технология СБИС). Обычно в них задаются разрядность данных, объем памяти, таблицы констант, перечень периферийных устройств, иногда - быстродействие, которое пропорционально аппаратурным затратам. Минимизация аппаратурных затрат вычислительных заготовок обеспечивает не только уменьшение стоимости СНК, но и минимизацию его энергопотребления, что является важным фактором для портативных и энергонезависимых ВУ, в которых применяются СНК.
Чтобы проект ВУ был принят как гибкая вычислительная заготовка, он должен иметь:
а исчерпывающую и ясную документацию;
а текст описания на VHDL или Verilog в хорошем стиле для синтеза, заготовка должна быть настраиваемой под технические условия потребителя;
а хорошие средства верификации в виде испытательных стендов, исчерпывающих тестов, возможно, экспериментальных макетов;
а четкую методику того, как ВУ вставлять в СНК, включающую надежные скрипты (программы на макроязыке САПР, автоматизирующие тестирование и создание жесткой или твердой заготовки) [2].
В сегодняшних условиях, чтоб быстрее перейти от идеи к "железу", эффективнее провести проектирование новой СНК, необходимо эту СНК "собрать" из имеющихся вычислительных заготовок (рис. 2), а отсутствующие заготовки - приобрести на рынке IP cores, который бурно развивается в последние годы.
Если приобрести не удастся или если проект - исследовательский, то необходимую заготовку можно поискать, например, в банке бесплатных IP cores, что на сайте www.opencores.org. Этот банк создан по инициативе организаций, содействующих развитию технологии СНК, а также инженеров, желающих поделиться своими результатами. Если оба этих пути не устраивают, то придется ВУ проектировать самостоятельно и данная книга может этому помочь.
Программируемые логические интегральные схемы
Что такое FPGA?
Программируемые логические интегральные схемы (ПЛИС) появились полтора десятилетия назад как альтернатива программируемым логическим матрицам (ПЛМ). ПЛИС отличаются от последних как по архитектуре, так и по технологии изготовления.
ПЛМ представляет собой матрицу многовходовых (более десятка входов) логических элементов с триггерами, в которых программируются конституенты единиц дизъюнктивных нормальных форм функций этих элементов. В первых ПЛМ программирование выполнялось пережиганием перемычек между источниками сигналов переменных и входами логических элементов. Затем перемычки заменили МОП-транзисторами с плавающим затвором, как в электрически перепрограммируемом ПЗУ. Поэтому сейчас. ПЛМ изготовляются по технологии флэш-памяти. Большие ПЛМ (CPLD) отличаются только тем, что несколько ПЛМ собраны на одном кристалле и объединены программируемым полем связей.
ПЛИС представляет собой матрицу маловходовых (от двух до пяти входов) логических элементов, триггеров, отрезков линий связи, соединяемых перемычками из полевых транзисторов. Судя по английскому названию ~ Field Programmable Gate Array (FPGA), ПЛИС программируются изменением уровня электрического поля (field) в затворах этих транзисторов. Затворы всех "программирующих" полевых транзисторов подключены к выходам триггеров одного длинного сдвигового регистра, который заполняется при программировании ПЛИС. Некоторые из участков этого регистра могут также исполнять роль ячеек ПЗУ.
Прошивка обычно хранится в ПЗУ, стоящем рядом с ПЛИС. После включения питания или по сигналу сброса она автоматически переписывается в программирующий сдвиговый регистр ПЛИС. Этот процесс называется конфигурированием ПЛИС. Так как основу ПЛИС составляют триггеры, хранящие прошивку, называемую конфигурацией, то ПЛИС изготавливаются по технологии микросхем статического ОЗУ.
По сравнению с CPLD, ПЛИС выигрывают, во-первых, в неограниченном количестве перепрограммирований, во-вторых, в логиче-
ской емкости, в том числе в удельной емкости вентилей на цент, в-третьих, в малом энергопотреблении. Как правило, ПЛИС имеют на два-три порядка большую емкость в числе эквивалентных логических вентилей, чем CPLD и также как статическое ОЗУ, почти не потребляют энергии при отсутствии переключений. Поскольку топология ПЛИС регулярна и масштабируема, период разработки и внедрения ПЛИС новых серий сравнительно мал, и они изготовляются по самой современной технологии. Наконец, у ПЛИС на порядок выше надежность (ниже интенсивность отказов), чем у CPLD.
Архитектура ПЛИС фирмы Xilinx
Фирма Xilinx принадлежит к числу родоначальников ПЛИС и самых крупных их производителей. Ниже рассматривается краткое описание архитектурных особенностей ПЛИС серии Virtex выпускаемой этой фирмой [3]. Эти особенности наследуются в новых сериях ПЛИС, а также в серии Spartan, микросхемы которой призваны заменить заказные СБИС в мало- и среднесерийном производстве изделий электроники. Кроме того, принципы функционирования структурных элементов ПЛИС этой серии узнаваемы в архитектурах ПЛИС других фирм-производителей, таких как, Altera, Actel, Atmel.
Топология ПЛИС
На площади кристалла ПЛИС (рис. 5.) размещены матрица конфигурируемых логических блоков (КЛБ или CLB), матрица отрезков линий межсоединений, покрытых матрицами из полевых транзисто-
ров - перемычек (МП). По краям кристалла размеше ны блоки настраиваемых ОЗУ - BlockRAMs. По пе риметру кристалла разме щены блоки ввода-вывода сигналов (IOBs), а также периферийный канал ли ний межсоединений, на зываемый VersaRing, предназначенный для сое динения КЛБ с произ вольным ЮВ линией свя зи с малой задержкой.
Логическая таблица
Роль основного логического элемента в ПЛИС играет логическая таблица (ЛТ) или look-
up table (LUT), представляющая собой однобитное ОЗУ на 16 ячеек (рис. 6).
В ЛТ по адресу G3,G2,G1,G0 записана единица, если код адреса представляет собой конституенту единицы заданной четырехвходо-иой логической функцией. Например, если по адресу 1,1,1,1 записана единица, а по остальным адресам - ноль, то ЛТ реализует че-1 ырехвходовую функцию И. На рис. 6 показан пример кодирования функции Исключающее ИЛИ на четыре входа. Триггеры ЛТ входят и состав программирующего сдвигового регистра, и их начальное (остояние заполняется в период конфигурирования ПЛИС.
Триггер
В ПЛИС используются программируемые D-триггеры (рис. 7). При конфигурировании можно задать такие режимы работы триг-
iepa, как триггер с начальным сбросом (R) или начальной ус-[ ановкой (S), с записью по фронту или спаду синхро-< ерии, с разрешением или без разрешения записи.
После окончания конфигурирования ПЛИС выдает сиг-кал общего сброса GSR, который устанавливает все триггеры в 0 или 1.
Структура КЛБ
В базовой серии ПЛИС ХС4000 фирмы Xilinx основной единицей оборудования считается КЛБ, состоящий из двух триггеров, двух ЛТ и схем ускоренного переноса, суммирования и управления CY. В новых сериях ПЛИС количество триггеров и ЛТ в КЛБ увеличилось вдвое и вчетверо. Чтобы оставить для всех серий одну и ту же единицу оборудования, условились называть КЛБ из двух триггеров и двух ЛТ эквивалентным КЛБ (ЭКЛБ) или CLB slice. Таким образом, КЛБ серии Virtex состоит из двух ЭКЛБ, а серии VirtexII - из четырех ЭКЛБ (рис. 8).
Схемы для ускорения арифметических операций
В ЭКЛБ две ЛТ и два триггера соеди-
нены вместе через схему ускоренного переноса и два однобитных полусумматора (рис. 9). Эти схемы позволяют эффективно реализовать многоразрядные параллельные сумматоры, а на их основе - различные счетчики и АЛУ.
Для минимизации оборудования и ускорения вычисления операции умножения используется дополнительная схема поразрядного произведения. Необходимо добавить, что в новой серии Virtex2 реализованы аппаратные умножители 18 на 18 разрядов.
Большую долю оборудования в ВС занимают мультиплексоры. С помощью одного ЛТ можно реализовать двух-входовой мультиплексор. Для эффективной реализации 4-х и более входовых коммутаторов в КЛБ имеются схемы мультиплексоров F5 и F6, которые играют роль верхних уровней древовидного мультиплексора (рис. 10).
Шины с тремя состояниями
Применение шин с тремя состояниями - типичное схемное решение ВУ, реализованных на плате. Благодаря такому решению, легко достигается многомодульность и наращиваемость системы, низкие аппаратурные затраты и малые задержки в системе межсоединений. I in утри заказных СБИС редко применяются шины с тремя состояниями из-за технологических трудностей их безотказной реализации, а также увеличенной задержки их переключения.
Несмотря на это, в ПЛИС фирмы ХШпх всё-таки широко применяются шины с тремя состояниями, хотя это существенно повышает их себестоимость. Зато, во-первых, проще выполнить переход от проекта схемы на плате к проекту СНК. Во-вторых, ВУ с общими шинами, к которым подключено несколько десятков модулей, имеет аппаратные затраты в несколько раз меньше, чем такое же ВУ, в котором глины заменены на эквивалентную схему из системы мультиплексоров. В-третьих, с помощью общих шин эффективно реали-иовать встроенное распределенное ОЗУ, о котором пойдет речь ниже.
Для реализации общей шины каждый КЛБ имеет два буфера с •громя состояниями BUFT, которые через транзисторы-перемычки могут подключаться к общим шинам, проходящим вдоль всего кристалла (рис. 11).
В обычных шинах третье состояние характеризуется уровнем, находящимся между уровнями логической 1 и логического 0. Однако в случае, когда все тристабильные буферы будут в третьем (за-
крытом) состоянии, выходные каскады приемников, подключенных к общей шине, Пудут полуоткрытыми, через них потечет большой постоянный ток, и они могут выйти из строя. Для исключения такого электрического режима, в ПЛИС общая шина нагружена на концах специальной тригтерной схемой - Weak Keeper, которая выводит уровень шины или к уровню Н, или к уровню L (слабые 1 или 0), если все буферы закрыты.
ОЗУ в ПЛИС
Для реализации в ПЛИС модулей ОЗУ предусмотрено две возможности. Первую возможность предоставляет каждая ЛТ, которая
пользуется только мультиплексор чтения.
Для наращивания емкости памяти выходы нескольких КЛБ с модулями ОЗУ через тристабильные буферы подключаются к общим шинам. При этом- требуется дополнительное оборудование только для построения схемы дешифрации адреса, которая выдает сигналы выборки той или иной ЛТ для записи или того или другого три-стабильного буфера для чтения. Такое ОЗУ распределено по площади кристалла и поэтому названо Distributed RAM.
Если ЛТ запрограммировать как примитив SRL16, то из ее триггеров будет реализован 16-разрядный сдвиговый регистр с однобитовым входом и программируемым номером выходного разряда, т.е. память FIFO регулируемой длины. Такие регистровые линии задержки удобно использовать при проектировании конвейерных специализированных ВУ, ВУ с поразрядной
обработкой, буферов для приема и передачи данных и т.п.
Вторую возможность предоставляют отдельные блоки памяти BlockRAM. В ПЛИС серии Virtex они могут быть сконфигурированы, как ОЗУ объемом 256 16-разрядных слов, 512 8-разрядных слов, и т.д. Эта память может быть запрограммирована как однопортовая или как полностью двухпортовая память (рис. 13). Начальное со-
сгоиние этой памяти задается при ее конфигурировании, поэтому ими может быть использована также как ПЗУ. В каждой новой серии ПЛИС объем блоков BlockRAM и их число - увеличиваются.
Блоки ввода-вывода сигналов
ПЛИС находят широкое применение благодаря тому, что их можно включать в большинство проектов ВУ и ими можно заменять схемы, реализованные на устаревшей элементной базе. Предпосылкой этому служит большое число блоков ввода-вывода сигналов ЮВ, настраиваемых под различные стандарты электрического соединения иходов микросхем. На рис. 14 показана структура одного ЮВ.
Сигнальный вывод ПЛИС получил название PAD. С помощью настройки к нему можно подключать внутренний нагрузочный резистор PULLUP или резистор PULLDOWN, соединенные с шиной питания или шиной земли, соответственно. Эти резисторы обеспечивают режим выхода с открытым коллектором (стоком) для систем с рп.шичными уровнями логики. Входной сигнал с PAD поступает на компаратор IBUF, порог срабатывания которого программируется мод уровни ТТЛ, КМОП, шины PCI и многие другие, а также может регулироваться установкой подаваемого снаружи потенциала уровня срабатывания Vref. Для обеспечения временного сдвига сигнала относительно фронта синхросерии, обеспечивающего надежный прием сигнала во внутренние триггеры, в цепь входного сигнала может иключаться специальная схема задержки.
Выходной сигнал в ЮВ формируется в тристабильном буфере OBUFT, причем его уровень максимального тока программируется ступенями и может достигать 20 мА. Для обеспечения быстродействующего ввода-пмвода передаваемые и принимаемые биты данных, а также сигнал управления тристабильным буфером могут запоминаться в триггерах.
В ПЛИС новых поколений к сигнальным выводам кристалла подключаются резисторы с программируемым сопротивлением, предназначенные для согласования импеданса источника или приемника сигнала с импедансом линии связи. Благодаря этому возможна надежная высокочастотная передача данных между микросхемами.
Напряжение питания ПЛИС каждого нового поколения постоянно уменьшается, благодаря чему минимизируется энергопотребление при высоком быстродействии (см. главу 4). Для того, чтобы обеспечить согласование входных и выходных уровней для как можно большего числа стандартов уровней напряжения логических схем, на блоки ЮВ подается отдельное питание.
ЮВ сгруппированы в банки, и на каждый из банков можно подавать различный уровень напряжения питания. Но для ПЛИС последних поколений это напряжение не должно превосходить 3,3 В. Сигнальные входы-выходы ПЛИС обычно защищены от перенапряжения цепочками из ограничивающего резистора и диода, подключенных между PAD и линиями питания и земли. Поэтому обычно допускается подавать на входы PAD уровень, больший 3,3 В через дополнительный резистор, ограничивающий входной ток и обеспечивающий входной уровень на PAD, не превосходящий напряжение питания плюс падение напряжения на открытом диоде.
При диагностике, отладке, в одном из режимов конфигурирования, ПЛИС может быть переключена в режим пограничного сканирования (Boundary Scan). В этом режиме все ЮВ соединяются в цепочку одного длинного регистра сдвига. Путем стандартного внешнего управления этим регистром сдвига через интерфейс JTAG можно считывать состояния выводов, подавать тестовые сигналы, конфигурировать ПЛИС.
В период конфигурирования ПЛИС для того, чтобы подключаемые к ней устройства не функционировали неопределенным образом, выходы ЮВ отключаются и на них обычно выставляется уровень Н слабой единицы.
Система синхронизации
Одним из принципов разработки проектов для ПЛИС является принцип однотактной синхронизации, согласно которому все триггеры в ВУ или в его блоке срабатывают одновременно по одному сигналу синхросерии (см. главу 4). Для его реализации в ПЛИС синхросигналы распространяются по быстродействующей древообразной
Для надежного функциониро-иимия ПЛИС синхросигнал должен подаваться через вывод GCLKPAD и попадать в сеть синхросерии через буфер GCLKBUF.
В ПЛИС предусмотрено 4 выпи дя GCLKPAD, размещенных на iipoi ивоположных сторонах ее
корпуса. Синхросигнал может вырабатываться и внутри ПЛИС, по в этом случае его следует завести в сеть синхросерии через i лобальный буфер BUFG.
С помощью синхронного автомата, сконфигурированного в ПЛИС, можно изменять частоту и фазу синхросерии. Но в этом <* л учае ее временные параметры будут недостаточно ста-бпмьными, и поэтому такой подход обычно не применяется. Для надежного регулирования частоты синхросерии в ПЛИС вклю-чпюг делители частоты синхросерии с автоподстройкой — блоки (MiKDLL. На рис. 16 показана типичная схема его включения. Инок CLKDLL обеспечивает умножение частоты синхросерии в 2 рм.за, сдвиг ее фазы на 90, 180 и 270 градусов, деление на 1.5, 2, 2.5, 3, 4.5, 8 и 16.
Для конфигурирования ПЛИС в ней предусмотрены входы задания режима М2, Ml, МО, вывод синхросерии программирования CCLK, вход последовательности конфигурации PROGRAM, выход флага окончания конфигурирования DONE и выводы порта JTAG. В зависимости от установленного режима можно загружать прошивку ПЛИС через однобитовый вход PROGRAM, порт JTAG или 8-разрядную шину D с использованием для управления выводов WRITE и BUSY.
Конфигурирование через однобитовый вход длится до нескольких десятков секунд. Это стандартный способ конфигурирования и для него не требуется дополнительного оборудования, кроме ПЗУ прошивки с однобитовым выходом. С помощью одной микросхемы ПЗУ можно запрограммировать несколько ПЛИС, цепи программирования которых для этого соединяются в кольцо.
Для реализации конфигурирования через шину D необходимо дополнительное внешнее устройство (автомат или микроконтроллер), управляющее записью и выдающее последовательность адресов чтения на входы ПЗУ восьмиразрядной шиной данных. Зато оно происходит значительно быстрее - практически с максимальным темпом чтения из ПЗУ.
В последнее время выпускаются ПЗУ, специально предназначенные для конфигурирования ПЛИС через шину D, в состав которых входит автомат управления записью.
Основы программирования на VHDL
Модели вычислителей VHDL
Начинающий программист VHDL легко осваивает структурный пчшь программирования, которым формально описывается структура ВУ. Без трудностей он программирует стилем потоков данных, пыражая операторами параллельного присваивания прохождение данных через некоторую комбинационную схему. Но при переходе к поведенческому стилю, основанному на операторах процессов, нередко возникают сложности с пониманием выполнения этих опера-1оров, программированием желаемого поведения системы и отладкой составленной программы.
Он знает, что VHDL — это язык программирования. Но у него возникает вопрос, программирования чего? При программировании на Он программист представляет, что он с помощью языка описывает ипдуманный алгоритм для его реализации на модели ЭВМ, содер-жмщей АЛУ, регистровую, оперативную, дисковую память и т.д., что существуют определенные типы данных и механизмы доступа к ним. Другими словами, он программирует некоторую программистскую модель вычислителя для реализации данного языка.
Алгоритм, описанный на VHDL, как и любой другой параллельный алгоритм, представляет собой определенное множество вычислительных процессов, организованных на строго заданной модели иычислителя (рис. 17).
Составление программы VHDL означает программирование этой модели. Поэтому далее рассмотрим программистскую модель вычислителя для реализации языка VHDL. Для понимания реализации VHDL в симуляторах будет также рассмотрена модель вычислителя с точки зрения разработчика симуляторов. Наконец, будет приведена аппаратная модель реализации VHDL, т.е. модель, реализуемая в СБИС или ПЛИС.
Модель вычислителя для программирования на VHDL
Наиболее полно программистская модель вычислителя VHDL описана в руководстве к стандарту языка [1]. В нем параллельно с описанием синтаксиса и семантики всех языковых конструкций приводятся объяснения их реализации в модели некоторого виртуального симулятора. Но, изучая это руководство, с первого раза трудно постичь основы этой модели. Ниже описывается упрощенная модель вычислителя VHDL, которая не противоречит модели, описываемой в [1].
В отличие от большинства современных языков программирования, язык VHDL основан на параллельной многопроцессорной модели. Нижний уровень модели образует архитектура виртуального процессорного элемента (ВПЭ), а верхний уровень - множество ВПЭ, объединенных некоторой запрограммированной системой межпроцессорных связей.
Структура ВПЭ состоит из арифметико-логического устройства (АЛУ), ОЗУ данных (ОЗУД), ОЗУ программы (ОЗУП) и определенного количества источников (ИС) и приемников (ПС) сигналов (рис. 18).
ЛЛУ выполняет такой же набор операций, какой требуется для Iтипизации большинства языков программирования, как, например, сложение, умножение, деление с фиксированной и плавающей запя-и>И. логические операции и т.д. Кроме того, АЛУ выполняет многие друие операции, специфические для VHDL, такие как операции над днимими с заданной разрядностью, функции с многозначным логическим представлением разрядов. При выполнении операций постоянно проверяется корректность результата, и фиксируются ошибки, как-то: выход за заданный диапазон представления числа, деление на ноль и т.п.
П ОЗУ данных хранятся переменные, участвующие в вычислениях. Переменные имеют статические адреса, но можно реализовать и динамический доступ к переменным. Источники и приемники сиг-мнмов служат, в основном, для связи ВПЭ с внешним миром. При поступлении сигнала приемник фиксирует это событие. В приемнике хранится как текущее, так и предыдущее состояние сигнала. При и i.i иол нении операции с идентификатором сигнала, как с операндом, выполняется чтение приемника или источника сигнала. Источник генерирует сигнал не сразу после выполнения оператора присва-шищия, а в момент остановки ВПЭ.
li ОЗУ программы хранится программа в виде цепочки оператором. Операторы, включая условные операторы, выполняются после-допптельно друг за другом, как в обычных языках программировании. Но на операторах wait выполнение программы останавливает-с и. Такая программа записывается в VHDL-программе как один пираллельный оператор, называемый процессом, а ВПЭ выполняет его как вычислительный процесс.
Операнды оператора wait - это набор входных сигналов, назы-иасмый списком чувствительности, заданный промежуток времени пидоржки или булевское выражение. Оператор wait ожидает появления внешнего события: прихода сигналов или истечения срока заданной задержки. После появления внешнего события программа продолжает выполнение со следующего оператора. Только при выполнении оператора wait в источниках сигналов генерируются сиг-пимы, которым в программе было присвоено новое значение. После исполнения последнего оператора программа переходит к своему первому оператору.
Отдельным входом-выходом ВПЭ является шина передачи гло-шшьных (shared) переменных. Глобальная переменная может прини-
маться (участвовать как операнд) или передаваться из ПЭ (как результат операции присваивания) в произвольные моменты времени.
К ВПЭ можно подключать дисковую память. При этом операторы открытия, чтения, записи, закрытия файлов используются аналогично, как в других языках.
Верхний уровень программистской модели составляет множество ВПЭ, объединенных линиями связи, по которым передаются сигналы (рис. 19). Консоль для связи с программистом (клавиатура и дисплей), дисковая память и ОЗУ глобальных переменных используются всеми ВПЭ как обшие.
Количество ВПЭ в системе равно числу процессов в программе VHDL после ее компиляции. В структуре параллельного вычислителя столько линий межпроцессорной связи, сколько необходимо для исполнения VHDL-программы.
Как и в других языках параллельного программирования, в VHDL сигнал используется одним вычислительным процессом для сообщения другим вычислительным процессам факта исполнения некоторого события. Кроме того, сигнал используется для передачи исходных и промежуточных данных между процессами. Наконец, выбранные сигналы при исполнении VHDL-программы можно записать в своем развитии и затем воспроизвести в виде временных графиков или таблиц.
При запуске скомпилированной программы сперва все переменные принимают заданное начальное значение. Затем во всех ВПЭ начинают выполняться вычислительные процессы со своих первых операторов. При достижении операторов wait ВПЭ генерируют новые значения сигналов и останавливаются. Эти сигналы, пройдя через соответствующие им линии связи до других ВПЭ, запускают в них продолжение вычислительных процессов. Такое функционирование вычислительной системы может продолжаться неопределенно долго, пока оно не будет остановлено с консоли или не выполнится оператор assert, требующий останова. В большинстве программ VHDL один из процессов является ведущим и задает поток возбуждающих состояний сигнала для других процессов. Например, этот процесс моделирует источник исходных данных или генератор синхросигнала. Тогда ВПЭ — генератор возбуждающего сигнала — запускает смежные с ним ВПЭ. Эти ВПЭ запускают ВПЭ следующие за ними и т.д. Таким образом, по вычислительной системе проходят волны запусков. Поэтому модель вычислителя для реализации VHDL можно трактовать как волновой процессор со специализированной топологией.
Если в процессе не использованы операторы wait с установленной задержкой, то цикл запуска-остановки этого процесса выполняется почти мгновенно, а точнее — с дельта-задержкой. Здесь дельта-задержка - исчезающе малый промежуток времени, одинаковый для всех таких процессов.
Основное назначение консоли - это запуск программы на исполнение и вывод сообщений на экран, которые генерируются специальными операторами assert и report.
ВПЭ могут иметь произвольный доступ записи-чтения к памяти глобальных переменных. Эти переменные служат дополнительным средством связи между ВПЭ, так как внутренние переменные в ВПЭ недоступны для других элементов вычислительной системы. ВПЭ функционируют асинхронно относительно друг друга и поэтому невозможно задать однозначный порядок доступа к глобальной переменной от нескольких ВПЭ без искусственного введения механизмов синхронизации. Поэтому корректное использование глобальной переменной возможно, если она используется как константа или запись в нее выполняется только одним ВПЭ, причем в случае, если момент записи переменной безразличен относительно вычислительных процессов в других ВПЭ.
При программировании на VHDL необходимо учитывать следующее.
□ Все процессы исполняются параллельно.
а Одновременно исполняемые процессы образуют фронт волны запусков процессов. Этот фронт может передвигаться с временным шагом, равным дельта-задержке.
а Все параллельные операторы языка VHDL преобразуются в функционально эквивалентные операторы процессов, поэтому данная вычислительная модель годится для произвольной VHDL-программы.
а Структура вычислительной модели остается неизменной после компиляции программы, т.е. после своего формирования. Эта структура не зависит от сигналов и переменных, изменяемых в процессе выполнения программы, т.е. она не может перестраиваться динамически.
□ Область действия всех переменных (кроме глобальных) огра ничена рамками операторов процесса. Вне процессов перемен ные невидимы.
а Порядок доступа к глобальным переменным непредсказуем. Следует с осторожностью программировать с этими переменными.
Вычислительная модель си муля тор a VHDL
Модель вычислителя с точки зрения программиста не может быть реализована в виде реальной многопроцессорной вычислительной системы из-за чрезмерно высоких аппаратурных затрат. С другой стороны, язык VHDL разрабатывался с целью реализации в симуля-торах дискретных систем. Такой симулятор, как правило, исполняется на однопроцессорной ЭВМ. Рассмотрим архитектуру вычислителя VHDL с точки зрения разработчика симулятора.
На рис. 20 условно показана архитектура симулятора VHDL. В данной модели каждый ВПЭ реализован как отдельный вычислительный процесс (ВП). Все вычислительные процессы разделяют во времени один и тот же аппаратный ресурс - центральный процессорный элемент (ЦПЭ) микропроцессора ПЭВМ.
Все ВП разделены на три подмножества - очередь спящих процессов, очередь готовых процессов и исполняемый процесс. Большинство ВП относится к числу спящих, т.е. к ВП, для исполнения которых нет готовых входных данных. Например, такой ВП ожидает какой-либо входной сигнал из списка чувствительности его one-
ратора wait. При поступлении сигнала этот ВП переносится в очередь готовых к исполнению ВП. Один из готовых ВП, выбранный произвольно, пересылается в кэш-ОЗУ микропроцессора для исполнения. Исполняемый ВП выполняет свои операторы в соответствии с семантикой функционирования ВПЭ на ресурсах ЦПЭ микропроцессора и с использованием соответствующих библиотек процедур. При достижении оператора wait ВП останавливается. Выработанные им сигналы запоминаются и пересылаются другим ВП, которые являются приемниками этих сигналов. Затем остановленный ВП пересылается в очередь спящих процессов.
Один особенный исполняемый ВП служит диспетчером для остальных процессов. Он называется ядром симулятора и формирует очереди спящих ВП и готовых к исполнению ВП, а также выбирает ВП для исполнения. Он также рассылает сигналы от исполняемого ВП к другим ВП. Кроме того, он ведет счетчик времени моделирования Тс, выполняет связь с консолью, обслуживает обращение к дисковой памяти и памяти глобальных переменных.
Для моделирования программист создает проект — каталог с файлами VHDL, имеющий название проекта. После компиляции в проекте создается библиотека проекта, которая имеет название проекта и содержит все скомпилированные объекты проекта. После запуска программы на моделирование выполняется связывание объектов
проекта и назначение начальных значений переменным и сигналам (elaboration).
Затем запускается собственно моделирование. При этом выбранные программистом сигналы записываются в отдельной области памяти в своем развитии и могут быть отображены на дисплее в виде таблиц или графиков.
Для того чтобы сохранить семантику исполнения множества параллельных процессов, такую же, как у системы из ВПЭ, симулятор в каждом цикле моделирования выполняет следующие шаги:
-
Каждый остановленный ВП, для которого произошло новое событие, т.е. пришло новое значение сигнала, который ожидается соответствующим оператором wait, запускается на исполнение; в ВП, остановленных для ожидания задержки, проверяется окончание этой задержки и если задержка истекла, эти ВП также запускаются.
-
Каждый запущенный ВП исполняется до своей остановки на операторе wait, при этом вычисляются новые значения сигналов в операторах присваивания сигналам.
-
Вычисляется новое значение текущего времени Тв как ближайший момент времени, в который будет запущен какой-либо ВП, остановленный на операторе wait ожидания окончания задержки или момент времени следующей активации источников сигнала.
-
Счетчик времени принимает новое значение Тс = Тв.
-
Каждому сигналу, для которого было вычислено новое значение, присваивается это значение, т.е. источники сигналов активизируются; эти изменения сигналов проверяются, являются ли они событиями для каких-либо ВП.
Если в следующем цикле моделирования не запускается ВП по окончанию заданной задержки или активация источников сигнала происходит без задержки, то в данном цикле счетчик времени Тс сохраняет свое прежнее значение, измеряемое в фемта-, пико- или наносекундах. В этом случае считается, что время моделирования увеличилось на дельта-задержку.
Моделирование имеет такую особенность, что серия, включающая от нуля до нескольких циклов (обычно не более 1000) с дельта-задержкой сменяется одним циклом с конкретной задержкой. Допустим, что в модели находятся два процесса, обменивающихся одной глобальной переменной. Тогда порядок обмена этой переменной
не контролируется программистом, так как он не может определить, какой из этих процессов сработает первым в серии циклов с дельта-задержкой. Для того чтобы эти процессы были запущены не в произвольном, а именно в последнем цикле с дельта-задержкой из серии циклов, причем после всех процессов, такие процессы обозначаются как отложенные (postponed).
Описанная модель симулятора является приближенной. В реальных симуляторах упомянутые процессы не имеют ничего общего с процессами и потоками, исполняемыми под управлением операционной системы. Обычно каждая новая версия симулятора отличается повышенным быстродействием. Например, для увеличения быстродействия, по результатам компиляции VHDL-программы строится ациклический граф потоков данных, вершинами которого являются процессы программы и который соответствует алгоритму, исполняемому за один главный цикл моделирования. Тогда моделирование сводится к обходу вершин этого графа.
Другой метод предполагает предсказание тех процессов, которые будут исполняться в следующем цикле моделирования. Тогда моделирование ускоряется за счет того, что проверяется готовность к исполнению не всех процессов, а только предсказанных [4].
При составлении VHDL-программ желательно иметь в виду следующее,
□ Даже небольшой процесс занимает в памяти несколько килобайт. Максимальное количество процессов в скомпилированной программе определяется объемом динамической памяти компьютера.
D Смена одного ВП другим ВП представляет собой смену контекста в работе ЦПЭ, которая может длиться несколько тысяч тактов ЦПЭ.
D Наибольшую долю времени занимает исполнение ВП ядра симулятора, которая возрастает нелинейно с увеличением числа ВП и числа сигналов в списках чувствительности их операторов wait. Поэтому, чем меньше процессов в скомпилированной программе и сигналов в списках чувствительности - тем быстрее выполняется эта программа в симуляторе.
D Нельзя программировать процесс без оператора wait (или без списка чувствительности), т.к. после того, как этот процесс станет активным, он монопольно захватит ресурсы ЦПЭ.
Аппаратная модель реализации VHDL
Одним из важнейших назначений VHDL является описание проектов дискретных устройств при автоматизированном проектировании микросхем. В основе технологии разработки микросхем (заказных СБИС или ПЛИС) лежит автоматическая трансляция VHDL-описания дискретного устройства в схему на логическом уровне, которая выполняется с помощью компилятора-синтезатора. Здесь под синтезом понимается получение аппаратной модели, которая исполняет исходную VHDL-программу и преобразование её в схему на логическом уровне. Причем подбор структуры модели и её логическая оптимизация по критериям минимума аппаратуры и максимума быстродействия с учетом элементного базиса целевой микросхемы выполняются автоматически.
Работа компилятора-синтезатора основана на взаимно-однозначном инъективном отображении программистской модели, отвечающей исходной VHDL-программе, в аппаратную модель. Это означает, что каждому из ВПЭ с его программой ставится в соответствие некоторый специализированный процессорный элемент (СПЭ) (рис.21), причем ПС, ИС и ИС/ПС отвечают входам, выходам и входам-выходам ВПЭ. В свою очередь, граф линий связи между ВПЭ и граф соединений между СПЭ - изоморфны (рис. 22). Так как отображение инъективно, то одна VHDL-программа может дать большое множество функционально эквивалентных схем, отличающихся по степени оптимальности и элементному базису.
Различают два типа СПЭ: СПЭ с памятью и СПЭ без неё. СПЭ без памяти представляют собой комбинационную схему, состояние выходов которой (источников сигнала) представляет собой некоторую логическую функцию от состояния её входов (приемников сигнала).
Если по семантике оператора процесса предполагается, что не все его переменные и сигналы выполняют присваивания при некотором запуске процесса, то это означает, что такие переменные и сигналы должны хранить свое предыдущее состояние при этом запуске. Поэтому эти процессы отображаются в СПЭ с памятью.
СПЭ с памятью имеют в своей структуре комбинационную схему, а также триггеры и регистры для хранения результатов и промежуточных операндов. Состояние выходов СПЭ представляет собой логическую функцию не только от состояния входов, но и от состояния регистров. Регистры могут запоминать операнды как по уровню синхросигнала (защелка), так и по его фронту (триггер).
В отличие от ВПЭ, задержка от входов СПЭ до его выходов равна величине, определяемой характеристиками элементного базиса, а не дельта-задержке или задержке, заданной оператором wait.
При отображении в аппаратуру вместо оператора каждого типа подставляется соответствующая ему логическая схема. Так, операции and ставится в соответствие логическое "И", а операции "*" -комбинационный умножитель.
На аппаратную модель реализации VHDL налагается ряд ограничений, связанных с особенностями элементной базы СБИС или ПЛИС. Эти ограничения имеют прообразы в программистской модели. В основном, они образуют множество объектов и операторов языка, которые не могут быть отображены в аппаратуру, так как не имеют в ней соответствующего эквивалента.
Например, на сегодняшний день не могут быть автоматически отображены в аппаратуру сигналы и переменные типа с плавающей запятой, динамического, файлового типа, операция деления, операторы wait с параметром задержки, операторы вывода на консоль
assert и report. Также в большинстве случаев глобальные переменные не находят своего отображения.
Некоторые значения перечисляемого типа, например, стандартного типа stcLlogic, такие как "и" - не инициализированное, "X" -неизвестное, "-" - безразличное, также не могут быть отображены в аппаратуру, а другие, как например, "н" - слабая единица или "L" -слабый ноль, отображаются, соответственно, в 1 и 0.
Не могут быть синтезированы такие языковые конструкции, для которых невозможно определить конкретную комбинационную схему или ее разрядность на период компиляции. Например, оператор цикла отображается в многоуровневую комбинационную схему, в которой число уровней равно количеству итераций. И если количество итераций неизвестно на период компиляции, т.е. не задается статическим выражением, (например, если параметр итераций вычисляется в процессе), то такую схему можно смоделировать, но построить невозможно,
Говорят, что VHDL-программа, в которой отсутствуют несинтези-руемые объекты, операторы и конструкции, написана стилем для синтеза. При составлении программы стилем для синтеза желательно принять во внимание следующее.
а Существует несколько распространенных компиляторов-синтезаторов от разных фирм-поставщиков. Эти компиляторы различаются, в частности, списком несинтезируемых элементов языка VHDL. Причем с появлением новых версий компиляторов этот список обычно сокращается.
□ Компиляторы-синтезаторы также существенно различаются по возможностям оптимизации отображения, набором атрибутов, управляющих синтезом, библиотеками процедур и функций, возможностями распознавания идиом языка, которые эффективно отображаются в СПЭ и адаптированы к целевой элементной базе. Например, не все компиляторы выполняют эффективно минимизацию оборудования путем разделения ресурсов. Поэтому для умелого написания программ для синтеза желательно накопить опыт работы с тем или иным компилятором.
Объекты и типы языка
37
Объекты и типы языка
Сигналы, переменные, константы и другие объекты языка VHDL служат для содержания некоторых значений. Эти значения могут быть присвоены объектам в одном месте и затем использованы в другом месте программы, как операнды в выражениях, функциях и т.п. Прежде чем остановиться на описании объектов, необходимо рассмотреть комментарии, литералы языка, а затем описать типы, которые бывают у объектов.
В приведенных ниже описаниях синтаксиса текст в квадратных скобках означает необязательный элемент, фигурными скобками выделяется текст, который может повторяться 0,1,2,... раз, вертикальными линиями разделяются альтернативы. Ключевые слова языка выделены полужирным шрифтом.
Комментарии
В языке VHDL комментарии начинаются двумя дефисами и продолжаются до конца строки. В книге комментарии выделены курсивом, как и во многих редакторах языка VHDL.
Литералы
В языке литералом задается такой лексический элемент, который остается постоянным в программе и принимает определенное числовое значение после компиляции. Константы, операнды в выражениях, идентификаторы представляются литералами. То, что синтаксис литерала отображает признак типа соответствующего ему объекта, является одной из особенностей VHDL.
Числовой литерал представляет собой целое или вещественное число.
Десятичный литерал - это числовой литерал в системе счисления по основанию (базису) 10, например, 120.
Вещественный литерал отличает обязательное наличие точки, отделяющей целую часть от дробной, например, 120.0, 1.20е2.
Базисный литерал - это число в системе счисления с заданным базисом от 0 до 16. Его условный синтаксис:
\базисный литерал\::=\базис\#\число в базисе\#[\экспонента\], например, 10#112# = 1б#70# = 5#422# = 2#1110000# = 2#111#е4.
Символьный литерал используется как значение для операторов или как элемент перечисляемого типа, например, бит. Он записывается как символ в одиночных кавычках, например, 'Г, 'F*, '@'.
Идентификатор. Идентификатор используется как имя константы, переменной, функции, сигнала, порта, подпрограммы, объекта проекта, а также как метка. Он содержит латинские буквы, с которых начинается, цифры и некоторые символы, например, однократный символ подчеркивания. Идентификаторы с одинаковым названием, но с различными заглавными и строчными буквами считаются одним идентификатором, т.е. они "нечувствительны" к высоте букв. Ключевое слово языка не может быть идентификатором.
Идентификатор может состоять из произвольной цепочки символов, в том числе из букв кириллицы. Но эта цепочка должна быть заключена между обратными косыми. Это, так называемый, расширенный идентификатор. Например:
С, A_and_B, \наш сигнал\, \а+в\, \process\
являются корректными идентификаторами.
Перечисляемый литерал. К перечисляемым литералам относятся символьный литерал и идентификатор. Из этих литералов формируется множество перечисляемого типа.
Строчный литерал. Строчным литералом является цепочка символов, заключенная в двойные кавычки, например, "абвг". Литерал битовой строки может иметь различный вид в зависимости от базиса системы счисления. Например, литералы "01111010", в"01111010", х"7А" представляют собой одно и то же значение, причем в и х означают двоичный и шестнадцатиричный базисы, соответственно.
В числовых литералах и битовых строках допускается вставлять символы подчеркивания для удобства чтения, которые удаляются при компиляции. Например, x'^BBA^CDCD", "1101_011Г\ 1_024.
Тип
Тип - это множество значений с общим признаком. VHDL - строго типизированный язык. Каждый объект объявляется своим типом и может присваивать значение только данного типа. Соблюдение строгого соответствия типов в операторах присваивания, выражениях, вызовах подпрограмм требует дополнительных усилий программиста. Но благодаря этой особенности, программы VHDL имеют высокую надежность и обеспечивают экономию времени при отладке.
Перечисляемый тип определяется как список (перечисление) всех возможных значений данного типа. Объявления этого типа выглядит как:
type \имя типа\ is (\перечисляемый литерал\
{Д перечисляемый литерал\});
Элементы списка литералов нумеруются при компиляции слева -направо, начиная с нуля. Например, объявление
type \цвет\ is (\красный\,\желтый\Дзеленый\);
означает, что состояния идентификатора \цвет\ будут кодироваться так, что \красный\ соответствует 0, \зеленый\ - 2. Целый тип. Объявление этого типа выглядит как:
type \имя типа\ is range \диапазон целых\;
где \диапазон целых\::=\выражение\ to \выражение\
|\выражение\ downto \выражение\ .
Выражение целого типа в диапазоне должно быть вычислимо в
период компиляции. Максимальный диапазон целых задается как:
-2147483647 to 2147483647.
Тип с плавающей запятой определяется аналогично целому типу, но с диапазоном с плавающей запятой. Максимальный диапазон зависит от компилятора.
Регулярный тип представляет собой множество элементов одинакового типа. Различают неограниченные и ограниченные регулярные типы. Неограниченный тип объявляется как:
type \имя регулярного типа\ is
array (\имя типа диапазона\гапде<>) of \имя типа элементах;
где \имя типа диапазонах — имя типа integer или какого-либо подтипа от integer.
Ограниченный регулярный тип объявляется как:
type \имя регулярного типа\ is
array (Хдиапазон целых\ of \имя типа элементах);
Неограниченный регулярный тип применяют тогда, когда заранее неизвестен диапазон типа, например, в процедуре. Но на период компиляции (точнее - на этапе связывания) диапазон объекта этого типа должен быть определен, например, при вызове процедуры с конкретным операндом.
VHDL допускает многомерные массивы. В их определениях диапазоны индексов перечисляются через запятую, например:
type MATR is array (integer range <>, integer range <>) of integer
Комбинированный тип определяет множество значений, как и регулярный тип, но эти значения могут быть разнотипными. Объявление комбинированного типа выглядит как:
type \имя комбинированного типа\ is record \имя элементах:\тип элементах; {\имя элементах:\тип элементах;} end гесо^[\имя комбинированного типа\];
Физический тип представляется целым числом, единица которого имеет вес единицы измерения некоторой физической величины. Наиболее распространенным физическим типом в VHDL является время time, которое измеряется в фемтосекундах (fs), пикосекундах (ps), наносекундах (ns) и т.д. Объекты физического типа, как правило, не синтезируются, но они могут участвовать как операнды в вычислениях констант других типов. Задание физического типа отличает VHDL от других языков.
Другие типы объектов
Особенными типами являются тип ссылки (access) и тип файла (file). Тип ссылки позволяет манипулировать с массивами переменных, объем которых заранее неизвестен и которые создаются и ликвидируются динамически во время вычислений, как и в других языках. Тип файла обеспечивает доступ к файлам, записанным в дисковой памяти. Переменные такого типа применяют для ввода-вывода исходных данных и результатов вычислений.
Подтип
Подтипом называется тип с дополнительными ограничениями. Объявление подтипа имеет следующий упрощенный синтаксис:
\подтип\::=subtype \имя подтипах is \базовый тип\ [\ограничение\];
Здесь \ограничение\ - диапазон или подмножество, в зависимости от базового типа. Подтип используют для отождествления группы объектов. Ограничение подтипа позволяет выявить ошибки на этапе моделирования. Объекты разных подтипов, у которых один родона-чальный тип, могут участвовать в вычислениях без конфликтов типов.
Предопределенные типы данных
Основные типы данных VHDL определены в пакете standard, который подключается к проекту по умолчанию. Вот так в нем определены некоторые стандартные типы объектов:
type boolean is (false, true);
type bit is CO', '!');
type integer is range -2147483647 to 2147483647;
subtype natural is integer range 0 to 2147483647;
type bit„vector is array (natural range <>) of bit;
Также определены типы character как набор букв, цифр и знаков, включая буквы альтернативного алфавита, подтип positive, включающий положительные значения типа integer, тип string как одномерный регулярный тип из элементов типа character.
Сигнал
Сигналом является объект, который переносит значение от одного процесса к другому и вместе с ним - синхронизирующее воздействие. Сигнал может быть запомнен в своей истории и воспроизведен в симуляторе в виде графика или таблицы. Объявление сигнала выглядит как:
signal:\идентификатор\{,\идентификатор\}[:= \начальное значение\];
где - \начальное значение\ - выражение, представляющее константу, значение которой принимает сигнал перед первым запуском процесса.
Константа
Константой является объект, не изменяющий свое значение при вычислениях. После объявления константы присваивание ей значения запрещено (кроме случая отложенной константы). Пример объявления константы:
constant thousand: integer:=1000;
Переменная
Переменная - это объект, хранящий значение в пределах операторов процесса, функции или процедуры. В отличие от сигнала, присваивание переменной выполняется немедленно. Синтаксис объявления переменной:
\объявление переменной\::=
[shared] variable \идентификатор\{Дидентификатор\}:\тип\ [:=\начальное значением;
Пример объявления переменной:
variable byte_int: integer range -128 to 127:=0;
При объявлении глобальных переменных используют ключевое слово shared. Глобальную переменную можно объявлять в любом месте объявлений проекта.
Порт
В структуре программы VHDL выделяются объекты проекта, называемые entity. Их не следует путать с объектами языка. Порт представляет собой интерфейсный сигнал объекта проекта. Как и в декларации сигнала, в декларации порта указывается его идентификатор, тип, начальное значение. Дополнительно указывается режим работы: in - прием, out - передача, inout - прием и передача, buffer - передача и использование как сигнал-операнд внутри объекта проекта и link. Упрощенный синтаксис объявления портов объекта проекта следующий:
\объявление портов объекта\::=port (\объявление порта\
{; \объявление порта\}); \объявление порта\::=\идентификатор\: in I out|inout|buffer|1ink
\тип\ [:=\начальное значение\] .
Режим link является анахронизмом. Он был введен для аналогового моделирования, но теперь в аналоговом VHDL он не используется.
Настроечная константа generi с
Настроечная константа generic кодирует определенное свойство объекта проекта. Она используется, например, для задания разрядности линий связи, кодирования структуры моделируемого устройства. При вставке компонента через интерфейс связывания настроечных констант, настройка объекта верхнего уровня передается объектам нижнего уровня. Упрощенный синтаксис объявления настроечных констант следующий:
\объявление настроечных констант\::=
депепс(\о6ъявление настроечной константы\
{; \объявление настроечной константы\}); \объявление настроечной константы\::=
\идентификатор\:\тип\[:=\начальное значение\]
Переменная цикла
Переменная цикла - это специальный объект в том смысле, что он не требует объявления. Подробнее о ней сказано при описании оператора цикла loop.
Начальное значение объекта
Начальное значение объекта в его объявлении - это то значение, которое принимает объект перед первым циклом моделирования. Если начальное значение не присвоено, то симулятор присваивает наименьшее значение данного типа, если тип - числовой или самое левое значение, если тип - перечисляемый.
Это значение может быть выражением. Но значение выражения должно быть вычисленным до момента трансляции данного объявления. Например, первое объявление:
signal bb:bit:=aa; signal aa:bit : = Ч';
неверно, так как при его рассмотрении компилятор еще не имеет сведений об идентификаторе аа.
В аппаратной модели начальное значение объекта эквивалентно состоянию триггеров и шин сразу после включения питания до прихода сигналов сброса, т.е. оно не определено. Поэтому компиляторы-синтезаторы, как правило, не допускают (иногда - игнорируют) начальные значения всех объектов, кроме констант или объектов, которые не изменяют свое значение при вычислениях.
Выражения
В VHDL выражения выполняют арифметические или логические вычисления над одним или несколькими операндами. Выражения используются в операторах присваивания сигналу, переменной, при присваивании начального значения, как операнд в других операторах, как входной параметр вызова процедуры или функции.
Операции в выражениях
Операции VHDL перечислены в таблице 3.1 в порядке их приоритета.
Тип операции |
Символ или ключевое слово |
Логические |
and, or, nand, nor, xor, хпог |
Сравнения |
=, /=f <, <=, >, >= |
Сдвига |
sll, srl, sla, sra, rol, ror |
Сложения |
+, -, & (конкатенация) |
Унарные (знак) |
+ » - |
Умножения |
*, /, mod, rem |
Различные |
**, abs, not |
Логические операции имеют самый низкий приоритет. Операнды логических операций должны быть одного типа bit или boolean, или одномерного регулярного типа (векторы) из элементов типа bit или boolean. Для однозначной компиляции логических выражений необходимо использовать скобки, например:
(a or b) and с and (d or с).
Операции сравнения выполняются над операндами одинакового типа и возвращают тип boolean. Операции равенства "=" и неравенства "/=" выполняются над всеми типами. Остальные операции сравнения выполняются над перечисляемыми типами, целыми типами и одномерными регулярными типами (векторами) из элементов такого типа.
При сравнении перечисляемых типов элемент, стоящий в ряду правее (старший), считается большим. При сравнении векторов сравниваются пары элементов векторов, начиная с самых левых. Если пара элементов неодинакова, то вектор с более старшим элементом считается бо лыиим. Если пара элементов одинакова то рассматривается следующая пара элементов. Например, в сравнении векторов битов "0111" >=м01011" результат будет true.
Операции сдвига выполняют сдвиг вектора битов на число разрядов типа integer. Например, результатом выражения "100110" sra 3 будет вектор "111100", т.е. происходит арифметический сдвиг вправо на 3 разряда.
Операции сложения - вычитания "+", "-" предопределены для целых чисел и чисел с плавающей запятой. Операция конкатенации "&" применяется со всеми одномерными регулярными типами или с их элементами. С помощью этой операции векторы - операнды объединяются в более длинные векторы. Например, выражение "101" & 'Г & "10" даст результат "101110".
Унарные операторы применяются к одиночным операндам. Оператор минус инвертирует значение операнда. Операторы умножения "*", деления "/" применяются с целыми операндами и операндами с плавающей запятой. Операторы mod (модуль), rem (остаток) применяются с целыми числами. Операции абсолютного значения abs и возведения в степень "**" определены для целых чисел и чисел с плавающей запятой, причем показатель степени должен быть целым.
Для многих операций языка существуют функции с таким же обозначением. Эти функции выполняют аналогичные действия, что и операции, но над другими типами операндов. Например, функция "+" из пакета numeric„bit библиотеки IEEE выполняет сложение векторов битов, которые кодируют целые числа. Такие функции перегружают операции в зависимости от типа операндов.
При программировании для синтеза следует учесть, что правый операнд для операций "/". mod, rem может быть равным только степени двойки, а левый операнд операции "**" должен быть равен 2, так что эти операции будут означать сдвиг двоичного кода.
Операнды в выражениях
Простейшими операндами являются литерал и идентификатор, такой как имя сигнала или переменной. Само выражение может быть операндом, если его окружить круглыми скобками. Операндами могут быть также агрегат, атрибут, вызов функции, имя с индексом, квалифицированное имя, значение комбинированного типа и его поля, вырезка регулярного типа, функция преобразования типа. Далее подробно рассматриваются эти виды операндов.
Простое выражение чаще всего представляет собой имя объекта со знаком +,- или без него. Для многих операторов операнды должны быть простыми выражениями. Особенно это касается стиля программ для синтеза.
Имя с индексом дает значение элемента регулярного типа, номер которого задается выражением з скобках. Например, vect(4) означает 4-й бит вектора vect, arr(i,j) означает элемент (i,j) двумерного массива агг.
Имя-вырезка задает цепочку элементов объекта регулярного типа. Его упрощенный синтаксис:
\имя-вырезка\::=\имя\(\выражение\ to | downto \выражение\)
\выражение\ - должно вычислять значение, не превосходящее диапазон индексов объекта регулярного типа с именем \имя\. Направление изменения индекса to или downto должно совпадать с направлением, заданным в объявлении типа. Например, если объявлен сигнал:
signal A: bit„vector(15 downto 0);
то А(15 downto 8) - старший байт сигнала А.
Поле комбинированного типа. Чтобы оперировать с полем объекта комбинированного типа его вставляют в выражение согласно синтаксису:
\поле комбинированного типа\::=\имя комбинированного типа\.\имя поля\
где \имя поля\ - может представлять поле любого типа, а также его имя с индексом, имя-вырезку, агрегат. Например, если объявлены тип и сигнал:
type comp„vect is record
(Re: bit_vector(0 to 15); Im:bit_vector(0 to 15)); end record; signal A: comp_vect;
то A.Re(0 to 7) - старший байт поля Re сигнала А типа comp_vect.
Вызов функции. При вызове функции выполняется функция с заданными значениями параметров. Упрощенный синтаксис вызова функции:
\вызов функции\::=\имя функции\ ([\имя параметра =>\] \выражение\ {,[\имя параметрах => ] \выражение\});
где \имя функции\ - имя функции, определенной ранее, \имя параметрах - необязательный формальный параметр этой функции. Выражение-параметр функции должно давать результат типа, соответствующий имени параметра. Параметры можно задавать с поименованным или позиционированным связыванием.
При позиционированном связывании выражения-параметры подставляются в порядке, определенном порядком следования имен параметров в определении функции. При поименованном связывании каждое имя параметра связывается с соответствующим параметром с помощью символов "=>", причем порядок следования параметров может быть произвольным.
Например, в пакете iEEE.Math_.Real определена функция синуса:
function Sin (x: in real) return real;
Ее вызов по аргументу вещественного типа выглядит как: SIN(x=>math_2_pI * angle) или sin(math_2„pi * angle),
где math__2_pi - константа, равная 2, определенная в этом пакете.
Преобразование типа. Так как в VHDL присваивание значения объекту требует строгого соответствия типов, то в случае, если типы объектов не совпадают, необходимо выполнить преобразование типа. Его синтаксис соответствует синтаксису вызова функций с одним аргументом.
Различают два вида преобразования типа: переход типа и вызов функции преобразования типа. Переход типа применяется для преобразования тесно связанных типов или подтипов. Такими парами типов являются, например, real и integer, integer и natural, регулярные типы с одинаковым числом элементов того же самого типа и с одинаковыми диапазонами индексов. Например, при переходе из значения с плавающей запятой к целому значению:
C:=integer(123.5);
результат с округляется до ближайшего целого, т.е. до 124.
Если типы не тесно связанные, то необходимо выполнить вызов функции преобразования типа. Например, типы boolean и bit - не тесно связанные т.к. принадлежат к перечисляемым типам с различными множествами элементов. Поэтому, например, преобразование переменной х типа boolean в переменную Y типа bit может выполняться функцией преобразования типов, которая включает оператор:
if X then Y: = 'l'; else Y: = '0'; end if;
Часто программисты пользуются своими функциями преобразования типов. Большинство стандартных и коммерческих библиотек содержат наборы функций преобразования типов.
Атрибут. У объектов языка имеется некоторое множество свойств и особенных значений. Атрибут объекта - это специальная функция, которая возвращает его особенное значение. Например, атрибут objectl'left возвращает значение самого левого элемента объекта objectl перечисляемого типа. Подробнее об атрибутах будет рассмотрено в разделе, посвященном атрибутам.
Агрегат. Агрегатом называется операция, которая объединяет одно или несколько значений в значение составного типа, т.е. регулярного или комбинированного типа. Его упрощенный синтаксис:
\агрегат\::=(\связывание элементов\ {Довязывание элементов\}) \связывание элементов\::=[\альтернативы\ =>] \выражение\ \альтернативы\::=Лальтернатива\ {Д альтернатива\}
\альтернатива\: :=\простое выражение\|\диапазон\|\имя элемента\| others
Связывание элементов означает подстановку одного выражения в одно или несколько заданных полей или элементов значений составного типа. Связывание элементов может происходить в порядке нумерации элементов составного типа. Тогда оно называется позиционированным связыванием. Например, в объявлении:
variable v_5: bit_vector (0 to 4) : = С09, '0', ,01, '1', Ч') ;
битам 0, 1 и 2 присвоено начальное значение 0, а битам 2,3 -значение 1. Если каждый элемент связывается со своим значением по имени, то такое связывание называется поименованным. Например, для той же переменной v_5:
(3|4 => '1\ others => '0') или (0 to 2 => '0'; 3 to 4 => 'Г).
Здесь ключевое слово others означает остальные элементы значения и оно должно стоять последним в списке связываний. Возможны и комбинированные агрегаты, в которых первым используется позиционное связывание, а затем - поименованное связывание, например:
СО9,'О9, 3 to 4 => '1\ others -> 'О').
Но такое связывание допускают далеко не все трансляторы VHDL.
Такая альтернатива, как простое выражение, применяется только для регулярных типов и должна определять номер элемента из диапазона этого типа, например, агрегат (i => '!', others => '0') задает вектор в котором на £-м месте стоит 1, а остальные биты — нулевые.
Альтернатива \имя элементах применяется только для комбинированных типов, например:
type complex is record (Re: integer; im: integer ); end record; variable x is complex:=(Re => 1000, im => 0);
Квалифицированное выражение. Результат выражения может принадлежать нескольким типам одновременно. Если этот результат должен принадлежать к конкретному типу, то его необходимо обозначить как результат, квалифицированный с заданным типом. Синтаксис такого выражения:
\квалифицированное выражение\::=\имя типа\'(\выражение\)
Например, если объявлено
type vect is bit„vector(0 to 9); var x: vect;
то выражение (3=>'l'.others => '0') может принадлежать к типу векторов любой длины и разных типов. Поэтому для присваивания переменной этого выражения необходимо выполнить его квалифицированным:
x^vect'O^'l' .others -> '0');
Статические выражения
Как уже указывалось, структура виртуальной параллельной вычислительной системы и ее параметры формируются при компиляций программы VHDL и остаются неизменными в процессе ее исполнения. Точнее, это происходит на последнем этапе - этапе связывания объектов (elaboration). В программах часто встречаются выражения, от результатов которых зависят структура и параметры системы. Это например, настроечные переменные (generic), определяющие порядок включения блоков, их разрядность. Некоторые операторы, например, case, вставки компонента, требуют, чтобы в них входили статические выражения. Результаты этих выражений должны иметь конкретные значения перед исполнением программы и не должны зависеть от входных сигналов и переменных. Такие выражение получили название статических. Другими словами, непосредственно перед моделированием статическое выражение должно быть вычислено до константы или приведено к сигналу или переменной конкретного типа. Выражения от литералов, констант, статических выражений и функций от них являются статическими выражениями.
Например, если объявлены сигналы
signal n: integer;
signal A: bit_vector(16 downto n+1);
то на момент начала моделирования операнд п неизвестен и симуля-тор будет пытаться подставить п = -2147483647, что вызовет аварийную остановку симулятора при размещении сигнала А в памяти, т.е. здесь выражение п+1 - не статическое.
Если симулятор дает широкие возможности исполнения программы, обеспечиваемые большими ресурсами памяти компьютера и последовательным многократным исполнением операторов, то при аппаратной реализации программы эти возможности значительно
уже. Поэтому если программа на VHDL предназначена для синтеза, то требования применения статических выражений встречаются значительно чаще.
В предыдущем примере симулятор может работать, если сигнал п - типа natural, который по умолчанию принимает начальное нулевое значение. Но для синтеза такая программа не годится, так как, во-первых, присваивание начального значения игнорируется или запрещается, во-вторых, в аппаратуре должны быть четко заданы разрядность регистров и шин, объем памяти и т.п.
Реализация выражения в аппаратной модели VHDL
Если выражение не упрощается при компиляции до константы или другого объекта, то оно реализуется в аппаратной модели в виде логических комбинационных схем. Операции в выражениях отображаются в схемы, выполняющие эти операции над операндами соответствующих типов.
Логические операции реализуются в соответствующих элементах: and — в элементе "И", not - элементе "НЕ" и т.д. При операциях над битовыми или булебскими данными реализуются одиночные логические элементы. При выполнении операции над операндами регулярного типа каждому элементу операнда ставится в соответствие один логический элемент.
Операции равенства и неравенства реализуются с помощью соответствующего числа элементов "И" с объединением их выходов в элементе "ИЛИ". Операции "больше" или "больше или равно" выполняются с помощью многоразрядной схемы сумматора-вычитателя, выход переполнения которой соответствует булевскому результату этой операции.
Операции, сложения, вычитания, изменения знака выполняются с помощью схемы сумматора, а операция умножения - с помощью комбинационного умножителя. При этом если операнды типа positive или natural, то умножение выполняется на умножителе без учета знака, а если типа integer - на умножителе со знаком.
Операция абсолютного значения abs выполняется на схеме получения положительного числа из отрицательного и мультиплексора, который в зависимости от знака числа пропускает результат на выход схемы.
Операция деления, модуля, остатка и возведения в степень, которые соответствуют сдвигу объекта, представленного двоичным числом, реализуются в схеме сдвигателя. При этом если операнд типа integer, то сдвиг вправо выполняется с учетом знака.
При выполнении операций сложения и вычитания разрядность результата должна быть равна максимальной разрядности операндов. Операнды
операции умножения должны иметь суммарную разрядность, равную разрядности произведения.
Если операнды объявлены как тип integer без диапазона, то им соответствуют 32-разрядные типы и соответствующие 32-разрядные схемы реализации операций. Для минимизации оборудования рекомендуется принять объявление переменной с диапазоном: например, если переменные объявлены как:
variable a, b: integer range (-128 to 127);
то выражение a+b выполняется на 8-разрядном сумматоре.
Сложное выражение от нескольких операндов при отсутствии скобок и с равноприоритетными операциями выполняется последовательно слева направо. Ему соответствует схема из цепочки модулей, выполняющих эти операции. Вставка скобок в это выражение задает приоритет выполнения операций, который отображается в аппаратную схему. Благодаря этому результирующая схема имеет вид дерева из модулей, задержка логических схем которого может быть намного меньше, чем в исходной схеме. На рис. 24 показаны аппаратные схемы, соответствующие выражениям a+b+c+d и (a+b)+(c+d).
Таким образом, вставка скобок в выражение является одним из способов управления ходом синтеза, выполняемого компилятором-синтезатором.
Последовательные операторы
Последовательные операторы в VHDL вставляются в операторы процессов и исполняются последовательно в виртуальных процессорных элементах программистской модели. Все операторы в VHDL оканчиваются точкой с запятой. Несколько операторов можно размещать в одной строке и один оператор может занимать несколько строк.
Оператор присваивания
Он выполняет присваивание переменной или сигналу результата выражения. Этот оператор выглядит следующим образом:
\результат\:= \выражение\; - для присваивания переменной \результат\ <= \выражение\; - для присваивания сигнала.
Здесь результат \результат\ может быть именем, например, var, именем с индексом, как var(l), вырезкой, как var(0 to 1), полем, как гее.var или агрегатом, как (ReTim).
Присваивание переменной отличается от присваивания сигналу. Присваивание переменной выполняется немедленно.
Выполнение оператора присваивания сигналу означает вычисление его выражения, и лишь назначение сигналу. Само же присваивание сигналу фактически выполняется в момент остановки процесса по ожиданию события. Поэтому если в одном процессе стоит несколько присваиваний одному сигналу, то истинное присваивание происходит в момент остановки процесса. Если перед остановкой процесса выполнялось чтение этого сигнала (участие его в качестве операнда в выражении), то будет прочитано значение, присвоенное в прошлом запуске процесса.
При выполнении присваивания для части элементов сигнала составного типа или перечисляемого типа, например, имени с индексом, вырезке считается, что выполняется присваивание всем элементам сигнала, причем те элементы, которые не указаны в операции присваивания, принимают старое значение. Например, по фрагменту программы
signal d:bit_vector(0 to 7);
d <= (others => '0'); d(l to 3) <= "Oil"; d(4 to 5) <= "IIй; wait ...
сигналу d будет присвоено значение "00111100".
Всем операторам присваивания сигналу в одном процессе в модели виртуального процессорного элемента соответствует один источник сигнала. Если одному и тому же сигналу выполняется присваивание в различных процессах, то несколько источников сигналов соединяются своими выходами и в общем случае, результирующий сигнал может быть неопределенным. Поэтому над таким сигналом должна быть задана функция разрешения, которая разрешает кон-
фликт присваивания одному сигналу значений из нескольких источников сигнала.
Если пользоваться пакетом ieee.STD_logic_1164, to сигнал, объявленный как stcLlogic, можно присваивать в разных процессах, так как в этом пакете есть функция разрешения для такого типа сигналов.
Присваивание сигналу при моделировании
При моделировании дискретных систем важное место занимает моделирование распространения сигнала с учетом задержки в проводниках или в вентилях. Для этого используют следующий расширенный синтаксис присваивания сигналу:
\присваивание сигналу\::=\результат\ <= [\способ задержки\] \график\; \спосо6 задержки\::= transport |[reject \выражение времени\] inertia! \график\::= \выражение\ [after \выражение времени\]
{, \выражение\ [after \выражение времени\] }
Здесь график (waveform) представляет собой запись, состоящую из одной или нескольких пар: величина сигнала - задержка сигнала. В первой паре задержка может не указываться, подразумевается, что она нулевая.
Способ задержки transport означает, что при присваивании сигналы, представленные в графике, будут задержаны подобно тому, как сигнал задерживается в линии задержки или в проводниках. Величина задержки отсчитывается относительно момента остановки процесса и задается выражением \выражение времени\, которое имеет тип time.
Способ задержки inertia! реализует поведение задержки в источнике сигнала, который не реагирует на слишком короткие входные импульсы. Фразой reject задается минимальная ширина импульса, которая выдается источником. Если этой фразы нет, то минимальная ширина импульса задается в фразе after. По умолчанию в операторе применяется способ задержки inertia"!. В следующем ряде примеров показано действие оператора.
Y<= х after 10 ns;
- значение сигнала х на момент запуска процесса присвоится сигналу Y с задержкой 10 не, при этом импульсы шириной менее 10 не будут подавлены.
Y<= '0\ '1' after 10 ns, '0' after 20 ns, '1' after 30 ns;
- сигналу Y сначала присвоится 0, через 10 не - 1, через 20 не - 0, и через 30 не - 1. Иногда таким способом задаются тестовые последо вательности сигналов.
Y<= а, А+в after delay_sum;
- сигналу Y сначала присвоится А, а через задержку, определяемую статическим выражением delay_sum - сумма сигналов А и в.
Y<= transport X after 1000 ns;
- модель линии задержки сигнала х с задержкой 1 мкс.
Y<= reject t_rej inertial A and в after t_d;
- моделируется вентиль "И" с задержкой t_d , который не пропус кает импульсы короче t_rej.
Оператор ожидания события wai t
Этот оператор уже упоминался при описании модели для программирования на VHDL и принципов работы симулятора. На этом операторе процесс останавливается, в момент остановки выполняются присваивания сигналам, и процесс продолжает исполнение при появлении события, которое выбирается этим оператором. Синтаксис оператора wai t:
\оператор waitY- :=wait [on \имя сигнала\ {Димя сигнала\}]
[until \6улевское выражение\] [for \выражение времени\];
где ключевое слово on начинает список чувствительности, until -условие ожидания, a for - означает задержку ожидания. По оператору
wait on clk, rst;
продолжение выполнения процесса начнется по событию изменения сигналов clk или RST. По оператору
wait until CLK='l';
продолжение начнется в момент изменения состояния clk из '0' в '1', т.е. по фронту этого сигнала. Оператор
wait for clk_period;
остановит процесс на время, заданное переменной clk_period типа ti me.
Возможно комбинирование списка чувствительности и условия ожидания в одном операторе. Оператор wait без списка чувствитель-
ности, условия ожидания и задержки останавливает процесс до конца моделирования.
Оператор i f
Этот условный оператор в зависимости от заданных условий выполняет цепочки последовательных операторов, причем от условия зависит, которая из цепочек операторов выполняется. Упрощенный синтаксис оператора:
\оператор if\::=if \условие 1\ then
{\последовательный оператор 1\}
[ { elsif \условие 2\ then
{\последовательный оператор 2\}]
[else
{"^последовательный оператор 3\}]
end if;
Каждое из условий должно быть выражением, вычисляющим результат булевского типа. При выполнении этого оператора условия проверяются последовательно друг за другом, пока результат условия не будет true. Тогда выполняется соответствующая этому условию цепочка операторов и выполнение данного оператора if прекращается.
Оператор case
Этот оператор разрешает выполнение одной из цепочек последовательных операторов в зависимости от значения выражения селектора. Его синтаксис:
\оператор case\::=case \простое выражение\ is
when \альтернативы\ => {"^последовательный оператор\} {when \альтернативы\ => {"^последовательный оператор\}} end case; \альтернативы\:= \альтернатива\{ | \альтернатива\}
В выражении селектора \простое выражение\ должен вычисляться целый результат или значение перечисляемого или регулярного типа. Каждая из альтернатив \альтернатива\ должна быть такого же типа, что и \выражение\ и представлена статическим выражением или диапазоном, например, 0 to 4. Никакие два значения, получаемые из выражений альтернатив, не должны быть равны друг другу, т.е. множества альтернатив не перекрываются. Последней альтернативой может быть ключевое слово others, которое указывает на не перечисленные альтернативы. Если others не применяется, то в аль-
тернативах должны быть перечислены все возможные значения, принимаемые в селекторе \выражение\. Пример оператора case:
variable sel, a: integer 0 to 9;
case sel is
when 0 => a <= 0;
when 112 I 3 => a <= 1;
when 4 to 7 -> a <= 2;
when others => a <= 3; end case;
Пустой оператор
Оператор null - не выполняет никаких действий и может быть вставлен в любом месте программы, как последовательный оператор. Например, если в операторе case по каким-то альтернативам не нужно ничего выполнять, то ставится этот оператор:
case sel is
when 0 => a <= 0; when 1 to 9 => a <= b; when others => null; end case;
Оператор цикла
Этот оператор несколько раз выполняет последовательность операторов. Его синтаксис:
\оператор цикла\::=[\метка\:][\схема итерации\]1оор ■^последовательный оператор\}
{next[\MeTKa\][when \условие\];} {ехЩ\метка\] [when \условие\];} end loop [\метка\]; \схема итерации\::=while \условие\
| for \переменная цикла \ in \диапазон\
Метка \метка\ необязательна, она отмечает начало цикла и с помощью ее во вложенных циклах указывается, в каком цикле начать новую итерацию по оператору next или из какого цикла выйти по оператору exit.
По первой схеме итераций цикл, ограниченный ключевыми словами loop и end loop будет выполняться, пока условие \условие\ не примет значение false. Причем, это условие проверяется до выполнения цикла и если оно сразу равно false, то цикл не выполняется.
В примере:
variable vec: bit_vector(l to n); variable or_vec:bit; variable i:natural;
i:=l;
or_vec:='0'; while i<=n loop
or_vec:= or_vec or vec(i);
i: =i +1; end loop;
вычисляется переменная or_vec, равная функции ИЛИ от всех разрядов вектора vec длины п. Если п = 0, то цикл не вычисляется. Этот пример можно записать с помощью второй схемы итерации как:
variable vec: bit_vector(l to n); variable or_vec:bit;
or_vec:='0'; for i in 1 to n loop
or_vec:= or_vec or vec(i); end loop;
Здесь переменная цикла i последовательно принимает значения 1,2,... из диапазона 1 to п. Если необходим обратный порядок изменения переменной цикла: п, п-1,... то этот диапазон может быть задан как: n downto 1. Переменную цикла не нужно объявлять, как другие переменные и ей нельзя выполнять присваивания.
Если необходимо завершить очередную итерацию до ее окончания, то применяют оператор next запуска следующей итерации.
В примере
variable vec: bit_vector(l to n); variable numb:natural;
numb:=0;
for i in 1 to n loop
next when vec(i)='0';
numb:=numb+l; end loop;
вычисляется число единиц в векторе vec.
При необходимости закончить оператор цикла до завершения всех итераций применяют оператор exit выхода из цикла.
В примере
variable vec: bit_vector(l to n); variable numb:natural;
numb:=0;
for i in 1 to n loop
exit when vec(i)='l';
numb:=numb+l; end loop;
благодаря оператору exit, находится номер самой левой единицы в векторе vec, т.е. реализована функция приоритетного шифратора.
Оператор loop часто применяется без схемы итерации, т.е. когда цикл может выполняться неопределенно большое число раз. Следующий пример иллюстрирует модель счетчика синхроимпульсов CLK.
signal elk: bit; signal numb:natural;
numb<=0; loop
wait until clk='l';
numb<=numb+l; end loop;
Вызов процедуры
Вызов процедуры также представляет собой последовательный оператор. Его упрощенный синтаксис:
\вызов процедуры\::=\имя процедуры\[([\имя параметра =>\] \выражение\ {,[\имя параметрах => ] \выражение\})];
Здесь \имя процедуры\ - имя ранее определенной процедуры. Связывание формальных и фактических параметров выполняется аналогично, как в вызове функции. Выражение - параметр функции должно давать результат типа, соответствующего имени параметра \имя параметрах. Параметры можно задавать с поименованным или позиционным связыванием. При позиционном связывании параметры-выражения подставляются в порядке, определенном порядком следования имен параметров в определении функции. При поименованном связывании каждое имя параметра связывается с соответствующим параметром с помощью символов "=>", причем порядок следования параметров может быть произвольным.
В пакете iEEE.Math_Real определена процедура генерации случайных чисел:
procedure uniform(variable SEEDl,SEED2:inout positive;