Altifigence Academy

30 / 37 · Теория

Ready/valid и эластичный буфер на один элемент

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

Передача происходит при valid и ready на одном фронте

Передатчик выставляет valid=1 при действительных данных, приёмник ready=1 при готовности. Передача определяется совместной выборкой сигналов на фронте такта.

transferk=validk∧readyk\mathrm{transfer}_k=\mathrm{valid}_k\land\mathrm{ready}_k

При valid=1, ready=0 передатчик обязан удерживать valid и данные. Если он вообще не выставляет valid до появления ready, правила второй стороны могут привести к взаимной блокировке. Предполагается один тактовый домен для всех сигналов. Ready/validРукопожатие (handshake) — соглашение, по которому передача подтверждается, когда valid передатчика и ready приёмника равны 1 на одном фронте. Оно также задаёт правила удержания данных во время ожидания. сам по себе не решает CDC.

Передайте ожидавшие данные ровно один раз

Столбцы ниже — циклы выборки 0–5. Читайте значения непосредственно перед соответствующим положительным фронтомПоложительный фронт — момент перехода такта из 0 в 1. Его следует отличать от уровня, означающего весь интервал CLK=1. Подробнее. В циклах 1 и 2 A ждёт при valid=1, ready=0, поэтому оба удерживаются. A принимается на фронте 3, B — на 4. Выравнивание линий иллюстрирует контракт и не моделирует задержки setupВремя предустановки (setup) — минимальное время, в течение которого входные данные должны быть стабильны до захватывающего фронта такта. При нарушении результат записи не гарантирован. Подробнее/hold.

Ready/valid: ожидание и последовательные передачи
Показать данные диаграммы
Данные диаграммы: каждый символ — один интервал; точка сохраняет предыдущее состояние; p — один тактовый цикл.
СигналДиаграммаЗначения шины
clkp.....
valid01...0
ready10.1..
передача0..1.0
datax3..4xA → B

Valid=1 несколько циклов не означает единственную передачу. На каждом фронте, где ready тоже 1, происходит отдельная передача.

Буфер, хранящий один элемент

Место для нового входа есть, если буфер пуст либо текущий элемент можно выдать на этом фронте.

in_ready=¬out_valid∨out_ready\mathrm{in\_ready}=\neg\mathrm{out\_valid}\lor\mathrm{out\_ready}
SystemVerilog
module elastic_buffer (
    input  logic       clk,
    input  logic       rst,
    input  logic       in_valid,
    output logic       in_ready,
    input  logic [7:0] in_data,
    output logic       out_valid,
    input  logic       out_ready,
    output logic [7:0] out_data
);
    assign in_ready = !out_valid || out_ready;

    always_ff @(posedge clk) begin
        if (rst) begin
            out_valid <= 1'b0;
        end else if (in_ready) begin
            out_valid <= in_valid;
            if (in_valid) out_data <= in_data;
        end
    end
endmodule

При приёме в пустой буфер out_valid и out_data обновляются после фронта. Комбинационного bypass нет, поэтому нельзя считать новый элемент переданным на выход в тот же фронт. Во время reset передачи не учитываются, а при out_valid=0 значение out_data не имеет смысла. Поэтому сам регистрРегистр хранит многобитное состояние. Синхронные регистры в этом курсе записывают определённый вход на фронте тактового сигнала. Подробнее данных не обязательно сбрасыватьСброс возвращает состояние к заданному начальному значению. Нужно определить, синхронен он или асинхронен и имеет ли приоритет над другими управляющими сигналами. Подробнее.

Замена возможна и в полном буфере

Состояние до фронтаout_readyin_validДействие на фронте
Пусто0 или 11Сохранить вход, valid=1
Полно00 или 1Хранить данные и valid
Полно10Передать выход и опустошить
Полно11Передать прежний выход и сохранить новый вход

Благодаря последней строке после заполнения можно обрабатывать по элементу за цикл. Наличие задержки не уменьшает пропускную способностьПропускная способность — число операций, принимаемых или завершаемых за единицу времени. Конвейер может повысить её, не уменьшая задержку отдельной операции. Подробнее автоматически вдвое.

Модель проверки порядка

Используйте эталонную очередь длиной максимум один. По прежним значениям каждого фронта определяйте передачу выхода и принятие входа. Сначала сравните выход с головой, затем добавьте новый вход в хвост. Dequeue и enqueue возможны на одном фронте, поэтому порядок должен быть явным.

0≤Naccepted−Ndelivered≤10\le N_{\mathrm{accepted}}-N_{\mathrm{delivered}}\le1

Инвариант действует на интервале нового учёта после reset. Дополнительно проверяйте устойчивость данных при stall, порядок и отсутствие повторной передачи. Одного инварианта числа недостаточно для проверки значений.

Длинная комбинационная цепь ready через буферы увеличивает обратный временной путь. При соединении структур проверяйте также отсутствие комбинационных петель.

Дополнительное чтение: AMD UG934 — READY/VALID Handshake

Попробуйте сами

Буфер заполнен A, на входе B с in_valid=1. На первом фронте out_ready=0, на следующем out_ready=1. Что происходит с A и B на каждом фронте и до какого момента передатчик должен хранить B?

Прочитать объяснение

На первом фронте in_ready=0: A хранится, B не принимается. Передатчик удерживает B и in_valid=1. На следующем in_ready=1: A передаётся, B одновременно сохраняется. После фронта выход буфера показывает B, но B ещё не передан. Его выходная передача произойдёт позже на фронте с out_valid=out_ready=1.

Выбор действует в этом браузере. Его можно изменить внизу страницы.