
Привет, Хабр!
Недавно я начал изучать такой интерфейс, как AXI, и столкнулся с тем, что нигде нет достаточно короткого описания, что в нем должно быть, и за что отвечают различные сигналы. В этой статье я хотел бы поделиться своей шпаргалкой, написанной во время изучения.
По сути данная статья это по большей части перевод Introduction to AXI, но с моими укорочениями или дополнениями моментов, которые мне оказались непонятны.
Дисклеймер!! В статье могут быть неточности и ошибки т.к. я сам еще глупый студент относительно недавно начавший изучать эту тему, ну и еще это моя первая статья. Буду рад любым отзывам, поправкам и дополнениям.
Так же я ориентировался больше на AXI4, так что во многих моментах отличия от AXI3 вырезаны.
Диаграммы соединений в AXI
В этом разделе представлены поверхностные диаграммы соединений, показывающие соединение с интерконнектом.


Write Data и Read Data используются для передачи данных.
Write Address и Read Address используются для передачи управляющей информации.
Write Response используется для передачи информации о статусе записи.
Операции, выполняемые при записи:
Master отправляет адрес по Write Address (AW) и данные по Write Data (W) к Slave.
Slave получает данные и отправляет ответ по Write Response (B).
Операции, выполняемые при чтении:
Master отправляет адрес по Read Address (AR) к Slave.
Slave отправляет запрошенные данные Master`у по Read Data (R).
Slave так же может отправить ошибку по Read Data (R) если адрес недействителен, данные повреждены или доступ не имеет соответствующих разрешений безопасности.
Каждый канал является односторонним, поэтому для передачи ответов обратно к главному устройству нужен отдельный канал ответа на запись. Однако канал для ответа на чтение не требуется, так как ответ на чтение передается в составе канала данных для чтения.
Фичи AXI
В AXI есть буфер, который позволяет хранить несколько незавершенных транзакций, это увеличивает скорость т.к. не нужно ждать завершения одной транзакции для обработки другой. (Multiple outstanding addresses)
Нет требований к времени получения данных относительно адреса. К примеру, могут прийти сначала данные, а потом адрес, или наоборот.(No strict timing relationship between address and data operations)
Невыровненные транзакции. Может работать с данными, не выровненными по сетке, шириной в шину данных. (Support for unaligned data transfers)
Внеочередное завершение транзакций. Транзакции могут быть завершены вне очереди. (Out-of-order transaction completion)
Пакетные транзакции. Позволяет не передавать адрес для последующих передач.(Burst transactions based on start address)
Транзакции и передачи (transaction's & transfer's)

Для согласования master и slave используется механизм valid/ready.
Передатчик выставляет valid, когда готов отправить данные, а приемник ready, когда готов их принять. В этот момент происходит рукопожатие (handshake).
То, является ли передатчик или приемник master или slave, зависит от используемого канала. Например, master является источником для канала Write Address, но приемником для канала Read Data.
Разница между транзакцией (transaction) и передачей (transfer):


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

1. Master устанавливает адрес на AWADDR и устанавливает AWVALID во втором такте.
2. Slave устанавливает AWREADY в третьем такте, чтобы указать на свою готовность принять значение адреса.
3. Рукопожатие происходит на фронте четвертого такта.
4. Slave ожидает данные при установленном высоком уровне WREADY на такте n.
5. Master помещает данные на шину WDATA и устанавливает WVALID на такте n+2.
6. Рукопожатие завершается на фронте такта n+3.
7. Master устанавливает сигнал BREADY.
8. Slave управляет сигналом BRESP для указания успеха или неудачи операции записи, и устанавливает сигнал BVALID.

1. На такте 2 master передает адрес чтения slave`у на ARADDR и устанавливает ARVALID.
2. На такте 3 slave устанавливает ARREADY, чтобы указать, что он готов принять значение адреса.
3. На такте n master указывает, что ожидает получения данных, устанавливая сигнал RREADY.
4. Slave получает данные и размещает их на RDATA на такте n+2. В этом случае, поскольку это одиночная передача данных, slave также устанавливает сигнал RLAST. В то же время slave использует сигнал RRESP, чтобы указать успех или неудачу операции чтения для master, и устанавливает сигнал RVALID.
5. Поскольку сигнал RREADY уже установлен master`ом, рукопожатие завершается на фронте такта n+3.

По похожему принципу могут передаваться множественные транзакции.
Здесь канал AR указывает последовательность из трех передач, поэтому на канале R мы видим три передачи данных от slave к master.
Одно из отличий между операцией чтения и записи заключается в том, что для операции чтения существует ответ RRESP для каждой передачи в транзакции. Это связано с тем, что в операции записи slave должен отправить ответ отдельной передачей на канале B.
Если для какой-либо из передач в транзакции указан сбой, полная указанная длина транзакции все равно должна быть выполнена. Понятия досрочного прекращения передачи данных не существует.
Для определения количества передач в транзакции используется сигнал ARLEN (На графике отсутствует).
Сигналы чтения


Все сигналы в каждом канале имеют один и тот же префикс:
AR для канала адреса чтения
R для канала данных чтения
Различия для каналов чтения у AXI3 и AXI4:
Для протокола AXI4 сигнал длины адреса чтения ARLEN шире. Поэтому AXI4 способен генерировать более длинные серии чтения, чем AXI3.
AXI4 уменьшает сигнал ARLOCK до одного бита, чтобы учитывать только эксклюзивные передачи, поскольку заблокированные передачи не поддерживаются.
Для канала чтения поддерживаются приоритет доступа(ARQOS) и доступ через разные пути(ARRGEGION). Сигналы находятся в канале AR.
AXI4 может поддерживать пользовательские сигналы для R и AR каналов.
Ширина и длинна данных (burst передачи)
Каждая операция чтения и записи имеет атрибуты, которые определяют длину данных, размер и атрибуты burst сигнала для этой операции.
В обозначениях атрибутов X обозначает и запись и чтение, поэтому они применяются как к каналу записи адреса, так и к каналу чтения адреса:
AxLEN описывает количество передач в транзакции. Для AXI4 AxLEN[7:0] имеет 8 бит, что задаёт диапазон от 1 до 256 передач данных в одной транзакции.
AxSize[2:0] описывает количество байт в одной передаче. Три бита указывают 1, 2, 4, 8, 16, 32, 64 или 128 байт для передачи.
AxBURST[1:0] описывает тип серии транзакций: Incrementing, Wrapping и Fixed. Описания этих типов приведены в таблице ниже.

FIXED: Использует один и тот же адрес несколько раз. Полезно для FIFO(First in, First out) и LIFO(Last in, First out).
INCR: Адрес увеличивается при каждой передаче, что позволяет заполнять большие массивы данных.
WRAP: Работает так же, как и INCR, но при достижении определенной границы возвращается в начальную точку. Используется для строк кэша.
RESERVED: Не используется.
Расчет границ для WRAP
Исходя из сказанного в прошлом разделе понятно, что для WRAP есть нижняя и верхняя граница. Далее в этом разделе будет описан метод их расчета и особенности.
Начальный адрес должен быть выровнен по размеру каждой передачи
Длина пакета должна быть 2, 4, 8 или 16 передач
Расчет нижней границы:
Wrap_Low - Нижняя граница для WRAP
int() - В данном случае откидывает остаток
Start_Address - Начальный адрес
Num_Bytes - Количество байт в передаче(Ax_Size)
Burst_len - Количество передач в транзакции(AxLen)
Следовательно эта формула по сути - выравнивание относительно количества байт в транзакции.
Расчет верхней границы:
Wrap_High - Верхняя граница для WRAP
Wrap_Low - Нижняя граница для WRAP
Num_Bytes - Количество байт в передаче(Ax_Size)
Burst_len - Количество передач в транзакции(AxLen)
Следовательно верхняя граница - это нижняя граница плюс размер транзакции.
Поддержка уровня защиты
AXI поддерживает сигналы разрешений доступа, AWPROT и ARPROT, которые могут защитить от недопустимых транзакций в последующих компонентах системы. Например, если транзакция не имеет соответствующего уровня защиты, контроллер памяти может отказать в доступе на чтение или запись, используя эти сигналы.
Это полезно для систем безопасности, таких как Arm TrustZone, где процессор имеет два отдельных режима: защищённый и незащищённый. AxPROT определяет три уровня защиты доступа, как показано на следующей схеме:

Распределение битов AxPROT задает следующие атрибуты:
-
AxPROT[0] (P) определяет доступ как непривилегированный или привилегированный:
1 - Привилегированный (privileged)
0 - Непривилегированный (unprivileged)
-
AxPROT[1] (NS) определяет доступ как защищённый или незащищённый:
1 - Незащищенный (Non-Secure)
0 - Защищенный (Secure)
-
AxPROT[2] (I) указывает, является ли транзакция доступом к инструкции или доступом к данным:
1 - Инструкция (Instruction)
0 - Данные (Data)
AxPROT[1] можно рассматривать как определяющий два адресных пространства: защищенное и незащищенное. Этот сигнал можно рассматривать как дополнительный бит адреса.
В AXI сигнал AxPROT[2] служит скорее подсказкой, чем правилом. Он показывает, к чему относится транзакция, к данным или к инструкциям. Но бывают ситуации, когда в одной транзакции смешиваются и данные, и инструкции. Поэтому в спецификации Arm для AXI3 и AXI4 советуют всегда ставить AxPROT[2] в ноль, чтобы обозначить доступ к данным.
Поддержка кэша
Современные системы на кристалле (SoC) часто содержат кэши, которые размещаются в нескольких точках системы. Например, кэш второго(L2 cache) уровня может быть внешним по отношению к процессору, а кэши третьего уровня(L3 cache) могут находиться перед контроллером памяти.
Чтобы поддерживать системы, использующие различные методы кэширования, сигналы AWCACHE и ARCACHE указывают, как транзакции должны проходить через систему.

Замечание: Данные сигналы использует сам кэш, а не компоненты AXI.
Но тут может возникнуть вопрос: чем же он отличается тогда от пользовательских сигналов? Ответ достаточно прост - этот сигнал имеет определенный стандарт, который понимает контроллер кэша.
Назначения битов AxCACHE определяют следующие характеристики:
-
AxCACHE [0] (B) - это бит, разрешающий буферизацию.
1 - Данные могут быть буферизованы.
0 - Транзакция должна быть немедленно выполнена.
-
AxCACHE [1] - это бит, разрешающий кэширование.
1 - Данные могут быть кэшированы.
0 - Данные идут напрямую, минуя кэш.
-
AxCACHE [2] - это бит Read Allocate (Указывает на то, что строка могла быть заранее выделена в кэше из-за действий другого менеджера).
1 - Выделена.
0 - Не выделена.
-
AxCACHE [3] - это бит Write Allocate (Указывает на то, что строка могла быть заранее выделена в кэше из-за действий другого менеджера).
1 - Выделена.
0 - Не выделена.
Смысл этих сигналов в том, что это позволяет кэшу на уровне системы оптимизировать свою производительность. Например, рассмотрим кэш, который видит доступ для чтения, определенный как «write-allocate, но не read-allocate». В этом случае кэш знает, что адрес может быть сохранен в кэше, поскольку он мог быть выделен при предыдущей записи, и, следовательно, должен выполнить поиск в кэше. Однако теперь рассмотрим ситуацию, когда кэш видит доступ для чтения, определенный как «no write-allocate и no read-allocate». В этом случае кэш знает, что адрес не был выделен в кэше. Кэш может избежать поиска и сразу передать транзакцию дальше.
Ответный сигнал (Response signal)
В AXI есть так называемый Response signal, он позволяет передавать ответы после записи и чтения.
RRESP для чтения.
BRESP для записи.
Этот сигнал имеет 2 бита, по этому может возвращать 4 типа ответов.

OKAY - Может значить как успешное завершение обычной транзакции, так и ошибку exclusive access транзакций.
EXOKAY - Сигнализирует о том, что транзакция была exclusive.
SLVERR - Ошибка на стороне slave. Происходит, когда инициализация slave прошла успешно, но он вернул ошибку, например, из-за некорректного размера данных.
DECERR - Ошибка декодирования. Происходит, когда нет slave по указанному адресу.
Стробирующий сигнал (Strobe signal)
Стробирующий сигнал или сигнал(WSTRB) указывает на то, какие данные будут записаны. На каждый байт приходится 1 бит стробирующего сигнала. Если для соответствующего байта стробирующий бит выставлен в 1, то эти данные будут использоваться.

Биты, выделенные желтым будут использованы.
0xFC - 11111100
0x3C - 00111100
0x81 - 10000001
0xE8 - 11101000 (перевел в двоичную систему для наглядности).
Транзакции с эксклюзивным доступом (Exclusive access)
Начиная с AXI4 используется Exclusive access. Транзакция с эксклюзивным доступом нужна по сути для того, чтобы понять, не изменились ли данные, в памяти, пока транзакция не была завершена.
Цикл у такой транзакции следующий:
Master выполняет чтение.
Slave отправляет ответ, EXOKAY, если поддерживает exclusive access, и OKAY если нет.
Данные записываются в monitor(компонент, следящий за тем, кто получал доступ к этой же памяти).
-
Далее Master выполняет запись модифицированных данных обратно, и получает ответ, EXOKAY если транзакция была эксклюзивной и OKAY, если кто то изменил данные, пока шла модификация данных. При OKAY записи не будет.

Механизм работы эксклюзивной транзакции


ID передачи
Протокол AXI использует для каждой транзакции свой ID, который позволяет обрабатывать некоторые из них вне очереди.
Для передачи ID используются сигналы:
AWID
BID
ARID
RID
Четких правил по последовательности обработки передач с разным ID нет. Передачи с одинаковым ID должны быть обработаны в порядке поступления.
При работе с ID передач следует придерживаться нескольких правил:
Все передачи должны иметь идентификатор (ID).
Все передачи в одной транзакции должны иметь одинаковый идентификатор.
Master может поддерживать несколько идентификаторов для нескольких потоков.
Slave устройства обычно требуют настраиваемую ширину идентификатора.
Также следует помнить о двух важных параметрах AXI для сигналов ID:
Ширина ID при записи, которая определяет количество бит, используемых для шин AWID и BID.
Ширина ID при чтении, которая определяет количество бит, используемых для шин ARID и RID.
Правила упорядочивания транзакций записи
Существует три правила упорядочивания AXI для операций записи.
-
Запись данных на канал W должна следовать тому же порядку, что и передачи адреса на канале AW.

Пример правила 1 Транзакции с разными ID могут завершаться в любом порядке.

Master может иметь несколько незавершённых транзакций с одним и тем же идентификатором, но они должны выполняться и завершаться в порядке поступления.

В этом примере у транзакции B другой идентификатор, поэтому она может завершиться в любой момент. Однако транзакции A и C имеют одинаковый ID, поэтому они должны выполняться в том же порядке, в котором были созданы: сначала A, затем C.
Правила упорядочивания транзакций чтения
Чтение данных для различных ID на канале R не имеет ограничений по порядку. Это означает, что slave может отправлять их в любом порядке.

Считанные данные для разных ID на канале R могут быть перемешаны, при этом значение RID определяет, к какой транзакции относятся эти данные.

Для транзакций с одним и тем же ID данные на канале R должны возвращаться в порядке их запроса.

Следующая диаграмма показывает пример, где у транзакций A и C одинаковое значение RID. Поскольку транзакция A была запрошена до транзакции C, slave должен вернуть все четыре значения данных R для A до возвращения значений данных для C.
Упорядочивание транзакций записи и чтения
Каналы чтения и записи не подчиняются правилам упорядочивания относительно друг друга. Это означает, что они могут завершаться в любом порядке. Таким образом, если master`у требуется соблюдение порядка для определенной последовательности операций чтения и записи, master должен гарантировать соблюдение порядка транзакций, явно ожидая завершения предыдущих транзакций перед выполнением новых.
На следующей диаграмме показан пример, где master требует определенного порядка для последовательности транзакций запись-чтение-запись с адреса:

Для того, чтобы правильно запустить транзакции, master пользуется сигналом Write Responce для подтверждения завершения записи, и сигналом RRESP на канале R. После получения нужного подтверждения master инициирует следующую транзакцию.
Невыровненные передачи (Unaligned transfer)
Невыровненная передача - это передача, при которой значения AxADDR не обязаны быть выровнены по ширине транзакции. Например, 32-битный пакет данных, начинающийся с байтового адреса 0x1002(4098 в десятичной), не выровнен по естественной 32-битной границе адреса, потому что 0x1002 не делится без остатка на 0x20(32 в десятичной).

Пример наглядно показывает, как выглядит доступ к памяти, не выровненный по маске.
Поддержка обратного порядка байт (Endianness support)
Протокол AXI поддерживает структуры с разным порядком байт в одном и том же участке памяти, используя режим Big Endian-8 (BE-8). По сравнению с режимом с младшим байтом вперед, в режиме BE-8 используются те же дорожки байтов, но порядок байтов обратный.

Замечание! - Это заранее заданная настройка, а не динамически изменяющееся во время работы состояние.
P. S. Ну вот в принципе и все, я практически уверен, что некоторые нюансы были упущены, но на то это и введение, спасибо всем, кто прочитал и оценил статью.
P. S. S. В будущем планирую и дальше работать с AXI и попробовать написать и верифицировать минимально работающий дизайн на systemverilog, так что вполне возможно что будет еще несколько статей по этой теме.