Pull to refresh

Comments 21

Подскажите, как вы получаете 25,175 МГц из 50 (для VGA)? У меня получается только 50 * 74 / 147 = 25,170
Такие коэффициенты умножения и деления для Spartan3E задать нельзя, поэтому я 50МГц просто поделил на 2.
Дальше достаточно экспериментально подстроить значения «Front Porch» и «Back Porch» для вертикальной и горизонтальной синхронизации. Мне хватило увеличить значение back porch до 36 для вертикальной, и все заработало.
Если есть желающие поэкспериментировать на железе самостоятельно, как раз ищу покупателя отличной отладочной плате на Altera Cyclone II FPGA.
Кстати, если это она, то плата и в самом деле не плохая — 20 тысяч логических элементов в продаже встречаются значительно реже. Обычно 10 тысяч и меньше. Так что если цена устроит, то можно и взять — влезет много.

image
Я когда-то на первом курсе делал сапера для доса и на Паскале.
Тогда была проблема, когда игрок открывал пустую ячейку и рядом с ней не было ячеек с минами и их нужно было открыть все Я тогда это решил просто методом растекающейся воды (рекурсия и все дела)
а вы как решили??
Я задумывался об этой проблеме на начальной стадии игры, а потом уже стало как-то не до этого — не стал делать (алгоритм конкретно для ПЛИС тоже несложный: проверка смежных ячеек на ноль мин вокруг, но рекурсия тут не пройдет: все строится на мультиплексорах). Сложность прохождения игры при этом не возросла — просто для открытия всех ячеек потребуется больше времени.
Абсолютно ничего не понимаю в ПЛИС, но давным давно реализовывал это на паскале, позже пригодилось для реализации волнового алгоритма при поиске путей. Делал цикл, условие выхода — достигнуто максимальное число повторений либо переменная нулю. Перед входом в цикл переменной присваиваем единицу. В цикле соответственно первым делом обнуляем переменную. Дальше пробегаемся в этом же цикле по всем точкам хранящимся в массиве и проверяем граничащие с ними точки, если есть хоть одна равная нулю то добавляем ее во второй массив, отмечаем на карте как открытую и переменную для выхода из цикла делаем равную единице. После завершения проверки точек первый массив переписываем вторым и цикл повторяется.
В итоге когда вокруг не будет ни одной нулевой точки цикл завершится и останется еще раз по такому же принципу пробежаться чтобы открыть точки граничащие с нулевыми.
Для ПЛИС скорее всего тоже подойдет. Сложность — учесть все задержки сигналов в цикле, чтобы правильно сравнивать. Попробую реализовать это в будущем.
А почему не сделать потактную обработку?
Даже если это будет 100-1000 тактов — глаз этого не заметит)
Как я понимаю — чтобы сравнить соседние ячеки на «0» — нужно пройти полный цикл вывода «кадра» на дисплей (сравнение по pixel_x, pixel_y ±1 от текущего). Пусть все мины лежат на одной линии, например, на последней строке поля — ситуация, когда количество нулей максимально. Открываем ячейку в левом верхнем углу. Тогда циклов проверки на 0 (и заполнения кадра) будет все равно мало для того, чтобы глаз мог это заметить.
Пока писал комментарий, понял, что можно учесть факт того, что мы сравниваем не по pixel_x, pixel_y, а поля размером 8х16. Тогда можно вывести нулевые ячейки вообще за один цикл отображения кадра на дисплей.
Не знаю как реализуется в ПЛИС, но хорошей практикой является является использование так называемого видеобуфера. Т.е. Имеется два буфера, назовем А и Б. На экран постоянно, непрерывно и аппаратно производится вывод того что хранится в буфере А. Мы в свою очередь во время хода игрока, каких либо вычислениях выводим данные в буфер Б. После завершения всех вычислений, когда все готово для обновления картинки буферы А и Б переключаются местами и на экран выводится буфер Б.

Есть различные реализации, например с тремя буферами или самая простая когда по завершении вычисления буферы не переключаются, а в буфер А копируется буфер Б с обновленными данными. В любом случае суть в том чтобы не выводить на экран какие-то промежуточные результаты а обновлять картинку только после того как она полностью готова.
Звучит интересно.
Меня смущает только объем ресурсов, необходимый для этих буферов.
Для выбранной ПЛИС внутри имеется всего 20 ячеек памяти по 16Кб.
Для реализации одного буфера (чтобы хранить всю картинку сразу) нужно: (640*480)/2^14 ~ 18.75 блоков памяти, что уже впритык, т.к еще нужно место для реализации генератора символов.

Можно уменьшить объем памяти, используя много мультиплексоров и выводить то одну картинку, то другую. Я так сделал для закрашенных полей и содержимым в каждом поле. То есть при нажатии «Enter» у меня происходит ряд вычислений (в частности — меняется признак выбранной ячейки для маски 8х8), закрашенный прямоугольник убирается, а на его место встает число или мина.

Как вариант можно подключить внешнюю память и делать буферы на ней. На этой плате распаяно 64Мб SDRAM.
Необязательно иметь «классический» фреймбуфер, где всю картинку хранить.
Можно хранить только текущее состояние игры/поля, для этого 16Кб должно хватить)
[Либо даже на регистрах всё сделать, если совсем мало получается].
Дальше уже иметь модуль, который из такой памяти «состояния» игры отрисовывает картинку.

Можно даже сначала только одну память (один буфер) — с двумя портами: одна для чтения ( её читает VGA модуль, и отрисовывает что-то на экране ), другая для чтения и записи — её читает/пишет логика, которая обеспечивает игру. Да, в таком подходе, возможно в какой-то момент будет отрисовываться неправда, но, возможно, глаз это не заметит :)
Согласен. Я думаю, что так скорее всего и нужно делать для более динамичных игр типа «танчики», где нужно постоянно отрисовывать анимацию движения нескольких объектов одновременно.
К счастью, для сапёра все очень статично и событийно, поэтому придумывать сложных буферов не пришлось!)
Почитал внимательней. Предполагал что вывод графики осуществляется через какой-то встроенный в макетную плату видео контроллер а оказывается видеосигнал генерируется ПЛИСом. Преклоняюсь перед таким хардкором. Тогда да, в таком случае не стоит заморачиваться, в любом случае для какой-то более практической задачи будет проще добавить специализированную микросхему для вывода графики а не мучить ПЛИС.
Да, вроде ПЛИС не особо напрягается от такой задачи :)
А какую микросхему предлагаете использовать?
На ПЛИС контроллер VGA в проекте занял меньше всего места (обратите внимание на маленький прямоугольник на третьей картинке, где я показал объем занимаемых ресурсов для каждой части проекта). Так что реализация VGA дело пустяковое, я его вообще из своего старого проекта взял и никак не переделывал для новой задачи.
Самый смак — в конечном автомате для логики игры. :)
Наверное ошибаюсь, плис для меня черный ящик. Плюс от контроллера будет скорее в удобстве кода, и цены теоретически очень демократичные, я правда сужу по устройстве и ценам хоббийных OSD плат, камер, LCD дисплеев с контроллерами. При использовании МК видеоконтроллер нам дает бонус в виде возможности обновления картинки в любой удобный для нас момент времени не задумываясь о сложных синхронизациях и т.д., Грубо говоря у нас дисплей 50 кадров в секунду чересстрочной развертки. Нам не надо задумываться о выводе одной половины строк, другой половины строк, синхронизации всего этого дела, мы просто в любой удобный момент для нас посылаем в контроллер например для текстового режима матрицу 80х25 или даже ее изменившуюся часть а контроллер уже сам занимается растеризацией этого счастья и вывода на экран, ну и собственно генерацией одной и той же картинки пока не получит новых данных. Тут пожалуй ключевым будет «любой удобный для нас момент» т.е. не важно сколько у нас вычисление занимает времени, пол кадра, кадр, 10 секунд.
С таким контроллером было бы неинтересно. =)
Но его присутствие в любом случае обязало бы в прошивке для ПЛИС описать интерфейс обмена между ПЛИС и контроллером. Но это уже другого рода задача.
Sign up to leave a comment.

Articles