Source

License

Index

Pipeline Handshake Multiplier

Accepts one ready/valid handshake at its input, along with a repeat count, and will not accept another input handshake until input_data_repeat_count output handshakes have been accepted. Each output handshake is a copy of the input handshake, without the repeat count.

input_data_repeat_count must be less or equal to MAX_REPEAT_COUNT.

Loading a repeat count of zero immediately resets the buffer, and so the input handshake is sunk and so no output handshakes happen, and we immediately are ready to accept a new input handshake.

`default_nettype none

module Pipeline_Handshake_Multiplier
#(
    parameter WORD_WIDTH        = 0,
    parameter MAX_REPEAT_COUNT  = 0,

    // Do not set at instantiation, except in Vivado IPI.
    parameter REPEAT_COUNT_WIDTH = clog2(MAX_REPEAT_COUNT) + 1 // +1 to hold exact number, not a 0-index
)
(
    input   wire                                clock,
    input   wire                                clear,

    input   wire                                input_data_valid,
    output  wire                                input_data_ready,
    input   wire    [WORD_WIDTH-1:0]            input_data,
    input   wire    [REPEAT_COUNT_WIDTH-1:0]    input_data_repeat_count,

    output  wire                                output_data_valid,
    input   wire                                output_data_ready,
    output  wire    [WORD_WIDTH-1:0]            output_data
);

    `include "clog2_function.vh"

First, let's buffer the input handshake. A Half Buffer will hold its output steady and not accept another input handshake until its output handshake completes. A repeat count of zero clears the buffer immediately.

    // verilator lint_off UNOPTFLAT
    wire output_data_ready_divided;
    // verilator lint_on  UNOPTFLAT

    reg clear_input_buffer = 1'b0;

    Pipeline_Half_Buffer
    #(
        .WORD_WIDTH         (WORD_WIDTH),
        .CIRCULAR_BUFFER    (0)  // non-zero to enable
    )
    input_buffer
    (
        .clock              (clock),
        .clear              (clear | clear_input_buffer),

        .input_valid        (input_data_valid),
        .input_ready        (input_data_ready),
        .input_data         (input_data),

        .output_valid       (output_data_valid),
        .output_ready       (output_data_ready_divided),
        .output_data        (output_data)
    );

We only need to control the buffer output ready signal and assert it once after input_data_repeat_count module output handshakes. The repeat count is stored in the Pulse Divider one cycle before the output handshake becomes ready.

    localparam REPEAT_ZERO = {REPEAT_COUNT_WIDTH{1'b0}};

    reg module_input_handshake_done  = 1'b0;
    reg module_output_handshake_done = 1'b0;

    always @(*) begin
        module_input_handshake_done  = (input_data_valid            == 1'b1) && (input_data_ready        == 1'b1);
        clear_input_buffer           = (module_input_handshake_done == 1'b1) && (input_data_repeat_count == REPEAT_ZERO);
        module_output_handshake_done = (output_data_valid           == 1'b1) && (output_data_ready       == 1'b1);
    end

NOTE: a input_data_repeat_count of zero DOES get loaded, which will cause the Pulse_Divider to immediately load the first non-zero value it sees, but since the input_buffer is not asserting valid at its output, any output from the Pulse_Divider cannot complete any handshakes and has no effect.

    Pulse_Divider
    #(
        .WORD_WIDTH         (REPEAT_COUNT_WIDTH),
        .INITIAL_DIVISOR    (MAX_REPEAT_COUNT [REPEAT_COUNT_WIDTH-1:0])
    )
    output_handshake_counter
    (
        .clock              (clock),
        .restart            (module_input_handshake_done),
        .divisor            (input_data_repeat_count),
        .pulses_in          (module_output_handshake_done),
        .pulse_out          (output_data_ready_divided),
        // verilator lint_off PINCONNECTEMPTY
        .div_by_zero        ()
        // verilator lint_on  PINCONNECTEMPTY
    );

endmodule

Back to FPGA Design Elements

fpgacpu.ca