Часть 0 - покупаем, паяем, ставим драйвера и софт Часть 1 - что это вообще за зверь? Часть 2 - наша первая схема! Часть 3 - кнопочки и лампочки Часть 4 - делитель частоты Часть 5 - подавление дребезга кнопки Часть 6 - заканчиваем кнопочки и лампочки Часть 7 - счетчики и жаба Часть 8 - передатчик UART Часть 9 - Hello, wolf! Часть 'hA - приёмник UART Часть 'hB - UART и жаба Часть 'hC - полудуплексный UART. Часть 'hD - МКО (МКИО, Mil-Std 1553) для бедных, введение.Часть 'hE - приёмопередатчик МКО "из подручных материалов" (в процессе)
Часть 'hF - модуль передатчика МКО Часть 'h10 - передатчик сообщений МКО Часть 'h20 - работа с АЦП ADC124s051 Часть 'h21 - преобразование двоичного кода в двоично-десятичный (BCD) Часть 'h22 - Bin2Bcd с последовательной выдачей данных Часть 'h23 - перемножитель беззнаковых чисел с округлением Часть 'h24 - перемножитель беззнаковых чисел, реализация Часть 'h25 - передаём показания АЦП на компьютер Часть 'h26 - работа над ошибками (быстрый UART) Часть 'h27 - PNG и коды коррекции ошибок CRC32 Часть 'h28 - передатчик изображения PNG Часть 'h29 - принимаем с ПЛИС изображение PNG Часть 'h2A - ZLIB и коды коррекции ошибок Adler32 Часть 'h2B - ускоряем Adler32 Часть 'h2C - формирователь потока ZlibЧасть 'h2D - передаём сгенерированное PNG-изображение
Часть 'h2E - делим отрезок на равные части Часть 'h2F - знаковые умножители, тысячи их! Часть 'h30 - вычислитель множества Мандельброта Часть 'h31 - ускоренные сумматоры Часть 'h32 - ускоренные счётчики (делаем часы) Часть 'h33 - ускоряем ВСЁ Часть 'h34 - ускоренные перемножители Часть 'h35 - умножители совсем просто Часть 'h36 - уравновешенный четверичный умножитель Соединяем модули, которые мы мучали чуть ранее:
Сохраняем эту схему как отдельный модуль, ZLIB_testbench (так уж получилось), и остаётся лишь поставить подавитель дребезга контактов, чтобы нажатие кнопки запускало процесс:
Прошиваем, и внезапно с первого же раза оно начинает работать:
Если эти данные сохранить в .png, они вполне себе открываются как картинка:
Да, очень простая картинка, 48х1, в градациях серого, простое чередование чёрного и белого - но надо же с чего-то начинать!
Вот исходное содержимое памяти ПЛИС:
Заголовок PNG и IHDR мы вписали сюда "ручками" (не считая CRC32, которых здесь быть не должно - они сгенерятся на этапе отправки по UART), для IDAT мы заранее вписали его размер (когда картинка несжатая, это можно посчитать заранее), само имя блока IDAT, а вот содержимое заполнили нулями. CRC32 тоже отсутствует, разумеется. Наконец, в конце "файла" мы задаём размер блока IEND (0 байт, иначе и быть не может) и вписываем его имя: IEND. Затем - байт FF, чтобы наш передатчик сообразил, что пора остановиться.
Всё остальное генерится на ходу - сама картинка, чудеса абстрактного искусства, а также все "обёртки" для неё - блоки Deflate, заголовок и контрольная сумма Zlib, ну и CRC-коды для блоков (chunks) PNG.
Происходит это как-то так:
Зная, что передача изображения по UART - процесс гораздо более медленный, чем генерация изображения (или его оцифровка) со скоростью 20 МБайт/с, мы запустили оба процесса одновременно, зная, что пока мы дойдём до блока IDAT, там уже будет лежать готовое изображение.
И предчувствия нас не обманули - хотя на этой симуляции мы выставили частоту UART 16 МБит/с (реальный UART вроде бы шибко быстрее 921,6 кбит/с не бывает), мы успели передать лишь 4 байта заголовка, когда наша картинка была сформирована :)
Вторую неделю у меня непреодолимое желание написать на ПЛИС генератор множества Мандельброта. Это научит нас, как формировать здоровенные изображения (как 1920х1080) при ограничении памяти в 12 кбайт, а также - как работать с комплексными числами на ПЛИС, а где комплексные числа - там и до кватернионов недалеко!