Medium · Interfaces & Handshakes · Pipelining
Implement a pipeline register slice for a valid/ready stream: one register stage that can be dropped between a producer and a consumer to break a long data path, without losing, duplicating or reordering any data and without reducing throughput.
A stream moves one beat (one data word) at a time between a sender and a receiver:
valid and data. The receiver drives ready.valid and ready are 1.valid, it must keep valid high and data unchanged until thetransfer happens. The receiver may change ready at any time.
valid is 0, data is meaningless.Your module is a receiver on its s_* (upstream) side and a sender on its m_* (downstream) side, so it must obey those sender rules on m_*.
module valid_ready_reg #(
parameter int WIDTH = 8
) (
input logic clk,
input logic rst, // synchronous, active-high
input logic s_valid, // upstream side
output logic s_ready,
input logic [WIDTH-1:0] s_data,
output logic m_valid, // downstream side
input logic m_ready,
output logic [WIDTH-1:0] m_data
);
The module holds at most one beat. "Full" means m_valid = 1.
m_valid and m_data are driven directly by flip-flops.s_ready is combinational and must be exactlys_ready = !m_valid || m_ready: the slice accepts a beat when it is empty, or when the beat it holds is leaving in the same cycle. (This makes s_ready depend combinationally on m_ready. That is fine for this simple version; the skid buffer problem removes that path.)
rst is 0):s_valid && s_ready: the slice stores s_data, and in the next cyclem_valid = 1 and m_data is that beat (latency: exactly 1 cycle);
m_valid && m_ready: the beat has been delivered and m_valid becomes 0;m_valid && !m_ready, m_valid stays 1and m_data must not change.
s_valid and m_ready both held at 1, one beat must transfer oneach side in every cycle.
rst = 1, the slice becomes empty: in the next cyclem_valid = 0 (and therefore s_ready = 1). A beat held at that moment is discarded. m_data does not need a reset.
s_data is ignored when s_valid = 0 (the tests drive garbage there), and m_data is not checked when m_valid = 0. The tests' sender follows the handshake rules above.
Beats A, B and C. In cycle 2 the downstream stalls (m_ready = 0) while the slice is full, so s_ready drops and B waits. From cycle 3 on, data flows at one beat per cycle.
| cycle | s_valid | s_data | s_ready | m_valid | m_data | m_ready | transfers at end of cycle |
|---|---|---|---|---|---|---|---|
| 1 | 1 | A | 1 | 0 | – | 0 | A in |
| 2 | 1 | B | 0 | 1 | A | 0 | (stall) |
| 3 | 1 | B | 1 | 1 | A | 1 | A out, B in |
| 4 | 1 | C | 1 | 1 | B | 1 | B out, C in |
| 5 | 0 | – | 1 | 1 | C | 1 | C out |
| 6 | 0 | – | 1 | 0 | – | 0 |
Sign up free to solve Valid/Ready Pipeline Register in your browser.