Основы AXI часть 6 – Введение в AXI4-Lite в Vitis HLS (часть 1)

Введение

В этом уроке мы будем изучать основы того как создавать пользовательские IP блоки с AXI4-Lite интерфейсом в Vitis HLS. Если вы еще не сталкивались с AXI и хотели бы познакомиться с основными терминами и основой, пожалуйста изучите урок  AXI Basics 1.

Примечание: Процесс создания IP блока с AXI в Vivado HLS отличается от процесса создания в Vitis HLS. Если вы хотите создать AXI IP в Vivado HLS, пожалуйста ознакомитесь с UG902.

AXI4-Lite является основой коммуникационного протокола AXI. Он часто используется для простых, низкопроизводителльных отображающих в память взаимодействий (к примеру, в/из контрольного и статусного регистров). 

AXI4-Lite интерфейс может одномоментно использоваться только для чтения (используя 2 канала чтения) или только для записи (используя 3 канала записи), как это видно из диаграммы выше.
В этом уроке, мы собираемся создать IP ядро s_axi_BUS_A которое будет является нашим AXI4-Lite интерфейсом:

 

К концу этого урока, вы будете:

  • Понимать основы создания AXI4-Lite интерфейса в Vitis HLS.
  • Узнаете о pragma директивах в Vitis HLS, которые определяют, как использовать AXI4 интерфейс.

Открытие примера AXI-Lite проекта 

Пример проекта для AXI4-lite доступен в Vitis HLS. Что бы открыть пример проекта для AXI-Lite, требуются следующие шаги:
1.    Открыть Vitis HLS GUI. Из появившегося окна, выбрать ‘Clone Examples’ что бы скопировать проект с примером для Vitis HLS из GitHub:

2.    В появившейся вкладке, выбрать куда проект будет сохранён и нажать OK:

3.    В следующем окне, проект с примером будет отображён в нижнем левом углу. Нужно раскрыть стрелку под ‘HLS Tiny Tutorials’ и ‘Working Tree’ что бы посмотреть структуру данного проекта.

4.    Прокрутить до момента, когда вы найдете пример interface_axi_lite. Кликнуть правой кнопкой на имени папки и выбрать опцию ‘Run and Open HLS Project’.

5.    По завершению, проект должен будет открыться в верхней левой вкладке. Два раза кликнуть на example.cpp и example_test.cpp что бы посмотреть исходный код и testbench.

Разбор исходного кода

Пример состоит из двух основных файлов:

Example.cpp – Код который будет синтезирован в RTL для дальнейшего создания нашего IP блока. Данный IP будет скомбинирован с другим IP блоком в Vivado Design Suite и в конечном счете размещен в вашем устройстве.

Example_test.cpp – Testbench который мы будем использовать для проверки правильности работы example.cpp. Алгоритм example.cpp проверяется сравнением его выходов с выполненным расчётным значением в testbench. Testbench в HLS всегда возвращает 0 если значение совпадает с возвращаемым результатом example.cpp. 

Если вы выберите example.cpp (в левой вкладке, папка Source), то исходный код будет открыт. Рассмотрим его более детально:

Аргументы функции

void example(char *a, char *b, char *c) 

Первое что вы увидите после входа в библиотеку будет функция example();. Если вы знакомы с основами разработки на С, вы знаете, что все операции ввода и вывода выполняются за нулевое время с помощью формальных аргументов функции (таких как char * a, char * b и char * c в приведенном выше примере).

В RTL, данные перемещаются в/из IP через порты ввода/вывода. Такие порты могут работать, используя специфические I/O протоколы (таких как AXI-lite, AXI4-Stream и т.д.) для того что бы стандартизировать взаимодействие между IP блоками.

Каждую часть данных, которую мы хотим послать в/из нашего IP следует специфицировать как отдельный аргумент функции в нашем main файле проекта. Потом это синтезируется в порты RTL.
Заметка: фактически порты могут быть созданы тремя разными способами, но основное внимание в этом уроке будет уделяться аргументам функций.

Порты могут быть получены из:

  • Любых специфицированных протоколов уровня функций.
  • Аргументов функции.
  • Глобальных переменных доступных top-level функции и определённых вне её зоны видимости.


Примечание: так как переменные в AXI-Lite интерфейсе являются аргументами функции, им нельзя присвоить значение по умолчанию в C коде. Следовательно, ни одному из регистров в интерфейсе AXI-Lite нельзя присвоить значение по умолчанию. Регистры могут быть проинициализированы ресетом с помощью команды ‘config_rtl’, но они не могут иметь значение по умолчанию. ( Пожалуйста, ознакомитесь с Controlling the Reset Behavior  для больших деталей).

Pragma интерфейс

В строках кода ниже мы можем увидеть наши pragma интерфейсы.
Рассмотрим каждый из этих компонентов:

#pragma HLS INTERFACE s_axilite port=a bundle=BUS_A
#pragma HLS INTERFACE s_axilite port=b bundle=BUS_A
#pragma HLS INTERFACE s_axilite port=c bundle=BUS_A
#pragma HLS INTERFACE s_axilite port=return bundle=BUS_A

Нам нужно определить входы и выходы нашего IP блока как s_axilite для того, чтобы использовать AXI-Lite протокол. Если этого не сделать, то эти входы и выходы данных могут быть синтезированы в обычные связи и не будут иметь советующих сигналов подтверждения. В этой ситуации, вход должен бы быть удержан стабильным до момента его чтения, что при неосторожности может привести к ошибкам.

Pragma интерфейс имеет следующий формат:

#pragma HLS interface <mode> port=<name> (register) bundle=<string>

Где:
<mode>: специфицирует режим интерфейсного протокола для аргументов функции. В данном уроке выбран s_axilite.

port = <name>:  специфицирует имя аргумента функции к которому применяется pragma интерфейс.

(register): Необязательное ключевое слово для регистрации (хранения) сигнала и любых ассоциированных с протоколом сигналов. Это позволяет сигналам сохраняться, по крайней мере, до последнего цикла выполнения функции. Этот вариант не применим к axilite. 

bundle=<string>: ключевое слово позволяет вручную сгруппировать сигналы порта в одну шину данных. Если возврат функции указан как интерфейс AXI4-Lite (т.е. строка 25 в примере кода), все порты данных автоматически объединяются в одну шину. Vitis HLS использовал бы по умолчанию имя bundle control как имя пакета по умолчанию, если бы мы явно не указали здесь имя пакета.

Это является обычной практикой, когда другое устройство, такое как ЦП, используется для настройки и управления запуском и остановкой работы блока.

s_axilite port=return: установка аргумента функции типа s_axilite и имени порта «return» которая создаст сигнал прерывания в блоке IP. Вы можете запрограммировать прерывание через интерфейс AXI4-Lite и файлы драйвера C. Более подробную информацию можно найти здесь.

Заметка: Если какой-либо аргумент функции верхнего уровня указан как интерфейс AXI4-Lite, возврат функции также должен быть указан как интерфейс AXI4-Lite.

Заметка 2: По умолчанию Vitis HLS автоматически назначает адрес для каждого порта, который сгруппирован в интерфейс AXI4-Lite. Vitis HLS предоставляет назначенные адреса в C Driver Files. Чтобы явно определить адрес, вы можете использовать опцию offset. В интерфейсе AXI4-Lite Vitis HLS резервирует адреса от 0x0000 до 0x000C для сигналов протокола ввода/вывода на уровне блоков и управления прерываниями.

Тело функции

*c += *a + *b;

В функции мы точно определяем, что мы хотим от нашего IP блока. В этом случае адрес нашего IP блока будет принимать два значения (a и b) и сохранять результат (c) в регистре. Чтобы протестировать функциональность, наш testbench выдаст значения функции example() для a и b, а потом сравнит их с собственными вычисленными значениями для a + b. Если результаты совпадают, testbench всегда должен возвращать 0,а симуляция должна пройти.

В следующей статье серии основы AXI Basics мы узнаем, как экспортировать наш адрес IP блока в Vivado Design Suite, чтобы мы могли подключить его к другим адресам IP или PS через интерфейс AXI Lite.

Оригинальная статья

Категория: High Level Synthesis | Добавил: soikadigital (31.08.2020)
Просмотров: 174 | Рейтинг: 0.0/0
Всего комментариев: 0
avatar