В течении последних трёх недель в МИЭТ, МГУ, МИФИ, МФТИ и других российских ВУЗах прошли семинары по процессору на ПЛИС MIPSfpga. В рамках семинаров прошли лабораторные работы на которых демонстрировалось как применять MIPSfpga на практике.
В публикации я расскажу о своих экспериментах с MIPSfpga, которые выходят за рамки лабораторных работ, рассмотрю возможности интеграции процессорного ядра MIPSfpga с IP-блоками opencores.org. Также поведаю о портировании MIPSfpga на некоторые платы на базе ПЛИС Altera (приведены значения Fmax и показатели использования ресурсов ПЛИС).
Хочу заранее оговориться, что я не являюсь сколь-нибудь опытным разработчиком аппаратуры на ПЛИС, и начал осваивать ПЛИС именно работая с MIPSfpga. Поэтому изложение ведётся в несколько программистко-центричной манере.
Предыстория: что же такое MIPSfpga
Компания MIPS Technologies, разработчик процессорной архитектуры MIPS имеет непростую судьбу: начав свою работу как независимая компания в 1984 году, она успела побыть в составе Silicon Graphics (SGI), затем вновь обрести независимость, а в начале 2013 года сделаться частью Imagination Technologies, в коем качестве и пребывает на момент написания этой публикации.
Процессоры с архитектурой MIPS традиционно применяются для обучения студентов архитектуре микропроцессоров, см. например, курс лаборатории МФТИ-Intel.
MIPSfpga — это процессорное ядро с архитектурой MIPS32 из семейства microAptiv, специально предназначенное для учебных целей. MIPSfpga поставляется в виде исходного кода на языке Verilog, что делает его пригодным для синтеза в ПЛИС. Следует отметить, что на момент написания этой публикации доступ к MIPSfpga могут получить только студенты и преподаватели ВУЗов.
MIPSfpga — совсем не игрушка, это процессорное ядро принципиально не отличается от процессорных ядер microAptiv, которые Imagination поставляет на коммерческой основе.
Ядра семейство microAptive, к которому принадлежит MIPSfpga, можно отнести к начальному уровню, и хотя эти ядра не нацелены достижение рекордной производительности, они полностью программно совместимы с более продвинутыми ядрами. Ядро MIPSfpga соответствует архитектуре MIPS32 release 3, имеет в своём составе MMU (TLB) и кэш-память. При желании на MIPSfpga вполне можно запустить linux.
Вместе с исходными MIPSfpga Imagination предлагает и методичку в которой изложены примеры того, как работать с MIPSfpga.
mipsfpga-plus: система-на-кристалле для лабораторных работ
Лабораторные работы (а проще лабы) по MIPSfpga в России провёл сотрудник Imagination Юрий Панчул. Юрий внёс в оригинальные материалы работ ощутимые изменения, связанные в первую очередь с тем, что пришлось подстраиваться под возможности ВУЗов, в которых проводились лабы.
Для проведения работ предлагается собрать систему-на-кристалле mipsfpga-plus в которую входит ядро MIPSfpga и небольшая обвязка.
С некоторыми упрощениями структура mipsfpga-plus выглядит так:
На рисунке m14 — процессорное ядро MIPSfpga (также известное как ядро M14Kc из семейства microAptiv). Для лабораторных работ важными являются интерфейсы, которыми ядро связано с внешним миром: EJTAG и AHB-Lite.
Интерфейс EJTAG является технологическим и предназначен для отладки программ, исполняющихся на процессоре, подробнее о нём можно почитать в публикации EJTAG: аттракцион для хакеров.
А вот интерфейс AHB-Lite является основным для связи процессора с внешним миром. Шина AHB-Lite является упрощённым вариантом шины AHB, и, в частности, AHB-Lite допускает наличие на шине только одного инициатора запросов ("master"). За подробностями отсылаю к документу AMBA 3 AHB-Lite Protocol v1.0 Specification (ARM IHI 0033A).
mfp_ahb-light decoder & mux
(далее декодер) — блок, декодирующий запросы процессора на шине AHB-Lite и, в зависимости от того, по какому адресу обратился процессор, перенаправляет запрос одному из IP-блоков:- RAM;
- boot RAM;
- GPIO.
RAM — это блок памяти для хранения программ и данных;
boot RAM — блок памяти, полностью аналогичный по своей природе блоку RAM; отличие состоит в том, что блок boot RAM содержит программу, которая исполняется сразу после снятия сигнала RESET (так как этот блок отображён на адрес 0x1fc00000).
Блок GPIO состоит из ряда регистров, разряды которых соединены со светодиодами и кнопками/переключателями на плате; программа, исполняющаяся на процессорном ядре таким образом может взаимодействовать с внешним миром.
Для лабораторных работ Юрий предлагает выводить отдельные сигналы m14 на светодиоды платы (подобные соединения носят ситуативный характер, и на рисунке не отражены).
Вот как декодер отображает IP-блоки на физические адреса шины AHB-Lite:
IP-блок | Базовый адрес | Длина |
---|---|---|
RAM | 0x00000000 |
32K — 256K |
GPIO | 0x1f800000 |
0x14 |
boot RAM | 0x1fc00000 |
4K |
Внимание: на шину AHB-Lite процессорное ядро выставляет физический адрес, который, как правило, не совпадает с адресом которым оперирует программа (программный адрес или виртуальный адрес). Подробнее об тонкостях адресации в MIPS смотрите книгу See MIPS Run, раздел Basic Address Space.
При проведении лабораторных работ процессор выполняет тестовые программы, загрузить которые в boot RAM можно несколькими способами.
Самый простой вариант — инициализировать boot RAM на этапе создания битового потока для ПЛИС. С одной стороны это очень просто — загрузил битовый поток в ПЛИС и программа начинает исполняться. Но с другой стороны, если захочется внести изменения в программу, то придётся заново перегенерировать битовый поток, что может быть весьма накладно.
Более продвинутый способ — использовать отладочный интерфейс EJTAG для загрузки программы, однако этот способ требует дополнительного программного и аппаратного обеспечения — JTAG-адаптера и ПО openocd (см. пример использования EJTAG для загрузки данных в ОЗУ платы Black Swift: geektimes.ru/post/249184).
JTAG-адаптер показался Юрию слишком экзотическим устройством, поэтому специально для mipsfpga-plus на языке Verilog он написал IP-блок, реализующий загрузку данных в формате S-record по интерфейсу UART (на рисунке обозначен как uart_recv srec parser). В этом случае для загрузки данных в boot RAM достаточно использовать недорогой адаптер USB-UART и стандартные программы, входящие в состав Linux или Windows. Сразу после включения блок uart_recv начинает приём данных по интерфейсу UART, при этом процессорное ядро остановлено (сигнал reset активен). После окончания приёма данных сигнал reset для процессорного ядра деактивируется, а блок uart_recv самоустраняется.
Более детальное описание mipsfpga-plus см. тут.
Портирование MIPSfpga
Каноничными платами для MIPSfpga являются Terasic DE2-115 и Digilent Nexys4 DDR.
Однако есть причины, которые сподвигли меня на работу по портированию MIPSfpga на другие платы.
Например, мне попросту не удалось купить плату Digilent Nexys4 DDR. Вот что выдал сайт Digilent:
На запрос в Терраэлектронику о возможности купить плату у них мне пришёл отрицательный ответ.
Что касается платы Terasic DE2-115, то на мой взгляд её применение для MIPSfpga отчасти похоже на стрельбу из пушки по воробьям: на плате установлена ПЛИС с избыточным для MIPSfpga количеством ресурсов, в тоже время стоимость платы довольно высока.
Но главное, портирование проекта на новые платы позволит лучше разобраться в работе с ПЛИС и расширит перечень плат, пригодных для проведения лабораторных работ!
Критерий возможности портирования
Для пробы я провёл синтез эталонного проекта для платы DE2-115:
Пусть вас не смущает, что проект съел 3 Мбита накристальной памяти — эта величина может быть легко уменьшена. Достаточно уменьшить размер блоков RAM и boot RAM. Для экономии накристальной памяти ПЛИС есть даже возможность пожертвовать частью кэш-памяти.
Как видно из представленного отчёта, от ПЛИС требуется около 15500 логических элементов (LE). Это означает, что надо ориентироваться на ПЛИС с количеством LE более 20000.
Попытаемся найти такие платы.
Платы Terasic
Тайваньская фирма Terasic предлагает широкий перечень плат на базе ПЛИС Altera, причём некоторые платы, приобретаемые для учебных целей можно купить со скидкой (цена Academic):
Плата | DE0-Nano | DE0-CV | DE1-SoC |
ПЛИС | EP4CE22 | 5CEBA4F23 | 5CSEMA5F31 |
семейство | Cyclone IV | Cyclone V | Cyclone V SoC |
кол-во LE | 22K | 49K | 85K |
память, Кбит | 594 | 3080 | 4450 |
цена | $79 | $150 | $249 |
цена Academic | $61 | $99 | $175 |
Плата Марсоход3
ООО "Инпро Плюс" из Таганрога ведёт интереснейший сайт marsohod.org, посвящённый разработке устройств на базе ПЛИС Altera. На сайте можно приобрести плату Марсоход3, вполне подходящую для MIPSfpga.
На плате Марсоход3 установлена ПЛИС MAX10 на 50000 LE с 1600 Кбит памяти, а стоимость платы составляет 8000 руб.
Подключение IP-блоков с opencores
Лабы в которых предлагается смотреть, что происходит внутри процессорного ядра довольно полезны и поучительны. Однако мне интересней было бы собрать на базе настоящего процессорного ядра от MIPS свою систему-на-кристалле. Этого надо подключить к процессорному ядру ряд периферийных устройств. Взаимодействовать с процессором нажимая кнопки и посматривая на светодиоды конечно хорошо, но хочется более удобный интерфейс. Практически во всех современных встраиваемых системах для технологических целей используется интерфейс UART, так что я решил добавить UART к mipsfpga-plus.
Написание с нуля IP-блока, реализующего UART, не входило в мои цели, так что я решил воспользоваться готовым. Не секрет, что самым известным сайтом с свободно-распространяемыми IP-блоками является opencores.org. И конечно же там нашёлся интересующий меня IP-блок. Но вот беда — для свободно-распространяемых IP-блоков стандартной шиной является Wishbone, которая не совместима c шиной AHB-Lite MIPSfpga.
Я попытался подключить IP-блок UART через "переходник" AHB-Wishbone, который нашёлся на opencores.org; я рассчитывал вот на такое подключение:
На практике оказалось, что переходник не работает, так как я рассчитывал, поэтому оказалось проще доработать интерфейсную часть IP-блока UART для поддержки шины AHB-Lite.
Так как с IP-блоком UART должно работать какое-то ПО, то я позаимствовал наномонитор nmon из загрузчика barebox. nmon взаимодействует с пользователем через UART и обладает лишь базовыми возможностями: позволяет записывать/распечатывать слово по адресу, а также передать управление на адрес.
Однако nmon не требует для своей работы ОЗУ (sic!), занимает менее 1200 байт, работает с любого адреса в памяти.
Небольшой размер позволяет поместить nmon в boot RAM сразу при синтезе. Так что теперь сразу после снятия сигнала reset на интерфейс UART выдаётся приглашение nmon, и пользователь может либо использовать nmon для загрузки и запуска программ, либо вручную производить записи/чтения в адресном пространстве процессора, что может быть полезно при начальной отладке пользовательского IP-блока. Типичный сеанс работы с nmon:
Для подключения ещё одного IP-блока к AHB-Lite пришлось вручную отредактировать блок дешифратора. Окончательно структура mipsfpga-plus с подключённым блоком UART выглядит так:
Итоговый проект, демонстрирующий, подключение IP-блока UART с opencores к mipsfpga-plus, получил название myMIPSfpga. myMIPSfpga работает на платах Terasic DE0-Nano, DE0-CV, DE1-SoC, а также на плате Марсоход3.
Проект myMIPSfpga опубликован на github: github.com/MIPSfpga/myMIPSfpga.
Использование свободнораспространяемого ПО
Хотя для генерации битового потока для ПЛИС Altera и приходится использовать проприетарное ПО Quartus (и с этим ничего не поделать), для многие других задач при работе с MIPSfpga удаётся обойтись свободнораспространяемым ПО.
Для компиляции программ под MIPS используется ПО gcc и binutils (можно использовать пресобранный toolchain Sourcery CodeBench Lite 2015.05-18, а можно собрать собственный при помощи crosstool-ng).
Для работы с процессором MIPS по EJTAG используется ПО openocd и gdb. openocd также можно ипользовать для загрузки битовых потоков в ПЛИС.
Для моделирования myMIPSfpga вполне годится Icarus Verilog, а временные диаграммы по результатам моделирования довольно удобно рассматривать при помощи GtkWave:
myMIPSfpga: использование ресурсов ПЛИС
У участников семинара возникли вопросы о показателях использования ресурсов ПЛИС, а также значения Fmax для myMIPSfpga. Ниже я привожу полученные значения показателя Slow 1200mV 85C Model Fmax Summary в МГц, при этом приведены значения для разных версий ПО Quartus II:
Плата | ПЛИС | Quartus 13.1.4 | Quartus 15.0.2 |
---|---|---|---|
DE0-Nano | EP4CE22F17C6 | 31.66 | 31.22 |
DE0-CV | 5CEBA4F23C7 | 31.24 | 34.06 |
DE1-SoC | 5CSEMA5F31C6 | 28.24 | 37.17 |
Марсоход3 | 10M50SAE144C8GES | --- | 27.06 |
А вот показатели использования ресурсов разных ПЛИС:
Характеристика | Quartus 13.1.4 | Quartus 15.0.2 |
---|---|---|
EP4CE22F17C6 | ||
Total logic elements | 15,342 / 22,320 ( 69 % ) | 15,660 / 22,320 ( 70 % ) |
Total combinational functions | 14,161 / 22,320 ( 63 % ) | 14,161 / 22,320 ( 63 % ) |
Dedicated logic registers | 7,665 / 22,320 ( 34 % ) | 7,665 / 22,320 ( 34 % ) |
Total registers | 7665 | 7665 |
Total memory bits | 95,872 / 608,256 ( 16 % ) | 95,872 / 608,256 ( 16 % ) |
5CEBA4F23C7 | ||
Logic utilization (in ALMs) | 7,283 / 18,480 ( 39 % ) | 6,972 / 18,480 ( 38 % ) |
Total registers | 7976 | 8127 |
Total block memory bits | 95,872 / 3,153,920 ( 3 % ) | 95,872 / 3,153,920 ( 3 % ) |
5CSEMA5F31C6 | ||
Logic utilization (in ALMs) | 7,264 / 32,070 ( 23 % ) | 6,978 / 32,070 ( 22 % ) |
Total registers | 7951 | 8104 |
Total block memory bits | 95,616 / 4,065,280 ( 2 % ) | 95,616 / 4,065,280 ( 2 % ) |
10M50SAE144C8GES | ||
Total logic elements | 37,206 / 49,760 ( 75 % ) | |
Total combinational functions | 30,763 / 49,760 ( 62 % ) | |
Dedicated logic registers | 25,165 / 49,760 ( 51 % ) | |
Total registers | 25165 | |
Total memory bits | 78,464 / 1,677,312 ( 5 % ) |
Примечание: ПО Quartus 13.1.4 не поддерживает ПЛИС MAX10.
Как можно было бы использовать MIPSfpga с IP-блоками с opencores
Для удобной работы с IP-блоками opencores.org созданы вспомогательные средства:
- fusesoc — средство для управления сборкой системы-на-кристалле из отдельных IP-блоков;
- wb_intercon — генератор коммутатора Wishbone.
fusesoc позволяет генерировать систему-на-кристалле используя высокоуровневые описания, при этом fusesoc не только проведёт генерацию исходных текстов на Verilog, но и конфигурационных файлов для САПР Altera или Xilinx.
wb_intercon позволяет генерировать код коммутатора Wishbone на языке Verilog; в качестве входных данных используется конфигурационный файл с указанием параметров портов Wishbone и правил коммутации.
По опыту полученный при подключении UART с шиной Wishbone к mipsfpga-plus можно заключить, что минимум проблем при сборке системы-на-кристалле из ядер c opencores.org и MIPSfpga будет, если само процессорное ядро будет сразу подключаться к Wishbone.
Предположим, что удалось сделать нормальный переходник между AHB-Lite и Wishbone. Тогда система-на-кристалле могла бы выглядеть так:
В на рисунке блоки GPIO, UART, I2C, VGA, ETH, SPI, SDRAM5, HPC2FPGA — реальные IP-блоки с opencores.org, для их соединения с ядром микропроцессора используется сгенерированный коммутатор Wishbone.
Примечание: конечно переходник AHB-Lite-в-Wishbone внесёт дополнительную задержку; лучшая производительность может быть достигнута, если поддержка Wishbone будет встроена в MIPSfpga. Причём, по примеру ядер OpenRISC можно вывести отдельные шины Wishbone для команд и данных.
Послесловие
Опыт работы с MIPSfpga позволяет утверждать, что начальное освоение проектирования систем-на-кристалле на базе ПЛИС не есть что-то сложное, затратное и требующее долгой подготовки. Наличие доступных плат с ПЛИС, бесплатных САПР, свободнораспространяемых инструментальных средств и руководств (особо отмечу сайт marsohod.org) позволяет освоить проектирование на ПЛИС даже в домашних условиях.
Благодарности
Автор благодарит сотрудников Imagination Роберта Оуэна и Юрия Панчула за возможность поработать с MIPSfpga.
Особая благодарность Николаю Ковачу и другим авторам сайта marsohod.org за платы Марсоход3, компании ЭФО за плату Terasic DE1-SoC и Алексею Жукову за плату DE0-Nano.
За помощь освоении САПР Quartus II автор благодарит сотрудников НИИСИ РАН: Сергея Аряшева, Андрея Щербакова, Александра Корниленко и Андрея Аракелова.
Автор надеется, что в будущем лицензия MIPSfpga будет пересмотрена и это процессорное ядро станет доступно всем интересующимся архитектурой микропроцессоров.
UA3MQJ
Отличная статья, спасибо!
А можно ли собрать все то же самое, но с процессором с OpenCores и сколько минимум ячеек для этого потребуется?
Специалист из Марсохода укладывал AmberSOC в 10 тыс ячеек. Но там было очень много работы.
Frantony
Я уже сделал такой проект!
См. github.com/open-design/mips32r1_soc_nano/tree/mips32r1_wb
За основу взято ядро mips32r1 c opencores (https://github.com/grantae/mips32r1_soc_nano).
И добавлены компоненты с opencores.
Ядро mips32r1 также как MIPSfpga не подключается к Wishbone напрямую,
использует свою собственную доморощенную шину.
Я сделал переходник с этой шины на Wishbone, так что получилась вот такая конструкция (в bootrom также прошит nmon):
Вот данные по потребляемым ресурсам для ПЛИС плат DE0-Nano, DE1-SoC и Марсоход3:
; Family; Cyclone IV E;
; Device; EP4CE22F17C6;
; Timing Models; Final;
; Total logic elements; 9,236 / 22,320 ( 41 % );
; Total combinational functions; 8,769 / 22,320 ( 39 % );
; Dedicated logic registers; 2,465 / 22,320 ( 11 % );
; Total registers; 2465;
; Total memory bits; 256 / 608,256 ( < 1 % );
; Device; 5CSEMA5F31C6;
; Timing Models; Final;
; Logic utilization (in ALMs); 3,642 / 32,070 ( 11 % );
; Total registers; 2669;
; Total block memory bits; 0 / 4,065,280 ( 0 % );
; Total DSP Blocks; 6 / 87 ( 7 % );
; Device; 10M50SAE144C8GES;
; Timing Models; Preliminary;
; Total logic elements; 9,117 / 49,760 ( 18 % );
; Total combinational functions; 8,754 / 49,760 ( 18 % );
; Dedicated logic registers; 2,465 / 49,760 ( 5 % );
; Total registers; 2465;
; Total memory bits; 256 / 1,677,312 ( < 1 % );
; Embedded Multiplier 9-bit elements; 16 / 288 ( 6 % );
Для лаб ядро MIPSfpga конфигурируется в little-endian режиме, но легко может быть переключено в big-endian.
А вот mips32r1, как я понял, предназначено для работы в big-endian, а работоспособность little-endian режима ещё надо проверять.
На фоне MIPSfpga ядро mips32r1 смотрится довольно блекло:
* версия r1 архитектуры против r3 в MIPSfpga;
* нет кэшей и TLB.
Раз нет кэшей и TLB, значит никто не пускал на этом ядре Linux, то есть ядро можно сразу считать малотестированным.
Опять же переходники на Wishbone отъедают такты, их надо убирать.
С другой стороны это ядро может привлечь энтузиастов, которым интересно самим сделать собственное ядро. Хотя ядро не очень новое, а желающих его развивать не видно.
Frantony
По поводу количества логических ячеек, которое требуется для mips32r1, надо внести поправку.
На самом деле из более чем 9000 LE надо вычесть те LE, которые пошли на реализацию bootrom (подозреваю, что bootrom можно было сделать на memory и cъэкономить LE). Так что за вычитом bootrom mips32r1_soc_nano занимает чуть меньше 6000 LE.
UA3MQJ
Я думаю, что можно как-то еще снизить количество LE каким-либо образом, разменяв производительность на объем. Ведь был же линукс на Atmega.