/* adjusted from pulp common_cells/spill_register_flushable.sv */ module skid_buffer #( parameter unsigned W = 2 )( input clk_i, input rstx_i, input valid_i, output ready_o, input [W-1:0] data_i, output valid_o, input ready_i, output [W-1:0] data_o ); logic a_fill, a_full, a_drain, b_fill, b_full, b_drain; logic [W-1:0] a, b; /* reg a */ always_ff @(posedge clk_i or negedge rstx_i) if (!rstx_i) a <= '0; else if (a_fill) a <= data_i; always_ff @(posedge clk_i or negedge rstx_i) if (!rstx_i) a_full <= '0; else if (a_fill || a_drain) a_full <= a_fill; always_ff @(posedge clk_i or negedge rstx_i) if (!rstx_i) b <= '0; else if (b_fill) b <= a; /* fill A first, if upstream can't read A in time, place A into B and skid the * input into A until upstream can clean out B */ assign a_fill = valid_i && ready_o; assign a_drain = a_full && !b_full; assign b_fill = a_drain && !ready_i; assign b_drain = b_full && ready_i; assign ready_o = !a_full || !b_full; assign valid_o = a_full || b_full; assign data_o = b_full ? b : a; endmodule // skid_buffer