Source

License

Index

Pipeline Fork (Eager)

Takes in a ready/valid handshake with the associated data, and replicates that transaction to multiple outputs. The input can proceed to the next transaction once all outputs have finished their transactions. Each output transaction can complete independently.

The outputs are buffered, so each output transaction can complete independently, in any order. This also breaks any long combinational path or loops which might happen when using the Lazy Pipeline Fork.

`default_nettype none

module Pipeline_Fork_Eager
#(
    parameter WORD_WIDTH    = 0,
    parameter OUTPUT_COUNT  = 0,

    // Do not set at instantiation, except in IPI
    parameter TOTAL_WIDTH   = WORD_WIDTH * OUTPUT_COUNT
)
(
    input  wire                     clock,
    input  wire                     clear,

    input  wire                     input_valid,
    output wire                     input_ready,
    input  wire [WORD_WIDTH-1:0]    input_data,

    output wire [OUTPUT_COUNT-1:0]  output_valid,
    input  wire [OUTPUT_COUNT-1:0]  output_ready,
    output wire [TOTAL_WIDTH-1:0]   output_data
);

    wire [OUTPUT_COUNT-1:0] output_valid_unbuffered;
    wire [OUTPUT_COUNT-1:0] output_ready_unbuffered;
    wire [TOTAL_WIDTH-1:0]  output_data_unbuffered;

    Pipeline_Fork_Lazy
    #(
        .WORD_WIDTH     (WORD_WIDTH),
        .OUTPUT_COUNT   (OUTPUT_COUNT)
    )
    input_fork
    (
        .input_valid    (input_valid),
        .input_ready    (input_ready),
        .input_data     (input_data),

        .output_valid   (output_valid_unbuffered),
        .output_ready   (output_ready_unbuffered),
        .output_data    (output_data_unbuffered)
    );

    generate
        genvar i;
        for (i=0; i < OUTPUT_COUNT; i=i+1) begin: per_output
            Pipeline_Skid_Buffer
            #(
                .WORD_WIDTH      (WORD_WIDTH),
                .CIRCULAR_BUFFER (0)            // Not meaningful here
            )
            output_buffer
            (
                .clock           (clock),
                .clear           (clear),

                .input_valid     (output_valid_unbuffered [i]),
                .input_ready     (output_ready_unbuffered [i]),
                .input_data      (output_data_unbuffered  [WORD_WIDTH*i +: WORD_WIDTH]),

                .output_valid    (output_valid [i]),
                .output_ready    (output_ready [i]),
                .output_data     (output_data  [WORD_WIDTH*i +: WORD_WIDTH])
            );
        end
    endgenerate

endmodule

Back to FPGA Design Elements

fpgacpu.ca