ECO Flow в Vivado или работа в режиме редактирования нетлиста. Часть 2
Оглавление
До п.3.6 см часть 1
- Аннотация
- Введение
- 1. ECO: краткий обзор
- 2. Design Сheckpoint
- 3. Разработка тестового проекта
- 3.1. Создание проекта
- 3.2. Создание и добавление HDL файлов в проект
- 3.3.Создание проекта MicroBlaze и работа в IP Integrator
- 3.4.Синтез и имплементация
- 3.5.Написание программы для MicroBlaze
- 3.6.Запуск программы и отладка
- 4. Переход в режим ECO
- 5. ECO: описание интерфейса
- 6. Внесение изменений в проект
- 7. Сравнительный анализ
- 8. Заключение
- 9. Домашнее задание
- Библиографический список
4. Переход в режим ECO
Как мы убедились выше:
По нажатию кнопки BTN0 загорается светодиод
- Посылки по UART отправляются, но мы не видим их в консоли (специально перепутаны rx и tx)
- Содержимое блочной памяти считывается циклически и непрерывно (содержимое блочной памяти в ASCII:”author: KeisN13”).
Для исправления ошибок, редактирования нетлиста и изменения содержимого и функционала некоторых компонентов мы воспользуемся режимом ECO, который доступен при работе с Design Checkpoint (DCP). Мы будем использовать DCP, который получается после этапа трассировки кристалла (post route).
При каждом новом запуске синтеза или имплементации Vivado удаляет DCP, поэтому общей практикой работы с DCP является «копипаста» необходимой DCP в новую директорию.
Давайте создадим папку edited_dcp. Я создам ее рядом с папкой проекта (рис. 78)
Рисунок 78 – Создание папки для сохранения DCP
Скопируем необходимый для дальнейшей работы DCP файл, который расположен «папка_проекта/название_проекта.runs/название_имплементации/имя_топ_модуля_routed.dcp» (рис. 79) в папку edited_dcp.
Рисунок 79 – Расположение DCP Просмотр доступен только для зарегистрированных пользователей. Зарегистрируйтесь, это не займет много времени
Переходим в Vivado и выполняем открытие DCP. Для этого нажмите File → Open Checkpoint (рис. 80)
Выберите расположение скопированного DCP файла в папке edited_dcp и нажмите OK.
После открытия DCP, по умолчанию, будет открыто представление (перспектива) Default или, та которую Вы использовали в последний раз, если открывали DCP (рис. 81).
Рисунок 81 – Перспектива Debug открытого DCP
Существует несколько режимов работы с DCP, однако сегодня нас интересует именно ECO Flow. Для перехода в режим ECO необходимо сменить представление. Для этого в верхнем правом углу из выпадающего списка выберите ECO (рис. 82).
Рисунок 82 – Переход в режим ECO
Как видим, графическое представление при переходе в режим ECO изменилось (рис. 83). Появились новые элементы управления и графического интерфейса, которые рассмотрим далее.
Рисунок 83 – Представление в режиме ECO
5. ECO: описание интерфейса
Работа в режиме ECO имеет свой маршрут, который изображен на рис. 84. Вся работа выполняется в соответствующей DCP. После открытия DCP выполняются необходимые изменения в нетлисте, с помощью инструментов графического интерфейса и/или Tcl-команд. Изменения сохраняются, и, в зависимости от того уже размещен полностью проект в кристалле или нет, выполняются размещение и трассировка либо только трассировка. Затем выполняется разводка кристалла, после чего генерируются новые файлы прошивки (битстрима, .bit) и цепей логического анализатора (.ltx). Следующим шагом выполняется проверка внесенных изменений «в железе», и если всё нормально, то сделанные изменения вносятся в исходный проект. Если же нет – то внесение изменений в DCP может быть повторено.
Рисунок 84 – Маршрут проектирования в режиме ECO
Внесение изменений возможно с помощью инструментов графического интерфейса. Оригинал описания интерфейса вы можете найти в [3] в разделе Vivado ECO Flow.
Графическое представление в режиме ECO разбито на несколько секций, расположение и назначение которых идентично стандартному представлению, в котором выполняется основное проектирование.
С левой стороны экрана расположен ECO Navigator, который представляет инструменты для маршрута проектирования. ECO Navigator состоит из нескольких секций.
Секция Edit (рис. 85): предоставляет доступ к инструментам, необходимым для редактирования нетлиста
Рисунок 85 – Команды секции Edit
Create Net: открывает диалоговое окно, предоставляющее доступ к созданию новых цепей. Цепи могут быть созданы для любого уровня иерархии, путём задания имени иерархии в названии цепи. Могут быть созданы шины. Если выбран pin или port, то цепь может быть автоматически подключена к ним, если установлена галка Connect selected pins and ports (рис. 86).
Рисунок 86 – Диалоговое окно Create Net
Create Cell: открывает диалоговое окно, позволяющее добавлять дополнительные компоненты в текущий нетлист. Также имеется возможность создавать ячейки в необходимом уровне иерархии. Можно создавать как библиотечные компоненты, которые доступны из списка, либо black box. Если вы создаёте LUT, то сразу можете редактировать функцию, которую она должна реализовывать (рис. 87).
Рисунок 87 – Диалоговое окно Create Cell
Create Port: вызывает мастер для добавления и настройки дополнительных портов в текущий нетлист. Возможно настроить несколько параметров: направление, ширину шины, стандарт напряжений и т.д. (рис. 88).
Рисунок 88 – Диалоговое окно Create Port
Create pin: выполняет добавление и настройку пинов в текущем нетлисте. Пин может быть создан для текущей ячейки (объектов типа cell) на любом уровне иерархии. Пин для иерархии верхнего уровня также может быть создан с помощью команды create_port. Пин не может быть создан, если не указана ячейка и название создаваемого пина (рис. 89).
Рисунок 89 – Диалоговое окно Create Pin
Connect Net: подключеняет цепь к выбранному пину или порту. Вызываемое диалоговое окно позволяет просмотреть список цепей или выполнить их поиск. Выбранная цепь будет подключена через все уровни иерархии, автоматически создавая необходимые пины.
Disconnect Net: отключает выбранную цепь, пин или порт от цепи. В случае, если выбран объект типа cell, то буду отключены все цепи, подключенные к нему.
Replace Debug Probes: позволяет вызвать диалоговое окно, в котором возможно выполнить редактирование портов ILA и/или VIO (Virtual Input Output), которые были созданы ранее, то есть отключить текущие цепи от и подключить новые.
Place Cell: позволяет разместить объект типа cell в выбранных ресурсах кристалла.
Unplace Cell: убирает выбранный объект типа cell из текущего размещения.
Секция Run
Команды секции Run предоставляет доступ ко всем командам, необходимым для выполнения имплементации.
Check ECO: Выполняет запуск проверки ошибок (DRC – Design Rule Check)
Примечание: Vivado позволяет вносить в нетлист множество изменений, используя команды режима ECO. Однако, внесённые логические изменения, внесённые в проект, могут привести к неосуществимой физической имплементации. Запуск Check ECO следует делать перед тем как вы соберетесь выполнять имплементацию проекта, чтобы устранить ошибки на ранних этапах маршрута ECO Flow.
Optimize Logical Design: в некоторых случаях рекомендуется выполнять оптимизацию нетлиста с помощью команды opt_design и её соответствующих опций [9]. Optimize Logical Design позволяет вызвать диалоговое окно, позволяющее внести соответствующие аргументы Tcl команды opt_design, которые задаются в строке options.
Place Design: Выполняет инкрементное (т.е. основываясь на предыдущем нетлисте) размещение компонентов текущего нетлиста. Отчёт Incremental Placement Summary, который выводится в консоли в конце выполнения команды place_design позволяет просмотреть статистику переиспользования результаттов предыдущего размещения, которое было в оригинальном DCP до внесения изменений. Нажатие на Place Design вызывает окно, в котором могут быть заданы соответствующие опции команды place_design [9]. Подробнее об инкрементной имплементации см. в [3] в разделе Incremental Compile.
Optimize Physical Design: в некоторых случаях может потребоваться выполнить физическую оптимизацию (команда phys_opt_design [9]). Диалоговое окно, вызываемое по нажатию на Optimize Physical Design позволяет ввести соответствующие опции команды phys_opt_design.
Route Design: вызывает диалоговое окно, которое позволяет в зависимости от выбора выполнить инкрементную трассировку внесенных изменений в нетлист, трассировку выбранных пинов или цепей. В случае, если процент переизпользованных разъеденных цепей менее 75%, то будет выпалена обыкновенная трассировка нетлиста.
Подробнее об инкрементной имплементации см. в [3] в разделе Incremental Compile.
Секция Report
В этой секции возможна генерация необходимых отчётов для измененного нетлиста, включая отчет используемых ресурсов, временных характеристик, пересечения тактовых доменов и т.д.
Секция Program
Инструменты этой секции позволяют сохранить внесённые изменения в новы DCP, создать файл прошивки ПЛИС, создать новый лист отлаживаемых через ILA цепей, в случае, если ILA подвергался изменениям, запрограммировать ПЛИС и выполнить отладку стандартными средствами Hardware Manager Vivado.
Вкладка Scratch
Позволяет отслеживать внесенные изменения в нетлист, включая просмотр и подключение незадействованных пинов, портов, цепей. Столбец подключений Con отслеживает статус подключения объектов, PnR отслеживает статус размещения и трассировки объектов.
Нажатием правок кнопкой мыши по вкладке Scratch будет вызвано меню дополнительных действий (рис. 90). Функционал, которые они выполняют, предполагаю интуитивно понятен исходя из их названий. Полный список и действия, которые выполняют команды приведен в [3] в разделе Vivado ECO Flow → Scratch Pad → Scratch Pad Pop-up Menu.
Рисунок 90 – Меню дополнительных действий вкладки Scratch
6. Внесение изменений в проект
Теперь мы можем приступить к внесению изменений в наш проект. Первое, что мы сделаем, это установка нового компонента в нетлист. Сделаем так, чтобы светодиод LD0 светился, а при нажатии кнопки BTN0 гас. Иными словами, мы должны вставить в нетлист инвертор, которого нет.
6.1. Создание новых элементов в нетлисте
Для начала, найдите на схеме порт ibtn, нажмите на него левой кнопкой мыши один раз, а затем нажмите F4. Таким образом, мы попробуем отфильтровать все лишнее в схематике, для повышения читаемости нетлиста.
Рисунок 91 – Открытие схематики для выбранного порта
В появившемся окне, мы увидим только один порт ibtn. Теперь отобразим всю цепь от порта ibtn до светодиода LD1 (порта obtn_led). Нажимаем правой кнопкой мыши по порту ibtn, затем Expand Cone и выбираем To Flops or I/Os. И нажимаем кнопку Regenerate Layout (рис. 92)
Рисунок 92 – Отображение конечных точек, к котором подключён порт
Теперь мы видим полный «тракт» от кнопки до светодиода (рис. 93).
Рисунок 93 – «Тракт» от порта ibtn до obtn_led
Следующий шаг, который необходимо сделать, это определиться, в каком месте разорвать цепь. Предлагаю разорвать её от модуля system_i до выходного буфера. Для этого выбираем цепь от пина obtn_led модуля system_i до пина I буфера obtn_led_OBUF_inst, затем в секции Edit выбираем Disconnect Net.
Рисунок 94 – Выбор разрываемой цепи
После нажатия на кнопку Regenerate Layout видим, что цепь была удалена (рис. 95)
Рисунок 95 – Схематика после разрыва цепи
Также обратите внимание на вкладку Scratch Pad, содержимое которой изменилось.
Теперь добавим на схему инвертор. Нажимаем в секции Edit строку Create Cell, вводим название компонента invertor, находим шаблон INV и нажимаем OK (рис. 96)
Рисунок 96 – Создание инвертора
Компонент INV будет добавлен на поле (рис. 97)
Рисунок 97 – Созданный инвертор на поле схематики
Как видите, инвертор реализован на LUT. Чтобы посмотреть логическую функцию, которую реализует LUT и при необходимости её изменить, Вы можете, нажав правой кнопкой мыши по компоненту, выбрать свойства Cell Properties, во вкладке Truth Table нажать Edit LUT Equation… (рис. 98).
Рисунок 98 – Свойство и таблица логической функции LUT
Выполним соединение пинов. Выберите или на схематике, или во вкладке Scratch Pad пины I0 компонента invertor и obtn_led компонента system_i.
Рисунок 99 – Выбор соединяемых пинов
Теперь создадим между ними цепь. Для этого в секции Edit нажимаем кнопку Create Net. В диалоговом окне вводим имя создаваемой цепи btn_led, устанавливаем галочку автоматического соединения двух портов и нажимаем ОК (рис. 100)
Рисунок 100 – Параметры создаваемой цепи
После этого два пина буду автоматически соединены. Нажмите Regenerate Layout (рис. 101)
Повторим действия для двух оставшихся пинов и соединим пин O компонента invertor с пином I компонента obtn_led_OBUF_inst. Цепь назовём по-другому, поскольку не может быть в проекте двух цепей с одинаковыми названиями на одном уровне иерархии. Назовём цепь btn_led_o. Результат подсоединения показан на рис. 102
Рисунок 102 – Схематика с созданным инвертором
Теперь сохраняем наш DCP и проверяем наличие ошибок, перед тем как запустить размещение и трассировку новых компонентов (рис. 103).
Рисунок 103 – Проверка ECO на ошибки
Из-за того, что мы не выполняли размещение и трассировку, появится ряд ошибок, говорящих об этом.
Теперь попробуем сгенерировать bit файл прошивки, и посмотреть, получилось ли внести изменения корректно. Для этого необходимо последовательно выполнить шаги из секции Run, не все разумеется и без каких-либо опций. Всё остаётся по умолчанию (рис. 104).
Нажимаем Place Design и не вводя никаких опций нажимаем OK. Дождавшись окончания выполнения операций нажимаем Route Design и выбрав Incremental Route в появившемся окне, нажимаем ОК.
После этого генерируем bit файл, нажав на Generate Bitstream. Убедитесь, что в поле пути к файлу указана папка edited_dcp. После этого открываем Hardware Manager для прошивки нашей ПЛИС.
Рисунок 104 – Последовательность действий для получения файла прошивки .bit
При открытии следует учесть, что должен будет открыться новый экземпляр Vivado. Но у меня он не открылся, поэтому я просто открываю новый экземпляр Vivado и запускаю Hardware Manager (рис. 105). При этом будьте внимательны, при выборе файла прошивки .bit и файла цепей для ILA .ltx
Рисунок 105 – Открытие Hardware Manager из начального окна Vivado
Выполните последовательность действий, согласно рис.67-69 и запрограммируйте ПЛИС. Обратите внимание, что прошивать мы будем файлом, расположенным в папке edited_dcp (рис. 106).
Рисунок 106 – Файл прошивки ПЛИС с изменённым нетлистом
Если всё было выполнено корректно, то светодиод LD0 должен будет светиться, а по нажатию кнопки BTN0 гаснуть.
6.2. Изменение свойств/параметров компонентов
В режиме ECO также возможно изменять содержимое компонентов и менять их параметры. Сейчас мы попробуем изменить содержимое блочной памяти модуля brom_reader, которая имитирует у нас, например, коэффициенты фильтра. Давайте найдём нашу BROM и просмотрим её свойство INIT, отвечающее за начальную инициализацию.
Перейдите во вкладку Netlist и найдите блочную память в модуле brom_reader (рис.107).
Рисунок 107 – Расположение блочной памяти модуля brom_reader в нетлисте
Нажав правой кнопкой по этому компоненту, мы можем просмотреть его свойства, выбрав Cell Properties (рис. 108). Затем перейдите во вкладку Properties и пролистайте до свойств INIT.
Рисунок 108 – Свойства INIT выбранной блочной памяти
Как видите, в свойствах INIT хранятся значения инициализации блочной памяти. Среди множества этих свойств нас интересуют только INIT_00 и INIT_01. Если скопировать содержимое этих двух свойств конвертор HEX to ASCII [15], то получим надпись, которую мы видели на рис. 77, но записанную в обратном порядке (рис. 109)
Рисунок 109 – Содержимое свойств INIT в формате ASCII
Изменить свойство компонента можно, если щелкнуть на значок карандашика и вписать новые значения или же воспользовавшись Tcl консолью и командой set_ptoperty.
Замените значения свойств согласно рис.110 и сохраните результат:
INIT_00: 256'h0061006700700066002E00770077007700200020002000200020002000200020
INIT_01: 256'h0020002000200020002000750072002E0073006D00650074007300790073002D
Рисунок 110 – Изменённое содержимое свойств INIT в формате ASCII
Поскольку мы не добавляли новых компонентов в нетлист и не переподключали цепи, то нет необходимости выполнять размещение и трассировку. Просто нажимаем Generate Bitstream и ожидаем окончания выполнения операции. На всякий случай сгенерируйте файл .ltx, который мы подцепим во время отладки (рис. 111).
Рисунок 111 – Генерация битсрима и файла цепей для отладки
Перейдите в Hardware manager и запрограммируйте FPGA только что сгенерированным файлом .bit и созданным списком пробников .ltx (рис.112). Обратите внимание, что файлы взяты из папки edit_dcp.
Рисунок 112 – Файлы прошивки измененного нетлиста и списка цепей
Выполните последовательность действий, описанных на рис. 73-75 (откройте hw_ila_2, переведите тип отображаемых значений в ASCII и просмотрите выводимую надпись). Если всё получилось корректно, то должна появиться надпись рис. 113.
Рисунок 113 – Измененное содержимое блочной памяти
Как видите, если Вам необходимо изменить содержимое или параметры компонентов не только блочной памяти, а в принципе любых, не требующих вмешательств в размещение и трассировку, то делается это очень быстро и достаточно просто. Однако следует быть осторожным, когда Вы изменяете параметры, отвечающие за рабочую частоту, например, когда вносите изменения в настройки MMCM или PLL Вашего проекта. В этом случае, прежде чем создавать файл прошивки, убедитесь, что тайминги проекта сходятся, а соответствующие отчёты не выдают ошибок (Report Timing Summary и т.д.).
6.3. Подключение других цепей к пробникам и ILA
Пожалуй, самым полезным вариантом использования ECO является замена в уже имплементированном проекте цепей, подключенных к пробникам. Единственным ограничением тут является то, что виртуальные пробники должны быть подключены все, ни один не должен «висеть в воздухе». Это ограничение обычно несущественно, так как неиспользуемые пробники всегда можно просто подключить к gnd или vcc.
Попробуем переключить пробник, наблюдавший за выходом блочной памяти, на значение счетчика, генерирующего для неё адрес.
Как мы знаем из описания интерфейса ECO, в нём есть инструмент, позволяющий выполнить переподключение пробников; им и воспользуемся.
Примечание: несмотря на наличие специального инструмента редактирования пробников и подключённых цепей, выполнять эти действия можно и «совсем вручную», подобно тому как мы делали при добавлении компонента: отсоединить одни цепи и подсоединить другие. Однако тут есть некоторые нюансы: по не совсем понятным причинам, иногда цепь от пина отсоединить не удается, нажатие на Disconnect Net не выполняется. В этом случае можно руками или через скрипты снять с цепи свойство «DONT_TOUCH» или отменить её трассировку (выполнить «unrote») – тогда Disconnect Net будет выполнятся. При работе мастером таких проблем не наблюдается.
Работа с мастером требует, чтобы мы знали название цепей, которые мы собираемся подключать. Давайте попробуем найти цепи, отвечающие за выставление адреса для блочной памяти в модуле brom_reader. Это можно сделать через схематическое представление или через сам нетлист. Поскольку модуль маленький, то просто просмотрим название через нетлист (рис. 114). Необходимая цепь называется cnt, это шина, шириной 5.
Рисунок 114 – Цепь адреса блочной памяти в нетлисте
Выбираем режим Replace Debug Probes. Поскольку наш счётчик считает только до 31, то требуется всего 5 линий, поэтому выбираем первые пять линий в ila_1, затем нажимаем правой кнопкой мыши и выбираем Edit Probes (рис. 115). Выбрать можно любой ila, но они достаточно громоздкие. Для руководства, выбраны попроще.
Рисунок 115 – Выбор заменяемых пробников
Выполняем поиск по списку цепей, введя название искомой цепи *cnt[*]. Пролистав вниз находим их, и нажимаем кнопку добавления в пробники. Обратите внимание, что мы одновременно заменяем 5 пробников, поэтому должно быть выбрано 5 цепей. Замена типа поиска с contains на match обусловлена правилами поиска в tcl и для текущего примера позволяет выводить более точный результат. При использовании поиска цепей рекомендуется хотя бы немного понимать и знать символы подстановки в языке Tcl и правила, по которым выполняется поиск.
Рисунок 116 – Поиск подключаемых к пробникам цепей
Оставшиеся три цепи мы подключим к «0», в Vivado цепи, подключенные к gnd называются const0. Выберем три оставшиеся цепи, правой кнопкой Edit Probes (рис.117).
Рисунок 117 – Доукомплектовывание ila_1
Вводим название в строку поиска *const0 и добавляем первую цепь из списка, три раза кликнув по стрелке, поскольку мы должны подключить три линии (рис. 118). БУДЬТЕ ВНИМАТЕЛЬНЫ!!! Не добавляете линии из иерархии Debug Hub (dbg_hub), в этом случае Vivado выдаст ошибку только в самом конце настройки пробников, и вся работа пойдет на смарку. Выберите цепь из любого IP, например, uartlite.
Рисунок 118 – Добавление константных цепей в пробники
Сформированный ila_1 должен выглядеть как на рис. 119. Еще раз отмечу, что не должно быть пустых пробников. В этом случае, будут ошибки на этапе DRC.
Рисунок 119 – Новые цепи в ila_1
После нажатия на кнопку OK появится окно, которое информирует, что атрибут DONT_TOUCH будет снят с цепей, ранее подключенных к пробникам ila_1. Это один из нюансов, которые я описал в примечании в начале этого раздела. Учитывайте это, в случае если вы не используете мастер подключений, а делаете всё вручную. Соглашаемся с изменениями, нажав Unset Property и сохраняем текущее состояние DCP.
Теперь последовательно выполняем размещение, трассировку, генерацию битсрима и создание списка цепей (рис.120). Все вместе занимает примерно 1 минуту на моем компьютере. Быстро, не правда ли!
Рисунок 120 – последовательность действий для создания файла прошивки списка цепей для отладки
Теперь открываем Hardware Manger и программируем наш кристалл, на забывая подключить правильные .bit и .ltx файлы.
Открыв hw_ila_2 мы увидим 4 сигнала: шину cnt и три const0. Измените вывод значений шины cnt с hex на unsigned decimal (по аналогии с рис. 75) и запустите запись, нажав синий треугольник. Если все корректно, то Вы увидите изменение на шине cnt с 0 по 31 с инкрементом 1 (рис.121).
Рисунок 121 – Значение шины cnt в пробнике ila_1
Как видим, мы смогли отключить цепи выхода блочной памяти от пробников и подключить новые.
6.4. Замена портов ввода/вывода
Последнее, что остаётся сделать это изменить rx и tx для модуля uart и наконец-то увидеть Hello World в консоли. Следует отметить, что при работе с ECO есть несколько путей, чтобы достичь результата. Я покажу один из них.
Отрываем нетлист. Прежде чем приступить к переназначению ножек, стоит написать, что необходимо будет удалить всю входную цепь до первого объекта типа cell, после чего ее просто восставим заново. Удалять будем порт, цепь и буфер.
Сначала разберемся с входной цепью.
Выберите порт uart_rtl_0_rxd, подключенную у нем цепь и входной буфер. Нажмите unplace cell и затем удалить (рис. 122). После нажатия кнопки удалить, порт останется, просто выберите его и нажмите удалить еще один раз.
Рисунок 122 – Выбор входной цепи и детрассировка компонентов
Теперь восстановим удаленные компоненты. Первым делом добавим порт uart_rx, нажав на кнопку Create Port затем выставив настройки в соответствии с рис. 123
Рисунок 123 – Параметры создаваемого входного порта
Поскольку ножка A9 уже занята нашим выходным портом, Vivado выдаст сообщение, в которым предложит отменить привязку другого порта к ножке A9. Соглашаемся с этим (рис. 124)
Рисунок 124 – Окно информации об уже имеющемся подключении к выбранной ножке
Теперь создадим входной буфер. Нажмем кнопку Create Cell, название создаваемой ячейки ibuf_rx (рис. 125)
Рисунок 125 – Создание входного буфера
Теперь создаем цепь. Это делается в несколько этапов. Сначала цепь подключается к порту, а затем выполняется подключение к буферу. Выберите порт uart_rx и нажмите Create Net. Название цепи rx_net.
Теперь выберите цепь и порт I входного буфера и нажмите Connect Net. После этого появится цепь (рис. 127)
Рисунок 127 – Подключение порта и входного буфера
Теперь создадим цепь, межу буфером и модулем system_i. Выберите выходной пин O буфера и цепь uart_rtl_0_rxd, подключённую к system_i и нажмите Create Net
Рисунок 128 – Подключение буфера и цепи
Теперь повторим туже последовательность действий для выходного порта.
Выбираем выходной порт uart_rtl_0_txd, подключенную к нему цепь и выходной буфер. Нажимаем Unplace cell, а затем красный крестик, для удаления компонентов (рис. 122). После нажатия кнопки удалить, порт останется, просто выберите его и нажмите удалить еще один раз.
Рисунок 129 – Выбор выходной цепи
Создаём порт uart_tx, нажав кнопку Create Port, задаём направление Output и устанавливаем стандарт LVCMOS33 (рис. 130)
Рисунок 130 – Настройка параметров выходного порта
Создадим цепь tx_net, которая будет подключена к порту uart_tx. Выбираем uart_tx и нажимаем Create Net
Рисунок 131 – Создание цепи tx_net
Создаём выходной буфер tx_obuf, нажав Create Cell и выбрав тип OBUF (рис. 132)
Рисунок 132 – Создание выходного буфера
Выбираем пин O выходного буфера и цепь, подключённую к порту uart_tx и нажимаем Connect Net.
Рисунок 133 – Подключение буфера и порта
Теперь подключим буфер к system_i. Выбираем пин I буфера и цепь uart_rtl_0_txd (рис. 134).
Рисунок 134 – Подключение буфера и цепи
Сохраняем проект и выполняем последовательно размещение и трассировку. После этого запускам генерацию бистрима (рис. 135).
Рисунок 135 – Последовательно действий для получения файла прошивки
Откройте Hardware Manager и запрограммируйте ПЛИС. Перейдите в SDK и выполните запуск приложения (см. рис. 70). Если всё нормально, но в консоли вы увидите сообщение Hello World: cycle (рис. 136).
Рисунок 136 – Сообщения Hello World в SDK Terminal
7. Сравнительный анализ
Проведем небольшой сравнительный анализ разных подходов к внесению изменений в проект по части времени, затрачиваемого на различные операции. Это сравнение будет, конечно, довольно условным, т.к. требуемое время сильно зависит от кристалла, от его загруженности, от количества свободных трассировочных ресурсов и т.д. Проделаны будут операции по изменению HDL файлов, после которого будет заново выполнен синтез, а также в «постсинтез-» нетлисте будут изменены пробники. Результаты приведены в таблице 1. Сразу следует отметить, что инкрементная имплементация даёт выигрыш только при работе с большими кристаллами, для которых получение конечного результата может занимать десяток часов. В учет тут не было включено время, затрачиваемое на внесение разработчиком изменений. Однако учтено то, что мы работали с IP Integrator – а он требует дополнительного времени на синтез IP и RTL.
Таблица 1. Сравнительный анализ времени, затрачиваемого на получение конечного файла прошивки в различных режимах.
Резюмируя сравнительны анализ, ещё раз скажу, что он очень поверхностный. Вы прекрасно понимаете, что FPGA – это сложная система и время того или иного этапа маршрута проектирования может изменяться очень сильно. Тем не менее, ECO не требует синтеза, и внесение небольших изменений в проект выполняется гораздо быстрее, особенно когда требуется сохранить трассировку кристалла и внести изменения только в содержимое компонентов.
8. Заключение
Применял ли я когда-нибудь на практике режим ECO? Да. Стояла задача, не изменяя трассировку кристалла поменять содержимое блочной памяти, в которой были зашиты некоторые значения, позволяющие защитить продукцию от копирования. Там как раз и пригодился ECO; правда, по большей части работа была выполнена при помощи Tcl-скриптов, а не графического интерфейса. Тем не менее, режим ECO оказывается действительно полезен при работе с большими проектами – особенно в случае, если вы являетесь горячим фанатом внутрисхемной отладки с LogicAnalyser (ChipScope) и любите делать ILA на пару сотен (или даже тысяч) пробников. Возможно, Вы найдете работу в этом режиме полезной для Вас, если просто попробуете сделать что-то большее, чем описано в данном руководстве.
Если Вы нашли для ECO Flow интересное применение, или просто решили попробовать использовать его в своём проекте, оставьте небольшой комментарий: будет любопытно узнать для чего Вам в Vivado пригодился ECO Flow.
Не забудьте сделать и домашнее задание. Удачи!
9. Домашнее задание
- Используя исправленный нетлист, измените логическую функцию LUT, которая реализует инвертор, чтобы она не инвертировала входной сигнал.
- Попробуйте запустить различные оптимизации с различными опциями в режиме ECO. Используйте для помощи гайд с Tcl командами Vivado [9].
- Просмотрите транзакции на шине AXI-lIte, которые идут к модулю GPIO. В режиме ECO замените цепи, которые подключены к ila_1 от модуля uartlite, на цепи от модуля gpio.
- *Попробуйте изменить частоты, которую вырабатывает MMCM, текущее значение 100МГц. Сделайте его 50 МГц. Если все сделано корректно, то светодиод должен мигать в два раза медленней. Не забудьте просмотреть отчет по таймингам, поскольку вы изменили модуль, отвечающий за частоту всего проекта.
- *Попробуйте создать Tcl команду или скрипт, который бы автоматически выполнял необходимую последовательность действий при изменении нетлиста в режиме ECO. Скрипт должен сохранять изменения, запускать размещение, трассировку, генерировать фал прошивки и т.д.
- **Напишите скрипт, который бы позволял изменять содержимое блочной памяти в блоке brom_reader, записывая любые 32 символа ASCII, вводимые в качестве аргументов разрабатываемой процедуры/скрипта
Библиографический список
1. Vivado на сайте Xilinx
2. Описание Arty Board на сайте Digilent
3. UG904 Vivado Design Suite User Guide: Implementation
4. UG908 Vivado Design Suite User Guide Programming and Debugging
5. UG986 Vivado Design Suite Tutorial: Implementation
6. Wiki: ECO
7. UG949 UltraFast Design Methodology Guide
8. UG892 Vivado Design Suite User Guide Design Flows Overview
9. UG835 Vivado Design Suite Tcl Command Reference Guide
10. UG894 Using Tcl Scripting
11. UG901 Vivado Design Suite User Guide Synthesis
12. Arty Reference Manual
13. UG908 Programming and Debugging
14. UG1037 Vivado Design Suite AXI Reference Guide
15. Hex-to-ASCII
16. Руководство: Разработка процессорной системы на базе софт-процессора MicroBlaze в среде Xilinx Vivado IDE/HLx
Приложение А. Листинг модуля flash_led
Скрытый текст
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity flash_led is
Port ( iclk : in STD_LOGIC;
oled : out STD_LOGIC);
end flash_led;
architecture rtl of flash_led is
signal cnt : natural range 0 to 100_000_001 := 0;
signal led : std_logic := '0';
begin
process(iclk)
begin
if rising_edge(iclk) then
if cnt = 100_000_000 then
cnt <= 0;
else
cnt <= cnt + 1;
end if;
if cnt < 50_000_000 then
led <= '0';
else
led <= '1';
end if;
end if;
end process;
oled <= led;
end rtl;
Приложение Б. Листинг модуля brom_reader
Скрытый текст
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity brom_reader is
Port (
iclk : in STD_LOGIC;
odout : out std_logic_vector(7 downto 0)
);
end brom_reader;
architecture rtl of brom_reader is
alias slv is std_logic_vector;
type rom_type is array (0 to 31) of natural;
signal rom : rom_type := (
32 , 32, 32, 32, 97, 117, 116, 104,
111, 114, 58, 32, 75, 101, 105, 115,
78 , 49, 51, 32, 32, 32, 32, 32,
32 , 32, 32, 32, 32, 32, 32, 32
);
signal cnt : natural range 0 to rom'length-1 := 0;
signal dout: slv(odout'range) := (others => '0');
attribute RAM_STYLE : string;
attribute RAM_STYLE of rom : signal is "BLOCK";
begin
process(iclk)
begin
if rising_edge(iclk) then
dout <= slv(to_unsigned(rom(cnt), dout'length));
if cnt = (rom'length - 1) then
cnt <= 0;
else
cnt <= cnt + 1;
end if;
end if;
end process;
odout <= dout;
end rtl;
Приложение В. Листинг программы helloworld
Скрытый текст
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"
XGpio Gpio; /* The Instance of the GPIO Driver */
#define DELAY 10000000
int main()
{
init_platform();
int Status;
volatile int Delay;
int k = 0;
/* Initialize the GPIO driver */
Status = XGpio_Initialize(&Gpio, XPAR_GPIO_0_BASEADDR);
if (Status != XST_SUCCESS) {
xil_printf("Gpio Initialization Failed\r\n");
return XST_FAILURE;
}
/* Loop forever blinking the LED */
while (1) {
/* Set the LED to High */
XGpio_DiscreteWrite(&Gpio, 1, 1);
xil_printf("Hello World: cycle %d\n\r", k);
k++;
/* Wait a small amount of time so the LED is visible */
for (Delay = 0; Delay < DELAY; Delay++){};
/* Clear the LED bit */
XGpio_DiscreteWrite(&Gpio, 1, 0);
/* Wait a small amount of time so the LED is visible */
for (Delay = 0; Delay < DELAY; Delay++){};
}
cleanup_platform();
return 0;
}
PS: Огромное спасибо пользователям intekus Des333, ishevchuk, roman-yanalov которые не только прочитали это 91 страничное руководство (именно столько оно занимает в Word), но и выполнили его и внесли необходимые редакторские правки.