// 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