- PVSM.RU - https://www.pvsm.ru -
Этот пост написан с целью показать разработчикам дизайна для ПЛИС, как с наименьшими затратами времени и сил начать работать с шиной PCI-express на платформе Ahronix Speedster22i. В статье описывается организация проекта, адаптация которого к конкретным требованиям разработчика сводится к несложной модификации исходного текста всего одного модуля, что позволяет подключиться к шине PCIe хост-компьютера буквально за 1 час. Надеюсь, разработчикам на других платформах эта статья будет так же небезинтересна.
В ПЛИС Speedster22i HD1000 имеется два аппаратных ядра PCIe, сертифицированных PCI-SIG® [1] на соответствие спецификации PCIe 3.0, а в отладочной плате Speedster22i HD1000 Development Kit (о которой я писал в предыдущем посте [2]) одно из этих ядер выведено на PCIe разъем. Через интерфейс PCIe очень удобно осуществлять взаимодействие отладочной платы с хост-компьютером. По сути, это единственное высокоскоростное решение для означенной цели. Альтернативой использования PCIe для связи отладочной платы с хост-компьютером может служить лишь встроенный com-порт, который на несколько порядков медленнее. Все остальные решения требуют больших или меньших аппаратных изощрений, как минимум, потребуется применение преобразователей уровня сигнала.
У компании Achronix имеется референс-дизайн, демонстрирующий работу аппаратного ядра PCIe во всей красе – ядро работает в режиме target с доступом как непосредственно CPU, так и через механизм DMA по чтению и записи. Я проверил, все работает отлично. Но этот дизайн оказалось достаточно сложно модифицировать под собственные цели в силу недостаточной модульности и излишней усложненности кода на языке Verilog. Поэтому было принято решение на основе фирменного дизайна создать собственный вариант, убрав из него все, связанное с обменом через DMA, а так же структурировав его таким образом, чтобы явно выделить в нем модули с неизменяемым кодом и модули, код которых требуется модифицировать для адаптации к конкретным задачам разработчика. В результате получился простой, хорошо структурированный проект, адаптация которого под конкретные задачи разработчика сводится к несложному изменению кода всего одного модуля.
Фирменной особенностью ПЛИС Achronix является наличие аппаратно реализованных IP-ядер контроллеров таких интерфейсов, как PCIe, DDR3, 100/40/10G Ethernet и Interlaken. Эти аппаратные ядра обеспечивают все, что необходимо для функционирования указанных интерфейсов, единственно что требуется от разработчика — написать собственные модули сопряжения с этими контроллерами. В результате объем работы драматически сокращается. Кроме того, существенно упрощается достижение требуемого тайминга. В случае дизайна PCIe, понадобилось всего несколько модулей сопряжения, причем большинство из них было взято из фирменного референс-дизайна.
В проекте реализован доступ к трем 128-разрядным регистрам. PCIe ядро сконфигурировано на 3 BARа: BAR0 – 64KB, BAR1 и BAR2 – по 8 KB. Доступ к регистрам осуществляется через BAR1. Наличие 3х BARов обусловлено требованиями совместимости с используемым драйвером. Описание регистров приводится ниже:
Имя | Смещение в АП BAR1 | тип | Описание |
---|---|---|---|
R0 | 0 | RO | {4{32’hDEADBEEF}} |
R1 | 20h | RW RW |
Биты [7:0] — вывод на линейку светодиодов Биты [127:8] – не используются |
R2 | 40h | RO RW |
Биты [7:0] – чтение линейки выключателей Биты [127:8] – не используются |
При модернизации проекта первое, что было сделано – удален код, связанный с обменом данными через DMA. После этого для подключения к ядру были использованы каналы чтения и записи target_read и target_write. Далее, была определена структура модулей, изображенная на рисунке:
Всего получилось 4 модуля (в некоторые из них входят подмодули)
Состав модулей:
В этом проекте для достижения необходимой разработчику функциональности требуется изменить исходный код всего одного модуля – lbus_registers.v. Все остальные модули при этом используются как есть, без единой переделки. При этом модуль lbus_registers.v может использоваться как шаблон, в который добавляется необходимая разработчику функциональность. Таким образом, чтобы получить работающий интерфейс с несколькими регистрами на шине PCIe, требуются затраты времени на дописывание кода модуля не более часа.
Для генерации ядра можно воспользоваться генератором ядер оболочки ACE. Все заданные параметры сохраняются в файле с расширением .axip, который в любой момент можно отредактировать. Результатом работы генератора являются текстовые файлы на языках Verilog и VHDL. Снимок экрана в процессе генерации ядра показан на рисунке:
Аппаратное ядро PCI включает в себя несколько интерфейсов, но нас интересует интерфейс target. Через этот интерфейс подключаются регистры, выступающие как пассивные устройства, а процессор выступает в качестве активного устройства. Интерфейс target состоит из 4х каналов: задания адреса записи, данных записи, задания адреса чтения и чтения данных. Каналы записи и чтения работают независимо друг от друга. Ниже приведены временные диаграммы транзакций записи и чтения. На этих же диаграммах показаны сигналы локальной шины.
Локальная шина имеет очень простую структуру. Она состоит из двух независимых каналов – записи и чтения и может быть настроена на разную ширину слова. В данном проекте используются слова шириной 128 бит.
Интерфейс локальной шины, реализованный в модуле lbus_registers.v обеспечивает запись в регистры без задержки и чтение с задержкой на 1 такт. Реальные задержки, однако, несколько больше, т.к. подмодули, входящие в модуль pci_target_bus_ctrl.v вносят свой вклад в латентность транзакций записи и чтения.
Имплементация проекта состоит из двух этапов – этапа синтеза и этапа трассировки.
Для имплементации была выбрана следующая организация каталогов:
pci_simple |--- src |--- syn |--- tr |--- tools
В каталоге src размещены исходные файлы на языке Verilog. В каталоге syn находятся файлы, необходимые для синтеза с помощью программы synplify, а в каталоге tr – файлы, необходимые для этапа трассировки. Так же в этом каталоге по умолчанию находятся сгенерированные ядра. В каталоге tools содержатся драйвера и программа PciExpress, помощью которой можно читать и записывать данные в регистры, подключенные к шине PCIe.
В каталоге syn находится файл проекта pcie_simple_design.prj. Этот файл необходимо указать программе синтеза synplify-pro, разработанной компанией Synopsys. Результатом работы этой программы является файл pcie_simple_design.vma в подкаталоге syn/rev_1. Этот файл является входным для следующего этапа – трассировки. Снимок экрана во время выполнения этапа синтеза показан ниже:
Этап трассировки осуществляется программой ACE собственной разработки компании Achronix. В каталоге tr находится файл проекта pci-simple.prj, который надо указать программе ACE. По окончании этапа трассировки в подкаталоге tr/impl_1/output появится файл прошивки pci-simple-design.jam, который загружается непосредственно в ПЛИС. Снимок экрана в процессе выполнения этапа трассировки:
Имеются всего два файла констрейнтов – один описывает тактовые цепи, а другой определяет используемые пины ввода-вывода. Файлы находятся в каталоге tr и имеют имена pcie_simple_design.sdc и pcie_simple_design.pdc соответственно. Они уже подключены через файлы проектов к программам синтеза и трассировки.
Результаты трассировки | |||
---|---|---|---|
Frequency (MHz) | |||
Clock/Group | Target | Achieved | Meets Timing |
user_clk | 212.5 | 308.5 | yes (+45.2%) |
core_clk | 212.5 | 433.5 | yes (+104.0%) |
sbus_clk | 50.0 | 138.7 | yes (+177.5%) |
Tck | 10.0 | 175.4 | yes (+1653.6%) |
Нас интересует тактовая группа user_clk, на которую подключены пользовательские регистры. Как видно, при заданной частоте 212.5 MHz, был достигнут результат 308.5 MHz, т.е. на 45% выше, чем требуется.
Ресурс | Занято |
---|---|
RLBs | 0.520% |
LUT4 Sites | 0.410% |
DFF Sites | 0.520% |
MUX2 Sites | 0.010% |
ALU Sites | 0.170% |
LRAM Sites | 1.280% |
BRAM Sites | 0.190% |
BMULT Sites | 0.000% |
I/O Pad Sites | 1.980% |
Data Pads | 1.740% |
Clock Pads | 12.50% |
Reset Pads | 0.000% |
Для подключения к хост-компьютеру требуется драйвер. При определенных условиях можно использовать драйвер из фирменного референс-дизайна. С этим драйвером работает приложение PciExpress.exe, через которое можно обращаться к регистрам, подключенным к шине PCIe. Чтобы можно было использовать эти средства, требуется сохранить структуру BARов оригинального дизайна и сохранить значения параметров VendorID и DeviceID.
Чтобы начать работать с хост-компьютером с операционной системой Windows, необходимо выполнить следующие действия:
На нижеследующем рисунке как раз показан результат чтения регистра со смещением 0 в адресном пространстве BAR1:
Для того, чтобы исходный код можно было использовать в собственных проектах, требуется ввести в дизайн регистры, необходимые разработчику. Все пользовательские регистры находятся в модуле lbus_registers.v и при его кастомизации требуется осуществить следующие простые действия:
Покажем, как осуществить эти действия на практике.
• Определяем имя регистра и его длину:
reg [AXI_DATA_WIDTH-1:0] my_register;
• Определяем стробы записи и чтения для этого регистра:
wire selw_my_register;
wire selr_my_register;
• Пишем always-блок для этого регистра. Это удобно делать с помощью оператора generate.
В самом простом случае код выглядит так:
genvar i;
generate
for (i = 0; i < AXI_BE_WIDTH; i = i + 1)
begin: leds_lanes
always @( posedge clk or negedge rst_n )
if (!rst_n) my_register [7+ 8*i: 8*i] <= 8'h0;
else
if (selw_my_register && lbus_wr_be[i] )
my_register[7+ 8*i: 8*i] <= lbus_wr_data[7+ 8*i: 8*i];
else
my_register [7+ 8*i: 8*i] <= my_register [7+ 8*i: 8*i];
end
endgenerate
Если требуется более сложная обработка отдельных разрядов, то, always-блок, естественно усложнится и, возможно, проще будет написать код явно, не используя оператор generate.
• Добавляем в список параметров строчку:
parameter ADDR_MY_REGISTER = 32'h1234_5678
,
где – вместо 32'h1234_5678 указываем реальное смещение в байтах в требуемом адресном пространстве
• Пишем формулы для сигналов выбора регистра:
selw_my_register = reg_wr_hit & (lbus_wr_addr[REG_ADDR_WIDTH-1:0] == ADDR_MY_REGISTER [REG_ADDR_WIDTH+AXI_REMAIN_WIDTH-1:AXI_REMAIN_WIDTH]);
selr_my_register = reg_rd_hit & (lbus_rd_addr[REG_ADDR_WIDTH-1:0] == ADDR_MY_REGISTER [REG_ADDR_WIDTH+AXI_REMAIN_WIDTH-1:AXI_REMAIN_WIDTH]);
• В блок always_comb
always_comb
begin
case (1'b1)
…
endcase
end
добавляем новую веточку внутри оператора case:
selr_my_register: c_reg_rd_data = my_register;
Вышеописанные действия повторяем для каждого пользовательского регистра.
Интерфейс модуля определен следующим образом:
module lbus_registers #(
parameter BAR_NMB = 3'd0
parameter AXI_DATA_WIDTH = 128,
parameter AXI_BE_WIDTH = AXI_DATA_WIDTH/8, // AXI Len Width
parameter LBUS_ADDR_WIDTH = 12, // 64 KB expected for NWL Reference Design
parameter REG_ADDR_WIDTH = LBUS_ADDR_WIDTH, // 64 KB expected for NWL Reference Design
parameter ADDR_R0 = 32'h000_0000,
parameter ADDR_R1 = 32'h000_0020,
parameter ADDR_R2 = 32'h000_0040
)
(
input wire rst_n,
input wire clk,
//
input wire [7:0] switches,
output wire [AXI_DATA_WIDTH-1: 0] rg1_out,
output wire [AXI_DATA_WIDTH-1: 0] rg2_out,
output wire [71: 0] debug_bus,
// Local Bus channel
input wire [LBUS_ADDR_WIDTH-1:0] lbus_wr_addr,
input wire [2:0] lbus_wr_region,
input wire lbus_wr_en,
input wire [AXI_BE_WIDTH-1:0] lbus_wr_be,
input wire [AXI_DATA_WIDTH-1:0] lbus_wr_data,
//
input wire [LBUS_ADDR_WIDTH-1:0] lbus_rd_addr,
input wire [2:0] lbus_rd_region,
output wire [AXI_DATA_WIDTH-1:0] lbus_rd_data
);
Параметры настройки модуля lbus_registers.v перечислены в таблице:
Имя параметра | Значение по умолчанию | Диапазон значений | Описание |
---|---|---|---|
BAR_NMB | 3'd0 | 3’d0-3’d7 | Номер BARа, на который настроен адресный селектор |
AXI_DATA_WIDTH | 128 | 128, 256 | Размер шины данных |
AXI_BE_WIDTH | AXI_DATA_WIDTH/8 | — | Не следует менять вручную |
LBUS_ADDR_WIDTH | 12 | 8-15 | Задает разрядность локальной шины адреса. Обычно соответствует размеру АП самого большого BARа |
REG_ADDR_WIDTH | LBUS_ADDR_WIDTH | <=LBUS_ADDR_WIDTH | Задает разрядность АП локальной шины адреса, соответствующей выбранному BARу |
ADDR_R0 ADDR_R1 ADDR_R2 |
32'h000_0000 | Зависит от размера BARа | Адрес регистра R0 (R1,R2). Адреса регистров указываются всегда в байтах и соответствуют их смещению в адресном пространстве BARа |
Отладка осуществляется с помощью внутреннего анализатора сигналов, для чего в проекте используется модуль ACX_SNAPSHOT.v, подключаемый директивой условной компиляции `define USE_SNAPSHOT. Документация по организации внутрисхемной отладки находится на сайте Achronix в файле Snapshot User Guide.pdf.
Даже такая непростая задача, как подключение к шине PCI-express решается на платформе Achronix Speedster22i легко и, главное, быстро. Создать работающий проект на базе аппаратного ядра PCIe оказалось не просто, а очень просто.
Рассказ о других аппаратных ядрах ПЛИС Achronix Speedster22i планируется по мере их освоения. В последующих постах будет рассказано про ядра DDR-3 и 100G Ehernet.
1. Achronix объявляет соответствие своих аппаратных ядер PCI Express в ПЛИС Speedster22i спецификации PCI-SIG® (англ.) www.achronix.com/wp-content/uploads/pr/2014_May_PCI-SIG.pdf [3]
2. Схема отладочной платы HD1000 dev kit (англ.) 22iHD1000_Development_Board_Schematic.pdf
3. Руководство по использованию контроллеров PCIe на Speedster22i (англ.) www.achronix.com/wp-content/uploads/docs/Speedster22i_PCIe_User_Guide_UG030.pdf [4]
4. Руководство пользователя Snapshot (англ.) www.achronix.com/wp-content/uploads/docs/Speedster22i_Snapshot_User_Guide_UG016.pdf [5]
5. Оригинальный reference design: Speedster22i_PCIe_Demo_Design.zip
6. Исходные файлы описываемого проекта: drive.google.com/file/d/0B9Gt8fTYH6s-VGhfbk5RQWM4bk0 [6]
Автор: fpgaFAE
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/pcie/76450
Ссылки в тексте:
[1] PCI-SIG®: https://www.pcisig.com/developers/compliance_program/integrators_list/pcie_3.0#addin
[2] посте: http://habrahabr.ru/post/231007/
[3] www.achronix.com/wp-content/uploads/pr/2014_May_PCI-SIG.pdf: http://www.achronix.com/wp-content/uploads/pr/2014_May_PCI-SIG.pdf
[4] www.achronix.com/wp-content/uploads/docs/Speedster22i_PCIe_User_Guide_UG030.pdf: http://www.achronix.com/wp-content/uploads/docs/Speedster22i_PCIe_User_Guide_UG030.pdf
[5] www.achronix.com/wp-content/uploads/docs/Speedster22i_Snapshot_User_Guide_UG016.pdf: http://www.achronix.com/wp-content/uploads/docs/Speedster22i_Snapshot_User_Guide_UG016.pdf
[6] drive.google.com/file/d/0B9Gt8fTYH6s-VGhfbk5RQWM4bk0: https://drive.google.com/file/d/0B9Gt8fTYH6s-VGhfbk5RQWM4bk0
[7] Источник: http://habrahabr.ru/post/244997/
Нажмите здесь для печати.