
Почти три года назад, когда я начал митапы Verilog Mettup в Hacker Dojo, на них пришел Владимир Чурюкин и когда посмотрел на мою инфраструктуру Basic‑Graphics‑Music, где баш‑скрипты по имени платы строят проект, сразу сказал «А давайте перепишем все на питон». И переписал! С оговоркой что это PoC, то бишь Proof of Concept, то есть он это проверил только на 5-ти платах, а не на всех 45-ти, как мой исходный репозиторий.
А теперь посмотрим что из этого получилось.
Так как я в это индустрии 40 лет и читал книжки Брукса и других еще когда ездил в трамвае в физматшколу и работал у мамы на работе на СМ-4, то я знаком с этой ситуацией более чем. Разработчик приходит в новый проект. Ковыряться в том что есть ему неинтересно, то что есть ему видится отвратительным, а аргументы, что существующее решение достаточно он отвергает. На предложение заняться новой фичей поверх существующей инфраструктуры он исчезает на некоторое время, а потом возвращается с «вот, смотрите, как нужно!» и показывает переписанную инфраструктуру.
Существующие люди на проекте на это смотрят, пару раз в это тыкают и говорят: «а вот оно не поддерживает это и это, а также вводит неудобство для пользователя вот тут и тут». Тут в воздухе повисает неудобное молчание, потому что становится непонятно что именно хочет новый человек:
Лично сесть и написать все фичи, а не только proof of concept.
Указать другим, что они должны остановить все свои проекты, срочно выучить новый язык и библиотеки и переписать весь проект под его руководством.
Уломать прользователей смириться, что отныне программа поддерживает не 45 плат, а только 5, а также теперь программа не умеет находить где установлены тулчейны, и их пользователь должен ручками ввести в YAML файл. А также пользователь должен сам отлаживать случаи когда не работает драйвер в Linux, потому что новая программа не сказала пользователю сделать update в /etc/udev. Или случаи когда macOS объявляет файл от FPGA вендора malware.
Уломать прользователей смириться с двумя несовместимыми системами вместо одной: для одних плат они пользуются первой, для других второй, причем новая инфраструктура не запоминает последней выбраной платы. Зато все на питоне.
Сразу скажу, что я в своей карьере видел все 4 сценария, причем и с одной, и с другой стороны.
Также интересно, что спор как правило ведется в двух плоскостях. Старый разработчик говорит что новый подход требует преобразования проприетарных форматов от нескольких вендоров и ad‑hoc файлов для мэппинга чего‑то в один формат, но при этом новая преобразовалка недостаточно умна чтобы например парсировать ifdef‑ы в преобразуемых файлах, а мануальное преобразование займет либо время, либо необходимость построчно проверять что там натворило AI с этими ifdef‑ами, что нудно и противно. И непонятно ради чего, так как существующая инфраструктура и так работает, а что под капотом пользователю наплевать.
Новый разработчик отметает это как несущественную деталь и вещает о важности абстракций. Я книжки про важность абстракций стал читать еще когда СССР правил Генсек Константин Устинович Черненко (да, в СССР переводили в издательстве Мир книжки по программированию в том числе на эти темы), поэтому для меня важность абстракций разбивается в один момент: кто должен править вывод программ, которая написана на абстракциях, но не обрабатывает все случаи для пользователя, которые обрабатывает старая программа — я или он?
А вы что думаете?

UPD 2026-09-24: Посмотрел на все решение Владимира еще раз и пришел к выводу, что главная проблема - не замена Баша Питоном, а попытка заменить Верилог Ямлом.
Написал следующий пост на Фейсбуке на основе ошибок по состоянию на 2026-09-20 (позже сам Владимир некоторые из них исправил) и превратил его Клодом в следующее issue в его репозитории.
Фейсбук:
basys3/top.sv и некоторые другие
Не сгенерен reset
basys3/constraints.xdc, omdazz/unifpga_top.sdc и некоторые другие
Не сгенерен constraint на clock. Интересно что в других платах (nexys_a7, de10_lite) constraint на clock сгенерен.
de10_lite/top.sv
Не сгенерен переходник между статическим и динамическим 7-сегментным индикатором
tang_nano_9k_hdmi_tm1638/top.sv и другие
Не сгенерена инстанциация PLL.
tang_nano_9k_lcd_480_272_no_tm1638/top.sv
Инстанциирован tm1638_board_controller хотя его там быть не должно.
Причем суть проблемы даже не в питоне против баша, а в попытка Владимира заметить верилог YAML-ом.
У меня файл на верилоге board_specific_top.sv в каждой из поддиректорий boards играет роль де-факто конфигурационного файла. Он меппит сигналы из файла вендора на сигналы файла юзера, а также добавляет модуля для периферийных устройств и делает всякие обходы недостатков - например если на плате нет выделенного reset-а, то он его привязывает к кнопке и восстанавливает из power up.
Что же собственно делает Владимир? Он вместо проприетарных файлов от вендоров и вместо моего board_specific_top.sv делает единый YAML, куда каким-то образом сливает всю информацию из проприетарных файлов и board_specific_top.sv, но во-первых делает это недостаточно хорошо, то есть теряет reset на платах где нет dedicated reset button, не генерит constraints на clock в Xilinx, вставляет периферийные блоки типа tm1638 где они не нужны
- а во-вторых, ему все равно надо из этого YAML+питона генерить обратно файлы для вендоров и свою версию board-specific-top.sv.
То есть он не убирает сложность. Он ее просто переносит из верилога в питон и YAML, и при этом вводит две дополнительные трансформации - из проприетарных файлов и обратно.
Issue на GitHub сгенеренное Клодом по моему тексту:
Issues found in generated board files as of 2026-09-20 and concerns about the YAML-based approach
I ran the UniFPGA generation scripts for several boards on 2026-09-20 and found a number of problems in the generated files. I think these examples also expose a more general architectural issue with the current approach.
Specific issues
basys3/top.sv and some other boards
Reset logic is not generated.
For boards without a dedicated reset button, reset still needs to be provided somehow, for example by mapping it to an available button and/or generating an appropriate power-up reset.
basys3/constraints.xdc, omdazz/unifpga_top.sdc, and some other constraint files
A clock constraint is not generated.
Interestingly, clock constraints are generated for some other boards, for example nexys_a7 and de10_lite.
de10_lite/top.sv
The adapter between the board's static 7-segment interface and the user's lab_top multiplexed/dynamic 7-segment display is not generated.
tang_nano_9k_hdmi_tm1638/top.sv and some other boards
The required PLL instantiation is not generated.
tang_nano_9k_lcd_480_272_no_tm1638/top.sv
tm1638_board_controller is instantiated even though this configuration does not have TM1638 and the controller should not be present.
Broader architectural concern
I don't think the main issue here is Python versus Bash. The more fundamental question is whether YAML should replace SystemVerilog as the representation of board-specific configuration and adaptation logic.
In the original BGM structure, each board directory contains a board_specific_top.sv. This file effectively serves as an executable board configuration. It does more than simply map vendor pin names to user-interface signals. It can also:
instantiate controllers for board-specific peripherals;
adapt different physical interfaces to the common user interface;
instantiate PLLs and other vendor-specific blocks;
handle differences in reset circuitry;
work around limitations of a particular board.
For example, if a board does not have a dedicated reset button, board_specific_top.sv can implement the required reset behavior using another button and/or power-up logic.
The UniFPGA approach appears to move information from the vendor constraint/project files and board_specific_top.sv into a common YAML representation. Python code then generates vendor files and a new board-specific top-level SystemVerilog file from that YAML.
The examples above suggest that some information or behavior is currently lost during this transformation:
reset handling is missing on some boards;
clock constraints are missing for some toolchains/boards;
required interface adaptation is missing;
required PLL instantiations are missing;
peripheral modules are sometimes instantiated when they should not be.
Even if all these individual bugs are fixed, I think there is an architectural question worth discussing: what complexity is eliminated by moving board-specific behavior from SystemVerilog and vendor files into YAML + Python?
The resulting flow is roughly:
vendor files + board-specific SV -> YAML representation -> Python generator -> vendor files + generated board-specific SV
This does not necessarily eliminate the board-specific complexity. It may instead move that complexity into the YAML schema and Python generator while adding two additional transformations: importing information into the common representation and generating the required vendor/SystemVerilog files back from it.
I think it would be useful to clarify the intended boundary between:
declarative board information that naturally belongs in YAML, such as pin assignments, clock frequencies, and device identifiers; and
actual hardware behavior and interface adaptation, which may be more naturally and explicitly expressed in SystemVerilog.
The concrete generation problems listed above may help determine where that boundary should be.
UPD2: По состоянию на 2026-09-24 Владимир некоторые из указанных мною ошибок поправил, но вопрос с тем является ли YAML+Python адекватной заменой SystemVerilog+Bash остается открытым. Я считаю, что это усложнение, а не упрощение.
