Данная технология имеет один существенный минус: для программирования используются довольно сложные и специфичные языки описания цифровой аппаратуры Verilog и VHDL. Это осложняет вхождение новичка в FPGA и для работодателя найти специалиста с этими специфичными знаниями на рынке труда сложно. С другой стороны популярный высокоуровневый язык программирования Python с фреймворком MyHDL делают программирование FPGA простым и приятным. Тем более людей знающих Python на порядок больше специалистов владеющих Verilog/VHDL. Серией статей я хочу показать как легко и просто войти в область FPGA зная Python и начать делать настоящие сложные FPGA проекты на этом языке. Отмечу, что на ПЛИС python непосредственно не исполняется, а является инструментом для генерации прошивки.
Во первых нам понадобится сам python версии 3.6 (здесь и далее все операции производятся в ОС Ubuntu 18.04).
Устанавливаем myhdl:
pip3 install myhdl
В качестве «Hello World!» Напишем простую программу, которая заставляет загораться светодиоды от нажатия на кнопку. В мире микропроцессоров «Hello World!» это программа, которая мигает одним светодиодом, в мире FPGA Hello World — это мигание тысячи светодиодов. На плате есть только четыре светодиода, так что мигать будем только ими в зависимости от нажатия кнопки. Важно отметить, что весь код в FPGA в отличие от микроконтроллеров выполняется одновременно, все диоды зажигаются и гаснут одновременно. А не последовательно в случае микроконтроллеров. В роли подопытного используется плата WaveShare OpenEPM1270 с плис Altera Max II EPM1270T144C5 на борту.
Создаём новый python файл:
from myhdl import *
from random import randrange
def led_blinker(input1, led1, led2, led3, led4):
@always_comb
def on_off_led():
if input1 == 1:
led1.next = 1
led2.next = 1
led3.next = 0
led4.next = 0
else:
led1.next = 0
led2.next = 0
led3.next = 1
led4.next = 1
return on_off_led
Чтобы узнать правильно ли работает наш код нужно средство верификации. По сути любая программа для FPGA это обработчик цифровых сигналов, соответственно разработчику необходимо убедиться что он правильно указал что делать микросхеме. Делается это через симуляцию, для этого нужно установить программу которая будет отображать обработанные сигналы. Таких программ довольно много, но на мой взгляд самая лучшая на данным момент бесплатная GTKWave. Ставится из терминала:
sudo apt-get install gtkwave
Далее в файле с прошивкой следует описать тестовое окружение. Это тоже питоновская функция:
def test():
input1, led1, led2, led3, led4 = [Signal(bool(0)) for i in range(5)]
test = led_blinker(input1, led1, led2, led3, led4)
@always(delay(10))
def gen():
input1.next = randrange(2)
return test, gen
Здесь тестовое окружение генерирует случайную последовательность из нулей и единиц (используется питоновский модуль random).
def simulate(timesteps):
tb = traceSignals(test)
sim = Simulation(tb)
sim.run(timesteps)
И инициализируем симулятор, протаскивая туда функцию окружения test_inverter. Таким образом получается матрёшка inverter > test_inverter > simulate(время в условных единицах).
После запуска скрипта в рабочей папке создаться .vcd файл и его следует пропустить через gtkwave, в терминале: gtkwave test_invereter.vcd.
В итоге сгенерировалась случайная последовательность входных сигналов input1, и то как обработала эти сигналы функция led_blinker.
После того как мы убедились, что логика отработал ровно так как мы хотели, далее следует эту функцию закинуть в FPGA. Я привык работать с микросхемами фирмы Intel (ранее Altera), данная последовательность действий аналогична и для микросхем других производителей с соответствующими САПР. На микросхему ПЛИС заливается бинарный файл, который создаёт компилятор производителя микросхемы, для Intel это Quartus, для Xilinx Vivado. Компиляторы умеют работать только с кодом в VHDL/Verilog, поэтому питоновский код следует транслировать в любой из этих языков (не принципиально в какой).
def convert():
input1, led1, led2, led3, led4 = [Signal(bool(0)) for i in range(5)]
toVerilog(led_blinker, input1, led1, led2, led3, led4)
convert()
В этом примере код транслируется в Verilog. Результат в файле led_blinker.v, его и надо будет дать Quartus для генерации прошивки FPGA:
module led_blinker (
input1,
led1,
led2,
led3,
led4
);
input input1;
output led1;
reg led1;
output led2;
reg led2;
output led3;
reg led3;
output led4;
reg led4;
always @(input1) begin: LED_BLINKER_ON_OFF_LED
if ((input1 == 1)) begin
led1 = 1;
led2 = 1;
led3 = 0;
led4 = 0;
end
else begin
led1 = 0;
led2 = 0;
led3 = 1;
led4 = 1;
end
end
endmodule
В данном подходе к разработке прошивок ПЛИС на этот файл можно не обращать внимания и просто закидывать его в Quartus.
Скачать Quartus можно с сайта fpgasoftware.intel.com, нужна бесплатная версия Lite, её нам будет достаточно. Качаем базовую версию размер 9 GB.
Установка Quartus не должна вызвать сложностей для обычного пользователя Linux. После установки необходимо задать некоторые параметры в системе, чтобы можно было пользоваться устройством для зашивки программы ПЛИС — программатором:
1. Создаем udev правило. Для этого создаем новый файл /etc/udev/rules.d/51-altera-usb-blaster.rules со следующим с содержанием:
# USB-Blaster
SUBSYSTEM=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6001", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6002", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6003", MODE="0666"
# USB-Blaster II
SUBSYSTEM=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6010", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6810", MODE="0666"
Перезагружаем udev, используя udevadm:
sudo udevadm control --reload
2. Разрешаем non-root доступ к устройству USB-Blaster. Для этого создаем файл /etc/udev/rules.d/altera-usb-blaster.rules со строкой:
ATTR{idVendor}=="09fb", ATTR{idProduct}=="6001", MODE="666"
Это даёт rw-rw-rw- доступ к программатору.
3. Конфигурируем jtagd. Quartus использует для работы демона jtagd, который связывет софт с устройством программатора. Копируем описание из вашей директории с Quartus:
sudo mkdir /etc/jtagd
sudo cp <Quartus install path>/quartus/linux64/pgm_parts.txt /etc/jtagd/jtagd.pgm_parts
Запускаем Quartus и создаём новый проект «File» — «New project wizard», набираем имя проекта.
Далее нажимаем Next. И в меню Add Files подключаем сгенерированный verilog файл с расширением .v. Таким образом, если verilog файл будет редактироваться из python файла то он автоматически будет подхватываться Quartus, Далее попадаем в меню выбора девайса, в нашем случае это MAX II EMP1270T144C5 и ещё пару раз next. Проект создан.
В Project Navigator заходим в меню файлов и правой кнопкой мыши задаем наш verilog файл «Set as top-level entity».
Компилируем проект. Теперь в меню «Assignments-Pin Planner» конфигурируем пины на микросхеме:
Ещё раз компилируем. Теперь всё готово к программированию: Tools-Programmer. Подключаем программатор и питание к плате, в Hardware Setup выбираем свой USB-Blaster, задаём галочки как изображено на рисунке и Start.
После того как Programmer отрапортовал Successful. Можно посмотреть результат на плате:
Заключение
В этом уроке рассмотрено как создавать рабочее окружение и первый простой проект на ПЛИС на языке программирования Python.
Рассмотрено:
- как устанавливать:
- myHDL;
- GTKWave;
- Quartus;
- Произведена настройка программатора USB Blaster в Ubuntu;
- Разработан проект на ПЛИС на python;
- Произведено тестирование и верификация проекта;
- Скомпилирован проект под ПЛИС;
- Загружен проект на ПЛИС.
Комментарии (31)
laviol
09.02.2019 16:07+2Для поиграться на первых порах (и понять, нужно ли вам это вообще), и, возможно, простецких тестов, сойдет.
А вот как у myHDL обстоят дела со скоростью (и избыточностью) сгенерированного кода?
По мне так, если захотелось опробовать FPGA, то лучше сразу привыкать к синтаксису VHDL и/или Verilog (а лучше SystemVerilog), если вы хотите лаконичный и производительный код, тем более что, судя по его вставкам, нет даже отличий в названии блоков логики, аля always и always_comb.alter_fritz Автор
09.02.2019 16:41Особых отличий по скорости я не заметил на более-менее крупных проектах. Плюсы python вылезут когда придётся писать сложное тестовое окружение для верификации проекта.
DmitrySpb79
09.02.2019 22:43-3Если будет возможность, проверьте мигание светодиодом в цикле из Python и напрямую из Verilog — какая разница в скорости будет? Просто в Python overhead гигантский бывает, и некоторые вещи в нем реально медленные, да и память жрут (sys.sizeof(1) = 28 к примеру — 28 байт на один Int! хотя я понимаю что это объект и все такое, но в FPGA памяти-то не так много).
И кстати, какие функции питона 3,6 поддерживаются, все или только ограниченное множество? Можно например numpy запустить?masai
10.02.2019 14:49+1Программа на Python не исполняется напрямую на ПЛИС, это просто кодогенератор, который выдаёт код на Verilog. Поэтому особенности языка никак не сказываются на, собственно исполнении. И, к сожалению, по этой же причине библиотеки для Python тоже использовать не получится.
DmitrySpb79
10.02.2019 15:43Так и интересно, какое качество этой кодогенерации в плане скорости.
Что транслируется в Verilog — исходный текст python-программы, или уже байт-код питона?proton17
10.02.2019 21:50+1Вы, видимо, совсем не понимаете как устроены ПЛИС. В них никакой код не выполняется. В них на уровне триггеров и логических элементов реализуется нужная вам схема, при этом никакой памяти не используется. Т.е. если вам надо с частотой 1Гц поморгать светодиодом, то внутри будет сформирован счетчик строго на необходимое количество разрядов и некая логическая схема декодера которая при одном значении счетчика будет зажигать светодиод, при другом гасить. Термин быстродействие тут вообще не применим. Хотя вопрос эффективности структур сформированных с MyHDL интересен.
DmitrySpb79
10.02.2019 22:05Спасибо. Если на ПЛИС уже и линукс запускают, то может кто-то и интерпретатор Питона сделал, почему бы нет. Собственно интерес как раз в том, имеем мы полностью полноценный Python или просто какое-то урезанное подмножество языка (типа Micropython для ESP32), пригодное только для самых простых операций.
Про моргание светодиодом пример был неудачный, да. Переформулирую вопрос, вот написали мы какую-то функцию, например, перемножения матриц — одну на Verilog, другую на этом Python, какая будет разница в их быстродействии?
А в целом, если для FPGA появился полноценный Python — то это реально круто, и действительно снижает порог входа в разы (уж больно лениво этот Verilog изучать, вещь совсем узкоспециализированная). Если Python сильно урезанный, то конечно не так интересно, хотя все лучше чем ничего.proton17
10.02.2019 22:20+1На ПЛИСе можно без проблем собрать какой-нибудь простой микропроцессор или использовать более дорогую ПЛИС со встроенным аппаратным ARMом. А на нем, пожалуйста, можно Linux или RTOS поднять без проблем, но это из пушки по воробьям, проще одноплатник взять типа RPi. А если говорить о чисто аппаратной реализации функций ЦОС, то можно сделать хоть за один так частоты работы ПЛИС, но это займет очень большой процент логики и не будет работать на больших частотах, а можно разбить на много тактов — сделать конвейер. Вообще почти во всех ПЛИСах есть встроенные аппаратные блоки ускоряющие такие операции, например умножители размером 18х18. Кстати Matlab давно умеет формировать годный HDL-код для ПЛИС. Т.е. можно запилить какой-нибудь фильтр в Matlab и получить готовый код для прошивки в ПЛИС.
masai
11.02.2019 21:34Что транслируется в Verilog — исходный текст python-программы, или уже байт-код питона?
Ни код, ни байт-код не транслируются в Verilog. Код для Verilog — результат исполнения программы на Python.
vasiliev
10.02.2019 09:08+1Вы правильно заметили, что отличий в названий блоков по сравнению с традиционными HDL нет. За счёт этого сгенерированный код получается достаточно компактный и вполне себе человекочитаемый по сравнению с высокоуровневыми генерилками типа C-to-HDL.
Основной плюс myHDL — как раз тесты. Поскольку он работает в экосистеме python, тесты достаточно легко организуются и запускаются. Кроме того, можно подключить множество библиотек для проверки правильности работы HDL-модели: например, в обработке сигналов пригодится numpy. Ещё есть режим ко-симуляции в случае разработки тестов на MyHDL, а кода — на verilog/systemverilog.
Пример организации тестов на MyHDL в более-менее серьёзном проекте можно посмотреть здесь.
Goron_Dekar
09.02.2019 16:19+1А я на несколько секунд поверил, что можно перестать запускать этот монстр Quartus с его сложным гуём.
bugdesigner
10.02.2019 04:37Можно, в принципе, не запускать гуй квартуса, а написать скриптик для компиляции с использованием quartus_map, quartus_fit, quartus_asm. Для этого нужно будет ещё 2 текстовых файла (.qpf и .qsf) с описанием проекта, ну и сами исходники на HDL (verilog/vhdl). Если проект простой, без использования мегакорок, то можно всё проделать в текстовом редакторе, но это для настоящих джедаев командной строки.
Alatarum
10.02.2019 13:55В своё время делал интеграцию кодблокса с квартусом: писал код, ситезировал и заливал чип в C::B, а квартус запускал только для конфигурирование проекта.
http://we.easyelectronics.ru/CADSoft/integraciya-ide-codeblocks-s-programmnym-kompleksom-altera-quartus-ii-chast-i.html
Daddy_Cool
09.02.2019 16:44Можно чайниковский вопрос?
Еще давно, когда узнал про FPGA сразу возникла мысль, что надо заставить его решать системы линейных уравнений. Но я так понимаю, что дело упирается в количество входов-выходов. Чтобы было интересно — надо загружать сразу много данных, а входов-выходов всего лишь порядка тысячи.
Нашел несколько работ по решению СЛАУ на FPGA, пишут — ускорение есть — по сравнению с софтовым решателем, но как-то в массе использования не видно. Ну и да — есть CUDA, суперкомпьютеры, и т.п… Но вот FPGA тоже хочется.Goron_Dekar
09.02.2019 17:03Данные можно загружать и по последовательной шине. Тогда много входов не надо. Но математикой придётся обойтись целочисленной.
NumLock
09.02.2019 19:19Но математикой придётся обойтись целочисленной.
Python прекрасно работает с дробями. Интересно, можно ли использовать питоновские функции при его конвертации в Verilog/VHDL.NumLock
09.02.2019 19:53Нашёл в документации, что как бы может конвертировать питоновские функции.
http://docs.myhdl.org/en/stable/manual/conversion.html
Function calls are mapped to Verilog or VHDL subprograms
The converter analyzes function calls and function code. Each function is mapped to an appropriate subprogram in the target HDL: a function or task in Verilog, and a function or procedure in VHDL. In order to support the full power of Python functions, a unique subprogram is generated per Python function call.
гугл перевод:
Преобразователь анализирует вызовы функций и код функции. Каждая функция сопоставляется с соответствующей подпрограммой в целевом HDL: функция или задача в Verilog и функция или процедура в VHDL. Чтобы поддерживать всю мощь функций Python, для каждого вызова функции Python генерируется уникальная подпрограмма.
Так что системы линейных уравнений в FPGA с решением и ответом в виде дробей вполне даже привлекательно.
Daddy_Cool
09.02.2019 20:13Как это? Т.е. имеем дело с integer и всё?
Поискал — нашел про плавающую точку на FPGA.
www.eetimes.com/document.asp?doc_id=1275350
вдруг кого заинтересует.
DmitrySpb79
09.02.2019 22:37+1Когда узнал про FPGA сразу возникла мысль, что надо заставить его решать системы линейных уравнений
Сейчас есть специализированные штуки типа Intel Neural Compute Stick — только не знаю, заточена она только под нейросети, или на ней можно и обычную математику считать.
А так да, проще на Cuda, там все довольно просто, главное придумать как распараллелить задачу.
AVDerov
09.02.2019 23:39Про СЛАУ надо сразу указывать, какая размерность системы вам нужна, разреженная или нет. Вообще то не стоит самому городить огород про линейные системы, профессионально написанного кода — вагон и маленькая тележка, пусть даже и для CPU.
xztau
09.02.2019 18:42+1А как же chisel?
Вопрос, раз уж в темуЕсть iverilog, где можно смоделировать Verilog модель.
А есть ли свободные инструменты (не ModelSim) для моделирования VHDL?aamonster
09.02.2019 21:23+1Э… Это Python или это просто аналог Verilog/VHDL с синтаксисом Python (вместо C/Pascal)?
alter_fritz Автор
09.02.2019 21:41Чистый python
aamonster
09.02.2019 22:40Э… "Чистый python" — в смысле, что исполняется нормальный питоновский код, и не надо въезжать в новые концепции (т.е. это с тем же успехом мог бы быть код на C или ещё каком языке общего назначения), или в смысле, что обошлись инфраструктурой питоновского интерпретатора, чтобы сделать DSL?
Des333
09.02.2019 23:11+1docs.myhdl.org/en/stable/manual/preface.html:
Conversion to Verilog and VHDL
Subject to some limitations, MyHDL designs can be converted to Verilog or VHDL. This provides a path into a traditional design flow, including synthesis and implementation. The convertible subset is restricted, but much wider than the standard synthesis subset. It includes features that can be used for high level modeling and test benches.
The converter works on an instantiated design that has been fully elaborated. Consequently, the original design structure can be arbitrarily complex. Moreover, the conversion limitations apply only to code inside generators. Outside generators, Python’s full power can be used without compromising convertibility.
Finally, the converter automates a number of tasks that are hard in Verilog or VHDL directly. A notable feature is the automated handling of signed arithmetic issues.aamonster
09.02.2019 23:40+1Для меня звучит как "вы должны разобраться в программировании fpga, тогда сможете использовать связку HDL+Python".
Т.е. нет упрощения входа, есть возможность помимо новых инструментов — оставить старый и привычный. Так?Arcpool
10.02.2019 11:18+1Две подряд идущие строки в verilog/vhdl выполняется паралельно с вероятностью 99%, для последовательного выполнения нужно предпринять дополнительные меры. Все потому, что verilog/hdl по факту описывает как соединить отдельные элементы ПЛИС в цифровую схему. Так что да, лучше hdl/verilog изучать как отдельные концепции.
uhf
10.02.2019 14:21+1Вы в тексте называете свой код программой, но это неправильно — для FPGA нет программы как таковой. Verilog — это язык описания аппаратуры, т.е. схемы железа, модулей, связей.
И в этом ключе, начинающим Python не даст понимания, как работает FPGA, разве что позволит поморгать светодиодами, не более.alter_fritz Автор
10.02.2019 14:41Впринцыпе согласен с Вами. Для новичка в FPGA после классического программирования сложно осознать тонкости ПЛИС, но статья не много не об этом. Программой этот код можно назвать с натяжкой, но ведь на ПЛИС можно запрограммировать некий алгоритм обработки информации.
lingvo
10.02.2019 22:42Неплохо было бы добавить в статью листинг VHDL для указанной программы мигания светодиодами. Тогда можно было бы сказать эффективный код или нет.
Если говорить о быстродействии, то в мире FPGA под этим подразумевается максимальная частота клока для синхронного дизайна при которой он еще выполняет заданную функцию.
dedyshka
Было бы полезно:
— описать (хотя бы, парой предложений) декораторы использованые в ваших примерах кода
— добавить ссылку на официальную доку по myHDL