Опытом настройки я с вами хотел бы поделиться в этой статье. Всех интересующихся — я по традиции приглашаю под кат!
❯ Скачиваем, всё что нужно для работы
Работа с Gowin и Tang Primer начинается с того, чтобы скачать архив c IDE с сайта Gowin. Для этого надо перейти на сайт и зарегистрироваться (или пролистать статью чуть ниже и скачать файл):
После несложной регистрации нужно перейти обратно по ссылке и скачать версию Education Edition:
Вообще — среда разработки доступна в двух версиях: Standard Edition и Education Edition, но для IDE Standard Edition требуется лицензия, которую можно попробовать получить у Gowin. Но если честно — я не пробовал и остановился на Education Edition т. к. она бесплатна в использовании.
Но есть ряд некоторых ограничений, которые могут быть существенными для некоторых разработчиков — Education Edition поддерживает меньшее количество моделей FPGA и включает в себя меньшее количество IP-ядер.
Поддерживаемые модели ПЛИС:
К счастью, GW2A-LV18PG256C8/I7 aka GW2A-18C которая установлена на плате Primer 20K поддерживается образовательной версией и мы можем идти дальше.
Итак, скачиваем файл по ссылке — проверял, прямая ссылка вроде работала, но лучше зарегистрироваться, чтобы обновляться и иметь доступ документации. Поле скачивания установка заключается в том, чтобы распаковать архив, присвоить права на исполнение файлу gw_ide и запустить его:
tar xvf Gowin_V1.9.8.11_Education_linux.tar.gz
cd Gowin_V1.9.8.11_Education_linux/IDE/bin/
chmod +x ./gw_ide
pwd
/home/megalloid/devel/gowin/distr/Gowin_V1.9.8.11_Education_linux/IDE/bin
Можно сделать быстрый alias на запуск IDE:
vim $(echo $HOME)/.bashrc
И добавим в конец файла удобную команду, я выбрал gowin_ide:
alias gowin_ide=’/home/megalloid/devel/gowin/distr/Gowin_V1.9.8.11_Education_linux/IDE/bin/gw_ide’
После этого можно перезапустить терминал и теперь достаточно просто ввести gowin_ide и запустится IDE:
Создадим новый проект, для этого жмём в New Project… и выбираем FPGA Design Project. Появится мастер создания нового проекта:
Выбираем модель нашего SoC — GW2A и жмём Next:
Смотрим саммари и нажимаем Finish:
Откроется главное окно IDE, теперь можно создать простой проект, типичных для подобных статей — Hello World, то есть простое мигание светодиодом.
Добавим к проекту новый Verilog-файл через File — New:
Обзовем файл как helloworld и выберем расширение .sv:
❯ Пишем модуль-мигалку на SystemVerilog
В общем давайте сделаем модуль, который заставит отладку моргать светодиодом раз в секунду т. е. менять свое состояние раз в половину секунды. Решение задачи максимально простое: создаем модуль у которого будет внутри организован счётчик. Счётчик будет прибавлять свое значение с каждым тактовым импульсом. На плате Tang Primer 20K расположен кварцевый генератор с частотой 27 МГц, с него мы и возьмем тактовый сигнал:
Для того чтобы получить 0.5 секунды при мигании светодиодом — надо просто досчитать до 13500000. При превышении значения 13500000 у счетчика — обнуляем его и инвертируем логическое значение ножки.
Задействуем первый доступный для пользовательских операций светодиод, например L14:
Обобщая вышесказанное получается следующая логика модуля (специально для новичков):
Начнем с заготовки модуля, назовём его blink и объявим входной и выходной порт для модуля. В теле модуля опишем эту логику на SystemVerilog:
module blink(input sys_clk, output led_l14);
// Задаем регистр для хранения записи о текущем состоянии светодиода
reg r_led;
// Задаем регистр для хранения значения счётчика, использующегося в задержке
reg [31:0] counter;
// Тут мы задаем действия которые должны быть выполнены при старте программы
initial begin
counter <= 32'b0; // Обнуляем счётчик
r_led <= 1'b0; // Делаем запись о состоянии светодиода
end
// Тут описываем поведенческий блок, который будет
// реагировать на ниспадающий фронт тактовой частоты
always@(posedge sys_clk)
begin
counter <= counter + 1'b1; // Увеличиваем счетчик
if(counter > 13500000) // Если счетчик больше некоторого условного значения
begin
r_led <= !r_led; // Инвертируем запись о значении состоянии светодиода
counter <= 32'b0; // Сбрасываем счетчик
end
end
assign led_l14 = r_led; // Присваиваем текущее состояние ножке (условно)
endmodule
Записываем это в файл и сохраняем.
❯ Synthesize
Теперь модуль готов к синтезу и базовой проверке синтаксиса. Переходим в меню Process и двойным кликом по Synthesize запускаем синтез:
Внизу будет выведен лог синтеза, который говорит о том, что все закончилось успешно:
GowinSynthesis start
Running parser ...
Analyzing Verilog file '/home/megalloid/hello_world/src/helloworld.sv'
Compiling module 'blink'("/home/megalloid/hello_world/src/helloworld.sv":1)
NOTE (EX0101) : Current top module is "blink"
[5%] Running netlist conversion ...
Running device independent optimization ...
[10%] Optimizing Phase 0 completed
[15%] Optimizing Phase 1 completed
[25%] Optimizing Phase 2 completed
Running inference ...
[30%] Inferring Phase 0 completed
[40%] Inferring Phase 1 completed
[50%] Inferring Phase 2 completed
[55%] Inferring Phase 3 completed
Running technical mapping ...
[60%] Tech-Mapping Phase 0 completed
[65%] Tech-Mapping Phase 1 completed
[75%] Tech-Mapping Phase 2 completed
[80%] Tech-Mapping Phase 3 completed
[90%] Tech-Mapping Phase 4 completed
[95%] Generate netlist file "/home/megalloid/hello_world/impl/gwsynthesis/hello_world.vg" completed
[100%] Generate report file "/home/megalloid/hello_world/impl/gwsynthesis/hello_world_syn.rpt.html" completed
GowinSynthesis finish
❯ Constraint
Следующим шагом необходимо создать constraint-файл в котором мы опишем для IDE какие пины мы будем использовать на плате для входных и выходных сигналов. Для этого кликаем на FloorPlanner:
Нас спросят создать ли cst-файл, соглашаемся:
Откроется окно FloorPlanner и необходимо перейти в меню I/O Constraints и в полях подставим значения пинов:
После установки нажимаем сохранить и закрываем окно:
Теперь в структуре проекта появился файл с constraints-правилами.
❯ Place & Route
Переходим в меню Process и делаем двойной клик по Place & Route.
Будет запущен генерации bitstream-файла, который будет представлять собой бинарный файл для прошивки платы. В случае успешной генерации будет выведен соответствующий лог:
Reading netlist file: "/home/megalloid/hello_world/impl/gwsynthesis/hello_world.vg"
Parsing netlist file "/home/megalloid/hello_world/impl/gwsynthesis/hello_world.vg" completed
Processing netlist completed
Reading constraint file: "/home/megalloid/hello_world/src/hello_world.cst"
Physical Constraint parsed completed
Running placement......
[10%] Placement Phase 0 completed
[20%] Placement Phase 1 completed
[30%] Placement Phase 2 completed
[50%] Placement Phase 3 completed
Running routing......
[60%] Routing Phase 0 completed
[70%] Routing Phase 1 completed
[80%] Routing Phase 2 completed
[90%] Routing Phase 3 completed
Running timing analysis......
[95%] Timing analysis completed
Placement and routing completed
Bitstream generation in progress......
Bitstream generation completed
Running power analysis......
[100%] Power analysis completed
Generate file "/home/megalloid/hello_world/impl/pnr/hello_world.power.html" completed
Generate file "/home/megalloid/hello_world/impl/pnr/hello_world.pin.html" completed
Generate file "/home/megalloid/hello_world/impl/pnr/hello_world.rpt.html" completed
Generate file "/home/megalloid/hello_world/impl/pnr/hello_world.rpt.txt" completed
Generate file "/home/megalloid/hello_world/impl/pnr/hello_world.tr.html" completed
Fri Jul 14 23:48:34 2023
❯ Прошивка платы в Ubuntu 22.04 через IDE
Теперь, после сборки, казалось бы можно прошивать плату, но не тут то было. Не обошлось в случае Gowin без прыгания на граблях. Не удавалось прошить плату непосредственно из IDE. Нажимаешь Program Device — и не обнаруживается плата. Выводится ошибка:
Перехожу в каталог с программатором и пробую сделать то же самое но уже с запрашиваемыми правами. И лучше попробовать для начала из Cli-версии программатора:
cd devel/gowin/distr/Programmer/bin
./programmer_cli --scan
Видим вывод о той же ошибке:
Error: Please run with root privileges while using the FT2CH cable.
rmmod: ERROR: ../libkmod/libkmod-module.c:799 kmod_module_remove_module() could not remove 'ftdi_sio': Operation not permitted
rmmod: ERROR: could not remove module ftdi_sio: Operation not permitted
rmmod: ERROR: Module usbserial is in use by: ftdi_sio
Scanning!
Target Cable: Gowin USB Cable(FT2CH)/0/0/null@2.5MHz
Error: No Gowin devices found!
Cost 0.12 second(s)
Пробуем дать ему этих самых прав, только запустив через sudo. Но теперь пишет, что якобы нет Gowin-устройств:
sudo ./programmer_cli --scan
Scanning!
Target Cable: Gowin USB Cable(FT2CH)/0/0/null@2.5MHz
Error: No Gowin devices found!
Cost 0.01 second(s)
В итоге, не найдя способа решить эту проблему — я обратился к рабочему варианту — программатору openFPGALoader.
❯ Прошивка платы в Ubuntu через openFPGALoader
Для этого необходимо настроить openFPGALoader, именно с его помощью мы будем загружать прошивку на плату. Итак, для начала, если у вас Ubuntu как у меня: установим необходимые зависимости:
sudo apt-get install libftdi1-2 libftdi1-dev libhidapi-hidraw0 libhidapi-dev
libudev-dev zlib1g-dev cmake pkg-config make g++
Потом склонируем исходники себе и скомпилим их:
git clone https://github.com/trabucayre/openFPGALoader.git
cd openFPGALoader
mkdir build
cd build
Для сборки версии со статической линковкой (когда все необходимые для работы библиотеки интегрируются в исполняемый файл) к cmake-команде добавьте флаг:
cmake -DBUILD_STATIC=ON ../
Или можно просто скомпилить и потом установить без доп.аргументов:
cmake ../
make -j$(nproc)
sudo make install
После сборки нужно прописать правила udev, чтобы не было проблем с доступом к железу со стороны собранного софта:
sudo cp 99-openfpgaloader.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger
Нужно еще убедиться, что текущий пользователь состоит в группе plugdev. Например, у меня это выглядит вот так:
megalloid@megalloid-dell:~$ groups
megalloid adm dialout cdrom sudo dip plugdev lpadmin lxd sambashare bladerf
При необходимости внести его в эту группу:
sudo usermod -a $USER -G plugdev
Только изменения вносятся не сразу и необходимо сделать Logout из системы и зайти обратно. После этого необходимо обязательно включить первый пин на DIP-переключателе, чтобы режим загрузки платы соответствовал тому, который подходит для перепрошивки:
После этого можно попробовать обнаружить отладку на шине USB:
megalloid@megalloid-dell:~$ openFPGALoader --detect
No cable or board specified: using direct ft2232 interface
Jtag frequency : requested 6.00MHz -> real 6.00MHz
index 0:
idcode 0x81b
manufacturer Gowin
family GW2A
model GW2A(R)-18(C)
irlength 8
Так, плата детектится, теперь для перепрошивки платы нужно ввести команду и в качестве аргумента указать тип прошиваемой платы и путь к bitstream-файлу. Все файлы после синтеза и роутинга хранятся в директории impl/pnr:
megalloid@megalloid-dell:~/devel/gowin/projects/hello_world/impl/pnr$ ll
total 6060
drwxrwxr-x 2 megalloid megalloid 4096 июл 14 23:48 ./
drwxrwxr-x 5 megalloid megalloid 4096 июл 14 23:38 ../
-rw-rw-r-- 1 megalloid megalloid 280 июл 14 23:48 cmd.do
-rw-rw-r-- 1 megalloid megalloid 550 июл 14 23:48 device.cfg
-r-xr-xr-x 1 megalloid megalloid 577178 июл 14 23:48 hello_world.bin*
-r-xr-xr-x 1 megalloid megalloid 577672 июл 14 23:48 hello_world.binx*
-rw-rw-r-- 1 megalloid megalloid 1712 июл 14 23:48 hello_world.db
-r-xr-xr-x 1 megalloid megalloid 4619303 июл 14 23:48 hello_world.fs*
-rw-rw-r-- 1 megalloid megalloid 1299 июл 14 23:48 hello_world.log
-rw-rw-r-- 1 megalloid megalloid 47622 июл 14 23:48 hello_world.pin.html
-rw-rw-r-- 1 megalloid megalloid 6724 июл 14 23:48 hello_world.power.html
-rw-rw-r-- 1 megalloid megalloid 52873 июл 14 23:48 hello_world.rpt.html
-rw-rw-r-- 1 megalloid megalloid 40074 июл 14 23:48 hello_world.rpt.txt
-rw-rw-r-- 1 megalloid megalloid 6985 июл 14 23:48 hello_world.timing_paths
-rw-rw-r-- 1 megalloid megalloid 7760 июл 14 23:48 hello_world_tr_cata.html
-rw-rw-r-- 1 megalloid megalloid 226333 июл 14 23:48 hello_world_tr_content.html
-rw-rw-r-- 1 megalloid megalloid 347 июл 14 23:48 hello_world.tr.html
Нас интересует файл hello_world.fs, его и зальём в SRAM т.е. без перепрошивки:
openFPGALoader -b tangprimer20k hello_world.fs
Jtag frequency : requested 6.00MHz -> real 6.00MHz
Parse file Parse hello_world.fs:
Done
DONE
Jtag frequency : requested 2.50MHz -> real 2.00MHz
erase SRAM Done
Flash SRAM: [==================================================] 100.00%
Done
Если хочется зашить bitstream на Flash — достаточно добавить флаг -f в команду. Сразу предупрежу о том, что плата в большинстве случаем шьётся не с первого раза (почему-то, не было времени на разбирательства), будьте готовы к тому, что придётся перетыкать кабели, повторяя прошивку и танцы с бубнами:
openFPGALoader -b tangprimer20k -f hello_world.fs
write to flash
Jtag frequency : requested 6.00MHz -> real 6.00MHz
Parse file Parse hello_world.fs:
Done
DONE
Jtag frequency : requested 2.50MHz -> real 2.00MHz
Jtag frequency : requested 10.00MHz -> real 6.00MHz
erase SRAM Done
Detail:
Jedec ID : 0b
memory type : 40
memory capacity : 16
EDID + CFD length : 0b
EDID : 1640
CFD :
Detail:
Jedec ID : 0b
memory type : 40
memory capacity : 16
EDID + CFD length : 0b
EDID : 1640
CFD :
RDSR : 00
WIP : 0
WEL : 0
BP : 0
TB : 0
SRWD : 0
flash chip unknown: use basic protection detection
Erasing: [==================================================] 100.00%
Done
Writing: [==================================================] 100.00%
Done
В этот раз плата прошилась с четвертой попытки. Думаю закажу еще одну отладку и другой программатор, возможно это специфика моего SoM и Onboard-программатора. Пока не понял в чем проблема.
В дополнение к этому. Для расширенного вывода информации о процессе прошивки нужно добавить аргумент --verbose. Это наверняка поможет разобраться с причинами того, что мешает прошивке платы.
Итак, после прошивки — можем обратить внимание, на плату и увидеть мигающий раз в секунду светодиод:
После того, как помигали светодиодом — вы можете ознакомиться с различными примерами из репозитория Sipeed. Там их предостаточно, чтобы поиграться с периферией и даже есть демо проекта на PicoRV32-based SoC с выводом в HDMI terminal.
❯ Заключение
В общем тем, кто не знал с чего начать получили ответ на свой запрос. Но меня ужасно опечалил тот факт, что нет нормальной возможности прошивать плату без лишнего гемороя из IDE и тут пользователи Windows могут ликовать. Буду пристально следить за обновлениями как IDE так и программатора — надеюсь что проблему с прошивкой плат рано или поздно решат и с Gowin будет работать гораздо комфортнее. А пока — печаль-беда для LInux-пользователей.
Но не будем расстраиваться, потому что проект который я планирую сделать — написан на SystemVerilog и по своей сути будет универсальным и может быть реализован в итоге как на Gowin, так и Xilinx с Altera.
Пора, думаю, переходить от обзоров к рассмотрению более серьезных технических проблем и способов их решения. Ожидайте новых интересных статей! До встречи! :)
Автор: Андрей