Altifigence Academy

30 / 37 · Concept

Ready/valid and a one-entry elastic buffer

Design lossless, duplicate-free transfers and simultaneous input/output in a datapath that can stall.

A transfer occurs when valid and ready are 1 at the same edge

The sender asserts valid when presenting valid data, and the receiver asserts ready when it can accept data. Sampling both signals together at the clock edge determines whether a transfer occurs.

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

While valid=1 and ready=0, the sender must hold valid and the data. Waiting to assert valid until ready is high can cause deadlock, depending on the other side's rules. Here all signals are assumed to share one clock domain. 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. itself does not solve CDC.

Transfer waiting data exactly once

The columns below represent sampling cycles 0 through 5 in order. Read each signal as its value just before that 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. In cycles 1 and 2, A is waiting with valid=1 and ready=0, so valid and data are held. A is accepted at edge 3 and B at edge 4. The alignment of the clock and signal traces illustrates the contract; it does not model setupSetup The minimum time that input data must be stable before the capturing clock edge. If it is violated, the stored result is not guaranteed. Learn more/hold delays.

Ready/valid · waiting and consecutive transfers
View waveform data
Wave data: each character is one interval; a dot holds the previous state; p is a clock cycle.
SignalWaveBus values
clkp.....
valid01...0
ready10.1..
transfer0..1.0
datax3..4xA → B

A valid signal held high for several cycles does not imply only one transfer. Every edge at which ready is also high performs a separate transfer.

Build a buffer that stores one item

There is room for new data if the buffer is empty or its current data can be delivered at this edge.

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

When an empty buffer accepts input, out_valid and out_data update after the edge. There is no combinational bypass, so the new value is not counted as an output transfer at the same edge. Transfers are not counted during reset, and out_data is meaningless when out_valid=0. Thus the data registerRegister A circuit that stores multiple bits of state. The synchronous registers in this course store their specified inputs at a clock edge. Learn more itself does not necessarily need resetReset A control that returns state to a specified initial value. Define whether it is synchronous or asynchronous and whether it has priority over other controls. Learn more.

A full buffer can replace its contents

State just before the edgeout_readyin_validAction at the edge
Empty0 or 11Store input and set valid=1
Full00 or 1Hold current data and valid
Full10Deliver output and become empty
Full11Deliver old output and store new input simultaneously

The last row allows one item per cycle after the buffer has first been filled. Having latency does not mean throughputThroughput The number of operations accepted or completed per unit time. A pipeline can increase throughput without reducing the latency of an individual operation. Learn more is halved.

A model to verify data order

Use a queue of maximum length 1 for the reference model. Determine output transfer and input acceptance from the previous values at each edge. If an output transfers, compare it with the queue's front item, then append the new input. Dequeue and enqueue can both occur at the same edge, so make their order explicit.

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

This invariant holds within a tracking interval restarted by reset. Also check that data stays stable during stalls, delivery order is preserved, and no item is delivered twice. The count invariant alone does not verify data-value correctness.

Chaining many buffers through combinational ready signals can create a long backward timing path. When connecting the structures, also check for combinational loops.

Further reading: AMD UG934 — READY/VALID Handshake

Try it yourself

The buffer is full with A, and a new input B has in_valid=1. Suppose out_ready=0 at the first edge and out_ready=1 at the next. What happens to A and B at each edge, and how long must the sender hold B?

Read the explanation

At the first edge, in_ready=0, so A is held and B is not accepted. The sender holds B and in_valid=1. At the next edge, in_ready=1, so A is delivered while B is stored simultaneously. After that edge, the buffer output is B, but B has not yet been delivered. Its output transfer occurs at a later edge where out_valid and out_ready are both 1.

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