Генерация видео математической функцией на ПЛИС

Здравствуйте!
В этой статье я хочу рассказать о своём опыте изучения разработки на ПЛИС и познакомить со своим проектом — генератором видео по формуле.



Цель поста


Я программист С++, профессионально занимаюсь разработкой и сопровождением системного софта. Около двух лет тому назад у меня возникло желание разнообразить свой опыт за счёт изучения схемотехники, точнее программирования ПЛИС с использованием языка Verilog. Далее я расскажу, что из этого вышло.

Цель работы


Направить вычислительную мощь ПЛИС на нужды генеративного искусства: порождать в реальном времени потоковое видео по сложной формуле в высоком разрешении, с высоким фрейм-рейтом. В качестве фронтэнда выбран IBNIZ, — язык описания формул для генерации демо, разработанный камрадом viznut в качестве виртуальной платформы для демосцены. Ранее я реализовывал на ПЛИС, на платформе "Марсоход", другую его находку.

Теория


Схемотехника и программирование

По моему мнению, схемотехника для программиста — интересная смежная область для освоения. Описание аппаратуры с одной стороны, во многом схоже с написанием программы что облегчает вхождение, а с другой определяет совершенно иной путь решения прикладной задачи, дает инженеру новые возможности и опыт. Обычно мы пишем программу, которая работает последовательно, строка за строкой. Поучительно попробовать написать программу, все части которой работают одновременно.

Итак, это интересно, но подумаем о целесообразности. Как выбрать задачу, решение которой на ПЛИС будет оправдано? Во-первых, в некоторых случаях схемное решение оказывается изящнее и надежнее программного. К примеру программировал я сумо-бот на микроконтроллере, сделал ему простейший голос — на один из выводов вешается динамик, сигнал на нем меняется со звуковой частотой. Всё просто — цикл, внутри переключение и задержка. Но робот на время гудка останавливался. Чтобы работало одновременно, нужна многозадачность, надо писать диспетчер, с ростом сложности превращающийся в ОС реального времени. В решении на ПЛИС же, не приходится делить ресурс центрального вычислителя, подсистема управления динамиком отъест некоторый объём ПЛИС-ы и далее никому мешать не будет.

Во-вторых, специализированная схема может иметь много большую производительность, чем программное решение. Для попиксельной обработки видеопотока 1280х1024@60Гц в реальном времени понадобится обрабатывать 80млн. точек в секунду, тут даже на мощном процессоре много не успеешь, схемное решение даст возможности куда богаче (при определенных ограничениях на алгоритм, — обработка должна быть стереотипной, ветвления нежелательны).

HDL

Для программирования ПЛИС можно использовать специальные языки, такие как Verilog и VHDL. Они на мой взгляд, значительно удобнее, чем схемный редактор, но человека привыкшего к высокоуровневому программированию разочаровывают. Мой опыт касается (System)Verilog-а, но насколько мне известно, VHDL отличается мало. Схема описывается на уровне регистровых передач (RTL), что вроде бы и естественно, но описание разделяется на две части: комбинационную схему и синхронную логику. Вот есть к примеру оператор цикла, описываю деление столбиком и обнаруживаю, что внутри тела цикла комбинационную часть описывать нельзя, только синхронную. Есть макросы, язык макросов верилога это С-шный препроцессор с точностью до замены '#' на '`'. Ну и у модуля могут быть числовые параметры (времени компиляции), вот пожалуй и все средства обобщенного программирования на нашем вооружении.

RTL, синхронные схемы

В подавляющем большинстве случаев разработчики электронных схем ограничиваются синхронными схемами. Это значит, что есть общий тактовый сигнал (clock, клок), и описание делится на множество регистров и комбинационную схему, определяющую, как значение регистра на следующем такте зависит от значения регистров на предыдущем. Комбинационная схема не обладает собственным состоянием. Минус — некоторое ограничение свободы, к примеру я встречал описание реализации генератора случайных чисел с помощью асинхронной схемы. Вообще, архитектура ПЛИС расчитана на работу только с синхронными схемами, а такие принципиально асинхронные модули как ФАПЧ(PLL) реализуются как отдельные аппаратные блоки.

ФАПЧ позволяет создавать несколько «клоковых доменов», например отделить вычислительный модуль от видеоадаптера, так чтобы у каждого была своя частота. К асинхронным схемам как я понял, схемотехники относятся примерно как программисты к самомодифицирующемуся коду.

Частота на которой сможет работать схема зависит, главным образом, от самой схемы, но и тип ПЛИС, её «класс скрости» играет роль. Смысл примерно такой — за один такт сигнал должен успеть пробежать по самому длинному пути вашей схемы и переключить целевой регистр. Когда я превышал частоту для описываемого решения, на экране появлялись характерные сопли.

Железо




Проект подготовлен для четырёх отладочных плат, Terasic DE0, Terasic DE2-115, Terasic DE0-nano с дисплеем LTM вместо VGA, а также Марсоход II. У Terasic-а отличное железо, с софтом не так радужно. Документация и примеры-образцы есть, но их не всегда достаточно. Например, уже научившись прошивать непосредственно ПЛИС, я убил день на то, чтобы загнать ту же прошивку в конфигурационную память(eeprom) (чтобы данная прошивка загружалась при включении платы). Еще проблема, что в России их трудно найти по разумной цене, а тайваньцы не отправляют обычной почтой. У Марсохода II функционал победнее, но гораздо лучше с описаниями и поддержкой, в статьях с их сайта я часто находил решение очередных своих трудностей. Моей первой отладочной платой был первый Марсоход, он слабее по возможностям но и проще в освоении выше названных, на попробовать самое то.

Инструментарий


Поскольку я использовал отладочные платы на базе ALTERA, то в качестве среды разработки выступал QUARTUS, бесплатный web edition. QUARTUS оставляет неоднозначное впечатление. Главная претензия — очень неинтуитивен и плохо документирован, туториалы никакие. В то же время, свои обязанности интегрированной среды разработки он выполняет. Это типичная ситуация при работе с ПЛИС — работать работает, но удобства (и в том числе лёгкость освоения) на последнем месте, энтузиастов тут как правило не ждут.

Реализация




Итак, генерируем видео по функции. ibniz, а точнее его «линейное» подмножество будет служить спецификацией. Польза в том, что во-первых можно позаимствовать несколько готовых демо, а во-вторых, можно сравнить результат работы с референсной софтовой реализацией что весьма ценно, поскольку отладка схемы куда сложнее чем отладка программы.

Работа в основном разделилась на две части, — инфраструктуру, подготавливающую данные и выводящую результат на дисплей и на ядро, реализующее отдельные элементарные функции ibniz.

Основной компонент инфраструктуры — VGA адаптер. Обычный подход — использовать буфер(ы) фрейма, вовлекает в проект внешнюю память (внутренней мало). Это усложнило бы проект и лишило возможности использовать память для чего-нибудь еще. Поэтому ядро работает синхронно с VGA, цвет пикселя вычисляется и тот сразу рисуется.

Недостатки:
Ядру навязана частота VGA
Пока VGA отрабатывает «невидимые куски экрана» ядро простаивает.
Жёсткое реальное время, на каждый такт надо отдать очередной пиксел, сэкономить там, чтобы потом потратить здесь не получится.
Команды ibniz прямой записи в буфер фрейма нереализуемы, также как и операторы перехода.

Преимущества:
Простота реализации
Можно использовать ширину канала, которую память бы не потянула.
Память сохранена для чего-нибудь еще (разделение ресурса тут вряд-ли было бы возможно).
Низкая латентность, тут от неё толку мало, а вот с сигналом от камеры выходит красиво, но это уже другой проект.
Тру 60Hz видео радует глаз.

Ядро



Ядро проекта составляют математические функции — sin, atan2, log, sqrt, а также деление; реализовал их сам, алгоритмами «цифра за цифрой» (CORDIC), благо был опыт программной реализации. Это итеративные алгоритмы, количество итераций пропорционально разрядности аргументов. Итерация у меня делается за такт, то есть от поступления аргументов на вход до выхода результата проходит количество тактов, равное разрядности чисел, для ibniz это 32. Как это примерить с необходимостью считать точку за такт? С помощью конвееризации, вычислительный блок состоит из 32-х (аппаратных) ступеней. Остаётся задержка, причём для последовательности блоков задержка накапливается. Бороться с ней несложно, но я для наглядности оставил, в результате изображение смещено вправо, а по левому краю видна артефактная полоса, ширина которой соответствует общей глубине конвеера конкретного примера.

Красивости




О генеративном искусстве на Хабре уже писали например тут, далее мои 5коп. Когда начинаешь генерировать компьютером картинки, по началу стремишься к необычному,- парадоксальным формам, ярким до кислотности краскам. Однако, такие «произведения» быстро надоедают. Интересная вещь — чтобы увеличить разнообразие приходится накладывать ограничения. «Случайная» картинка выглядит плоской, но можно добавить ощущение объёма, натянув её на некую форму. В демо «Юпитер» промежуточная картинка-текстура накладывается на сферу. Для этого просто используется преобразование координат от декартовых к сферическим также, как описано в этой статье. Ощущение объёма усиливается за счёт освещения, а также движения, см. демо с четырьмя кругами-сферами.

Итог



Итак, стоит ли программисту лезть в схемотехнику? Только при условии серьёзных намерений, надо хотя бы точно знать цель, поскольку дело это энергозатратное, что обусловлено работой на низком уровне, менее совершенными средствами разработки и менее очевидной логикой работы программы. На другой чаше весов — новые возможности и опыт. Я своим опытом вполне удовлетворён, кроме описанного проекта я ещё сделал генератор процедурной музыки, MIDI-синтезатор, фильтр сигнала от видеокамеры.
Сейчас у меня на стадии обдумывания и написания программной модели гораздо более серьёзный проект, — ненейманновский компьютер на базе комбинаторной логики. Главная идея, — на статическом большом регулярном графе, зашитом в железо живёт динамическое дерево функциональной программы, при этом ветви дерева эволюционируют по возможности одновременно. Узлы максимально простые, умеют только применять комбинаторы; целые числа только в виде нумералов Чёрча. Преимуществом должно стать массовое выполнение простых символьных операций в чистом функциональном стиле. Может быть, что-то вроде разбора регулярных выражений или логического вывода. Конечно, на подавляющем большинстве практических задач традиционную архитектуру не обогнать, но если вдруг найдётся хоть одна подходящая область, глядишь, и до кремния дойдём. Ну или по крайней мере мере появится архитектура с unlambda в качестве языка ассемблера:

```s``s``sii`ki
`k.*``s``s`ks
``s`k`s`ks``s``s`ks``s`k`s`kr``s`k`sikk
`k``s`ksk
Поделиться публикацией

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 27

    +3
    Открыл видео на весь экран, присмотрелся и на 0:52 секунде словил переполнение буфера ушел в баг мод.

    /теперь хочу на новый год плюшевого мишку, верю в деда мороза, заново обучился печатать на клавиатуре, водить по столу мышку, хочу в школу, жду выхода новой сеги мега драйв/

    Как вернуться обратно и стоит ли вообще это делать?
      +2
      Глубина-глубина, я не твой… Отпусти меня, глубина…
        +2
        Дайверы на хабре?
          –2
          Да, совсем забыл про главное. Слава Гипножабе!
        +1
        Зря вы на квартус наговариваете, по-моему. Вот хотя бы ресурс, где человек выкладывает самостоятельно переведенную документацию на это ПО. Слышать про него «неинтуитивен», тоже довольно странно. Я в свое время начинал работу С ПЛИС-ами тоже на квартусе, ну так вот я понял насколько в нем удобно сделана работа с симуляцией только когда перешел на Xilinx. Внезапно оказалось что чтобы создать тестбенч и подать тестовые воздействия, нужно написать отдельный модуль. В квартусе все решалось рисованием вэйвов в графическом интерфейсе мышкой… Сейчас работаю с профессиональными тулами irun и vcs… короче, мне вот наоборот кажется, что квартус создавали именно для энтузиастов и не очень опытных RTL-разработчиков
          +1
          По-моему тестбенч в виде отдельного модуля это хорошо и правильно. Хотя бы потому, что любой человек может взять ваш модуль и протестировать его без квартуса.
            0
            Полностью с вами согласен, именно поэтому я и считаю, что квартус — это хороший вариант именно для вхождения в тему, для начинающих. Да и квартус, кстати, по-моему сам генерит тесбенчи по нарисованным вами вэйвам… Так что отдельный модуль где-то в проекте должен присутствовать…
            +1
            Тоже не возникало проблем с Квартусом, да и с заливкой прошивки в DE1 проблем не было. Хотя конечно по сравнению с разными VS и прочим кажется сложней но это ИМХО из за не понимания с чем имеешь дело и что к чему относитcя, потом становится всё понятно.
              +1
              Так я не обвиняю собственно Quartus или verilog, в конце концов, всё что тут показано, сделано с их помощью. Я хочу сказать, что вся экосистема схемотехники менее дружелюбна. И дело тут не только в специфике работы железа, например, хорошо написанная функция на С++ документирует саму себя, а когда смотришь на исходник на HDL взгляд теряется в служебных конструкциях. И я считаю, что более удобные и простые в освоении средства описания вызовут прорыв в разработке железа, в том числе, сделав её демократичнее.
              0
              По сравнению с другими CAD-ами очень может быть, но не по сравнению со скажем, MS Visual Studio. Я, конечно, привык к последней, но и с квартусом я уже два года работаю, так в нём я тропинку себе протоптал и не схожу с неё. Потому как шаг в сторону требует непонятных ритуалов. Вот вам Model Sim удобен, я к нему тоже было приноровился, а в очередной версии квартус его вынесли отдельно, и каждый чих в отладке превратился в головную боль. С тех пор отлаживаюсь через VGA (тоже плохо, проект перекомпилировать приходится). Можете с этим не соглашаться, но одна из основных посылок моей статьи, — схемотехника нуждается в более удобном инструментарии.
              0
              У меня вопрос касательно CORDIC. Сам недавно его сделал для sin&cos, но столкнулся с несколькими проблемами. Во-первых, мне пришлось считать все углы в первой четверти и потом их «вращать» на 90, 180, 270 градусов, потому что случались переполнения из-за арифметического сдвига отрицательного числа, например -1 >>> 10 = -1. Проблему можно было бы решить, уменьшив множитель cordic gain, но это был бы хак. Причем моя реализация на си и на verilog вели себя одинаково плохо. Во-вторых меня интересует погрешность в нуле для синуса, опять же из-за арифметического сдвига отрицательного числа эталонный нуль не получается, а получается "-6", в остальных точках дельта достигает так же пикового значения в 6 по модулю.
              image
              Как у Вас обстоят дела с подобными проблемами? ЗЫ слова 16 бит, 15 итераций на точку, конвеер
                0
                Прошу прощения что влазию в диалог, я никогда не работал с CORDIC. Хочу поинтересоваться, чем этот метод лучше использования формулы Эйлера? Я просто не вижу на первый взгляд каких-то принципиальных ограничений в реализации вычислений с комплексными числами на verilog-e. Кстати и на opencores даже есть уже готовый модуль комплексной арифметики
                  0
                  Метод CORDIC использует только сдвиги и сложения, без умножений.
                    0
                    Совершенно верно, и когда в ПЛИС-е хватает встроенных умножителей, лучше использовать их.
                      0
                      А ещё лучше использовать пзу, в которой будет таблица брадиса. Стабильно 1 такт и никаких вычислений. Наш спутник буран использовал такую оптимизацию. Хотя на сегодняшних мощностях может уже и не актуально.
                  0
                  Знакомая картина. Рекомендую посмотреть сигнал первой итерации потом второй и т.д.
                  0
                  А какую функцию/алгоритм Вы использовали для получения изображения, как на картинке?
                  0
                  А вот к этому не присматривались? habrahabr.ru/post/133291/
                  144 ядра, нетактируемый (асинхронный) forth-процессор, $20.
                    0
                    Да, очень интересная архитектура, надо будет почитать. Хотя я пока не представляю, как можно было бы дерево комбинаторной программы разложить на такой структуре, а потом поддерживать. На двухстековой машине можно довольно изящно выполнять аппликативную программу, был у нас даже такой проект в аспирантуре. Но разнести её на распределённую сеть весьма нетривиально.
                    0
                    Интересный язык программирования. Интересна плис. Интересно, имеет ли ПЛИС преимущество, если использовать её в качестве видеоадаптера?
                      0
                      Это не язык программирования, а язык описания аппаратуры. ПЛИС без высокоскоростной DDR на периферии не имеет никаких преимуществ, если использовать её в качестве видеоадаптера.
                      +1
                      И сможет ли такой чип обойти GPU ядра по скорости выполнения операций с плавающей точкой?
                        0
                        Скорее нет чем да. Нужна очень специализированная задача, чтобы ПЛИС обогнала GPU. За пределами вариаций того, что я продемонстрировал в данной статье, даже в голову ничего особенно не приходит. Разве что вы захотите чего-то странного, типа 128-битной плавучки.
                        0
                        Странно, что вы ссылаетесь на viznut'а и демосцену, но совсем не упомянули lft, который сделал на fpga свой процессор с шейдерными ядрами, fm-синтезатором, написал тулчейн и херачит на это всём 3d графон: www.youtube.com/watch?v=h42neZVvoMY

                        В остальном, добро.
                          0
                          Ну так ведь там совсем другой подход. У меня ведь нет процессора, всё что есть это, говоря грубо, один пиксельный шейдер на весь экран. А именно viznut, потому что он предлагает язык, спецификацию, а значит я могу взять готовую демо, сделать реализацию и сравнить с программной.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое