If reports show a long producer-to-consumer path and the latency budget permits it, evaluate a registered boundary with physical placement near the intended split. Registers create new timing endpoints; RTL alone does not guarantee shorter routes or balanced stages.
Read the two rows as the same connection. The slice does not make the wire shorter; it gives each half its own cycle.
Without the slice, the whole route delay must fit in one clock period.
With it, leg 1 ends at req_mid (E1) and leg 2 at req_dst (E2), matching the waveform below.
The benefit depends on placing req_mid near the middle; RTL alone does not decide that.
Scope: an always-accepting, same-clock delay line with no READY or storage management for stalls. Reset asynchronously clears both valid stages and data, cancelling in-flight work. For a consumer that can stall, use the elastic stage instead.
Edge convention | First stage | Second stage / consumer |
|---|---|---|
Producer launches A just after E0 | Old value at E0 | Old value |
E1 pre-update / post-update | Captures A / exposes A | Captures old first-stage word |
E2 pre-update / post-update | Captures next word | Captures A / exposes A |
E3 pre-update | Next word | A is consumed by a clocked sink |
Thus E0 launch to E2 output availability is two cycles, and a downstream flop consumes at E3. The waveform slots and bench inspect settled post-update values; they do not describe a consumer reading the new value at that same edge.
The waveform follows one request pulse through both slice stages. The testbench drives req_src just after a rising edge, as a producer register would. The data word travels with it.
Slot 1: rst_n is 0, so req_mid and req_dst are 0.
Slot 2: rst_n is 1. Nothing has been launched yet, so all three are 0.
Slot 3: the producer launches req_src just after this edge (E0). Neither stage has captured it yet.
Slot 4: E1 captured the pulse, so req_mid is 1. req_src has returned to 0 and req_dst is still 0.
Slot 5: E2 captured it in the second stage, so req_dst is 1 and req_mid is 0. That is two cycles after launch.
Slot 6: the pulse has drained, so all three are 0.
Throughput stays at one transfer per cycle. Latency grows by two cycles, so the consumer must expect data two cycles after the request.
Alignment. The valid bit arrives two cycles before its word, so the consumer acts on stale data. The pitfall above shows the fix.
The two-stage delay line with a checker that samples the source at every rising edge and compares each stage in the low phase, after the stimulus has moved to the next word. There a register still shows the sampled value and a plain wire would show the new one, so each stage's one-cycle delay is tested on its own. Replacing stage 1 with a wire makes the bench fail 17 of its checks.
`timescale 1ns/1ps
module reg_slice #(
parameter int DW = 32
) (
input logic clk,
input logic rst_n,
input logic req_src,
input logic [DW-1:0] data_src,
output logic req_mid,
output logic [DW-1:0] data_mid,
output logic req_dst,
output logic [DW-1:0] data_dst
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
req_mid <= 1'b0;
data_mid <= '0;
req_dst <= 1'b0;
data_dst <= '0;
end else begin
req_mid <= req_src;
data_mid <= data_src;
req_dst <= req_mid;
data_dst <= data_mid;
end
end
endmodule
The finite checker compares settled post-update valid and data over 8 transfers. It checks alignment, not stall handling or routed timing.