30 / 37 · Теория
Ready/valid и эластичный буфер на один элемент
Спроектируйте передачу без потерь и повторов, включая одновременный ввод и вывод в останавливаемом тракте.
Уроки доступны бесплатно. Запишитесь, чтобы сохранять прогресс.
Передача происходит при valid и ready на одном фронте
Передатчик выставляет valid=1 при действительных данных, приёмник ready=1 при готовности. Передача определяется совместной выборкой сигналов на фронте такта.
При 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.
Показать данные диаграммы
| Сигнал | Диаграмма | Значения шины |
|---|---|---|
| clk | p..... | |
| valid | 01...0 | |
| ready | 10.1.. | |
| передача | 0..1.0 | |
| data | x3..4x | A → B |
Valid=1 несколько циклов не означает единственную передачу. На каждом фронте, где ready тоже 1, происходит отдельная передача.
Буфер, хранящий один элемент
Место для нового входа есть, если буфер пуст либо текущий элемент можно выдать на этом фронте.
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_ready | in_valid | Действие на фронте |
|---|---|---|---|
| Пусто | 0 или 1 | 1 | Сохранить вход, valid=1 |
| Полно | 0 | 0 или 1 | Хранить данные и valid |
| Полно | 1 | 0 | Передать выход и опустошить |
| Полно | 1 | 1 | Передать прежний выход и сохранить новый вход |
Благодаря последней строке после заполнения можно обрабатывать по элементу за цикл. Наличие задержки не уменьшает пропускную способностьПропускная способность — число операций, принимаемых или завершаемых за единицу времени. Конвейер может повысить её, не уменьшая задержку отдельной операции. Подробнее автоматически вдвое.
Модель проверки порядка
Используйте эталонную очередь длиной максимум один. По прежним значениям каждого фронта определяйте передачу выхода и принятие входа. Сначала сравните выход с головой, затем добавьте новый вход в хвост. Dequeue и enqueue возможны на одном фронте, поэтому порядок должен быть явным.
Инвариант действует на интервале нового учёта после 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.