// skid_buffer.v - 2-entry skid buffer with valid/ready handshake
//
// When valid_i && ready_o, capture data_i. Output via valid_o && ready_i.
// Stores one extra entry in skid register. Pure combinational ready_o path.
//
// Parameters:
//   DW = data width (default 12)
//
// Interface:
//   clk, rst_n    - clock, active-low reset
//   data_i, valid_i, ready_o - input side
//   data_o, valid_o, ready_i - output side

module skid_buffer #(parameter DW = 12) (
    input              clk,
    input              rst_n,
    input  [DW-1:0]    data_i,
    input              valid_i,
    output             ready_o,
    output [DW-1:0]    data_o,
    output             valid_o,
    input              ready_i
);

    // Internal state
    reg               skid_valid;     // skid register has valid data
    reg [DW-1:0]      skid_data;      // skid register data

    // Output register (pipeline stage)
    reg               out_valid;
    reg [DW-1:0]      out_data;

    // ready_o is combinational: ready when output slot is empty
    // (either out_valid is 0, or ready_i is high and we can accept new data)
    assign ready_o = !out_valid || ready_i;

    // valid_o drives from output register
    assign valid_o = out_valid;
    assign data_o  = out_data;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            skid_valid <= 1'b0;
            skid_data  <= {DW{1'b0}};
            out_valid  <= 1'b0;
            out_data   <= {DW{1'b0}};
        end else begin
            if (out_valid && ready_i) begin
                // Output consumed: load from skid if available
                if (skid_valid) begin
                    out_data   <= skid_data;
                    out_valid  <= 1'b1;
                    skid_valid <= 1'b0;
                end else begin
                    out_valid <= 1'b0;
                end
            end

            if (valid_i && ready_o) begin
                if (!out_valid || (out_valid && ready_i && !skid_valid)) begin
                    // Output slot free: go directly to output
                    out_data   <= data_i;
                    out_valid  <= 1'b1;
                end else begin
                    // Output slot occupied: store in skid
                    skid_data  <= data_i;
                    skid_valid <= 1'b1;
                end
            end
        end
    end

endmodule
