Подключи ISE, Vivado и Quartus к общему итератору версии и HDL-паспорту. Проверяй новый bit/sof до создания manifest, SHA-256 и архива выпуска. Добавь установку локальных команд ISE, инструкции переноса и регрессионные проверки успешных и прерванных сборок.
242 lines
17 KiB
Markdown
242 lines
17 KiB
Markdown
# Контроль прошивок ПЛИС: Xilinx ISE, Vivado и Altera Quartus
|
||
|
||
Для ISE: запустите `INSTALL_ISE.bat`, укажите `.xise`, затем используйте
|
||
созданный в проекте `build_firmware.bat`. [Краткая инструкция](ISE_PORTING.md).
|
||
|
||
Шаблон подключает к существующему проекту ПЛИС общий механизм
|
||
[`firmware-info`](../../../c/firmware-info/README.md): сохраняемый итератор
|
||
SemVer, время сборки в UTC, Git build ID, manifest, SHA-256 и архив выпуска.
|
||
Параметры кристалла, выводы, частоты, ограничения и транспорт чтения регистров
|
||
задаёт проект платы.
|
||
|
||
Цепочка: проект → Tcl своей САПР → `identity.py` из этого каталога → общий
|
||
`c/firmware-info/tools/identity.py`. Итератор, правила Git и архивирования
|
||
используются те же, что для CCS и Keil.
|
||
|
||
## Файлы и зависимости
|
||
|
||
| Файл | Назначение | Зависимости |
|
||
|---|---|---|
|
||
| `firmware_identity.example.json` | Начальная конфигурация изделия и счётчика | Копируется в проект |
|
||
| `INSTALL_ISE.bat`, `ise_project.py` | Автоматическая установка локальных BAT, JSON, HDL и памятки из `.xise` | Windows, Python 3.9+ |
|
||
| `ise-build.bat`, `ise_bootstrap.py`, `ise-project.md` | Шаблоны локальной команды сборки и памятки | Копируются установщиком в проект |
|
||
| `identity.py` | Генерация Verilog-2001/VHDL-93 и контроль готового файла | Python 3.9+, stdlib, общий `identity.py` из templates |
|
||
| `common.tcl` | Пути, язык, вызовы Python, обработка отказов | Tcl 8.5+ в САПР |
|
||
| `ise.tcl` | Полная сборка `.xise` до `.bit` | Xilinx ISE / `xtclsh` |
|
||
| `vivado.tcl` | Полная сборка `.xpr` до `.bit` | Vivado Project Mode |
|
||
| `quartus.tcl` | Полная сборка `.qpf` до `.sof` | Altera/Intel Quartus II или Prime / `quartus_sh` |
|
||
|
||
Python 3 должен быть доступен как `python` из окружения САПР. Если ISE или
|
||
Quartus подставляет старый Python, передайте путь к `python.exe` шестым
|
||
аргументом. Git в PATH нужен для хешей; при недоступном Git получается
|
||
явный `NOGIT000`, локальная сборка продолжается.
|
||
|
||
## 1. Конфигурация проекта
|
||
|
||
Скопируйте `firmware_identity.example.json` рядом с `.xise`, `.xpr` или `.qpf`
|
||
под именем `firmware_identity.json`. Пример намеренно требует заменить имя
|
||
кристалла; задайте своё изделие и точный part number.
|
||
|
||
| Поле | Смысл |
|
||
|---|---|
|
||
| `product` | Имя изделия, например `MY_FPGA_BOARD` |
|
||
| `target` | Точное обозначение кристалла; информационное поле, настройки part в проекте не меняет |
|
||
| `version` | Последний занятый номер `[major, minor, patch]`; в примере `[0, 1, 0]` |
|
||
| `increment_version` | `true` включает общий сохраняемый итератор; `false` оставляет ручную версию |
|
||
|
||
Первая подготовка примера выдаёт **0.1.1**. Следующий pre-build выдаёт 0.1.2,
|
||
включая попытки после ошибки синтеза. Переносы: 0.1.999 → 0.2.0,
|
||
0.255.999 → 1.0.0. После 255.255.999 сборка останавливается. Post-build номер
|
||
не увеличивает. Clean не сбрасывает конфигурацию.
|
||
|
||
Храните этот JSON в Git. Каталог `build/` добавьте в `.gitignore` проекта;
|
||
файлы результатов САПР также должны игнорироваться, иначе они пометят сборку
|
||
как dirty. Одна конфигурация JSON обслуживает только одну сборку одновременно.
|
||
Для независимых ревизий платы используйте отдельные JSON и выходные каталоги.
|
||
|
||
## 2. Подключение паспорта к логике
|
||
|
||
Генератор создаёт `generated/firmware_identity.v` и
|
||
`generated/firmware_identity.vhd`. Tcl добавляет в проект только выбранный
|
||
язык. Паспорт — комбинационный ROM из 12 слов по 16 бит:
|
||
|
||
| Относительный адрес слова | Значение |
|
||
|---|---|
|
||
| 0 | Версия контракта: 1 |
|
||
| 1, 2, 3 | Major, minor, patch |
|
||
| 4 | Год, 2000..2199 |
|
||
| 5 | Месяц в битах 15..8, день в 7..0 |
|
||
| 6 | Час UTC в битах 15..8, минута в 7..0 |
|
||
| 7 | Секунда UTC |
|
||
| 8..11 | Восемь ASCII-символов build ID, первый символ пары в старшем октете |
|
||
| 12..15 | Ноль |
|
||
|
||
Адреса относительные, без привязки к CPU, AXI, Avalon, SPI, Modbus или SETCAN.
|
||
Базовый адрес в системе назначает проект. Это тот же порядок слов, что в
|
||
`firmware_info_to_registers()`. Порядок байтов на конкретной шине задаёт
|
||
адаптер проекта.
|
||
|
||
В верхний модуль Verilog добавьте экземпляр:
|
||
|
||
```verilog
|
||
wire [15:0] identity_data; // 16-битное слово паспорта для мультиплексора чтения шины проекта.
|
||
firmware_identity u_identity ( // Экземпляр генерируемого до синтеза паспорта текущей сборки.
|
||
.word_addr(identity_word_offset), // Четыре младших бита относительного адреса слова в выделенном окне регистров.
|
||
.word_data(identity_data) // Выход должен участвовать в ответе шины, чтобы синтезатор сохранил паспорт.
|
||
); // Выбор окна и тактовое согласование выполняет логика проекта.
|
||
```
|
||
|
||
Для VHDL объявите component в declarative part архитектуры и подключите его
|
||
в теле архитектуры; component не требует заранее анализировать generated entity:
|
||
|
||
```vhdl
|
||
component firmware_identity is -- Объявление размещается до begin архитектуры верхнего уровня.
|
||
port ( -- Интерфейс совпадает с генерируемой entity firmware_identity.
|
||
word_addr : in std_logic_vector(3 downto 0); -- Относительный адрес одного из 12 слов паспорта.
|
||
word_data : out std_logic_vector(15 downto 0) -- Данные для ответа шины проекта.
|
||
); -- Закрывает список портов компонента.
|
||
end component; -- Привязка к entity из work выполняется при elaboration.
|
||
signal identity_data : std_logic_vector(15 downto 0); -- Объявляется до begin и подключается к чтению регистров.
|
||
-- Следующий экземпляр размещается после begin архитектуры верхнего уровня.
|
||
u_identity : firmware_identity -- Создаёт экземпляр паспорта без примитивов производителя.
|
||
port map ( -- Согласует имена сигналов проекта с интерфейсом компонента.
|
||
word_addr => identity_word_offset, -- Четырёхбитный сигнал относительного адреса слова задаёт проект.
|
||
word_data => identity_data -- Выход включается в мультиплексор ответа хосту.
|
||
); -- Завершает подключение экземпляра.
|
||
```
|
||
|
||
`identity_word_offset`, декодер окна и ответ шины реализуйте в проекте.
|
||
Паспорт не имеет clock/reset, чтение комбинационное; при необходимости
|
||
зарегистрируйте ответ в тактовом домене шины. Без подключения выхода синтезатор
|
||
удалит паспорт. Смена языка существующего проекта требует удалить прежний
|
||
generated-файл из списка исходников, чтобы не получить два одноимённых модуля.
|
||
|
||
## 3. Полная сборка
|
||
|
||
Команды запускаются **из корня проекта** в командной строке с настроенным
|
||
окружением соответствующей САПР. В примерах templates подключён как
|
||
`lib/templates`. Проект должен уже содержать свой top, part и UCF/XDC/QSF.
|
||
Сценарии регистрируют generated-исходник в существующем проекте и выполняют
|
||
полную цепочку до файла программирования.
|
||
|
||
Аргументы общие: `project config output image verilog|vhdl [python]`.
|
||
Пути разрешаются относительно начального рабочего каталога. `image` — точный
|
||
путь результата вашей САПР, а `output` — отдельный каталог паспорта и архивов;
|
||
передача `output` не меняет настройки выходного каталога САПР.
|
||
|
||
**ISE:**
|
||
|
||
```bat
|
||
rem Собирает существующий ISE-проект, в котором BitGen создаёт top.bit рядом с .xise.
|
||
xtclsh "lib/templates/tools/firmware-build/fpga/ise.tcl" "board.xise" "firmware_identity.json" "build/ise" "top.bit" verilog
|
||
```
|
||
|
||
Используется `Generate Programming File -force rerun_all`: XST, реализация
|
||
и BitGen выполняются заново. Логический `false` от процесса считается ошибкой.
|
||
|
||
**Vivado:**
|
||
|
||
```bat
|
||
rem Замените board.runs/impl_1/top.bit реальным путём .bit выбранного implementation run.
|
||
vivado -mode batch -source "lib/templates/tools/firmware-build/fpga/vivado.tcl" -tclargs "board.xpr" "firmware_identity.json" "build/vivado" "board.runs/impl_1/top.bit" verilog
|
||
```
|
||
|
||
Берётся активный implementation run и его родительский synthesis run;
|
||
нестандартные имена runs поддерживаются. Оба запуска сбрасываются, затем
|
||
выполняются синтез и реализация до `write_bitstream`. После `wait_on_run`
|
||
отдельно проверяется `PROGRESS`, поэтому завершение с ошибкой не вызывает упаковку.
|
||
|
||
**Altera / Intel Quartus:**
|
||
|
||
```bat
|
||
rem Собирает текущую revision из .qpf; image должен совпадать с результатом Assembler.
|
||
quartus_sh -t "lib/templates/tools/firmware-build/fpga/quartus.tcl" "board.qpf" "firmware_identity.json" "build/quartus" "output_files/board.sof" vhdl
|
||
```
|
||
|
||
`execute_flow -compile` запускает полную компиляцию с Assembler.
|
||
Для другой revision передайте седьмой аргумент после пути к Python:
|
||
|
||
```bat
|
||
rem Укажите реальный Python 3 и отдельный JSON счётчика ревизии B.
|
||
quartus_sh -t "lib/templates/tools/firmware-build/fpga/quartus.tcl" "board.qpf" "identity_B.json" "build/quartus_B" "output_files/board_B.sof" vhdl "C:/Python313/python.exe" "board_B"
|
||
```
|
||
|
||
Не добавляйте второе увеличение версии в существующие pre-flow/pre-synthesis hooks.
|
||
Эти Tcl-файлы предназначены для запуска полной сборки из командной строки;
|
||
их нельзя подключать как вложенные hooks этапов синтеза. Для выпуска через
|
||
данную схему запускайте указанный сценарий, в том числе после работы в GUI.
|
||
|
||
## 4. Результаты и проверка
|
||
|
||
```text
|
||
build/vivado/
|
||
generated/
|
||
firmware_identity.h
|
||
firmware_identity.v
|
||
firmware_identity.vhd
|
||
firmware_identity.json
|
||
firmware/
|
||
HASH_YYYY-MM-DD_HH-MM-SS_UTC+3/
|
||
top.bit
|
||
top.bit.manifest.json
|
||
top.bit.sha256
|
||
firmware_identity.v
|
||
firmware_identity.json
|
||
```
|
||
|
||
Для VHDL архив содержит выбранный `.vhd`, для Quartus — `.sof` вместо `.bit`.
|
||
Manifest и `.sha256` также создаются рядом с исходным файлом программирования.
|
||
Хеш и дата архивной папки берутся из pre-build, дата имени переводится в UTC+3;
|
||
в самом паспорте остаётся UTC. Знак `+` у build ID означает изменённые исходники
|
||
или templates. `firmware_identity.h` — сопутствующий результат общего генератора;
|
||
FPGA-сценарии используют HDL.
|
||
|
||
Упаковка отклоняет отсутствующий, пустой или не обновившийся после prepare
|
||
файл. Проверяется содержимое и время записи: повторная запись тех же байтов
|
||
допускается. Это защита от старого результата; она не проверяет наличие паспорта
|
||
внутри vendor bitstream. Правильность подключения подтверждается чтением всех
|
||
12 регистров с работающей ПЛИС и сравнением с `fpga.register_words` в manifest.
|
||
SHA-256 относится к файлу программатора целиком и хранится снаружи образа.
|
||
|
||
Проверить сохранённый файл можно общим инструментом:
|
||
|
||
```bat
|
||
rem Проверяет размер и SHA-256 указанного файла по созданному рядом manifest.
|
||
python "lib/templates/c/firmware-info/tools/identity.py" verify --image "board.runs/impl_1/top.bit" --manifest "board.runs/impl_1/top.bit.manifest.json"
|
||
```
|
||
|
||
Для локального экспорта папки выпуска повторите только finish с `--export`;
|
||
номер версии при этом не меняется:
|
||
|
||
```bat
|
||
rem Копирует текущую архивную папку и проверяет SHA-256 экспортной копии.
|
||
python "lib/templates/tools/firmware-build/fpga/identity.py" finish --metadata "build/vivado/generated/firmware_identity.json" --output "build/vivado/firmware" --export "D:/Firmware/FPGA"
|
||
```
|
||
|
||
Шаблон выпускает `.bit` и `.sof`. Преобразование в `.mcs`, `.bin`, `.pof` или
|
||
`.rbf`, загрузка на плату и публикация в сетевую базу требуют отдельного
|
||
проектного этапа. Контрольная сумма нативного образа не переносится на
|
||
преобразованный файл: для него создайте отдельные seal/verify общим инструментом.
|
||
|
||
## Проверки и состояние
|
||
|
||
Хостовые тесты проверяют эталон всех 12 слов, совпадение Verilog/VHDL,
|
||
итератор, свежесть результата, повреждение SHA-256, архив и экспорт. Реальные
|
||
Tcl-сценарии исполняются в Tcl из Python tkinter с заменой API производителей;
|
||
Python-генератор и упаковка выполняются полностью. Нужен Python с tkinter/Tcl,
|
||
графическое окно не открывается.
|
||
|
||
```bat
|
||
rem Запускает проверки адаптера и управляющих сценариев без лицензии САПР.
|
||
python -m unittest discover -s tools/firmware-build/fpga/tests -v
|
||
```
|
||
|
||
Шаблон пока не подключён к конкретной плате. Полный синтез и чтение паспорта
|
||
на железе требуют установленной САПР, проекта и платы; хостовые тесты эти
|
||
проверки не заменяют.
|
||
|
||
Команды сверены с руководствами производителей:
|
||
[ISE Command Line Tools UG628](https://docs.amd.com/v/u/en-US/devref),
|
||
[Vivado: запуск синтеза и реализации UG939](https://docs.amd.com/r/2023.1-English/ug939-vivado-designing-with-ip-tutorial/Step-8-Launch-Synthesis-and-Implementation),
|
||
[Quartus: полный Tcl flow](https://www.intel.com/content/www/us/en/docs/programmable/683432/22-1/the-tcl-shell-in-interactive-mode-example.html).
|