Любой программист микроконтроллеров, Imho, рано или поздно (сейчас, скорее, рано) от одного из коллег или из статьи в интернете слышит загадочное ПЛИС или FPGA, CPLD, ПВМ — что-то такое. Если честно, то я услышал вот это загадочное, занырнул чуть-чуть, и теперь думаю, что мой опыт пригодится кому-то ещё. Если совсем честно, то статья ещё планируется как небольшая (всего в трёх частях) заметка для себя. Я когда погружался, делал пометки в текстовом файле, здесь получится их хорошо отредактированная версия.
Очень много вещей в подобных этому туториалах, которые я читал, пропускаются как сами собой разумеющиеся. Подробные инструкции куда и как тыкать есть в документации к плате разработки. Но там не хватает ответов на вопросы зачем и почему. Здесь я хочу скомбинировать 2 подхода.
В самом начале мы имеем такое понимание: вот эти ваши программируемые вентильные матрицы это программно собираемые элементы логических схем - И, ИЛИ, НЕ, и всё такое прочее, чему учат в древности на радиокружках, или в универах на парах цифровой схемотехники. Для понимания и погружения в тему ПЛИС без этой картинки в голове никак. Здесь я не буду описывать "базу", к сожалению, это как простейшая арифметика или умение писать - надо пройти в "школе", (можно в интернете найти какое-нибудь видео с лекцией - другой). Но, думаю, очень многие embedded программисты, хотя бы на интуитивном уровне, понимают как работает элемент "И", "ИЛИ", "2И-НЕ" К155ЛА3 и прочее. В дальнейшем я буду считать, что читатель имеет это базовое представление.
Дальше нужно определиться с инструментарием. Просто так читать теорию, не держа ничего в руках, совсем не интересно. Эмуляторы, конечно, эмуляторами, но всё равно не то. Нужна железка. Из древних времён в картонной коробке у меня завалялась ожидая своего времени плата QMTECH Cyclone 10 Starter Kit:

К сожалению (или к счастью, я не знаю) эту плату сейчас не представляется возможным найти без особых усилий (с особыми, думаю, можно), так что просто копи пасте кода из этой статьи, скорее всего, не получится. Но этого совершенно не надо, Надо разобраться что и как. Есть в закромах ещё плата с циклоном 5 (циклон - это серия ПЛИС от бывшей Altera, а теперь – Intel), но для циклона 5 пришлось бы устанавливать старую версию софта для разработки, а софт он и новый кривоватый, скажем честно, а устаревший кривоватый софт это вот совсем то, чего не хочется. Особенно полезной эта статья будет полным новичкам, которые будут использовать железку, совместимую с последней версией софта. Для прошивки понадобится программатор altera usb blaster. Его достать с быстрой доставкой совсем не проблема.
Под "софтом" здесь я понимаю среду разработки quartus от Intel, а именно её light версию, которая бесплатная. Она скачивается с сайта интел, даже ссылка вот. Есть вероятность, что ссылка не откроется, потому, что мы с вами ужасные люди по паспорту, но нам помогут 3 буквы, какие – не скажу, сами догадаетесь.
Софт официальный, лицензионный, так что установка это привычное далее->далее->согласен->далее. Единственное, что я сделал не по умолчанию, так это в окошке, где нас спрашивали про устройства, с которыми мы собираемся работать, отметил всё, что можно было. Не знаю, может быть и не стоило.
И вот у нас установилась среда разработки, мы её открыли а она смотрит на нас своим серым цветом в стиле Windows 98. Не пытайтесь меня убедить, что мигание светодиодом это для детей и полных хелоуворлдщиков. Мигание светодиодом на новом для нас устройстве даёт огромный эндорфиновый всплеск от осознания своей власти над ничтожной железякой. Так что приступим!
file -> new -> new quartus prime project -> next -> вводим имя и расположение проекта.
По умолчанию quartus проект пытается запихнуть туда, где мы его будем искать долго и с фонариком (AppData\Local\quartus) — неудобно. Выберите здесь расположение, где вы храните остальные свои проекты. Папку для проекта он сам не создаёт, так что там, где путь, нужно ввести имя папки проекта в конце пути (/LedBlink, например) - она будет создана.
Имя проекта, наверное, что-то наподобие LedBlink. Там же нас спрашивают имя top-level entity. Оставляем по умолчанию, потом объясню что это.
->next (yes) ->empty project ->next -> (add files – не надо, ничего не меняем) next ->
(Family, device and board settings) Тут мы выбираем чип нашей платы. В моём случае я должен выбрать Family Cyclone10 LP и только потом в Name filter ввести мой чип 10CL016YU484C8G (это написано на корпусе кристалла). Тогда в отфильтрованной таблице Available devices появится мой чип. Я его выбираю и жму next. В вашем случае здесь можно сначала выбрать чип, который поддерживается средой, чтобы заказать плату разработки с ним, или, может быть, у вас есть уже какая-нибудь плата разработки ПЛИС, и она поддерживается quartus prime. Дальше оставляем по умолчанию, next -> finish.
И вот опять. Ещё более серое и унылое пустое окно. Когда мы говорим про ПЛИС, практически всегда упоминается какой-нибудь HDL (Hardware Description Language) Язык описания схемы. Их не один. Чаще всего это Verilog, VHDL и System Verilog. Для нас сейчас не особо важно какой. Я для себя выбирал язык, советуясь с LLM. Выбрал Verilog. Очень важно понимать, что язык HDL это не язык программирования. Это язык описания схемы. И на выходе у нас не программа, а схема электрическая принципиальная. Поэтому для мигания лампочкой я выбрал даже не описание на языке, а графическое представление. Так вот на фоне серого пустого окна нажимаем file -> new -> Block diagram/Schematic file. Откроется редактор схем с пустым листом.
Top-level entity это сущность высшего порядка Это, собственно, наш чип. В проекте могут быть различные модули, соединённые друг с другом, и вложенные друг в друга. У каждого модуля есть входы и выходы.
Сами по себе модули (те, которые не содержат внутри других модулей) это соединённые друг с другом примитивы – те самые элементы "И", "ИЛИ", "2И-НЕ", ещё триггеры. То есть, например, можно объединить 2 логических элемента "И". Получится модуль с 3 входами и одним выходом –"3-И". Добавим туда инвертор на выход и вот вам модуль "3-И-НЕ".
Cхемы могут быть куда сложнее, так что удобно небольшие функции делать отдельными модулями со своими входами и выходами, а потом их соединять друг с другом. Тот модуль, который содержит в себе все остальные - у него входы и выходы предназначены не для соединения с другими модулями, а для выхода наружу. Его входы и выходы мы назначаем в пин-планнере (потом объясню), и к ним уже подсоединены светодиоды и прочая периферия. Собственно этот модуль и является top-level entity. Вообще, в top-level entity можно запихнуть 4 модуля "И" с инверсией выхода, назначить 8 входов и 4 выхода, и тогда весь дорогущий чип ПЛИС превращается в полный (ну, ладно, не совсем pin-to-pin, да и уровни другие, скорее всего) аналог микросхемы К155ЛА3.
На данном этапе такого понимания достаточно. Нажимаем вот так:

Получаем один D-триггер. Мигать светодиодом на микроконтроллере элементарно! Строчка за строчкой в цикле подали напряжение, подождали, сняли напряжение, ещё подождали.
Тут у нас нет строчек! Зато есть тактовый сигнал. Наверное в самом примитивном примере, когда мы реализуем логику без триггеров, можно и без тактового. Но мигать светодиодом на ПЛИС это уже не самый примитивный пример!
D-триггер – хранитель одного бита – элементарная ячейка памяти. Но их ещё используют для деления частоты. В моём случае (вообще - он не уникальный, у многих так будет). Тактовая частота 50МГц. Можно, конечно, подключить диод напрямую к тактовой, и сказать: "Он мигает, просто очень быстро. Не верите? Подключите осциллограф!" Но это, как-то, слишком лениво, что ли? Так что, чтобы было заметно как диод мигает, скажем, что нам нужна частота около одного герца. D-триггер делит частоту напополам, так что нам нужно 50000000 разделить на 2 сколько-то раз. Сколько? Логарифм нам в помощь, больше 25 раз! Для получения делителя частоты из D-триггера используют его инверсный выход, но у нас тут нет инверсного выхода, так что добавим ещё элемент not из primitives->logic, и соединим пару вот так:

Ну и ещё 23 раза то же самое. Настало время добавить выходы и входы. Вот эта кнопочка:

Нажимаем, добавляем один input и обзываем его clk, потом добавляем один output и обзываем его led. А впрочем, называйте как хотите, главное не забывайте что и как назвали. Подсоединяем вход к треугольничку самого первого триггера, а выход к выходу самого последнего элемента not. Должно получиться что-то такое:

Благо copy-paste можно использовать для области, выделенной рамкой. Здесь меня поджидал первый глюк - напасть. У каждого такого примитива (говорят инстанса примитива (instance)) должно быть уникальное имя, а у меня, почему-то после вставки имена автоматически не назначились - пришлось вручную каждому добавлять порядковый номер. Сейчас, когда я пишу эту статью, всё получилось нормально.
Теперь этот файл можно сохранить. Вот тут выясняется ещё момент. Имя файла схемы - это заодно ещё и имя модуля. Для успешной компиляции проекта в проекте должен быть модуль, являющийся top-level entity. Если нажать file->save (или ctrl+s), то по умолчанию он задаст имя файла как LedBlink. Если так и оставить, то всё будет работать как надо, но момент проплывёт мимо нас. А если назвать файл например module1, то работать ничего не будет. А всё потому, что при создании проекта мы оставили имя top-level entity по умолчанию (LedBlink), и теперь у проекта нет top-level entity. Его можно для проекта задать с помощью правой кнопки мыши так:


Следующий момент: в пин-планнере (утилита для назначения имён пинов, вызывается: assignments -> Pin Planner) имена входов и выходов модуля верхнего уровня появляются в табличке только после "анализа и обработки".

Первая кнопка - делает готовый файл для прошивки в чип, вторая - только анализ и обработка, третья - это анализ и синтез. Так вот, после "анализа и обработки", если всё в порядке, если вызвать пин планнер (assignments -> Pin Planner), то там появятся наши пины clk и led. Их надо назначить физическим пинам на чипе (Location). То есть, куда именно на вашей плате разведены тактовый сигнал и светодиод. Для моей платы (QMTECH Cyclone 10 Starter Kit) эта информация есть в документации на гите. Оттуда беру, что clk у меня это PIN_g1, а лампочек аж целых 2, это PIN_w17 и PIN_y17. Я выбираю y17 (кстати небольшое удобство - когда в столбце "Location" мы выбираем пин - можно просто написать там y17, не надо набирать "PIN_" он это сам подставит)

Всё, теперь можно жать "Start compilation" - синий треугольник без ничего на нём, и квартус подготовит нам файл для заливки в чип. Мы с вами занимаемся FPGA, а значит процессорных ядер в нашем компьютере а также гигагерцев в каждом из них у нас куры не клюют. Поэтому компиляция пролетает в доли секунды (на i5 9600 этот пример собирается за ~20 секунд). Теперь настало время зашить в чип и любоваться миганием.
Для этого надо подключить altera usb blaster. Драйвер по-умолчанию не ставится. Его надо принудительно установить из диспетчера устройств. Драйвер есть в папке C:\intelFPGA_lite\24.1std\quartus\drivers (версия квартуса может быть другой) поставить галочку "искать в подпапках" тогда драйвер находится и устанавливается.
Нажимаем кнопку для программирования и... Ничего не происходит, потому сначала надо в утилите программирования выбрать свежеподключенный usb blaster со свежеустановленным драйвером:

Дальше для перепрошивки не надо каждый раз настраивать hardware setup, до тех пор, пока вы не нажмёте кнопку вызова утилиты программирования с отключенным программатором – тогда он сбрасывается на "No hardware".
Да, после нажатия кнопки старт можно испытывать радость от своего могущества, лампочка-то замигала (с частотой 50000000 / 33554432. Приблизительно полтора герца). Но эта радость недорога, скоротечна, и вызывает жжение сделать что-то чуть более сложное. Об этом – в следующих статьях. Следующая статья – небольшая передышка на семисегментниках.
Комментарии (8)
mozg37
22.08.2025 11:43Ни в коем случае не начинайте с схемного проектирования. Деды, проектирование жуткие вещи на 155 серии в 80х - творят подобную дичь схемным образом на плис, разбираться в которой та ещё задача. Безусловно, без знания логики, триггеров и прочего можно и не начинать, но начинать - с HDL языков. Важнейшим атрибутом, имхо, является владение внутрисхемной отладкой. Без нее, например, выводы на свободные ноги что либо - не получится ничего сложнее блинканья диодом. В квартусе это сигналтап, в говине так и называется лоджик энелайзер. Все это конечно дискутабельно, каждый, прошедший путь от блинканья до каких нибудь fft - может иметь разное мнение.
av-86 Автор
22.08.2025 11:43Спасибо за совет! Как раз так и будет. Здесь схема только для моргания диодом, и то монстр уже) В следующей части в начале для контраста будет тот же блинк в 4 строчки)
Moog_Prodigy
22.08.2025 11:43Между прочим в среде OWEN logic тоже подобный подход (хотя можно писать модули). И довольно востребовано, поддается трассировке. Я как раз один из таких "дедов", проектировавший жуткие вещи на 155 (и 500). Мне наверное не стоит браться за ПЛИС, да? Вопрос не троллящий, я сам и правда не знаю (но хотелось бы кое-что поделать со звуком и видеосигналами). Башка она не резиновая, и если HDL выучить я осилю, то уйти от парадигмы составлять все на логике - будет пожалуй очень сложно, если не невозможно.
av-86 Автор
22.08.2025 11:43HDL просто очень сильно сокращает запись, и позволяет намного более компактно делать всё то же самое. При этом сложность получающихся схем можно очень сильно нарастить.
apcs660
22.08.2025 11:43чуть ранее 2010го, на https://opencores.org/projects заходил частенько и там кипела жизнь, попался как то проект под спартан или алтеру, уже не помню, демка, с небольшим процессором risc, видео и контроллером клавиатуры. Все было в виде учебника, включая настройку gcc под учебный процессор.
Сейчас глянул, жизнь еще продолжается, но как то вяло, часть на гитхаб отделились: https://github.com/openrisc и https://github.com/librecores
Strijar
22.08.2025 11:43Навеяло как я уже почти 20 лет назад также будучи эмбедером разбирался со Spartan3. Правда я как программист сразу начал с VHDL и Verilog. Потом была отладка с помощью одного светодиода процессора JOP и пошло-поехало (; Удачи в освоении!
KonstantinC
Жду продолжения, т.к. все время хожу вокруг FPGA, но текущие задачи не создают "волшебного пинка", чтобы таки заняться по-серьезному.
Один раз (года три назад) пробовал играться с FPGA (GOWIN Tang Nano 9K) без особой цели, но что-то пошло не так. Толи драйвера кривые, толи руки - чип превратился в кирпич, хотя вначале шустро мигал светодиодами.
Софт от GOWIN - тогда был жуть. Не знаю как сейчас, хотя судя по Вашей статье такая беда у всех производителей FPGA.
HardWrMan
Не соглашусь. Из моего опыта, у Altera (потом Intel и сейчас что-то другое) самый френдли-софт и что касается всего зоопарка бластеров. Как только они перешли на JTAG там всё просто до самопальности. Следом шёл Xilinx, там с софтом посложнее, но в общем и целом, после настройки работа примерно так же как и с Altera, только что зоопарк JTAG интерфейсов сильно меньше, чем на Altera. А вот с GoWin изначально была беда, а сейчас они подтягиваются к уровню Xilinx по моему внутреннему ощущению. А компилирует софт GoWin реально быстро, секунды 4 тот же Verilog проект, который для Cyclone компилируется почти минуту. Единственный минус это их JTAG. Он тоже сильно сокращён количеством но самое раздражающее - нестандартная распиновка, учтите это!