Hello World на Tang Primer 20K под Linux

После обзора на Tang Primer 20K — стало очевидно, что она вызывает немалый интерес и было решено немедля сделать разбор о том, каким образом можно настроить свой ПК и IDE для того чтобы начать взаимодействовать с отладочной платой, которую я рассмотрел в прошлой статье. Изначально, до момента пока я не познакомился сам лично с ПЛИС от Gowin и не запустил демо-проект — юзабельность, скорость и простота работы с их IDE вызывала сомнение. Но как только попробовал — все опасения были развеяны и я остался доволен.

Опытом настройки я с вами хотел бы поделиться в этой статье. Всех интересующихся — я по традиции приглашаю под кат!

image

Скачиваем, всё что нужно для работы


Работа с Gowin и Tang Primer начинается с того, чтобы скачать архив c IDE с сайта Gowin. Для этого надо перейти на сайт и зарегистрироваться (или пролистать статью чуть ниже и скачать файл):

image

После несложной регистрации нужно перейти обратно по ссылке и скачать версию Education Edition:

image

Вообще — среда разработки доступна в двух версиях: Standard Edition и Education Edition, но для IDE Standard Edition требуется лицензия, которую можно попробовать получить у Gowin. Но если честно — я не пробовал и остановился на Education Edition т. к. она бесплатна в использовании.

Но есть ряд некоторых ограничений, которые могут быть существенными для некоторых разработчиков — Education Edition поддерживает меньшее количество моделей FPGA и включает в себя меньшее количество IP-ядер.

Поддерживаемые модели ПЛИС:

image


К счастью, 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:

image

Создадим новый проект, для этого жмём в New Project… и выбираем FPGA Design Project. Появится мастер создания нового проекта:

image

Выбираем модель нашего SoC — GW2A и жмём Next:

image

Смотрим саммари и нажимаем Finish:

image

Откроется главное окно IDE, теперь можно создать простой проект, типичных для подобных статей — Hello World, то есть простое мигание светодиодом.

image

Добавим к проекту новый Verilog-файл через File — New:

image


Обзовем файл как helloworld и выберем расширение .sv:

image


Пишем модуль-мигалку на SystemVerilog


В общем давайте сделаем модуль, который заставит отладку моргать светодиодом раз в секунду т. е. менять свое состояние раз в половину секунды. Решение задачи максимально простое: создаем модуль у которого будет внутри организован счётчик. Счётчик будет прибавлять свое значение с каждым тактовым импульсом. На плате Tang Primer 20K расположен кварцевый генератор с частотой 27 МГц, с него мы и возьмем тактовый сигнал:

image


Для того чтобы получить 0.5 секунды при мигании светодиодом — надо просто досчитать до 13500000. При превышении значения 13500000 у счетчика — обнуляем его и инвертируем логическое значение ножки.

Задействуем первый доступный для пользовательских операций светодиод, например L14:

image


Обобщая вышесказанное получается следующая логика модуля (специально для новичков):

image

Начнем с заготовки модуля, назовём его 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 запускаем синтез:

image


Внизу будет выведен лог синтеза, который говорит о том, что все закончилось успешно:

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:

image


Нас спросят создать ли cst-файл, соглашаемся:

image


Откроется окно FloorPlanner и необходимо перейти в меню I/O Constraints и в полях подставим значения пинов:

image


После установки нажимаем сохранить и закрываем окно:

image


Теперь в структуре проекта появился файл с constraints-правилами.

Place & Route


Переходим в меню Process и делаем двойной клик по Place & Route.

image


Будет запущен генерации 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 — и не обнаруживается плата. Выводится ошибка:

image

Перехожу в каталог с программатором и пробую сделать то же самое, но уже с запрашиваемыми правами. И лучше попробовать для начала из 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-переключателе, чтобы режим загрузки платы соответствовал тому, который подходит для перепрошивки:

image


После этого можно попробовать обнаружить отладку на шине 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. Это наверняка поможет разобраться с причинами того, что мешает прошивке платы.

Итак, после прошивки — можем обратить внимание, на плату и увидеть мигающий раз в секунду светодиод:

image


После того, как помигали светодиодом — вы можете ознакомиться с различными примерами из репозитория Sipeed. Там их предостаточно, чтобы поиграться с периферией и даже есть демо проекта на PicoRV32-based SoC с выводом в HDMI terminal.

Заключение


В общем тем, кто не знал с чего начать получили ответ на свой запрос. Но меня ужасно опечалил тот факт, что нет нормальной возможности прошивать плату без лишнего гемороя из IDE и тут пользователи Windows могут ликовать. Буду пристально следить за обновлениями как IDE так и программатора — надеюсь что проблему с прошивкой плат рано или поздно решат и с Gowin будет работать гораздо комфортнее. А пока — печаль-беда для LInux-пользователей.

Но не будем расстраиваться, потому что проект который я планирую сделать — написан на SystemVerilog и по своей сути будет универсальным и может быть реализован в итоге как на Gowin, так и Xilinx с Altera.

Пора, думаю, переходить от обзоров к рассмотрению более серьезных технических проблем и способов их решения. Ожидайте новых интересных статей! До встречи! :)


Возможно, захочется почитать и это:
mxuanbovcusqgmqdgugvpnql8vq.jpeg

© Habrahabr.ru