
Типичные ошибки новичков в FPGA: от выбора платы до неинтуитивных кнопок
Начинающие плисоводы в своих первых проектах часто совершают одни и те же промахи — причем большинство их либо не описано в методических указаниях, либо описано вскользь. Старший преподаватель ОмГТУ Артём Аверченко уже более 10 лет ведет связанные с FPGA дисциплины. Он организовал множество лабораторных работ и уверен: едва ли возможно объять одним текстом абсолютно все препятствия на старте пути. Но те основные, без которых можно быстрее получить скомпилированный проект, Артём постарался осветить в этой статье.
- как выбирать плату для FPGA
- как избежать распространенных ошибок в САПР
- что может привести к проблемам в проекте на SystemVerilog
- какие ошибки могут всплыть на этапе аппаратной реализации
Выбор отладочной платы
Первые проблемы могут возникнуть уже при выборе отладочной платы. Предварительно стоит изучить документацию выбранной платы и сопоставить ее с требованиями проекта. На начальном этапе обучения важнее наличие светодиодов, переключателей и индикаторов — компонентов, которые выдают информацию прямо на плате. На более поздних этапах возрастает приоритет подключаемой периферии — то есть наличие у платы необходимых коннекторов.
Обратите внимание, есть ли на плате USB Blaster — устройство для подключения ПЛИС к ПК и последующего программирования и конфигурирования. Существуют отладочные платы с установленным USB Blaster, которым требуется только провод USB для подключения к ПК. Но также могут встретиться платы просто с разъемом JTAG, и для них нужно докупать внешний программатор. У обеих реализаций есть свои плюсы и минусы.

USB Blaster, изображенный на иллюстрации, продается во многих интернет-магазинах, но ни в одной карточке товара вы не увидите, что внутри корпуса. А внутри может быть два разных схемотехнических решения — рабочее из двух микросхем или нерабочее из одной — как минимум для кристалла Altera Cyclone IV. Есть шанс спасти даже одномикросхемный USB Blaster в подобном корпусе с помощью прошивки, но лучше купить более дорогую и точно рабочую модель, например, производства Waveshare.

Для питания важно использовать блок с заданным в спецификации отладочной платы напряжением и током. Иначе плата может выйти из строя. Некоторые отладочные платы, особенно с минимумом возможностей по периферии, могут получать питание по шине USB прямо с разъема программирования. Естественно, подключить к ним требовательную по питанию периферию не получится.
• Неверный выбор платы — отсутствие нужной в проекте функциональности.
• Дешевый USB Blaster — плата не подключается к ПК.
• Неподходящий блок питания — плата может выйти из строя.
• Питание платы только по USB — требовательную периферию не подключить.
Общие рекомендации в САПР
Для дальнейших примеров я буду использовать САПР Quartus Prime 20.1 Lite Edition. Но на подобные проблемы можно натолкнуться и в других версиях и средах проектирования. При создании нового проекта необходимо указать директорию, в которой будет сохраняться проект. У Quartus здесь по умолчанию всегда находится папка, в которой установлен он сам.

Чтобы не забивать основную директорию, здесь стоит прописать иную папку. При этом важно, чтобы во всем пути от корневой директории (диск C, D…) до папки с проектом в имени самого проекта и всех его файлов не было русских символов.
На всякий случай стоит предварительно перевести все не задействованные в проекте ножки ПЛИС в третье состояние с подтяжкой. В Quartus для этого нужно перейти в настройки проекта Assignments/Device и в открывшемся окне на вкладке Device нажать на кнопку Device and Pin Options.

На вкладке Unused Pins в списке выберите As input tri-stated with weak pull-up. Это позволит избежать неожиданного короткого замыкания, если на отладочной/макетной плате физически установлены какие-либо элементы, подающие на ПЛИС свои сигналы.

Пожалуй, самая распространенная ошибка на начальном этапе — это отсутствие модуля верхнего уровня (top-level).

Проект для ПЛИС — это иерархическая структура с широчайшими возможностями ветвления. Quartus необходимо «знать» и «находить» модуль, который принимается за начальный: с него начинается компиляция и все ветвление подключений в проекте. Первый раз мы сталкиваемся с этим понятием еще на этапе создания нового проекта, во второй вкладке New Project Wizard.

В третьей строке как раз и задается имя модуля, который Quartus будет считать top-level. Эта строка по умолчанию копирует предыдущую, поэтому обычно ее никто не меняет, хотя это возможно, и не обращает на это внимание в методических указаниях. В других САПР бывает возможность указать top-level через контекстное меню (правой кнопки мыши).
Второй раз мы видим отсылку на top-level в окне Project Navigator.

Изменить отсылку на top-level можно в меню Assignments/Settings. Здесь во вкладке General и задается top-level.

Мы разобрались, как Quartus получает ссылку на top-level и как ее можно изменить. Теперь нужно понять, как создается сам top-level. Это зависит от того, какую реализацию вы выбрали — схемную или текстовую. В любом случае придется взаимодействовать с файлами, подключенными к проекту.
В Quartus посмотреть все подключенные к проекту файлы можно в окне Project Navigator, где в открывающемся списке необходимо выбрать Files. Добавить файлы к проекту можно через меню Assignments/Settings./Files или еще на этапе создания проекта в одном из окон New Project Wizard.
При схемной реализации модулем верхнего уровня считается сам файл с расширением .bdf. Согласно примеру на иллюстрации, Quartus будет сканировать папку проекта и искать среди файлов top.bdf. Если найдет, то запустит компиляцию с него. Вообще, некоторые специалисты не советуют пользоваться bdf вовсе.
При текстовой реализации top-level Quartus будет искать явное описание модуля — причем во всех текстовых файлах, подключенных к проекту. Название самих файлов, в которых описаны модули, не играет важную роль — сканироваться будут все текстовые файлы. Для более удобной работы с проектом стоит организовывать текстовые файлы так, чтобы название текстового файла совпадало с названием описанного в нем модуля и в каждом текстовом файле был только один модуль.
Если описанная выше ошибка с top-level возникает, это значит, что отсутствует либо схемный файл с необходимым именем при схемной реализации, либо текстовое описание модуля в подключенных к проекту текстовых файлах. Для решения проблемы можно добавить или исправить имеющиеся файлы проекта так, как хочет Quartus, или сказать ему, что top-level будет другой — тот, что есть в проекте.
• Некорректный путь к директории проекта — проблемы с доступом к файлам.
• Свободные ножки ПЛИС не подтянуты — неожиданные короткие замыкания.
• Отсутствие или некорректный top-level — неправильное ветвление проекта.
Схемотехнический редактор
При вытаскивании элемента на рабочую область Quartus дает элементам имя inst с индексом на единицу больше последнего имеющегося.

В проекте могут быть элементы с одинаковыми названиями — как AND4 на иллюстрации. Но не может быть элементов с одинаковыми именами экземпляров (instance name) — на иллюстрации это inst, inst1, inst2. Иногда при копировании элементов САПР начинает дублировать индексы, что приводит к одинаковым именам экземпляров, и в итоге проект не собирается. Вероятность дублирования повышается, если в проекте много объектов. Двойной левый клик на элементе открывает его меню, где можно изменить instance name.
Для рисования проводников предназначен инструмент Node Tool. Соединительные линии стремятся сохранить соединение со своими элементами, даже когда их перемещают. В результате при перетаскивании соединенных элементов проводники часто накладываются друг на друга, особенно если их много. Это приводит к возникновению паразитных замыканий, отыскать которые очень сложно. Поэтому инструментами соединения типа Node Tool нужно пользоваться с осторожностью.

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

При таком именованном способе соединений элементы можно перемещать по рабочей области, не опасаясь за паразитные связи. Назначить имя проводнику можно через контекстное меню. Или просто выделить проводник и начать писать имя на клавиатуре.
Одиночные проводники и шины рисуются разными, но похожими линиями. Здесь важно внимание, чтобы не перепутать:

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

На рисунке показаны проводники sk и pl, а также восьмибитная шина с именем sh и индексами от 7 до 0. Чтобы взять один проводок из шины, его нужно нарисовать и назвать так, как указано — sh[5]. Тогда значение с шестого провода шины с индексом 5 будет передано на этот проводник. Чтобы собрать шину нужной разрядности в нужном порядке, необходимо использовать конкатенацию. На рисунке собрана семибитная шина, два старшие сигнала — это сигналы с проводников sk и pl соответственно, а далее идет часть шины sh.
Иногда нужно перенести часть схемы из одного схемного файла в другой, но комбинации Ctrl-C / Ctrl-V не срабатывают. Непонятно, связано ли это с САПР Quartus или ОС Windows. Чтобы копирование удалось, нужно открыть каждый проект в своей оболочке Quartus так, чтобы были видны обе рабочие области, и просто перетащить нужный объект: захватить мышкой в одной области и отпустить в другой.
• Дублирование имен элементов — проект не собирается.
• Перетаскивание элементов при соединении через Node Tool — случайные паразитные замыкания.
• Невнимательность к схеме — путаница в проводниках и шинах.
Создание кода на SystemVerilog
Поскольку код на VHDL/Verilog — это не текст программы, а текстовое описание схемы, то и выполняться он будет не последовательно, как в программах на C, Python или других языках программирования, а параллельно. Поэтому неважно, в какой строке будет описан конкретный модуль — он в любом случае запустится, когда на его входы поступят входные сигналы. Однако здесь действуют требования компилятора и «правила хорошего тона», что позволяют писать код, понятный сторонним разработчикам и самому себе при возвращении к проекту через продолжительное время. В частности, для этих целей рекомендуется не пренебрегать комментариями.
Как и в других языках, здесь важна правильная иерархия сущностей, именование входных и выходных портов каждого модуля. Новым модулям/входам/выходам часто дают случайные названия: sv5, sv6, led15 и тому подобные. Некоторые модули нужно затем подключать в качестве дочерних к модулям более высокого уровня. Так появляются одинаковые названия. Это не ошибка с точки зрения Verilog, но впоследствии становится очень сложно отследить логику работы каждого модуля в отдельности и общего проекта в целом. Также это приводит к непониманию: когда, допустим, сигнал led15 подключается к сигналу led15. Приходится возвращаться и восстанавливать логику, давать уже осмысленные имена модулей/входов/выходов.
Общая рекомендация здесь такая: создайте сначала один модуль самого верхнего уровня с необходимыми подключениями к ножкам ПЛИС, а дочерним модулям давайте затем осмысленные названия. Так весь проект становится более понятным.
При оперировании шинными сигналами в Verilog стоит учесть, что в отличие от схемного редактора, здесь для определения диапазона (в квадратных скобках) может быть использован символ двоеточия. При определении диапазон может быть как слева, так и справа — это будет, соответственно, unpacked или packed array. Каждая строка заканчивается точкой с запятой — но есть исключения, поскольку не каждая команда является однострочной.

После написания и компиляции кода важно хотя бы в целом убедиться, как Quartus понял вашу задумку. Для этого можно воспользоваться графическим представлением проекта через инструмент RTL Viewer, который вызывается из контекстного меню при клике на название проекта в Project Navigator.

Для модуля, представленного на Verilog выше, RTL Viewer выдает схему, полностью соответствующую записанной логике. Но на всякий случай лучше дополнительно перепроверить схему после синтеза.

При возникновении ошибок в коде Quartus при попытке компиляции выдаст сообщение с указанием строки кода в специальном окне сообщений. Важно правильно понимать такие сообщения: не «в данной строке ошибка», а «данная строка не может выполнена из-за ошибки». Компиляция — это последовательный процесс, где чтение файла с кодом ведется построчно. Так что ошибку нужно искать не только в «данной строке», но и в строчках выше. Для удобного поиска лучше включить нумерацию строк, как на рисунке выше. В Quartus это делается через галочку напротив Show line numbers в меню Tools/Options./Text Editor.
Когда возникают ошибки, в строке сообщений об ошибках обычно появляется не одиночное сообщение, а довольно много красных строчек. С ходу это может напугать. Но Quartus показывает не только основные, но и все зависимые ошибки. Возможно, что исходная ошибка только одна, а весь ворох проблем тянется уже вслед за ней. Так что без паники находим первую строчку с ошибкой, исправляем ее и запускаем новую компиляцию. Вполне вероятно, что все остальные ошибки тоже исчезнут, если вы верно исправили единственную исходную.
При определении числовых значений с явным указанием разрядности используется апостроф. На клавиатуре обычно есть сразу два подобных символа — на кнопках «Ё» и «Э». Выглядят они чуть по-разному: один как «`», другой как «'». Есть еще более экзотические варианты — например, английская одиночная кавычка «‘», — но сейчас мы их опустим. Знание различий в доступных типографских знаках поможет найти и исправить досадную ошибку.
• Бездумное именование элементов — потеря логики при выходе на новые уровни подключения.
• Неправильное определение диапазонов — некорректное поведение шинных сигналов.
• Не проверили итоговый код «в графике» — логика проекта не соответствует задумке.
• Анализируете лишь строку с ошибкой — проблема с компиляцией так и не решится.
• Путаете апостроф с другими типографскими знаками — ошибки на компиляции.
Аппаратная реализация
Работая с отладочными платами, легко упустить основы физики. Светодиоды на платах могут быть подключены к соответствующим ножкам ПЛИС двумя способами — анод к ПЛИС и катод на земляной полигон или катод к ПЛИС и анод на полигон питания.
Если светодиоды уже имеются на отладочной плате, то значит, там установлены и специальные резисторы, которые называются токоограничивающими. Если вы подключаете светодиоды к ножкам ПЛИС самостоятельно, нужно обязательно рассчитать и поставить токоограничивающие резисторы — чтобы не превысить максимальный допустимый ток, протекающий через светодиод.

В варианте подключения а) светодиод будет светиться при подаче логической единицы. В варианте б) — при подаче нуля. Чтобы получить именно ожидаемый результат, нужно подключать внимательно. Эти же проблемы возникают и при подключении одиночных семисегментных индикаторов.

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

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

Особенность таких индикаторов — в их матричной структуре. Для физического подключения используется всего 12 контактов.

Здесь необходимо применить принцип динамической индикации. В каждый момент значение отображается только на одном индикаторе. При этом переключение индикаторов происходит достаточно быстро, чтобы глаз не успевал это заметить — то есть как минимум 24 раза в секунду на каждый индикатор.
При четырех индикаторах общая частота переключения колеблется в районе 200 Гц. На отладочных платах обычно устанавливается тактовый генератор с частотой 50 МГц, и напрямую подключать его для переключения разрядов не стоит. При такой частоте физика работы светодиода не позволит что-то увидеть, так что частоту нужно поделить до приемлемых значений. Для этого производители плат могут предоставлять специальный IP-блок — делитель частоты, или PLL. Такие блоки используют для работы специальные ячейки, расположенные на плате.
Переключатели на отладочных платах обычно подключены так, что в верхнем положении подают на ножку ПЛИС логическую единицу, а в нижнем — логический ноль, тут трудностей не возникает. Но вот с кнопками нужно быть осторожней. На отладочных платах они обычно установлены с подтяжкой к напряжению питания, так что в ненажатом состоянии на ножку ПЛИС подается логическая единица, а в нажатом — логический ноль. Это может показаться контринтуитивным.

• Подключение светодиодов без ограничивающих резисторов — светодиоды перегорят.
• Путаница в полярности светодиода — поведение компонента противоположно задуманному.
• Подключение светодиодов к встроенному высокочастотному генератору — показания физически невозможно отследить.
• Неверно считанные состояния кнопок — поведение схемы противоположно ожидаемому.
Пожалуй, на этом обзор самых распространенных ошибок можно завершить. Совсем не факт, что моих рекомендаций будет достаточно. Но если следовать им, то ваш проект точно станет более понятным и наглядным. Кроме того, вы сможете быстрее получить успешную компиляцию.
Чек-лист: что проверить в своем FPGA-проекте
Скачивайте эту памятку, чтобы в нужный момент она была под рукой.







