Российские технологии и цифровая экономика
ПоискRSS

Pcie и Ddr3 на ПЛИС gowin: как добиться стабильной передачи данных

5 минут чтения

PCIe и DDR3 на ПЛИС Gowin: как мы добились рабочей передачи данных

Привет! Меня зовут Владимир Заикин. Под руководством Семёна Григорьева я занимаюсь разработкой на ПЛИС в лаборатории YADRO в СПбГУ. В этой статье расскажу, как мы реализовали обмен данными по PCIe с платой Sipeed Tang Mega 138K Pro на базе кристалла Gowin GW5AST-138K.

Изначальная задача выглядела достаточно прямолинейно: устройство на ПЛИС должно принимать данные от компьютера по PCIe, складывать их в DDR3, а затем передавать пользовательской логике для обработки. Однако готовый пример от производителя оказался нерабочим: хост-программа сообщала об успешном завершении операции, но данные, поступающие в ПЛИС, всегда состояли из нулей. Поэтому вместо адаптации демонстрационного проекта пришлось практически полностью разбираться с трактом передачи самостоятельно.

Целью проекта было создание интерфейса для вычислителя на основе модели Interaction Nets, реализованного на Haskell с использованием Clash. Но прежде чем переходить к вычислительной части, требовалось наладить базовую инфраструктуру: устойчивый обмен по PCIe и корректную работу памяти DDR3. Результатом стали аппаратное описание на Verilog, Linux-драйвер и хост-программа на C. Материалы проекта доступны в подробном разборе PCIe и DDR3 на ПЛИС Gowin.

Как устроен обмен по PCIe

PCIe - это стандарт подключения периферийных устройств, объединяющий физический интерфейс и набор протоколов. Передача выполняется пакетами TLP - Transaction Layer Packets. Основными типами являются Memory Write для записи, Memory Read для чтения и Completion with Data для ответа на запрос чтения.

Размеры PCIe-пакетов задаются в dword, то есть блоках по четыре байта. Это важно учитывать при проектировании логики и программного обеспечения: данные выравниваются по 32-битным границам, а несоблюдение порядка байт или разрядности может привести к тому, что формально успешная транзакция будет содержать неверное содержимое.

После установления соединения хост настраивает BAR - Base Address Registers. Эти регистры определяют диапазоны адресов, выделенные устройству операционной системой. Когда процессор обращается к адресу внутри такого диапазона, PCIe Root Complex формирует TLP. Контроллер на ПЛИС сравнивает адрес пакета с диапазонами BAR и передаёт запрос пользовательской логике с учётом смещения.

В нашем проекте физический уровень обеспечивал SerDes внутри PCIe-контроллера Gowin. Контроллер выдавал пользовательской логике низкоуровневые RX- и TX-порты с TLP-пакетами. Их мы подключили к специализированному PCIe SGDMA IP. Этот блок скрывает значительную часть внутренней маршрутизации и преобразует PCIe-трафик в два интерфейса AXI4-Stream:

- H2C - Host to Card, передача данных от компьютера к ПЛИС;
- C2H - Card to Host, передача данных от ПЛИС к компьютеру.

Для настройки DMA используется BAR0. Пользовательской логике доступен BAR2, через который можно управлять собственными регистрами и запускать прикладные операции. Поскольку регистры имеют 64-битную ширину, BAR1 и BAR3 в этой конфигурации не используются.

Почему пример производителя не помог

Проблема с демонстрационным проектом заключалась не в одном очевидном дефекте. Хост-программа корректно обнаруживала устройство, выполняла настройку и сообщала об успешной передаче. Но при чтении буфера на стороне ПЛИС данные оказывались нулевыми. Такой сценарий особенно неудобен: PCIe-линк поднят, драйвер работает, ошибок на программном уровне нет, а полезная нагрузка теряется внутри тракта.

Дополнительную сложность создало появление нового PCIe SGDMA IP от Gowin в начале 2026 года. Старый пример перестал соответствовать актуальному набору компонентов, а обновлённого рабочего проекта производитель не предоставил. Поэтому мы решили строить решение вокруг свежего SGDMA-блока, проверяя каждый этап отдельно.

В процессе выяснилось, что особое внимание нужно уделить описанию регистров, порядку байт и правилам формирования команд DMA. Документация описывала интерфейсы на высоком уровне, но не всегда объясняла, в какой последовательности следует изменять управляющие поля и когда контроллер считает дескриптор готовым к обработке.

Архитектура собственного решения

Аппаратная часть проекта состоит из PCIe-контроллера, SGDMA, AXI4-Stream-трактов, контроллера DDR3 и пользовательской логики. Поток H2C принимает данные от хоста, после чего они направляются в память. Для обратного канала используется C2H. Управляющие регистры, доступные через BAR2, позволяют задавать параметры обмена, запускать тестовые операции и получать статус.

Отдельно пришлось проверить согласование тактовых доменов. PCIe, AXI4-Stream и DDR3 работают с разными частотами и сигналами готовности. Если игнорировать `valid/ready` или неправильно обработать переход между доменами, часть пакетов может потеряться даже при корректной работе каждого блока по отдельности.

Работа с DDR3 также требует аккуратной инициализации. До завершения калибровки памяти нельзя считать буфер доступным для DMA. Поэтому в управляющей логике мы добавили проверку готовности DDR3 и разрешали передачу только после успешного старта контроллера. Такой подход помогает отличить ошибку PCIe от проблемы памяти.

Программная часть включает драйвер Linux и пользовательскую программу на C. Драйвер отвечает за обнаружение устройства, отображение BAR в адресное пространство, настройку DMA и обмен служебной информацией. Хост-программа выделяет буферы, заполняет их тестовыми шаблонами, запускает передачу и проверяет результат.

Отладка и проверка

Для диагностики использовались последовательности с легко узнаваемым содержимым: счётчики, повторяющиеся шаблоны и различные значения в соседних dword. Это позволило быстро определить, где именно возникает ошибка - при формировании TLP, передаче через DMA, записи в DDR3 или обратном чтении.

Важную роль сыграла аппаратная индикация. На плате отображались состояния PCIe-линка, готовность DDR3, запуск H2C- и C2H-операций, а также признаки завершения транзакции. Такие сигналы значительно ускорили отладку: вместо предположений по логам можно было сразу увидеть, на каком этапе остановился тракт.

После исправления порядка байт и последовательности настройки SGDMA данные начали стабильно проходить от хоста в ПЛИС, сохраняться в DDR3 и возвращаться обратно без искажений. Таким образом, удалось подтвердить не только факт установления PCIe-соединения, но и полную функциональность цепочки "хост - DMA - память - DMA - хост".

При этом у решения остаются ограничения. Пока оно ориентировано на стендовую проверку и не претендует на универсальный высокопроизводительный драйвер. Требуют дальнейшей доработки обработка ошибок, параллельные очереди DMA, оптимизация размера пакетов и более глубокая интеграция с пользовательской логикой.

Что показал проект

Главный вывод заключается в том, что разработка на ПЛИС редко сводится к соединению готовых IP-блоков по схеме из документации. Даже если PCIe-контроллер, DMA и DDR3 по отдельности проходят тесты, их совместная работа может выявить проблемы с тактированием, выравниванием, порядком байт и управляющими протоколами.

Надёжная отладка ПЛИС требует проверять систему поэтапно: сначала физический линк, затем BAR-доступ, после этого простой обмен без DMA, далее работа SGDMA и только потом подключение DDR3 и прикладной обработки. Такой порядок заметно сокращает область поиска неисправности.

Особенно полезным оказался принцип минимального воспроизводимого теста. Вместо сложной вычислительной нагрузки мы сначала передавали небольшие буферы с известным содержимым, фиксировали состояния регистров и сравнивали данные на каждом участке пути. Благодаря этому удалось отделить ошибки инфраструктуры от проблем пользовательской логики.

В итоге мы получили рабочий стенд для PCIe на ПЛИС, DDR3 на ПЛИС Gowin и дальнейших экспериментов с вычислителем. Проект показал, что даже при недостаточно стабильной демонстрационной базе производителя можно построить функционирующее решение, если последовательно исследовать протоколы, аппаратные интерфейсы и программную часть. Подробное описание регистров, структуры тестов и исходных файлов представлено в материалах о разработке PCIe на ПЛИС.

Прокрутить вверх