Программист ООО «СМАРТС-Кванттелеком» Данная серия статей является туториалом по установке линукса на плату KC705 с софт-процессорным ядром Микроблэйз. - В первой части я описываю процесс создания схемы платформы, на которую мы поставим систему, с описанием некоторых нюансов.  - Во второй части я опишу процесс сборки образа линукса и тестирование его работоспособности на отладочной плате путем прошивания через usb.  - В третей части я расскажу о том, как прошить SPI флэшку на плате, чтобы система стартовала сразу при включении платы.  Буду рад любым советам, замечаниям и фидбэку в комментариях. Статью считаю полезной, т.к. в процессе столкнулся с достаточно большим количеством неочевидных вещей, настроек и решений, информацию о которых в интернете нашёл с трудом. Да и вообще, актуальных туториалов и статей, конкретно по этой отладочной плате в интернете ничтожно мало.  Поехали! Для начала немного теории: MicroBlaze — soft-процессорное ядро, разработанное компанией Xilinx для использования в FPGA. MicroBlaze реализуется с помощью стандартной логики и блоков памяти ПЛИС. С точки зрения архитектуры, MicroBlaze очень похож на процессор с основанной на RISCDLX-архитектурой, описанной в книге Д. Паттерсона (David Patterson) и Дж. Хеннеси (John L. Hennessy). За исключением отдельных случаев MicroBlaze может выполнять по одной инструкции за такт, сохраняя такую производительность практически в любых условиях. Soft-микропроцессор (также «микропроцессор с программным ядром») —микропроцессорное ядро, которое может быть полностью создано с использованием только логического синтеза. Реализуется с использованием различных полупроводниковых устройств, содержащих программируемую логику (ПЛИС — например, как в нашем случае). Программи́руемая логи́ческая интегра́льная схе́ма (ПЛИС, англ. Programmable logic device, PLD) — электронный компонент (интегральная микросхема), используемый для создания конфигурируемых цифровых электронных схем. В отличие от обычных цифровых микросхем, логика работы ПЛИС не определяется при изготовлении, а задаётся посредством программирования (проектирования). Для программирования используются программатор и IDE (отладочная среда), позволяющие задать желаемую структуру цифрового устройства в виде принципиальной электрической схемы или программы на специальных языках описания аппаратуры (Verilog, VHDL, AHDL и других). Linux— это полностью готовая операционная система на основе ядра Linux, которая предназначена для выполнения конкретных задач в соответствии с видением ее создателей. Существуют дистрибутивы для серверов, настольных компьютеров, мобильных телефонов, встраиваемых устройств, старых компьютеров и многих других областей применения. Linux можно настроить, как угодно. Существует множество интерфейсов, программ и систем для удобства работы, поэтому он идеально подойдёт для использования совместно с софт-процессором MicroBlaze. Передо мной стояла следующая задача: установить на плату KC705 Линукс. Должен быть доступ к ethernet в режиме SGMII, сама прошивка должна загружаться из SPI флешки в DDR при включении отладочной платы, а также при нажатии кнопок, имеющихся на плате, должны происходить такие действия как; смена IP адреса (повторное нажатие возвращает исходные настройки IP), включение какого-либо приложения, соединение с NTP сервером. Так как придется собирать образ линукса, весь проект я решил выполнить на Ubuntu 22.04.2 LTS (актуальная, стабильная версия на момент написания статьи). Выбор пал именно на этот дистрибутив, так как он обладает обширным количеством пакетов и большинство ответов и подсказок в интернете можно найти именно для ubuntu. Дистрибутив можно установить, как на виртуальную машину (VirtualBox, VMware и тд.), так и реально на железо. Лично я установил на VirtualBox, так как железо позволяет, да и как оказалось позже, это мне помогло, но обо всем по порядку. Для выполнения задачи нам понадобится следующее ПО: Vivado 2022.1 Petalinux 2022.1 Putty (если вы работаете на чистом линуксе)/TeraTerm (для windows, если вы работаете с виртуалкой) Драйвера для подключения к плате через COM порт и по USB. В моём случае уcтановить пришлось как на Linux, так и на Windows. Саму задачу можно разделить на несколько этапов: Создание блок дизайна в Vivado и экспорт созданной платформы Создание и конфигурирование образа линукса в Petalinux Создание функционала кнопок, отладка проекта в Petalinux Запись прошивки в SPI флешку. Порадоваться за выполненную задачу! Итак, установив Ubuntu на VirtualBox, устанавливаем Vivado. Тут все несложно, но есть нюанс. При выборе компонентов установки – снимаем галочку с пунктаVitis Model Composer. Это нужно для того, чтобы установка успешно и правильно завершилась. Без снятия данной галочки, лично у меня, установка зависала на определенном моменте, и никогда не доходила до успешного завершения. По крайней мере, у меня успешно установка не завершалась, и в меню приложений Vivado появляться отказывался. Также снимаем выделение со всего, что нам не нужно, чтобы ускорить установку и уменьшить конечный вес установленной программы. После установки запускаем Vivado. В появившемся окне, нажимаем Create Project, выбираем название и расположение проекта, тут все стандартно. Дойдя до выбора Project Type, оставляем все as is и жмём Next. Попадаем в меню выбора платы (Default Parts), выбираем вкладку Boards и из появившегося списка выбираем нашу плату. Наконец, мы приступаем к созданию блочного дизайна. При создании схемы я опирался на примеры схем с использованием MicroBlaze от Xilinx (File –> Project –> Open Example…), которые можно найти прямо в самой Vivado, официальную документацию от Xilinx, а также на общую информацию в интернете (вопрос обширный и затрагивает очень много областей). В интернете довольно много примеров для ZynQ, Artix, меньше для Spartan, а вот по Kintex я нашел крайне мало информации, так что пришлось проводить параллели с примерами для других плат и пытаться опытным путем найти подходящее решение. Во Flow Navigator слева жмем на Create Block Design.Выбираем название и расположение блочного дизайна (я всегда оставляю <Local to Project>). Жмем ОК. Перед нами раскидывается меню создания блок дизайна. Справа от Flow Navigator находим окно, содержащее вкладку Board. Открыв ее, мы можем просмотреть список компонентов, имеющихся на нашей плате, и выбрать те, что нас интересуют. Теперь мы готовы к созданию блочного дизайна. Дело кажется сложным, но все проще, чем могло бы быть. Сначала добавим в схему софт-процессор Microblaze (порядок добавленияэлементов на схему значения не имеет, но мне нравится делать это в порядке, описываемом в данной статье). Для этого кликаем правой кнопкой мыши в любом месте окна Diagram и в выпадающем меню выбираем Add IP… В появившемся меню, набираем microblaze и выбираем его из списка двойным нажатием. И видим блок на нашей схеме. Подобным образом добавляем AXI Timer и AXI Smart Connect. Блоки, которые мы видим перед собой называются IP ядрами. IP(Intellectual Property) ядра – это описанные на языке Verilog/VHDL компоненты на нашей плате(исходный код ядер компания Xilinx заботливо закрыла от посторонних глаз), кстати теперь компанией Xilinx владеет компания AMD. Vivado позволяет даже начинающим разработчикам довольно быстро подготовить платформу для своей встроенной системы без необходимости знать языки программирования озвученные ранее. Теперь добавим оставшиеся компоненты. Нам нужен UART для соединения с COM портом компьютера и выводом терминала платы в TeraTerm или Putty, чтобы мы могли понять на сколько успешны наши действия. Мы можем добавить это, перетащив нужный компонент в любое свободное место на схеме. Таким образом, добавляем Pushbuttons, так как нам понадобиться создать функциональные кнопки. SPI flash, где будет храниться наша прошивка и от туда загружаться в DDR. DDR3 SDRAM – наша оперативная память. Последним компонентом добавим Onboard PHY. При добавлении данного ядра на схему появляется меню, позволяющее нам сразу выбрать режим, в котором будет работать ethernet, с соответствующим пресетом компонентов. В появившемся окне выбираем SGMII mode, жмем ОК. Прежде чем соединять блоки, произведем настройку некоторых IP ядер. Начнем с AXI Uartlite. Дважды кликаем по блоку, чтобы реконфигурировать ядро. В появившемся окне выбираем вкладку IP Configuration. На против Baud Rate выбираем 115200 из выпадающего списка. Это скорость передачи в бодах, с которой информация будет выводиться в терминал Putty/TeraTerm. Больше ничего не меняем, нажимаем ОК. Далее открываем AXI GPIO, наши кнопки, и ставим галочку в Enable Interrupt, чтобы создать линию прерывания. Это понадобиться нам в линуксе, когда мы будем создавать функционал кнопок. Нажимаем ОК. Далее, настроим AXI Quad SPI. В открывшемся окне переходим во вкладку IP Configuration.В графе Mode выбираем Quad. В качестве Slave Device выбираем Micron (Numonyx), так как флэшка от этого производителя установлена у нас на отладочной плате. К слову, поиск правильных настроек SPI флэши оказался довольно нетривиальной задачей из-за неочевидных настроек. Вроде бы кажется, что вот мы все указали, и этого должно хватать...но это не так. Нажимаем OK. Теперь, настроим AXI Smart Connect. Нам необходимо вписать туда 5 Slave Interfaces, а также 2 Clock Inputs. Тут тоже хотелось бы отметить, что только после добавления этого блока, решились ошибки, связанные с адресным пространством. Данный блок автоматически настраивает корректное соединение мастера и слэйвов. Нажимаем OK. Имея все необходимые элементы на схеме, теперь мы можем их соединить. Vivado от Xilinx имеет хорошую функцию Designer Assistance, которой мы и воспользуемся. Для этого вверху окна Diagram видим зеленую полоску, на ней нажимаем Run Block Automation. В появившемся окне выбираем All Automation, чтобы Designer Assistance добавил необходимые блоки в схему и соединил их.  Теперь надо настроить каждое из этих ядер. Нажимаем на microblaze_0. В меню настройки, в области Options, выбираем Application в качестве Preset, Local Memory – 128KB.Вообще, выбор количества памяти в данном месте зависит от поставленных задач, если я правильно понял, то для запуска линукса, необходимым минимумом является 32. Далее убеждаемся в том, что Interrupt Controllerвключен, проверив наличие галочки в соответствующем пункте данного окна. Далее переключаемся на axi_ethernet_0 и убеждаемся, что в качестве Physical Interface Selection выставлен SGMII, а в качестве Connect AXI Streaming Interface to выбрано DMA. Нажимаем ОК. После того, как Block Automation сработал, мы видим, что на схеме появились новые блок и порты. Все автоматические действия можно проделать вручную, но ради экономии времени, а также, чтобы не совершить ненужных ошибок, стоит прибегнуть к автоматическому способу. На данный момент схема может выглядеть достаточно громоздко и неупорядоченно. Для удобства работы воспользуемся кнопкой Regenerate Layout. Хотя кнопки автоматизаций весьма удобны, но не всегда делают то, что нам нужно. Поэтому некоторые вещи приходиться проделывать вручную. Сперва, увеличим количество линий прерываний. Для этого находим блок Concat и дважды кликаем по нему. Нам понадобится 8 линий прерываний, соответственно в поле Number of Ports пишем 8, нажимаем ОК. Теперь соединяем пины прерываний от блоков AXIGPIO, AXI Uartlite, AXI Quad SPI, AXI Timer с входными портами блока Concat. С Сoncat следует соединить пины mm2sintrout и s2mmintrout блока AXI Direct Memory Access.Соединяем пины mac_irq и interrupt блока AXI 1G/2.5G Ethernet Subsystem с Concat. Далее соединим M_AXI_DC и M_AXI_IC от MicroBlaze c S03_AXI и S04_AXI блока AXI Smart Connect. Теперь соединим AXI Direct Memory Access с AXI Smart Connect как на скриншоте ниже. Пин M00_AXI блока AXI SmartConnect следует соединить с пином S_AXI блока Memory Interface Generatоr. Настроим MicroBlaze. Двойным нажатием открываем конфигурационное меню. В поле Select Configuration выбираем Linux with MMU.Нажимаем OK. Теперь можем включить Run Connection Automation в Designer Assistance. В открывшемся меню выбираем All Automation, нажимаем OK. После того как была проведена автоматизация соединений, следует внести коррективы для получения работающей схемы. У AXI Quad SPI отсоединяем ext_spi_clk. И соединяем этот пин с той же линией, к которой подключен s_axi_aclk. Аresetn AXI Smart Connect следует соединить с общей aresetn линией. Пин aclk соединяем с ui_clk блока Memory Interface Generator и далее aclk1. У блока AXI Direct Memory Access следует внести следующие изменения. AXI 1G/2.5G Ethernet Subsystem s_axi_lite_clk и s_axi_lite_clk так же следует сделать синхронными. Последнее, что остается поправить – это блок Processor System Reset. Отсоединяем ext_reset_in пин от порта reset и присоединяем его к пину ui_clk_sync_rst блока MIG 7 Series. Последнее, что мы соединим, так это aresetn блока MIGc общей сетью aresetn. Теперь нужно исправить регистры. Рядом со вкладкой Diagram можно найти вкладку Address Editor. Открываем ее. В данном случае автоматические инструменты Vivado хорошо справляются. Нажимаем на кнопку Unassign All, в результате чего все интерфейсы отвяжутся от каких-либо адресов. Затем нажимаем Assign All, таким образом все интерфейсы автоматически и, что самое важное - корректно, будут назначены на свои адреса. Далее видим сообщение об успешном выполнении автоматического назначения адресов. Нажимаем ОК. Теперь следует произвести валидацию дизайна. Нажимаем соответствующую кнопку. Если все сделано правильно, то мы увидим сообщение об успешной проверке нашего дизайна. Если у вас вылетают какие-либо ошибки, то читайте что не так и исправляйте. Далее нам нужно синтезировать дизайн. Чтобы это сделать, для нашей схемы, нам необходимо создать HDL Wrapper. Для этого открываем вкладку Sources, кликаем правой кнопкой мыши по файлу схемы и нажимаем Create HDL Wrapper. В открывшемся окне, выбираем пункт Let Vivado manage wrapper and auto-update. Жмем ОК. Открываем Flow Navigator, нажимаем Run Synthesis. В новом окне, в поле Number of jobs, мы можем выбрать количество потоков, в котором будет происходить синтез, у меня это 12, у вас может быть другое число, либо оставляем все как есть, либо выставляем нужное количество потоков, ничего больше не меняем и нажимаем ОК. Ждем окончания синтеза. После завершения синтеза, в появившемся окне выбираем Open Synthesized Design и нажимаем OK. Делаем мы это для того, чтобы создать файл c так называемыми "констрэнтами" для этого слева, во Flow Navigator находим Constraints Wizard и открываем его.  Нажимаем Define Target, затем Create File. Называем наш файл как удобно. Я назову его - constr. Нажимаем OK. В появившемся окне, ставим галочку напротив только что созданного файла. Дальнейшие изменения в "констрэйнтах", которые мы совершим будут отражены в этом файле. Нажимаем ОК. Снова открываем Constraints Wizard. Жмем Next. Теперь нам необходимо задать частоту для sgmii_mgt_clk_clk_p.  Выставляем 125 в соответствии с User Guide к нашей плате и нажимаем Skip to Finish. И далее Finish. К слову, этот момент для меня стал своеобразными граблями, так как без указания нужной частоты, вылетали малоинформативные ошибки. Тут дело в том, что Vivado знает с какого порта и на какой передается тактовый сигнал, но не знает с какой частотой (странно, что Vivado не берет это из порта на схеме, ведь там эта цифра присутствует, причём Vivado сам, автоматом это выставляет). Тут нужно задать настройки битстрима, связанные с SPI флэшкой, а также оптимизировать размер самого битстрима. Для этого во Flow Navigator открываем Settings. Выбираем вкладку Bitstream, а в ней нажимаем Confiure additional bitstream settings. ВАЖНО, что дополнительные настройки битстрима можно открыть только, если мы совершили синтез или имплементацию и открыли синтезированный дизайн или имплементированный. В открывшемся меню выбираем TRUE для поля Enable Bitstream Compression, чтобы уменьшить размер битстрима, так как в дальнейшем он станет часть прошивки, которую придется загружать на флэшку емкостью 16Мб. Затем выбираем вкладку Configuration. Во вкладке Configuration устанавливаем 6 в поле Configuration Rate (MHz), а также Bus width 4 в SPI Configuration (от одна из тех неочевидных настроек SPI флешки, которую зачем-то засунули сюда, хотя мы вроде и так уже указали Quad режим ранее). Далее открываем вкладку Configuration Modes. В списке листаем до Master SPI x 4 и ставим галочку в соответствующем поле. Нажимаем ОК. Также нажимаем ОК в окне Settings. Нажимаем Ctrl+S для сохранения произведенных настроек. На всякий случай, следует проверить файл с "констрэйнтами", убедиться, что в нем отображены внесенные изменения. Теперь, когда все необходимые настройки сделаны, мы можем сгенерировать битстрим файл. Для этого во Flow Navigator нажимаем Generate Bitstream. Во всех появляющихся окнах нажимаем Yes или ОК, закрываем окно к синтезированного дизайна и ждем, когда будет сгенерирован bitstream файл. Дождавшись окончания генерации, мы наконец-то можем создать файл, содержащий созданную нами платформу. Для этого нажимаем File –> Export –> Export Hardware. В открывшемся окне нажимаем Next. Далее выбираем Include bitstream –> Next. Выбираем расположение файла платформы. Снова Next. Потом Finish. Поздравляю! Это было долго, но мы справились. Из-за обилия действий, которые надо произвести, я не стал описывать почему это надо делать именно так, иначе гайд вырос бы еще сильнее. Но ведь гораздо легче искать информацию по интересующим вопросам, когда знаешь ответы! Если вы все же хотите задать вопросы, то я постараюсь на них ответить в комментариях. В следующей статье я расскажу, как создать проект в Petalinux и произвести необходимые настройки для запуска линукса на созданной нами платформе с софт процессором Microblaze на отладочной плате KC705.