The post has been translated automatically. Original language: Russian
В первой части этой серии статей мы познакомились с основами аналогово-цифровых преобразователей (АЦП) и программируемых логических интегральных схем (ПЛИС), рассмотрели общую архитектуру системы для передачи данных с АЦП ПЛИС Intel MAX 10 на персональный компьютер, подготовили рабочее место с использованием Quartus Prime Lite и описали поставленную задачу.
Теперь, во второй части, мы перейдем к практическим шагам по созданию аппаратной платформы: соберем систему в Platform Designer, настроим ключевые компоненты, такие как Nios II, Modular ADC, PLL и mSGDMA, исправим возможные баги, пропишем тайминги, назначим пины и скомпилируем проект. Это позволит создать основу для дальнейшей работы с программной частью на Nios II, которую мы разберем в третьей части.
Создаем проект
Заходим в Quartus Prime, кликаем File -> New Project Wizard. Указываем папку и название проекта. Имя папки и проект желательно сделать одинаковыми. Дальше кликаем далее, пока не дойдем до следующей страницы.
Тут выбираем модель ПЛИС. Выбираем семейство и внизу в таблице находим нужную модель. На последующей странице везде ставим None. И завершаем настройку проекта.
Строим систему
Открываем Platform Designer, он позволяет автоматически генерировать логику межсоединений для подключения компонентов. В открывшемся окне будет 4 части. Слева в IP Catalog можно по поиску найти все нужные компоненты, а в правой части будет отображаться компоненты и соединения между ними.
Построить мы должны систему как на рисунках ниже. Далее я подробней остановлюсь на каждом из компонентов.
NIOS II
Выбираем версию /f для максимальной производительности. В остальных вкладках пока ничего не меняем
On-chip Memory
Тут меняем только Total Memory Size на 16384.
Modular ADC (АЦП)
Выбираем все как на рисунке ниже. Ставим вариант Standard sequencer with sample storage который позволяет сохранять образцы в память. Частоту дискретизации ставим на 25 кГц чего достаточно для нашей задачи (вспоминаем Теорему Котельникова). Не забываем ставить Input Clock на 2 МГц. Выбираем внутреннее опорное напряжение. Снизу можно выбрать каналы для оцифровки, я выбрал 7 канал.
Важно после выбора канала указать его в слоте в секвенсере. Секвенсер можете создавать до 64 слотов для хранения образцов и для каждого из них можно выбрать свой канал. В этом проекте нам нет нужды использовать больше одного слота.
PLL
Данный компонент мы еще не обсуждали ранее. На русском он звучит как ФАПЧ - Фазовая Автоподстройка Частоты. В нашем проекте он помогает нам сгенерировать сигнал с частотой 2 МГц для тактирования нашего АЦП.
Здесь надо указать частоту входного тактового сигнала. Мы будем использовать основной тактовый сигнал от осциллятора в 50 МГц.
Убираем галочку с areset
Остальное не трогаем и переходим на 3 часть. Ставим частоту выходного сигнала на 2 МГц и завершаем процесс настройки.
В версии Quartus Prime Lite Edition 23.1 у некоторых пользователей была проблема с PLL. А именно после определенной страницы у них вылетало с окна настройки модуля и они не могли добавить данное IP. В интернете два разных решения этой проблемы.
Исправляем баги
Первое это использование модуля с предыдущей версии. Инструкция по ссылке ниже.
Второе это установка патчей от Intel для исправления данной ошибки в самой программе.
https://www.intel.com/content/www/us/en/support/programmable/articles/000098457.html
Помимо этого у вас может появиться или уже быть еще один баг, когда вы будете способны настроить PLL, но после нажатия Finish, модуль не будет отображаться в Platform Designer и соответственно отсутствовать в проекте. Чтобы исправить этот баг следуем инструкции по ссылке ниже
mSGDMA
Поменяем пару настроек, выставим FIFO на пути данных на 1024 байтов чтобы не потерять данные. Maximum Transfer Length что означает максимальная длина передачи ставим на 8KB. Включаем Extended Feature Support, эта расширенные возможности DMA позволяющие делать разные манипуляции и операции при передаче данных. Нам это нужно для последовательного чтения/записи памяти при работе с кольцевым буфером.
FIFOED_UART
В качестве UART в данном проекте был задействован сторонний модуль, который является расширенной версии модуля предоставленной в Quartus Prime Lite. Прежде чем скомпилировать проект нужно добавить данный модуль вручную.
Ссылка на архив с модулем:
https://drive.google.com/file/d/1ayBqxPtSYAUMgunJB_L9qiTec6BIIxME/view?usp=sharing
После разархивирования в папке будет находится Word документ с названием “FIFOed_Avalon_UART_v13.1”. В нем находится инструкция по установке/интеграции модуля в Quartus Prime и NIOS II.
Настраиваем его следующим образом
TX FIFO нам нужен для буферизации данных при передаче чтобы не потерять их. Baud Rate выставлен на 921600 бод. Позже в третьей части объясню как мы пришли к этому значению.
После того как добавили его, нужно в колонке Export в строке external_connection кликнуть два раза по надписи “double click to export”. Этим действием мы позволяем вывести пины данного модуля для приема/передачи наружу, так как нам нужно соединить его с внешним последовательным портом.
Как добавили все компоненты, соедините их как на рисунке выше. Дальше нужно снова вернуться к NIOS II. Щелкаем по нему, справа появится окно с параметрами, переходим на вкладку Vectors и для Reset Vector Memory и Exception Vector Memory выбираем onchip_memory2_0.s1. Теперь мы настроили все компоненты, осталось их расположить правильно в памяти. Кликаем сверху на System -> Assign Base Addresses. На этом этапе снизу должны остаться лишь несколько предупреждений, их можно проигнорировать.
Снизу нажимаем на Generate HDL, чтобы сгенерировать код описывающий все наши соединения и настройки. В открывшемся окне в язык выбираем Verilog. Появится окно с предложением сохранить систему, сохраняем с таким же именем как и сам проект. Ждем генерацию, после завершения нажимаем Finish и возвращаемся на главную страницу.
После закрытия всплывет окно с предупреждением, его можно закрыть, там говорится о том, что наши сгенерированные файлы с кодом нужно добавить в файлы проекта прежде чем компилировать.
Слева в окне Project Navigator кликаем два раза на Files -> три точки -> папка с названием проекта -> synthesis -> *.qip. Закрываем. В этом файле хранится код описывающий логику всех компонентов и соединении между ними
Настройки
Код вроде бы есть, все добавили, что еще нужно? Не забываем, что мы работаем с железом и тут нужно настраивать пины и тайминги.
Сперва позаботимся о таймингах. Несмотря на то, что мы уже указали частоты, нам нужно снова прописать ограничения по частотам тактовых сигналов. Все это из-за того, что ранее мы их указывали чтобы система понимала какие будут частоты и смогла эффективно описать блоки в коде. Теперь же нам надо указать их в отдельном файле, чтобы система учитывала это при физическом расположении нашей всей логики внутри ПЛИС.
И так кликаем по File -> New. Выбираем Synopsys Design Constraints. В новом окне пишем следующие строчки
create_clock -name clk_clk -period 20.000 [get_ports {clk_clk}]
derive_pll_clocks
derive_clock_uncertainty
Тут мы обозначаем, что период главного тактового сигнала 20 нс. И что он подается с порта clk_clk. Вторая строчка делает такие же манипуляции для тактовых сигналов PLL. И третья строчка выполняет автоматический расчёт и установку неопределённости тактового сигнала (clock uncertainty).
Далее надо обозначить какую конфигурацию мы хотим использовать. Помним, что мы добавляли память и выделяли 16 кБ. Поэтому кликаем Assignments -> Device -> Device and Pin Options -> Configuration -> Configuration mode -> Single Uncompressed Image with Memory Initialization. Выбираем конфигурацию с инициализацией памяти.
Без memory initialization память остается пустой после загрузки, что приводит к ошибкам: Nios II не сможет загрузиться, так как его векторы сброса и исключений (reset/exception vectors) указывают на onchip_memory, а без инициализации там нет кода.
Теперь когда прописали ограничения по таймингу и настроили все, пришло время провести анализ нашей работы и посмотреть все ли в порядке. Нажимаем на иконку как на рисунке
И ждем, это займет некоторое время. После этого слева снизу в окне Tasks вы должны увидеть зеленую галочку у строки Analysis&Elaboration под Analysis&Synthesis.
Наш код про синтезирован и Quartus должен был вывести все нужные пины для назначения. Этим пинам надо присвоить физические провода на нашей отладочной плате. Кликаем Assignments -> Pin Planner. Откроется окно с схемой ПЛИС по середине. Нас интересную часть внизу со списком пинов.
Как видно на рисунку нас интересует лишь 4 пина. Clk для тактового сигнала, reset - для сброса, rxd - для приема данных в UART, txd - для передачи данных с UART. Как раз к пину txd мы и будем подключать последовательный порт.
Clk_clk обязательно назначаем на PIN_27 если используете плату как у меня, так как на нее приходит тактовый сигнал с осциллятора. В разных ПЛИС это может быть разный пин. Остальные пины можем повесить на любые свободные цифровые пины.
Важно выставить все пины на уровень 3.3V LVTTL. Это связано с тем, что отладочная плата использует банки питания I/O с напряжением 3.3 В.
Компиляция и программирование
Закрываем окно и нажимаем на Start Compilation для компиляции нашего проекта. Ждем пока галочки на всех строках до Timing Analysis включительно в окне Tasks.
Скомпилировали проект, теперь нужно его загрузить в сам ПЛИС. Нажимаем на иконку для программирования ПЛИС. Нажимаем на Hardware Setup, выбираем там программатор обычно подписан как USB Blaster и закрываем.
Так как нам требуется записать конфигурацию только в ПЛИС, не затрагивая её встроенную конфигурационную память. Выбираем в качестве файла конфигурации файл с расширением *.sof. Он должен быть автоматически уже выбран. Если его нет, добавляем его с помощью Add File. Cтавим галочку на Program/Configure.
Нажимаем старт и ждем пока ПЛИС прошьется.
После прошивки выйдет окно с обратным отсчетом в 1 час. Не пугаемся, это из за NIOS II, который не доступен без лицензии для использования без ограничений.
Заключение
На этом мы завершаем настройку аппаратной платформы для передачи данных с АЦП ПЛИС Intel MAX 10 на ПК. Мы успешно собрали систему в Platform Designer, настроили компоненты, исправили потенциальные ошибки, прописали ограничения по таймингу, скомпилировали проект и загрузили его в ПЛИС. Теперь устройство готово к работе: АЦП оцифровывает сигналы, DMA обеспечивает эффективную передачу, а UART готов к обмену данными с компьютером. В третьей части мы перейдем к программной реализации на Nios II, включая код для чтения данных из АЦП, управление кольцевым буфером и отправку информации на ПК.
Список литературы
- Intel. (2017, July 6). Intel® MAX® 10 analog to digital converter user guide (Document ID: UG-M10ADC). Intel Corporation. https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug-m10adc.pdf
- Intel Corporation. (2023, August 15). Embedded peripherals IP user guide (Document ID: UG-01085; Document No. 683130). https://www.intel.com/content/www/us/en/docs/programmable/683130
- Intel. (2024, February 21). Intel® Quartus® Prime Standard Edition User Guide: Timing Analyzer (Version 18.1 Public, ID 683068). https://www.intel.com/content/www/us/en/docs/programmable/683068/18-1/timing-analysis-introduction.html
- Intel Corporation. (2023, January 8). Intel® MAX® 10 FPGA (10M08S, 144-EQFP) evaluation kit user guide (Document No. 812857). https://www.intel.com/content/www/us/en/docs/programmable/812857
В первой части этой серии статей мы познакомились с основами аналогово-цифровых преобразователей (АЦП) и программируемых логических интегральных схем (ПЛИС), рассмотрели общую архитектуру системы для передачи данных с АЦП ПЛИС Intel MAX 10 на персональный компьютер, подготовили рабочее место с использованием Quartus Prime Lite и описали поставленную задачу.
Теперь, во второй части, мы перейдем к практическим шагам по созданию аппаратной платформы: соберем систему в Platform Designer, настроим ключевые компоненты, такие как Nios II, Modular ADC, PLL и mSGDMA, исправим возможные баги, пропишем тайминги, назначим пины и скомпилируем проект. Это позволит создать основу для дальнейшей работы с программной частью на Nios II, которую мы разберем в третьей части.
Создаем проект
Заходим в Quartus Prime, кликаем File -> New Project Wizard. Указываем папку и название проекта. Имя папки и проект желательно сделать одинаковыми. Дальше кликаем далее, пока не дойдем до следующей страницы.
Тут выбираем модель ПЛИС. Выбираем семейство и внизу в таблице находим нужную модель. На последующей странице везде ставим None. И завершаем настройку проекта.
Строим систему
Открываем Platform Designer, он позволяет автоматически генерировать логику межсоединений для подключения компонентов. В открывшемся окне будет 4 части. Слева в IP Catalog можно по поиску найти все нужные компоненты, а в правой части будет отображаться компоненты и соединения между ними.
Построить мы должны систему как на рисунках ниже. Далее я подробней остановлюсь на каждом из компонентов.
NIOS II
Выбираем версию /f для максимальной производительности. В остальных вкладках пока ничего не меняем
On-chip Memory
Тут меняем только Total Memory Size на 16384.
Modular ADC (АЦП)
Выбираем все как на рисунке ниже. Ставим вариант Standard sequencer with sample storage который позволяет сохранять образцы в память. Частоту дискретизации ставим на 25 кГц чего достаточно для нашей задачи (вспоминаем Теорему Котельникова). Не забываем ставить Input Clock на 2 МГц. Выбираем внутреннее опорное напряжение. Снизу можно выбрать каналы для оцифровки, я выбрал 7 канал.
Важно после выбора канала указать его в слоте в секвенсере. Секвенсер можете создавать до 64 слотов для хранения образцов и для каждого из них можно выбрать свой канал. В этом проекте нам нет нужды использовать больше одного слота.
PLL
Данный компонент мы еще не обсуждали ранее. На русском он звучит как ФАПЧ - Фазовая Автоподстройка Частоты. В нашем проекте он помогает нам сгенерировать сигнал с частотой 2 МГц для тактирования нашего АЦП.
Здесь надо указать частоту входного тактового сигнала. Мы будем использовать основной тактовый сигнал от осциллятора в 50 МГц.
Убираем галочку с areset
Остальное не трогаем и переходим на 3 часть. Ставим частоту выходного сигнала на 2 МГц и завершаем процесс настройки.
В версии Quartus Prime Lite Edition 23.1 у некоторых пользователей была проблема с PLL. А именно после определенной страницы у них вылетало с окна настройки модуля и они не могли добавить данное IP. В интернете два разных решения этой проблемы.
Исправляем баги
Первое это использование модуля с предыдущей версии. Инструкция по ссылке ниже.
Второе это установка патчей от Intel для исправления данной ошибки в самой программе.
https://www.intel.com/content/www/us/en/support/programmable/articles/000098457.html
Помимо этого у вас может появиться или уже быть еще один баг, когда вы будете способны настроить PLL, но после нажатия Finish, модуль не будет отображаться в Platform Designer и соответственно отсутствовать в проекте. Чтобы исправить этот баг следуем инструкции по ссылке ниже
mSGDMA
Поменяем пару настроек, выставим FIFO на пути данных на 1024 байтов чтобы не потерять данные. Maximum Transfer Length что означает максимальная длина передачи ставим на 8KB. Включаем Extended Feature Support, эта расширенные возможности DMA позволяющие делать разные манипуляции и операции при передаче данных. Нам это нужно для последовательного чтения/записи памяти при работе с кольцевым буфером.
FIFOED_UART
В качестве UART в данном проекте был задействован сторонний модуль, который является расширенной версии модуля предоставленной в Quartus Prime Lite. Прежде чем скомпилировать проект нужно добавить данный модуль вручную.
Ссылка на архив с модулем:
https://drive.google.com/file/d/1ayBqxPtSYAUMgunJB_L9qiTec6BIIxME/view?usp=sharing
После разархивирования в папке будет находится Word документ с названием “FIFOed_Avalon_UART_v13.1”. В нем находится инструкция по установке/интеграции модуля в Quartus Prime и NIOS II.
Настраиваем его следующим образом
TX FIFO нам нужен для буферизации данных при передаче чтобы не потерять их. Baud Rate выставлен на 921600 бод. Позже в третьей части объясню как мы пришли к этому значению.
После того как добавили его, нужно в колонке Export в строке external_connection кликнуть два раза по надписи “double click to export”. Этим действием мы позволяем вывести пины данного модуля для приема/передачи наружу, так как нам нужно соединить его с внешним последовательным портом.
Как добавили все компоненты, соедините их как на рисунке выше. Дальше нужно снова вернуться к NIOS II. Щелкаем по нему, справа появится окно с параметрами, переходим на вкладку Vectors и для Reset Vector Memory и Exception Vector Memory выбираем onchip_memory2_0.s1. Теперь мы настроили все компоненты, осталось их расположить правильно в памяти. Кликаем сверху на System -> Assign Base Addresses. На этом этапе снизу должны остаться лишь несколько предупреждений, их можно проигнорировать.
Снизу нажимаем на Generate HDL, чтобы сгенерировать код описывающий все наши соединения и настройки. В открывшемся окне в язык выбираем Verilog. Появится окно с предложением сохранить систему, сохраняем с таким же именем как и сам проект. Ждем генерацию, после завершения нажимаем Finish и возвращаемся на главную страницу.
После закрытия всплывет окно с предупреждением, его можно закрыть, там говорится о том, что наши сгенерированные файлы с кодом нужно добавить в файлы проекта прежде чем компилировать.
Слева в окне Project Navigator кликаем два раза на Files -> три точки -> папка с названием проекта -> synthesis -> *.qip. Закрываем. В этом файле хранится код описывающий логику всех компонентов и соединении между ними
Настройки
Код вроде бы есть, все добавили, что еще нужно? Не забываем, что мы работаем с железом и тут нужно настраивать пины и тайминги.
Сперва позаботимся о таймингах. Несмотря на то, что мы уже указали частоты, нам нужно снова прописать ограничения по частотам тактовых сигналов. Все это из-за того, что ранее мы их указывали чтобы система понимала какие будут частоты и смогла эффективно описать блоки в коде. Теперь же нам надо указать их в отдельном файле, чтобы система учитывала это при физическом расположении нашей всей логики внутри ПЛИС.
И так кликаем по File -> New. Выбираем Synopsys Design Constraints. В новом окне пишем следующие строчки
create_clock -name clk_clk -period 20.000 [get_ports {clk_clk}]
derive_pll_clocks
derive_clock_uncertainty
Тут мы обозначаем, что период главного тактового сигнала 20 нс. И что он подается с порта clk_clk. Вторая строчка делает такие же манипуляции для тактовых сигналов PLL. И третья строчка выполняет автоматический расчёт и установку неопределённости тактового сигнала (clock uncertainty).
Далее надо обозначить какую конфигурацию мы хотим использовать. Помним, что мы добавляли память и выделяли 16 кБ. Поэтому кликаем Assignments -> Device -> Device and Pin Options -> Configuration -> Configuration mode -> Single Uncompressed Image with Memory Initialization. Выбираем конфигурацию с инициализацией памяти.
Без memory initialization память остается пустой после загрузки, что приводит к ошибкам: Nios II не сможет загрузиться, так как его векторы сброса и исключений (reset/exception vectors) указывают на onchip_memory, а без инициализации там нет кода.
Теперь когда прописали ограничения по таймингу и настроили все, пришло время провести анализ нашей работы и посмотреть все ли в порядке. Нажимаем на иконку как на рисунке
И ждем, это займет некоторое время. После этого слева снизу в окне Tasks вы должны увидеть зеленую галочку у строки Analysis&Elaboration под Analysis&Synthesis.
Наш код про синтезирован и Quartus должен был вывести все нужные пины для назначения. Этим пинам надо присвоить физические провода на нашей отладочной плате. Кликаем Assignments -> Pin Planner. Откроется окно с схемой ПЛИС по середине. Нас интересную часть внизу со списком пинов.
Как видно на рисунку нас интересует лишь 4 пина. Clk для тактового сигнала, reset - для сброса, rxd - для приема данных в UART, txd - для передачи данных с UART. Как раз к пину txd мы и будем подключать последовательный порт.
Clk_clk обязательно назначаем на PIN_27 если используете плату как у меня, так как на нее приходит тактовый сигнал с осциллятора. В разных ПЛИС это может быть разный пин. Остальные пины можем повесить на любые свободные цифровые пины.
Важно выставить все пины на уровень 3.3V LVTTL. Это связано с тем, что отладочная плата использует банки питания I/O с напряжением 3.3 В.
Компиляция и программирование
Закрываем окно и нажимаем на Start Compilation для компиляции нашего проекта. Ждем пока галочки на всех строках до Timing Analysis включительно в окне Tasks.
Скомпилировали проект, теперь нужно его загрузить в сам ПЛИС. Нажимаем на иконку для программирования ПЛИС. Нажимаем на Hardware Setup, выбираем там программатор обычно подписан как USB Blaster и закрываем.
Так как нам требуется записать конфигурацию только в ПЛИС, не затрагивая её встроенную конфигурационную память. Выбираем в качестве файла конфигурации файл с расширением *.sof. Он должен быть автоматически уже выбран. Если его нет, добавляем его с помощью Add File. Cтавим галочку на Program/Configure.
Нажимаем старт и ждем пока ПЛИС прошьется.
После прошивки выйдет окно с обратным отсчетом в 1 час. Не пугаемся, это из за NIOS II, который не доступен без лицензии для использования без ограничений.
Заключение
На этом мы завершаем настройку аппаратной платформы для передачи данных с АЦП ПЛИС Intel MAX 10 на ПК. Мы успешно собрали систему в Platform Designer, настроили компоненты, исправили потенциальные ошибки, прописали ограничения по таймингу, скомпилировали проект и загрузили его в ПЛИС. Теперь устройство готово к работе: АЦП оцифровывает сигналы, DMA обеспечивает эффективную передачу, а UART готов к обмену данными с компьютером. В третьей части мы перейдем к программной реализации на Nios II, включая код для чтения данных из АЦП, управление кольцевым буфером и отправку информации на ПК.
Список литературы
- Intel. (2017, July 6). Intel® MAX® 10 analog to digital converter user guide (Document ID: UG-M10ADC). Intel Corporation. https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug-m10adc.pdf
- Intel Corporation. (2023, August 15). Embedded peripherals IP user guide (Document ID: UG-01085; Document No. 683130). https://www.intel.com/content/www/us/en/docs/programmable/683130
- Intel. (2024, February 21). Intel® Quartus® Prime Standard Edition User Guide: Timing Analyzer (Version 18.1 Public, ID 683068). https://www.intel.com/content/www/us/en/docs/programmable/683068/18-1/timing-analysis-introduction.html
- Intel Corporation. (2023, January 8). Intel® MAX® 10 FPGA (10M08S, 144-EQFP) evaluation kit user guide (Document No. 812857). https://www.intel.com/content/www/us/en/docs/programmable/812857