Портирование RISC-V системы на плату Марсоход3

github screenshot

Итак, портируем RISC-V систему SCR1 от компании Syntacore на плату Марсоход3. Я уже писал, почему я выбрал именно эту систему для изучения в предыдущей статье. Что нужно для запуска этой системы на нашу плату? Посмотрим, что там у них в исходниках на github: https://github.com/syntacore/scr1-sdk

В репозитории есть директории doc, fpga, images, scr1, sw. При этом, директория fpga и scr1 это субмодули git, указывающие на другие репозитории. Внутри папки sw так же есть два субмодуля это папки sc-bl и zephir. Ну что ж, приступим к работе!


Я сделал fork всех репозиториев и готовлюсь добавлять в них свои изменения, касающиеся нашей платы Марсоход3. Взять мой форк можно здесь https://github.com/marsohod4you/scr1-sdk

Выполните команды
> git clone https://github.com/marsohod4you/scr1-sdk
> cd scr1-sdk
> git submodule update --init --recursive

После этого у вас появятся все нужные исходники для работы с проектом.

Давайте еще раз внимательно посмотрим, что тут есть. Вообще, сразу видно, что изначально компания Syntacore подготовила SDK для использования на нескольких разных платах FPGA. Предлагаемые варианты плат это:

  • Altera Arria-V Starter Kit,
  • Digilent Arty Edition,
  • Terasic DE10-Lite Edition,
  • Digilent Nexys4DDR Edition.

К этим платам соответственно подготовлена документация в папке doc. К этим же платам есть готовые образы для загрузки в платы в папке image. В папке fpga есть исходники соответствующих FPGA проектов к каждой плате. Папка scr1 общая для всех проектов и содержит ядро RISC-V. Ну и остается папка sw в которой расположены исходники запускаемых программ: hello, tests, sc-bl, zephyr. Наиболее интересной здесь для меня является программа начальной загрузки, bootloader sc-bl. Она должна быть откомпилирована и её бинарный образ должен быть зашит в статическую память системы SCR1 для успешной инициализации и дальнейшей работы микропроцессора RISC-V при включении питания платы.

Первое, что я буду делать - создам свой проект Quartus Prime Lite в папке fpga/marsohod3. Я добавляю поддержку нашей платы в SDK. На самом деле будет очень разумно изначально скопировать к примеру проект для платы Terasic DE10-Lite Edition в мою папку. Почему я выбираю именно этот проект как прототип моего будущего проекта? Ответ прост: и плата DE10 и плата Марсоход3 имеют FPGA одного семейства Intel MAX10. Да, конечно, платы разные, но хоть в чем-то они да похожи, а именно семейством ПЛИС.

Можно попробовать сразу без изменений откомпилировать этот проект. Я попробовал с установленным у меня Intel Quartus Prime Lite v20.1. Попробовал и у меня не получилось - ошибки сборки. Оказывается, проект изначально выполнен в среде Quartus Prime Standard Edition v17.1. У меня стоит версия Lite версии 20.1 и, к сожалению, в новых версиях квартуса отсутствует поддержка контроллера микросхем SDRAM. Мы на нашем сайте принципиально делаем проекты к нашим FPGA платам Марсоход только в бесплатных версиях Quartus, чтобы большее число людей смогло познакомиться с технологией FPGA. Похоже, что версия Intel Quartus Prime Lite 17.1 была последней, которая содержит контроллер SDRAM, который можно запросто использовать в своих проектах. Я скачал версию Lite 17.1 и у меня теперь исходный проект для DE10 собирается без проблем, но да, квартус выдает предупреждение, что в следующих версиях квартуса бесплатной поддержки SDRAM не будет. Вот же вредители.

Теперь, когда прототип есть нужно попробовать его изменить под особенности платы Марсоход3. Первое, что я сделал, это переименовал все исходные файлы с de10lite_scr1.* в соответствующие файлы m3_scr1.*.
Дальше вручную редактируем файл настроек проекта m3_scr1.qsf (Quartus Settings File).

Задаем тип микросхемы FPGA, указываем, что на нашей плате Марсоход3 стоит ПЛИС 10M50SAE144C8, а так же указываем новое имя топ модуля:

set_global_assignment -name FAMILY "MAX 10"
set_global_assignment -name DEVICE 10M50SAE144C8G
set_global_assignment -name TOP_LEVEL_ENTITY "m3_scr1"

Аналогично переименовываем и файл de10lite_sopc.qsys в файл qsys/m3_sopc.qsys. В настройках проекта указываем новое имя для QSYS:

set_global_assignment -name QSYS_FILE qsys/m3_sopc.qsys

Следующее очень важное изменение - нужно исправить назначения выводов FPGA. В нашем чипе и выводов меньше и разведены на печатной плате эти выводы совсем подругому. Нужно найти все настройки set_location_assignment и удалить их. Вместо этих настроек нужно поставить свои. Их можно взять из любого другого марсоходовского проекта. Да хоть из этого https://github.com/marsohod4you/light-music из файла max10_50.qsf. Я перенес назначения сигналов из того проекта в этот. Ещё одно важное замечание. На плате DE10-Lite есть семисегментные индикаторы, светодиоды и переключатели. На плате Марсоход3 только светодиоды и две кнопочки. Чтобы как-то соответствовать я пожалуй установлю на плату Марсоход3 наш шилд семисегментного индикатора:

shield 3x7seg 2

Теперь у меня и кнопок больше и четыре цифры индикатора есть. Что дальше?

Дальше редактируем Verilog файл модуля самого верхнего уровня m3_scr1.sv. В этом файле я заменяю все упоминания "de10lite_" на мои "m3_". Теперь модуль верхнего уровня называется m3_scr1, как и указано в файле настроек m3_src1.qsf.

В модуле верхнего уровня m2_scr1 я удаляю входы и выходы соответствующие семисегментным индикаторам HEX0-HEX5 и переключателям SW. Вместо них я поставлю выводы inout wire [15:0]IO, которые идут к контактам шилда платы Марсоход3.

На шилде есть 4 кнопочки, пусть это будут как будто переключатели SW платы. Я не исправляю весь модуль Verilog, SW как входы модуля я удалил, но определил эти сигналы заново как wire:

//use shield 4 buttons as Switchers
wire [9:0]SW; assign SW[9:4] = 0;
assign SW[3] = ~IO[11];
assign SW[2] = ~IO[10];
assign SW[1] = ~IO9];
assign SW[0] = ~IO8];

Младшие четыре SW[3:0] подключены к четырем кнопкам шилда семисегментного индикатора.

С семисегментными индикаторами чуть сложнее. В исходном проекте De10-Lite не экономят выводы к семисегментным индикаторам. Там чип FPGA в другом корпусе, используется BGA микросхема и из-за этого свободных выводов у них много. На каждый сегмент в индикаторе там просто идет один вывод FPGA. В случае с платой Марсоход3 шилд семисегментного индикатора использует динамическую адресацию сегментов с целью экономии выводов. Поэтому я в проект добавил еще один файл seg4x7.v, который содержит простой Verilog модуль


module seg4x7(
    input wire clk, // 20MHZ

    input wire [31:0] in,
    output reg [3:0] digit_sel,
    output reg [7:0] out
)
;


reg    [19:0] cnt;
always @ (posedge clk)
    cnt<= cnt +1'b1;

wire [1:0]digit_idx; assign digit_idx = cnt[17:16];
reg [31:0]in_fixed;
always @ (posedge clk)
begin
    digit_sel<= 4'b0001 << digit_idx;
    in_fixed<= in;
    out<= in_fixed >> (digit_idx*8);
end
endmodule


Этот модуль принимает 32 бита для 4-х отображаемых цифр и выдает 4 селектора отображаемой цифры и восемь бит самой цифры. Вот и получается экономия выводов: вместо 32-х выводов при динамической индикации используется всего 12.

В модуле верхнего уровня m3_scr1 я устанавливаю экземпляр моего модуля seg4x7 и подключаю его сигналы к выходам IO:


// m3 board 7seg shield
wire [3:0]seg_digit_sel;
wire [7:0]seg_out;
seg4x7 seg4x7_instance(
    .clkcpu_clk ),

    .in{ pio_hex_3_2, pio_hex_1_0 } ),
    .
digit_selseg_digit_sel ),

    .outseg_out )
);

assign IO[15],IO[13],IO[12],IO[14] } = seg_digit_sel;
assign IO[7:0]  = seg_out;


Еще очень важное изменение, которое нужно сделать касается тактовой частоты. На плате DE10-Lite стоит генератор 50МГц, а на плате Марсоход3 стоит 100МГц. Сигналы в исходном проекте имели имена osc_50_clk и MAX10_CLK2_50 и я их везде переименовал в osc_100_clk и в CLK100MHZ. Однако, просто переименование сигналов это только косметическое изменение. Конечно я не поднимаю тактовую частоту проекта в два раза. Мне нужно перенастроить сам PLL в проекте. Для этого в навигаторе проекта Quartus нужно выбрать вид отображения IP Components и кликнуть на m3_sops. 

navigator

После клика на m3_sops откроется новое окно Platform Designer в котором настраивается взаимосвязь имеющихся в системе компонентов.Меня интересует компонент sys_pll. Нужно выбрать его и справа в окне Parameters нажать кнопку Edit Parameters.

Тут уже открывается обычное окно редактирования параметров PLL.

ALTPLL

Была входная частота 50МГц, я поставил 100МГц. Но при этом выходная частота сигнала с0 у PLL была 50/5*2=20МГц. Теперь я умножитель ставлю равным единице и, таким образом, выходная частота остается такой же, как и раньше 20МГц. Два других выхода PLL сигналы c1 и c2 так же имели умножитель "2" и выходная частота у них получалась 100МГц. У мен же входная 100МГц, так что я просто ставлю умножитель в единицу и все. Свойства PLL я поменял, но по итогу выходные частоты остались такие же, как и были раньше. На процессоре будет 20МГц, на памяти SDRAM будет 100МГц.

Пожалуй основные изменения проекта сделаны, теперь можно компилировать и пробовать запускать в плате Марсоход3.

Обращаю внимание, что я в первый раз запускал проект в плате прямо с оригинальным загрузчиком, который использовался с платой DE10-Lite. Программа начального загрузчика скомпилирована и ее образ находится в файле ip/scbl.hex. Этот файл используется квартусом при компиляции проекта. Содержимое scbl.hex помещается в компонент onchip_ram системы. Это статическая память размером 64 килобайта. Загрузчик должен быть меньше этого объема. Настройки onchip_ram так же делаются в Platform Designer.

onchip ram

Для испытания проекта скомпилируйте его и загрузите в плату Марсоход3. На плате имеется встроенный программатор MBFTDI на базе двухканальной микросхемы FT2232H. Первый канал используется для программатора JTAG, а второй канал это просто последовательный порт который соединен с FPGA. Наш проект SCR1 имеет встроенный модуль последовательного порта UART. Через этот последовательный порт я могу подавать из консоли команды в начальный загрузчик. На компьютере нужно запустить терминал на последовательный порт, например, Putty или TeraTerm. Скорость связи 115200, 8 бит, 1 стоп, без четности.

teraterm

На этом скриншоте показан программатор MBFTDI и терминал TeraTerm. По нажатию в терминале кнопки "i" начальный загрузчик системы SCR1 выводит начальную информацию о версии SOC, используемой RISC-V ISA RV32IMC (о! есть умножитель и поддержка сжатых команд?), а так же назначенные диапазоны памяти и других устройств ввода вывода. Пока используется загрузчик от проекта к de10lite, поэтому он отображает такое же имя платформы.

Должен сказать, что пока семисегментный индикатор отображает какую-то белиберду и видимо перепутаны биты в сегментах. Это можно починить как на аппаратном уровне перетасовав биты, как и на программном уровне исправив загрузчик.

Как раз моя следующая задача будет исправить загрузчик, научиться его компилировать и встроить в мой проект для платы Марсоход3.

 

Добавить комментарий