Однажды мне прилетела задача реализовать DMR на ПЛИС. Опустившись на дно интернета, я нашел лишь мануал ETSI и пару примеров по генерации кода – с этого начался мой тернистый путь изучения данной тематики. Недавно наткнулся на мем, и тут нахлынули воспоминания. Решил, дабы сэкономить время людей, которые столкнутся с чем-то подобным, поделиться подробным гайдом таких задач с примерами реализации.
Пока писал вступление, совсем забыл про то, ради чего мы здесь, естественно, ради мемов и крутых инженерных фишек!
![](https://habrastorage.org/getpro/habr/upload_files/b05/11e/172/b0511e172aaa9d32ef42a1a93fe7aa9d.png)
FPGA по-русски – программируемые пользователем вентильные матрицы. ПЛИС – программируемые логические интегральные схемы.
Главная разница между ПЛИС и FPGA – это то, что первое по сути класс устройств, а второе – вид устройств.
Для чего они нужны и что с ними делать?
ПЛИС имеют широкий спектр применения: их используют в цифровой обработке сигнала, для передачи данных на высокой скорости, для криптографических операций, для систем защиты информации или в качестве прототипов для будущих СБИС (ASIC).
Алгоритмы под ПЛИС реализуются на языках описания аппаратуры, например на Verilog HDL. Так причем же здесь MATLAB?
MATLAB имеет возможность генерации кода HDL, а что более интересно, прямо из него можно получить готовый проект под Vivado и выполнить его синтез и имплементацию уже там. О том как сотворить это чудо, я хочу поговорить с вами далее в статье.
Я расписал подробный гайд, чтобы упростить работу инженеров, проектирующих на ПЛИС. Цель статьи – описание процесса разработки приемопередатчика на ПЛИС по стандарту цифровой подвижной радиосвязи (DMR). Проект будет реализован под отладочную плату ZedBoard Zynq-7000. Для реализации проекта используется подход модельно-ориентированного проектирования (МОП). Его структура отображена на рисунке 1, все достаточно просто: есть приемные и передающие тракты цифровой обработки, которые в итоге мы реализуем на ПЛИС.
![Рис. 1. Общая схема проекта Рис. 1. Общая схема проекта](https://habrastorage.org/getpro/habr/upload_files/378/544/3b0/3785443b0d72dd9234565ffb400ac6e6.png)
Эту задачу можно образно разделить на три этапа:
Первый этап – это разработка системной модели. Он позволяет реализовать модель, на основе которой в дальнейшем можно выполнить верификацию разрабатываемых алгоритмов на отладочных или макетных платах за счет взаимодействия с реальным оборудованием.
Второй этап – это трансформация модели под генерацию HDL кода. Основными задачами этапа являются перевод всех применяемых в проекте типов данных в фиксированную точку и изменение алгоритмов, не поддерживающих генерацию кода HDL.
Третий этап – реализация полученного HDL кода на ПЛИС. Здесь выполняется работа со сгенерированным кодом и Vivado. Главная задача – успешные синтез, имплементация проекта и взаимодействие с полученными файлами прошивки и управляющих программ.
Системная модель
На рисунке 2 представлена системная модель приемопередатчика DMR. Эта модель реализована при помощи Communications System Toolbox, работает в «реальном времени» и позволяет захватывать сигнал с рации и передавать записанные данные на рацию. Также она реализует виртуальную рацию. Для передачи радиосигнала используется ADALM-PlutoSDR. Это отладочная плата на основе трансивера AD9363 и FPGA Xilinx® Zynq Z-7010.
На данном этапе разработки мы получаем возможность отладки приемопередатчика, учитывая факт использования стандартных библиотечных блоков. Мы можем в максимально короткие сроки произвести верификацию разработанных алгоритмов.
![Рис. 2. Системная модель Рис. 2. Системная модель](https://habrastorage.org/getpro/habr/upload_files/d58/198/9d4/d581989d4ce3f2307f7f3125f7ac1aa4.png)
В этой статье я не хочу затрагивать анализ системной модели и тратить ваше и свое время на разбор каждого конкретного блока и обзор его функционала. Если кому-то интересен этот вопрос, напишите об этом – я сделаю обзорную статью по каждому блоку и разберу аспекты перевода модели из системной в модель под генерацию HDL кода в деталях.
Единственные блоки, которые я затрону более подробно, это «ADALM-Pluto Radio Transmitter», который позволяет использовать Pluto как передатчик сигнала в эфир, и «ADALM-Pluto Radio Receiver», который в свою очередь принимает сигнал. В данной модели многие алгоритмы написаны MATLAB скриптами, поэтому я думаю, что в дальнейшем найдутся люди, которым будет интересно узнать, как на практике реализуется кадровая синхронизация, перемежители или как формируются заголовки пакетов. Честно говоря, я сам надеюсь на продолжение нашего с вами общения на эту тему.
¯\_(ツ)_/¯
На рисунках 3 и 4 я показал работу системной модели и взаимодействие с рацией и Pluto. В этой реализации на приемной и передающей стороне есть задержка, равная длине накапливаемого буфера. На 3 рисунке показана работа передатчика. Как вы видите, рация улавливает сигнал и декодирует адресата, а на рисунке 4 показана работа приемника. На графике MS видны пики корреляции, также можно заметить, что сигнальные конструкции определяются в тот момент, когда я начинаю передачу сигнала с рации, а на графике Error показан сдвиг символьной синхронизации.
![Рис. 3. Работа передатчика Рис. 3. Работа передатчика](https://habrastorage.org/getpro/habr/upload_files/83c/deb/fa8/83cdebfa888e54c42c2e8ce0ca59dbce.gif)
![Рис. 4. Работа приемника Рис. 4. Работа приемника](https://habrastorage.org/getpro/habr/upload_files/60c/f1e/fe9/60cf1efe92dbb9a32a1f37fc31ddc490.gif)
Модель для генерации HDL кода. Реализация на ПЛИС.
Перейдем к HDL реализации. Что это и зачем оно нужно, мы уже разобрали, предлагаю взглянуть на рисунок 5: на нем представлена HDL модель, построенная на основе системной модели. Отличием от системной модели является использование блоков, поддерживающих генерацию HDL кода, и перевод всего тракта цифровой обработки в фиксированную точку. Для удобства отладки на плате для приемной части реализована возможность переключения режимов, за счет чего у нас есть возможность отследить все изменения данных в процессе обработки. Для передатчика этот подход не использовался, так как он имеет достаточно простую реализацию, и с ним изначально не возникало вопросов.
![Рис. 5. HDL модель Рис. 5. HDL модель](https://habrastorage.org/getpro/habr/upload_files/2be/309/fbb/2be309fbb784ef71c7ba8ae426c561fa.png)
В этой части я хочу акцентировать внимание на процессе генерации HDL кода из модели, а не на самой модели и ее архитектурных изысках. Первым этапом является подключения САПР Vivado от Xilinx к MATLAB, ниже показан MATLAB скрипт для подключения.
![Рис. 6. Подключение Vivado Рис. 6. Подключение Vivado](https://habrastorage.org/getpro/habr/upload_files/21b/671/290/21b671290f6c2d468e1a0bdc564ae085.png)
Чтобы сгенерировать код, наверное нам надо задать какие-то настройки, условия под наш проект, но это не точно.)
Дак о каких настройках я говорю и где они находятся?
Откроем HDL Workflow Adviser. Там мы увидим эти настройки, на рисунках 7, 9-11 они также показаны и объяснены. На рисунке 7 настройки референса-проекта, здесь мы выбираем плату, под которую будем генерировать код, в нашем случае это ZedBoard + FMCOMMS, сама плата показана на рисунке 8.
![Рис. 7. Настройки референса Рис. 7. Настройки референса](https://habrastorage.org/getpro/habr/upload_files/90f/b15/fc9/90fb15fc97cb60b9836988cd9cc43bbd.png)
![Рис. 8. Плата ZedBoard + FMCOMMS Рис. 8. Плата ZedBoard + FMCOMMS](https://habrastorage.org/getpro/habr/upload_files/3a1/380/33d/3a138033de6c9a35416d4618779c3877.png)
На рисунке 9 показаны настройки ядра прошивки, в данном случае мы создаем ядро приемника и передатчика.
![Рис. 9. Настройки ядра Рис. 9. Настройки ядра](https://habrastorage.org/getpro/habr/upload_files/81d/fad/9e0/81dfad9e0404530e89f1492c35751360.png)
![Рис. 10. Настройки частоты Рис. 10. Настройки частоты](https://habrastorage.org/getpro/habr/upload_files/873/1ba/990/8731ba990ab2b435216dcc93b4e417d7.png)
На рисунке 11 представлены настройки входных и выходных портов IP-ядра, а также размерности этих портов и их размерности в битах.
![Рис. 11. Настройки портов Рис. 11. Настройки портов](https://habrastorage.org/getpro/habr/upload_files/dcf/be1/1ea/dcfbe11eac5b4ef9522e8151d56ce516.png)
После того как мы настроили параметры генерации кода, переходим в пункт 4.1 и создаем проект Vivado с нашим IP-ядром, после чего уже в самой Vivado создаем бинарный файл прошивки (вкладка «Generate Bitstream»). На самом деле не думаю, что на данном этапе хоть у кого-то с первого раза выполнилась имплементация, обычно это всегда несколько дней работы, прежде чем у вас нормально сойдутся тайминги, так что не судите строго за отсутствие описания этой боли в статье. Если интересно, то могу с вами обсудить это в комментариях.)))))
После создание бинарного файла мы получаем полноценную прошивку под ПЛИС, которая выполняет заложенный нами функционал. Залить прошивку на ПЛИС можно несколькими способами: либо использовать загрузчик Vivado (на рисунке 12 показан процесс открытия таргета), либо можно вручную заменить стандартный файл system.bit на сгенерированный system_top.bit, естественно переименовав его в system.bit.
![Рис. 12. Открытие таргета Рис. 12. Открытие таргета](https://habrastorage.org/getpro/habr/upload_files/550/eb3/eec/550eb3eec17d8b79adaaea8bd9fd4a3b.png)
После загрузки прошивки необходимо загрузить управляющую программу. Чувствую назревший вопрос: откуда взялась управляющая программа и почему мы раньше о ней не говорили?
Погодите-погодите, я сам только что о ней вспомнил. Управляющая программа позволяет реализовывать управление интерфейсами на отладочной плате.
В модели управляющей программы мы объявляем AXI-порт как управляющий. За счет него мы переключаем различные режимы работы приемника, также мы определяем, что по протоколу UDP выполняется прием и передача данных на ПК, компьютер я использую в этой связке для трансляции аудиосигнала от микрофона и к акустическому динамику. И здесь же описана взаимосвязь кристалла ПЛИС с FMCOMMS (блоки AD936x). Сама модель, о которой я так много сейчас сказал, показана на рисунке 13.
![Рис. 13. Модель управляющей программы Рис. 13. Модель управляющей программы](https://habrastorage.org/getpro/habr/upload_files/74e/529/c54/74e529c547d899f6e4f3c0de71525dfa.png)
Из этой модели при помощи комбинации клавиш Ctrl+B (люблю горячие клавиши, не могу) мы генерируем управляющую программу на языке C и файл *.elf , который дальше можно либо заранее загрузить на SD-карточку отладочной платы и вызывать из командной строки, либо каждый раз загружать ее через командную строку. Для второго варианта используется набор команд, показанный на рисунке 14, первая команда отправляет наш файл по IP платы в корень файловой системы, а дальше уже из-под отладки мы его запускаем.
![Рис. 14. Загрузка управляющей программы Рис. 14. Загрузка управляющей программы](https://habrastorage.org/getpro/habr/upload_files/698/fcc/9a8/698fcc9a84dc10225db4a62bc30ff4d8.png)
После вызова управляющей программы мы получаем возможность уже с ПК захватывать и передавать данные. На рисунке 15 показана модель, которую я для этого использовал.
![Рис. 15. Модель захвата и передачи потока по UDP Рис. 15. Модель захвата и передачи потока по UDP](https://habrastorage.org/getpro/habr/upload_files/53b/99a/21c/53b99a21c2b301a1378345e8c3aa13df.png)
Подведем итоги: на мой взгляд я довольно подробно раскрыл методологию МОП, применяемую нами в проектах. Надеюсь, статья была вам интересна и полезна, жду ваших вопросов, критики, буду рад любому фидбеку.))))