Altifigence Academy

61 / 63 · Теория

Останавливаемый конвейер и обратное давление

Вычисляйте ready каждой ступени, предотвращая потери, повторы и повторное вычисление при остановке и одновременном продвижении.

Когда получатель не всегда готов

Предварительные знания: однопозиционный ready/validРукопожатие (handshake) — соглашение, по которому передача подтверждается, когда valid передатчика и ready приёмника равны 1 на одном фронте. Оно также задаёт правила удержания данных во время ожидания. Подробнее-буфер и выравнивание данных конвейераКонвейер делит вычисление на разделённые регистрами стадии и перекрывает обработку нескольких входов. Данные, valid и управляющие сигналы необходимо согласовать по стадиям. Подробнее.

Добавить out_ready к конвейеру фиксированного темпа и заблокировать выход недостаточно. Когда последняя ступень заполнена и стоит, предыдущую нельзя перезаписывать. Нужно обратное давлениеОбратное давление (backpressure) останавливает поток данных: приёмник сообщает передатчику, что временно не готов принимать. Во время остановки ещё не переданные данные должны сохраняться. Подробнее, передающее остановку в сторону входа.

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

r2=¬v2∨out_ready,r1=¬v1∨r2r_2=\neg v_2\lor\mathrm{out\_ready},\qquad r_1=\neg v_1\lor r_2

Внешний in_ready равен r1. Даже при r2=0 пустая первая ступень может принять один вход. Это использует память лучше, чем безусловный запрет всех входов при остановке выхода.

Ступень обновляется только при разрешении движения

Пример вычисляет y=2(x+1) для unsignedБеззнаковая интерпретация (unsigned) рассматривает битовую последовательность как неотрицательное целое. Диапазон n бит — от 0 до 2^n−1; знаковая интерпретация тех же битов может дать другое число. Подробнее 8-битного x. Первая ступень хранит x+1 в 9 битах, вторая сдвигает влево до 10 бит. Максимальный вход 255 даёт точно представимое 512.

SystemVerilog
module stallable_pipeline (
    input  logic       clk, 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 [9:0] out_data
);
    logic v1, v2, r1, r2;
    logic [8:0] d1;
    logic [9:0] d2;
    assign r2 = !v2 || out_ready;
    assign r1 = !v1 || r2;
    assign in_ready  = r1;
    assign out_valid = v2;
    assign out_data  = d2;

    always_ff @(posedge clk) begin
        if (rst) begin
            v1 <= 1'b0;
            v2 <= 1'b0;
        end else begin
            if (r2) begin
                v2 <= v1;
                if (v1) d2 <= {d1, 1'b0};
            end
            if (r1) begin
                v1 <= in_valid;
                if (in_valid) d1 <= {1'b0, in_data} + 9'd1;
            end
        end
    end
endmodule

Из-за nonblockingНеблокирующее присваивание обозначается <= в последовательностном RTL. Оно вычисляет правую часть, затем планирует обновление, позволяя регистрам на одном фронте рассчитываться по предыдущему состоянию. Подробнее вторая ступень получает прежнее d1, а не вычисленное на том же фронте. При r1=0 хранятся v1,d1, при r2=0 — v2,d2. Удерживать только valid, продолжая менять данные, неправильно.

Трассировка двух заполненных ступеней

Пусть v2 содержит результат A, v1 — промежуточное B, а на входе ждёт C.

out_readyin_readyДействие на фронте
00Хранить A,B; C не принят
00Хранить A,B; C не принят
11Передать A, переместить B во вторую ступень, принять C

Передатчик удерживает C и in_valid до принятия. Если считать C отправленным на первом остановленном фронте и перейти к следующему, C потеряется.

Каждый столбец ниже — значения перед положительным фронтомПоложительный фронт — момент перехода такта из 0 в 1. Его следует отличать от уровня, означающего весь интервал CLK=1. Подробнее. Изначально последняя ступень содержит A, первая — B, на входе ожидает C. После передачи A и приёма C на E2 выход перед E3 становится B.

Обратное давление при заполнении обеих стадий
Показать данные диаграммы
Данные диаграммы: каждый символ — один интервал; точка сохраняет предыдущее состояние; p — один тактовый цикл.
СигналДиаграммаЗначения шины
фронт2345E0 → E1 → E2 → E3
out_ready0.1.
out_valid1...
out_data2..3A → B
in_valid1...
in_ready0.1.
in_data2..3C → D

Проверяемый закон сохранения

Пусть после reset Nin — число принятых входов, Nout — переданных выходов. Число сохранённых элементов задаётся следующим соотношением; на фронте reset передачи не учитываются.

Nin−Nout=v1+v2,0≤Nin−Nout≤2N_{\mathrm{in}}-N_{\mathrm{out}}=v_1+v_2,\qquad 0\le N_{\mathrm{in}}-N_{\mathrm{out}}\le2

Одного совпадения количества недостаточно: можно дважды выдать A и потерять B. Эталонная очередь проверяет значения и порядок. Независимо меняйте in_valid и out_ready, включите долгие остановки, непрерывную работу и очистку при reset.

Ready тоже образует временной путь

В длинной цепочке ступеней удлиняется и обратный комбинационный путь вроде r2→r1. Если задержать ready регистром, может понадобиться дополнительное место для входов, уже обещанных во время этой задержки. Просто вставить триггер в ready без учёта памяти и протокола — небезопасная оптимизация времени.

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

v1=0, v2=1, out_ready=0. Можно ли принять вход с in_valid=1? Можно ли продолжать приём следующего входа, если out_ready остаётся 0 и в следующем цикле?

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

Изначально r2=0, но r1=1, поэтому один вход заполняет первую ступень. После фронта v1=v2=1 и r1=r2=0: дальнейший приём невозможен. Это различие позволяет реально использовать оба места хранения.

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