Pipelines the path of a ready/valid handshake with zero or more Skid
Buffers to control the propagation delay and
increase the possible clock frequency. The latency from input to output is
PIPE_DEPTH
cycles. This module is a variation of the Simple Register
Pipeline.
Unlike a Pipeline FIFO Buffer, a Skid Buffer Pipeline will not improve concurrency by absorbing any irregularities in the transfer rates of the input and output interfaces: if one interface stalls, the other interface will eventually see that stall. However, a FIFO buffer will not add much pipelining.
Alternatively, if you can afford a FIFO or if your hardware supports it well, you may want to use a Pipeline Credit Buffer instead, which might use less hardware for longer pipelines and has both the pipelining benefits of a Skid Buffer Pipeline and the buffering of a FIFO.
clear
sets all registers to zero. If PIPE_DEPTH
is zero, the input
handshake ports becomes directly wired to the output handshake ports and no
logic is inferred.
`default_nettype none module Skid_Buffer_Pipeline #( parameter WORD_WIDTH = 0, parameter PIPE_DEPTH = -1 ) ( // If PIPE_DEPTH is zero, these are unused // verilator lint_off UNUSED input wire clock, input wire clear, // verilator lint_on UNUSED input wire input_valid, output wire input_ready, input wire [WORD_WIDTH-1:0] input_data, output reg output_valid, input wire output_ready, output reg [WORD_WIDTH-1:0] output_data ); localparam WORD_ZERO = {WORD_WIDTH{1'b0}}; initial begin output_valid = 1'b0; output_data = WORD_ZERO; end genvar i; generate if (PIPE_DEPTH == 0) begin assign input_ready = output_ready; always @(*) begin output_valid = input_valid; output_data = input_data; end end else if (PIPE_DEPTH > 0) begin
We strip out first iteration of Skid Buffer instantiations to avoid having to refer to index -1 in the generate loop, and also to connect to the input handshake ports rather than the output of a previous Skid Buffer.
wire valid_pipe [PIPE_DEPTH-1:0]; wire ready_pipe [PIPE_DEPTH-1:0]; wire [WORD_WIDTH-1:0] data_pipe [PIPE_DEPTH-1:0]; Pipeline_Skid_Buffer #( .WORD_WIDTH (WORD_WIDTH), .CIRCULAR_BUFFER (0) // Not meaningful here ) input_stage ( .clock (clock), .clear (clear), .input_valid (input_valid), .input_ready (input_ready), .input_data (input_data), .output_valid (valid_pipe[0]), .output_ready (ready_pipe[0]), .output_data (data_pipe [0]) );
Now repeat over the remainder of the pipeline stages, starting at stage 1, connecting each pipeline stage to the output of the previous pipeline stage.
for (i=1; i < PIPE_DEPTH; i=i+1) begin: pipe_stages Pipeline_Skid_Buffer #( .WORD_WIDTH (WORD_WIDTH), .CIRCULAR_BUFFER (0) // Not meaningful here ) pipe_stage ( .clock (clock), .clear (clear), .input_valid (valid_pipe[i-1]), .input_ready (ready_pipe[i-1]), .input_data (data_pipe [i-1]), .output_valid (valid_pipe[i]), .output_ready (ready_pipe[i]), .output_data (data_pipe [i]) ); end
And finally, connect the output handshake ports of the last Skid Buffer to the module output handshake ports.
assign ready_pipe [PIPE_DEPTH-1] = output_ready; always @(*) begin output_valid = valid_pipe[PIPE_DEPTH-1]; output_data = data_pipe [PIPE_DEPTH-1]; end end endgenerate endmodule