В статье будет рассмотрен весь процесс от создания проекта с синтезируемым процессором Nios II до запуска прошивки на нём в ПЛИС, а также описаны возможные проблемы, возникающие в процессе, и способ их решения. Получившийся проект доступен для свободного скачивания (под Cyclone 10 LP) и любой может повторить все описанные ниже действия как самостоятельно с нуля, так и подсмотрев в проекте.
Здесь не будет рассмотрен процесс создания файла прошивки для конфигурационной памяти (для автономного запуска проекта), т. к. статья и так вышла довольно объемной и логично будет эту часть отделить.
Статья будет полезна новичкам, осваивающим ПЛИСы, и если вас заинтересовало, добро пожаловать под кат:
Создание проекта
Итак, создаём новый проект с нуля, выбираем 10CL025YU256I7G, стоящую на Intel Cyclone 10 LP FPGA Evaluation Kit (или любую другую, которая на вашей плате, это не принципиально):
Настройки EDA я не трогаю и можно всё оставить по умолчанию, т. к. никакой симуляции нам тут не потребуется (пока что):
Сохраняем проект куда душе угодно и приступаем к его наполнению.
Простой тест работоспособности на Verilog
Итак, нам понадобится добавить в проект 3 файла. Первый — C10LP_TOP.v :
module C10LP_TOP ( // Тактирование input SYS_CLK50M, // Пользовательское управление input [3:0] USER_PB, output [3:0] USER_LED ); wire reset; assign USER_LED = USER_PB; debouncer db ( .in(USER_PB[0]), .clock(SYS_CLK50M), .out(reset) ); endmodule
Это будет ТОП-файл, который сейчас выполняет просто отображение нажатия кнопок на светодиодах.
Можно заметить, что в ТОП-файле выше используется фильтр для одной из кнопок — логично, что он будет в файле debouncer.v:
module debouncer ( input wire in, input wire clock, output reg out ); reg [7:0] shiftreg; initial begin shiftreg=8'hFF; out=1'b0; end always @ (posedge clock) begin shiftreg[7:0] <= {shiftreg[6:0], in}; if (shiftreg[7:0] == 8'b00000000) begin out <= 1'b1; end else if (shiftreg[7:0] == 8'b11111111) begin out <= 1'b0; end else begin out <= out; end end endmodule
Это нам понадобится для формирования четкого сигнала сброса для процессора, без дребезга.
И последний файл — C10LP_TOP.sdc:
#************************************************************** # Time Information #************************************************************** set_time_format -unit ns -decimal_places 3 #************************************************************** # Create Clocks #************************************************************** create_clock -name clock_50M -period "50 MHz" [get_ports {SYS_CLK50M}]
Этот файл необходим для Timing Analizer, для которого мы здесь описываем, какой сигнал у нас тактирующий и какую частоту он имеет. По факту в статье Timing Analizer не будет рассмотрен, потому что проект крайне простой, но в дальнейшем это пригодится. Да, этот файл должен называться аналогично ТОП-файлу, иначе не будет автоматом подхвачен при компиляции и анализе!
Примечание: В окошке создания новых файлов он находится в самом низу:
Итак, добавили 3 файла, теперь можно сделать черновую компиляцию — вызываем только анализ и синтез:
Да, перед этим не забываем назначить ТОП-файл:
Примечание: Если проект новый, то стоит зайти в настройки:
И указать использование всех доступных ядер процессора для компиляции — это положительно повлияет на время компиляции проекта:
После успешного анализа, если нет ошибок, заходим в Pin Planer и видим все пины ввода-вывода:
Назначаем их в соответствии со схемой на отладочную плату:
Теперь компилируем проект полностью и заливаем прошивку в плату. Результат должен быть вот такой:
Всё работает, можно закрывать Quartus…
Дальше мы уже пойдем по модулям собирать наш процессор.
Осваиваем Platform Designer
Запускаем Platform Designer (или в старых версиях Quartus это был Qsys):
Перед нами предстаёт почти пустое окно с единственным IP — источником тактового сигнала и сброса:
Двойной клик на нём, в свойствах устанавливаем частоту источника (осциллятора, если сигнал будет взят напрямую или PLL), с которого будет всё затактировано:
В моём случае это 50 МГц, на плате установлен осциллятор 50 МГц и я просто возьму с него тактирующий сигнал напрямую, для теста этого будет достаточно более чем.
Начинаем добавлять IP, первое, что добавим, собственно, ядро процессора — Nios II Processor:
Выбираем Economy вариант, т. к. он бесплатный и не требует лицензии. Правда, фарша у него кот наплакал, но ничего не поделать без лицензии.
В настройках из важных моментов — расположение векторов памяти:
Векторы должны указывать на реальные блоки RAM памяти, нужно не забыть сменить их в выпадающих списках.
Также в настройках не стоит отключать JTAG Debug, иначе банально залить прошивку не сможете:
Следующее IP, которое будем добавлять, — On-Chip Memory (RAM or ROM):
Здесь все можно оставить по умолчанию (выбрана RAM), сменив только размер RAM на 32768 (32 Кб) — с большим запасом хватит на тестирование процессора.
Далее добавляем PIO (Parallel I/O) IP:
Выставляем количество выводов = 4, т. к. у нас всего пользовательских светодиодов 4 шт., и устанавливаем их выходами.
Далее уже парочка не обязательных, но крайне рекомендуемых к добавлению IP, первое — это JTAG UART:
Это IP поможет просматривать любые сообщения из printf в консоли Eclipce без дополнительных USB-UART.
Второе рекомендуемое IP — System ID Peripheral:
Это IP позволяет задать уникальный идентификатор (ID) для процессора в нашем проекте, чтобы случайным образом не прошить не то, что надо, в другую плату. Это поначалу кажется избыточным, но лучше к такому привыкать сразу — позволяет избежать возможных проблем в будущем. Здесь выставляем ID = 0x12345678 (или любой другой, который хочется).
Итак, мы добавили все необходимые IP модули, и окно сообщений теперь пестрит красным — кучи ошибок:
Не беда, часть из них говорит нам о том, что то там, то здесь нет тактирования или сброса, соединяем мышкой сигналы тактирования, сброса, шины данных и команд как показано ниже:
Примечание: Также для PIO модуля я задал экспортное имя «GPIO» в колонке Export, чтобы при генерации ТОП-файла процессора было более осмысленное обозначение этих выводов.
Вот, уже лучше, но не всё. Прочитав сообщения ошибок, можно видеть, что большинство из них — это ошибки адресов добавленной периферии, они накладываются. Исправить это можно автоматически, вызвав пункт в меню:
Или вручную, расставив Base адреса:
Почти всё! Нажимаем Generate HDL…:
Появляется окно с настройками генерации, я убрал создание графического символа, т. к. я его не использую (на удивление почти во всех мануалах подключают процессор именно через графический символ — зачем, для меня загадка) и поменял имя папки, куда будет сгенерирован процессор, на «nios2»:
Перед генерацией первый раз спрашивается, куда сохранить настройки Platform Designer:
После чего будет «первый проход»:
И потом генерация, но она завершилась с предупреждением:
Смотрим, что за предупреждение:
Мда, забыл подключить выход прерывания JTAG UART — исправляем:
Генерируем:
Всё успешно! После закрытия окна будет выведена напоминалка, что вам необходимо вручную добавить сгенерированный файл nios2\synthesis\nios2.qip в проект:
Добавляем синтезированный Nios II в проект
Ну что же, половина пути уже пройдена! :) Добавляем сгенерированный файл nios2.qip в проект так же, как обычный исходник на Verilog:
Но он раскрываемый, если посмотреть, что он за собой притягивает, то видно все синтезированные IP, что мы добавили:
Здесь нас интересует только файл nios2.v — он является ТОП-файлом процессора. Открываем его:
И здесь мы видим в оглавлении модуля сигналы, которые необходимо подключить в своём проекте (тактирование, сброс и шина PIO).
Открываем ТОП-файл проекта, создаём экземпляр процессора и подключаем к нему, собственно, тактирование (осциллятор на 50 МГц, частоту которого я и указывал в IP из Platform Designer, а также в C10LP_TOP.sdc файле), сигнал сброса от кнопки (для которого и используется подавитель дребезга из файла debouncer.v) и шина пользовательских светодиодов (кнопки не используются, были добавлены для теста вначале). Выглядит ТОП-файл проекта теперь вот так:
Компилируем. Всё успешно:
Занимает проект вполне немного — 7% логических элементов, а вот памяти… 45% — это уже ощутимо. А всё из-за того, что Cyclone 10 LP — бюджетная серия и тут в принципе памяти довольно мало, по сравнению с тем же MAX 10.
Руки чешутся наверное уже. :) Прошиваем:
Просто горят. Не густо, но так должно быть, ведь у нас прошивки-то у процессора еще никакой нет…
Осваиваем Nios II Software Build Tools for Eclipse
Ну а теперь окунаемся в использование IDE для богов (нет) — Eclipce. А то, что она то подвисает, то залипает по непонятным причинам или на вполне ровном месте — это мелочи… стартуем:
Eclipse спросит, где расположить workspace (настройки IDE и т. д.), можно, к примеру, сделать папку рядом с Quartus’ом и поставить галку, чтобы больше не спрашивал (тут как вам удобнее):
И перед нами возникает эта «божественная IDE»:
Создаем проект (точнее их будет 2 — проект собственно прошивки и проект BSP — Board Support Package, который генерируется на основе выбранных IP) из шаблона:
В появившемся окне указываем имя проекта (Firmware), выбираем файл настроек nios2.sopcinfo для Platform Designer, с которого прочитаются настройки, и выбираем шаблон Blank Project (в принципе можно и Hello World, для теста особой разницы нет):
Далее можно ничего не менять:
Примечание: не редкость, у вас на этом шаге может появится следующее окно:
Оно может возникать по вполне очевидным ошибкам, о которых можно прочитать в окне лога. К примеру, у меня там было следующее сообщение:
SEVERE: .entry section mapping not created because reset memory region not located at base address: 0xffffffffffffffff
Которое говорит нам о том, что я забыл сменить векторы памяти процессора с дефолтных на реальную RAM, IP которой добавил позже. Вот правильный выбор векторов памяти:
А что можно выбрать в выпадающем списке:
Стоило просто сменить оба вектора на onchip_memory2_0.s1 и заново сгенерировать проект процессора в Platform Designer, как оба проекта прошивки для Nios II сгенерировались успешно.
Иногда для решения этой ошибки нужно запускать IDE от администратора, это в основном касается тех, кто работает на Windows 7, или же почистить все сгенерированные папки проекта Quartus и заново скомпилировать всё.
Вот и сгенерировались два проекта:
Окей. Идём в свойства проекта Firmware_bsb и открываем свойства BSP:
Странно. Всё серое… тупо ждём 5-10 секунд, ничего не делаем.
Вуаля и всё доступно к редактированию:
Здесь для начала стоит убрать поддержку С++, если она вам не нужна, и указать использование Small C Library (правда, это, к примеру, убирает возможность выводить float в printf) — это очень ощутимо сбрасывает объём скомпилированной прошивки.
Далее открываем BSP Editor:
Здесь редактируем ввод\вывод, выбираем jtag_uart_* для взаимодействия с консолью Eclipse во время отладки:
Остальные настройки можно не трогать. Нажимаем Generate. После чего компилируем bsp проект:
Успешно:
Теперь переходим к основному проекту, который, собственно, и будет прошивкой. Если был выбран ранее шаблон Blank Project, то он будет пустой. Создаём файл main.c со следующим содержимым:
#include "system.h" #include "altera_avalon_pio_regs.h" #include int main () { unsigned int leds = 0x1; unsigned int i = 0; printf("Hello\n"); while(1) { IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, leds); for (i=0; i<(ALT_CPU_CPU_FREQ/500); i++); // небольшая задержка leds = ((leds<>3) & 0x1); // код Джонсона } return 0; }
Здесь стоит отметить, что обращение к портам PIO происходит по адресу PIO_0_BASE, объявленному в system.h, который, в свою очередь, и генерируется на основе выбранных модулей и их заданной адресации в Platform Designer. Поэтому никогда не прописывайте в коде магические числа и адреса, прямо зависящие от добавленных IP — всегда пользуйтесь объявлениями из system.h.
Компилируем:
Всё ок. Теперь переходим к запуску прошивки на синтезированном процессоре в железе:
Перед нами менеджер конфигураций запуска, двойной клик на Nios II Hardware и создаётся экземпляр настроек:
Переходим в Targert Connection, здесь должна отображаться подключенная отладочная плата:
Но залить прошивку (кнопка Run) менеджер не даёт, в чем дело ? Раз плата нашлась, первое, что делаем — нажимаем на System ID Properties… :
Процессор определился! ID сходится, а вот временной штамп работающего в ПЛИС и откомпилированного на данный момент в проекте процессора — нет. Это и есть причина того, что нам не дают залить прошивку. Можно, конечно, поставить две галочки с игнорированием ID\timestamp, но крайне не рекомендую этого делать и привыкать к такой практике, чтобы случайным образом не прошить не то, что надо, в другую плату или долго промучиться, почему прошивка не работает на старом процессоре (к примеру, вы добавили новое IP, проект скомпилировали, а залить в ПЛИС забыли, прошивка же в итоге со старым процессором работать не будет).
Примечание: на этом шаге также может быть такое, что процессор даже не определяется. Причины этого надо смотреть везде, возможно, вы банально забыли дать тактирование процессору, или он в сбросе постоянно (сброс у него нулём!), или в Platform Designer не подключили шину данных или адреса к jtag… И да, если были изменения в Platform Designer и перекомпилировали проект в Quartus, то необходимо заново сгенерировать BSP командой:
В моём случае я просто забыл залить новую прошивку в ПЛИС. После обновления всё определилось и совпало с ожидаемыми значениями:
Как и стала доступна кнопка Run…
Итог
После заливки прошивки в процессор Eclipse открывает консоль, в которую выводится ожидаемое сообщение:
А светодиоды так же ожидаемо переливаются (код Джонсона):
На этом всё, в целом настройка и добавление Nios II в свой проект хоть и кажется большим, трудным занятием, всё это скорее нудное, т. к. особых трудностей не должно вызвать и повторяется крайне легко! Главное не спешить и вникать в то, что ты делаешь.
Хоть проект и крайне простой, но надеюсь он даёт краткое представление, что же такое процессор Nios II и как его готовить.
Спасибо, что прочитали до конца! ;)
Ссылки
- Cyclone10_NiosII_Example — проект с исходниками, на основе которого написана эта статья;
- Nios® II Processor — все официальные материалы и доки для Nios II;
- Cyclone 10 LP Nios II ‘Hello World’ Lab Manual — краткий официальный мануал на ангельском под демо борду Cyclone 10 LP;
- Ваш первый проект на Nios II — старый мануал с некоторыми неточностями или упущениями, написан под Quartus Prime 14.0 аж.