Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions Labs/06.AXI-Stream/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ endmodule
При поступлении пакета данных происходит декремент кредитного счётчика, то есть, счётчик уменьшается на 1. Таким образом, выпустив в конвейер N пакетов, кредитный счётчик достигает значения "0". Если значение кредитного счётчика нулевое, то сигнал `ready_o` опускается и отправитель более не готов принимать данные до момента, когда ему "вернут кредит".

#### Получатель данных
Основным элементом получателя данных является FIFO. Очень важно то, чтобы FIFO имело глубину, равную максимальному значению кредитного счетчика (N). Идея заключается в том, что FIFO должен иметь возможность "подхватить" все пакеты с данными, попавшие в конвейер, и, в определённый момент покинувшие его. Таким образом, при гипотетической ситуации, при которой `ready_i` никогда не поднимается в "1", кредитный механизм не потеряет ни одного пакета данных -- все пакеты, выпущенные отправителем, после обработки, окажутся в FIFO приёмника данных.
Основным элементом получателя данных является FIFO. Очень важно то, чтобы FIFO имело глубину, равную максимальному значению кредитного счетчика (N). Идея заключается в том, что FIFO должен иметь возможность "подхватить" все пакеты с данными, попавшие в конвейер, и, в определённый момент покинувшие его. Таким образом, при гипотетической ситуации, при которой `ready_i` никогда не поднимается в "1", кредитный механизм не потеряет ни одного пакета данных все пакеты, выпущенные отправителем, после обработки, окажутся в FIFO приёмника данных.

Когда происходит handshake и данные из FIFO отправляются наружу, покидая кредитный механизм, происходит инкремент (увеличение на 1) кредитного счётчика, то есть, возврат кредита. По сути, возврат кредита является сообщением для отправителя данных "в FIFO освободилось место для одного пакета данных, поэтому можно безопасно начать обработку ещё одного пакета".

Expand All @@ -418,23 +418,24 @@ AXI Stream (Advanced eXtensible Interface Stream) — это протокол д
Интерфейс AXI Stream содержит следующие основные и обязательные сигналы:
1. `ACLK` (Сигнал тактовой частоты)

2. `ARESETn` (Сигнал сброса) -- Асинхронный сброс интерфейса (активный уровень — низкий)
2. `ARESETn` (Сигнал сброса) Асинхронный сброс интерфейса (активный уровень — низкий)

3. `TVALID` (Valid — Валидность данных) Указывает, что master готов передать данные. Этот сигнал генерирует Master. Данные на шине считаются действительными только при `TVALID` = 1.

4. `TREADY` (Ready — Готовность приёмника). Указывает, что приёмник готов принять данные. Этот сигнал генерируется Slave. Передача данных происходит только при одновременной активности `TVALID` и `TREADY` (handshake).

При этом в спецификации интерфейса AXI Stream существует важные правила, определяющие работу сигналов `TVALID` и `TREADY`
* Slave может удерживать `TREADY` = 1 во то время, когда `TREADY` = 0.
* Slave может удерживать `TREADY` = 1 во то время, когда `TVALID` = 0.
* Slave может опускать `TREADY` в 0 в любой момент времени и "слушающий этот сигнал" Master должен это учитывать.
* Однажды выставив `TVALID` в 1 Master более **не имеет права** выставлять `TVALID` в 0 до момента, пока не произойдёт рукопожатие и транзакция. То есть, Master не имеет права "передумать", выставляя флаг валидности.
* Однажды выставив `TVALID` в 1 Master более **не имеет права** выставлять `TVALID` в 0 до момента, пока не произойдёт рукопожатие. То есть, Master не имеет права "передумать", выставляя флаг валидности.
* После выставления `TVALID` = 1 Master также не имеет права изменять передаваемые данные и сопутствующие управляющие сигналы до момента рукопожатия. Иными словами, если `TVALID` = 1, а `TREADY` = 0, данные должны оставаться неизменными.

5. `TDATA` -- Основная шина для передачи данных.
1. `TDATA` Основная шина для передачи данных.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нумерация поломалась. Это 5 сигнал по счёту

Разрядность: Может быть 8, 16, 32, 64, 128 бит и т.д. (зависит от реализации).

Если вернуться к началу данной лабораторной работы, то можно убедиться в том, что обязательный набор сигналов AXI Stream представляет из себя просто интерфейс valid-ready.

Рассмотрим пример транзакции по минимальному интерфейсу AXI Stream -- мы не увидим никаких значимых отличий от valid-ready. На временной диаграмме показана передача трёх транзакций.
Рассмотрим пример транзакции по минимальному интерфейсу AXI Stream мы не увидим никаких значимых отличий от valid-ready. На временной диаграмме показана передача трёх транзакций.

<!---
{signal: [
Expand All @@ -451,12 +452,12 @@ AXI Stream (Advanced eXtensible Interface Stream) — это протокол д
Теперь давайте рассмотрим набор дополнительных сигналов шины AXI Stream.


1. `TSTRB` -- Определяет, какие байты в `TDATA` являются валидными. Разрядность данного сигнала -- по 1 биту на каждый байт в `TDATA` (например, для 32-битной `TDATA` — 4 бита `TSTRB`).
1. `TSTRB` Определяет, какие байты в `TDATA` являются валидными. Разрядность данного сигнала по 1 биту на каждый байт в `TDATA` (например, для 32-битной `TDATA` — 4 бита `TSTRB`).
Например: Если `TSTRB` = 4'b1100, то активны только третий и четвертый байты `TDATA`. Если же `TSTRB` = 0 для байта, то этот байт не содержит полезной информации и называется *position byte*. При передаче данных нет необходимости поддерживать корректное значение `TDATA` в байтах, для которых `TSTRB` = 0, но позиция байтов относительно *position byte* должна быть неизменна.

2. `TKEEP` — Указывает, какие байты `TDATA` должны быть переданы от источника к приёмнику.
Разрядность сигнала аналогична `TSTRB`, по одному биту на байт `TDATA`.
Если `TKEEP` = 1 для байта, то соответствующий байт должен дойти до приёмника. Если же `TKEEP` = 0, то байт может быть удалён из потока. В этом кроется принципиальное отличие `TKEEP` от `TSTRB` -- в случае с `TSTRB` важно сохранять "пропуски данных", в то время как с `TKEEP` можно эти пропуски удалить, смещая и как-бы "уплотняя" байты.
Если `TKEEP` = 1 для байта, то соответствующий байт должен дойти до приёмника. Если же `TKEEP` = 0, то байт может быть удалён из потока. В этом кроется принципиальное отличие `TKEEP` от `TSTRB` в случае с `TSTRB` важно сохранять "пропуски данных", в то время как с `TKEEP` можно эти пропуски удалить, смещая и как-бы "уплотняя" байты.

> Часто `TSTRB` используется для формирования пропусков данных "внутри" пакета, а `TKEEP` для непосредственно границ пакета, если они не выровнены по ширине шины `TDATA`.

Expand All @@ -478,6 +479,7 @@ AXI Stream (Advanced eXtensible Interface Stream) — это протокол д

6. `TUSER` User-defined, передача произвольных метаданных (например, контрольная сумма, флаги ошибок, параметры данных). Разрядность определяется разработчиком.

7. `TWAKEUP` Дополнительный сигнал пробуждения, введённый в AXI5-Stream (новейшая версия AXI-Stream). Он используется для индикации любой активности, связанной с интерфейсом AXI5-Stream, и может подаваться, например, на контроллер тактирования или питания для включения связанных компонентов. Сигнал `TWAKEUP` синхронен `ACLK`, он может быть выставлен как до, так и после `TVALID`. Однако, если `TWAKEUP` и `TVALID` одновременно находятся в единице, `TWAKEUP` должен оставаться активным до тех пор, пока не произойдет рукопожатие. Рекомендуется выставлять `TWAKEUP` как минимум за один такт до `TVALID` и сбрасывать его, когда дальнейшие передачи не требуются.

## Потоки данных

Expand Down Expand Up @@ -820,7 +822,7 @@ endmodule
![](./pic/rr_arb.png)

- Мы добавили указатель `ptr_ff`, который указывает текущий приоритет. При этом, следующее значение указателя всегда выбирается таким, чтобы он указывал на следующий порт относительно того, на котором в данный момент происходит транзакция. Таким образом, приоритет порта с транзакцией на следующий такт понизится до наименьшего.
- В сердце показанного примера до сих пор находится статический арбитр, но мы делаем интересный трюк: сначала мы циклический сдвигаем вектор `req` вправо на количество бит из текущего значения `ptr_ff`, то есть, мы поворачиваем входной вектор `req` так, чтобы `ptr_ff`-й элемент имел максимальный статичный приоритет, в результате получая вектор `req_rotated`. Результат вычисления приоритета `grant_rotated` нельзя просто так использовать для управления портами, его нужно "повернуть обратно", выполнив циклический сдвиг влево на те же `ptr_ff` бит. Таким образом, мы хитрым образом вращаем биты вокруг статического приоритета, чтобы получить динамический арбитраж. Всё гениальное -- просто!
- В сердце показанного примера до сих пор находится статический арбитр, но мы делаем интересный трюк: сначала мы циклический сдвигаем вектор `req` вправо на количество бит из текущего значения `ptr_ff`, то есть, мы поворачиваем входной вектор `req` так, чтобы `ptr_ff`-й элемент имел максимальный статичный приоритет, в результате получая вектор `req_rotated`. Результат вычисления приоритета `grant_rotated` нельзя просто так использовать для управления портами, его нужно "повернуть обратно", выполнив циклический сдвиг влево на те же `ptr_ff` бит. Таким образом, мы хитрым образом вращаем биты вокруг статического приоритета, чтобы получить динамический арбитраж. Всё гениальное просто!

Стоит обратить внимание на то, что формирование сигналов `req_rotated` и `grant` можно описать более красивым и изящным способом, который, помимо всего прочего, легко ложится на параметризуемый дизайн с переменным числом портов.

Expand Down