понедельник, 8 февраля 2016 г.

Как я придумал свой процессор 2: Из виртуальности в реальность

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

Решив, что останавливаться на достигнутом ещё рано, я стал думать, что делать дальше. Перебрав несколько вариантов я решил, что надо от симулированных схем переходить к настоящим. В качестве "мягкого" варианта работы с железом я выбрал экспериментирование ПЛИСом. В поисках подходящий платы я перебрал много вариантов и в итоге я выбрал для себя Terasic DE0 с чипом Cyclone III. Этот набор имеет достаточно мощный чип и хороший набор интегрированных портов и вспомогательных устройств (ОЗУ, Flash, SD-слот, кнопки, светодиоды)

ПЛИС: Начало

Цель - сделать свой процессор на ПЛИС - более амбициозная и более сложная, чем нарисовать его в программе-симуляторе. Помимо того, что надо осваивать новый язык (VHDL) и инструментарий (Altera Quartus II), здесь надо было думать о некоторых вещах, которые в симуляторе уже были сделаны за меня. Например, самому реализовать консольный ввод/вывод при помощи VGA-монитора и PS/2-клавиатуры.

Чтобы ускорить процесс, я искал и применял готовые наработки:
  1. Прототип текстового VGA-контроллера (нашёл на сайте проекта "Марсоход").
  2. Контроллер PS/2 клавиатуры вместе с ASCII-декодером: тут.
  3. Простейший SDRAM-контроллер.
Все эти компоненты для в той или иной мере перерабатывал, тестировал, склеивал друг с другом в тестовых конфигурациях. После этих экспериментов с этими почти готовыми модулями настал момент написать с нуля самый важный модуль - собственно, процессор.

Через тернии

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

Другой проблемой, над которой изрядно пришлось поломать голову, стала проблема взаимодействия двух схем, синхронизированных разными тактовыми частотами. Проявлялась она в том, что периодически зависал мой видеоконтроллер, который работал на частоте 25 МГц, но взаимодействовал с шиной низкой частоты (сотни герц). Разрешение этой проблемы потребовало чтение многих статей, изучения новых для меня понятий и концепций (например, "метастабильное состояние", "домен синхронизации"). Итог - вставленный за десять минут между шиной и контроллером асинхронный FIFO-буфер из библиотеки Altera Quartus II решил проблему. Но шёл я к этому тривиальному ответу долго...

Результат

Сказать по правде, пару раз руки опускались. Возникала мысль, мол, а не взялся ли я за проблему не по моим способностям? Но благодаря проявленной моральной и интеллектуальной стойкости мне удалось продраться через возникавшие по пути проблемы. Результатом стала точная логическая копия второго процессора на ПЛИС, бинарно совместимая с оригиналом. Даже микрокод из оригинала был повторно использован без изменений. В подтверждение скриншот виртуального терминала и фото реального монитора с выводом программы самотестирования:


Естественно, что программа, загруженная в обе реализации была одной и той же. Полученная система имеет следующие характеристики:
  1. Ширина машинного слова: 16 бит.
  2. Ширина адреса: 16 бит, максимально адресуемая память - 128К (65536 двухбайтовых слов). Отдельные байты не адресуются.
  3. Ввод-вывод с отображением на адресное пространство.
  4. ОЗУ на чипе ПЛИС - 16К (8192 двухбайтовых слова).
  5. Ввод: PS/2 клавиатура.
  6. Вывод: текстовый VGA-терминал, матрица 80х30 символов. Знакогенератор использует прошивку от CGA-адаптера с шрифтом 8х8 точек (эх, ностальгия!).
  7. Потребленные ресурсы ПЛИС: 2147 логических модуля (примерно 15% от ресурсов чипа).

Итог


Успешный прогон программы самотестирования - значительная веха моего домашнего "процессорного" проекта. Однако почти всё ещё впереди: видеотерминал надо превратить в полноценный адаптер с графическим режимом, для ОЗУ использовать SDRAM-чип, установленный на плате, освоить работу с Flash-чипом и SD-слотом, установленными на плате. После этого можно писать свой монитор и совершенствовать процессор, который ещё бесконечно далёк от совершенства.