A pipeline cuts a long combinational path into stages. Each clock a new input can enter; results emerge after a fixed latency.
flowchart LR a[A] --> add[add] b[B] --> add add --> s1[s1_reg] s1 --> mul[mul_C] c[C] --> mul mul --> s2[s2_reg]
Two-stage sketch
always_ff @(posedge clk) begin
if (in_valid) s1 <= a + b;
s2 <= s1 * c;
out_valid <= s1_valid;
end
Push valid (and later ready/stall) through the same number of stages as the data.
Wrong vs right
Wrong — only pipeline the datapath, leave control combinatorial across all stages:
assign out_valid = in_valid; // lies about latency
Right — delay control with the data:
always_ff @(posedge clk) begin
v1 <= in_valid;
v2 <= v1;
end
assign out_valid = v2;
Habits
- Document latency (
// +2 cycles). - Stall must hold every stage that still owns in-flight data — or drop with a documented flush.
- Wide multiply / add is the usual reason to pipeline; do not pipeline a 2-gate mux “for style”.