Altifigence Academy

61 / 63 · Concept

Stallable pipelines and backpressure

Compute ready for each stage to prevent data loss, duplication, and recomputation during stalls and simultaneous movement.

When the receiver cannot always accept data

Prerequisites: a one-entry ready/validHandshake A contract that accepts a transfer when the sender's valid and the receiver's ready are both 1 at the same edge. It also defines how data must be held while waiting. Learn more buffer and data alignment in pipelinesPipeline A structure that divides computation into register-separated stages and overlaps processing of multiple inputs. Data, valid and control signals must be aligned by stage. Learn more.

Simply adding out_ready to a fixed-rate pipeline and blocking its output is insufficient. If the final stage is full and stalls, earlier stages must not overwrite their data either. Design backpressureBackpressure A way for a receiver to tell a sender that it temporarily cannot accept data, stopping the flow. Undelivered data must be preserved while stalled. Learn more to propagate the stop request toward the input.

Represent each of two stages with one data item and one valid bit. Stage 2 can accept a new value if it is empty or can deliver its current output. Apply the same rule to stage 1.

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

The external in_ready is r1. Even when r2=0, an empty first stage can accept one new input. This uses storage more effectively than rejecting all input whenever the output stops.

Update each stage only when movement is allowed

The following example computes y=2(x+1) for an unsignedUnsigned A rule for interpreting a bit pattern as a nonnegative integer. The n-bit range is 0 through 2^n−1 and may differ from the signed interpretation of the same bits. Learn more 8-bit x. Stage 1 stores x+1 in 9 bits; stage 2 shifts it left by one bit into 10 bits. This represents even the maximum-input result, 512 for x=255, exactly.

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

Because these are nonblockingNonblocking assignment An assignment written as <= in sequential RTL. It evaluates the right-hand side and schedules the update, allowing registers at the same edge to compute from the previous state. Learn more assignments, stage 2 receives the previous d1, not the d1 newly calculated at the same edge. With r1=0, v1 and d1 hold; with r2=0, v2 and d2 hold. Holding valid while continuously updating data is incorrect.

Trace both stages when full

Initially, suppose v2 holds A's result, v1 holds B's intermediate value, and input C is waiting.

out_readyin_readyAction at the edge
00Hold A and B; do not accept C
00Hold A and B; do not accept C
11Deliver A, move B to stage 2, accept C

The sender holds C and in_valid until C is accepted. If it assumes that C was sent at the first stalled edge and presents the next item, C is lost.

Each column shows values just before a rising edgeRising edge The instant at which the clock changes from 0 to 1. Distinguish it from a level, which refers to the entire interval during which CLK=1. Learn more. Initially, the last stage contains A, the first stage contains B, and C is waiting at the input. After E2 delivers A and accepts C, the output before E3 has changed to B.

Backpressure with both stages full
View waveform data
Wave data: each character is one interval; a dot holds the previous state; p is a clock cycle.
SignalWaveBus values
edge2345E0 → E1 → E2 → E3
out_ready0.1.
out_valid1...
out_data2..3A → B
in_valid1...
in_ready0.1.
in_data2..3C → D

Conservation laws to verify

Let Nin count accepted inputs and Nout count delivered outputs since reset, excluding transfers at a reset edge. The number of stored items is

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

Correct counts alone could miss a fault that outputs A twice and drops B, so check values and order against a reference queue as well. Vary input valid and output ready independently, including long stalls, continuous processing, and flushing during reset.

The ready path is also a timing path

Connecting many stages lengthens backward combinational paths such as r2→r1. Delaying ready by one register may require extra storage for inputs already promised during that delay. Adding a flip-flop to ready without considering storage and the protocol is not a safe timing optimization.

Try it yourself

With v1=0, v2=1, and out_ready=0, can an input with in_valid=1 be accepted? If out_ready remains 0 in the following cycle, can more inputs continue to be accepted?

Read the explanation

Initially r2=0 but r1=1, so one item can be accepted to fill stage 1. After the edge, v1=v2=1 gives r1=r2=0, preventing further acceptance. This distinction is what allows both storage slots to be used.

Your choice applies to this browser. Change it any time using the footer.