diff options
Diffstat (limited to 'src/skid_buffer.sv')
| -rw-r--r-- | src/skid_buffer.sv | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/skid_buffer.sv b/src/skid_buffer.sv new file mode 100644 index 0000000..3ea6d0d --- /dev/null +++ b/src/skid_buffer.sv @@ -0,0 +1,53 @@ +/* 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 |
