Imax9
NEWS   ARTICLES   MINIMIG   FILES   ABOUT

В ярости.

Оригинальная статьи On the Rampage… с сайта уважаемого Alastair M. Robinson. Мне показались интересными решения, как автор выкрутился в ситуации с недостатком блочной памяти FPGA, поэтому предлагаю свой перевод.

Портирование аркадного ядра на Turbo Chameleon 64 – Часть 1

Сейчас существует очень много ядер аркадных автоматов, и лишь немногие из них были портированы на Turbo Chameleon 64. Когда я обнаружил, что Rampage существует как для MiSTer, так и для MiST, мой интерес возрос, потому что это игра, в которую я играл на Amiga в детстве, и хотя у Amiga неплохая конверсия, оригинальная аркадная игра значительно лучше.

Плата MiST в чем-то очень похожа на оригинальную Minimig; она имеет FPGA, которая подключена к встроенной памяти, видео и аудиовыходу, а также отдельный микроконтроллер, который подключен к клавиатуре, мыши, портам SD-карты и джойстика; микроконтроллер отвечает за загрузку файла ядра FPGA с SD-карты, а затем связывается с ядром через интерфейс SPI, обеспечивая ввод данных, загрузку ROM, эмуляцию привода и т.д.

Turbo Chameleon 64 совсем другой. Хотя он имеет ту же FPGA (Cyclone III с 25 000 логических элементов – или, в случае Chameleon 64 V2, Cyclone 10LP, что в основном одно и то же в другом корпусе) и 32 мегабайта 16-битной SDRAM с той же структурой (13 бит адрес строк, 9 бит адрес столбцов), устройства ввода и SD-карта являются чисто обязанностью ядра, поэтому для переноса ядра из MiST нам нужно заменить недостающую функциональность микроконтроллера MiST.

Ядра Хамелеона хранятся во флэш памяти, и в слоте флэш памяти определенное пространство, которое связанно с образами ROM, но протокол доступа к нему достаточно сложен, так что мне не хочется пытаться реализовать его на одной логике. Если вам нужно добавить софт микроконтроллер в проект, вы можете с таким же успехом загрузить данные с SD-карты, так что это то, что я делал с большинством моих проектов до сих пор.

Первым делом я хотел реализовать soft копию микроконтроллера в ядре FPGA, что и было сделано для ядра Minimig. Я вполне могу сделать это, но, как вы скоро увидите, в некоторые местах есть трудности с использованием этого подхода для Rampage…

Вначале, что нужно сделать, это взглянуть на MIST версию этого ядра и посмотреть, насколько оно велико и какие могут у нас возникнуть трудности с портированием на Хамелеон. Исходное ядро можно найти в репозитории пользователя Gehstock - речь идет о ядре “Midway MCR 3 Monoboard”, которое поддерживает три игры. Но сейчас я сосредоточусь только на "Rampage". Итак, загрузив и откомпелировав ядро, мы можем взглянуть на отчет о сборке, в частности, на часть отчета “Fitter -> Resource Section”. На первой странице написано:

Total logic elements: 13,160 / 24,624 ( 53 % )
Total memory bits: 464,096 / 608,256 ( 76 % )

Что ж, это обнадеживает – осталось много логических элементов, а также много памяти. Но подождите – посмотрите внимательнее: в глубине отчета мы видим:

M9Ks: 63/66 ( 95 % )

Это не так уж хорошо – это означает, что у нас есть только три блока памяти M9K (каждый из которых в основном килобайт). Если мы собираемся добавить soft микроконтроллер для работы с SD – картой, то нам понадобится, по крайней мере, 8K ROM, что означает 8 M9Ks в запасе и многие soft процессоры требуют по крайней мере один блок памяти для своих внутренних регистров.

Если, почти все блоки используются, но все еще есть много свободных битов памяти, то ядро испольует блоки памяти не оптимально – и если мы более внимательно посмотрим на раздел “Resource utilisation by entity” отчета Fitter, то увидим, сколько битов памяти использует каждый элемент. Особый интерес представляют элементы “gen_ram:sprlinebuf1a” шириной 2 бита четыре отдельных блока оперативной памяти по 1024 бита каждый, но каждый из них использует целый блок M9K. Еще хуже то, что gen_ram:palette требует всего 576 бит, но использует весь M9K блок.

Можно изменить использование логики под оперативную память, определив атрибут “ramstyle”, так что давайте сделаем это. В определении gen_ram оперативная память определяется следующим образом:

type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0);
signal ram: ramDef;

Поэтому мы скопируем это в новый VHDL-файл, переименуем объект из gen_ram в gen_ram_logic и сразу после определения ОЗУ добавим строки:

attribute ramstyle : string;
attribute ramstyle of ram : signal is "logic";

Теперь мы изменим файл mcr3mono.vhd, чтобы использовать новый элемент gen_ram_logic вместо gen_ram для пяти ОЗУ, указанных выше, и теперь у нас есть пять дополнительных блоков M9Ks, доступных после сборки, за счет использования около 4500 дополнительных логических элементов.

Есть еще один трюк, который мы можем использовать, чтобы освободить блок M9K: gen_ram:sprite_ram и gen_ram:sprite_ram_cache - это однопортовые ОЗУ с 4096 битами. Мы можем объединить их в двухпортовую оперативную память объемом 8192 бита, которая затем будет использовать только один M9K. Нам просто нужно добавить дополнительный бит адреса, которым мы выбираем низким уровнем - первую оперативную память и высоким - вторую.


Адрес для контактов : imax9@narod.ru

Если вам понравились мои работы и вы желаете поддержать сайт - сделайте дотацию.

При копировании статьи – обязательна ссылка на авторство и источник. Без разрешения автора копирование запрещено.

© Максим Ильин 2022г.

Яндекс.Метрика