diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2026-09-27 22:30:41 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2026-09-27 22:30:41 +0300 |
| commit | f4afcfa58eb90d14abd55d79640ecda13b23dc21 (patch) | |
| tree | c0f63b35502d74cbdf3d2bc881675859a235596d /src/skid_buffer.sv | |
| parent | bc5941a1fcfd0a607a6aef51f7659c3f233b65dc (diff) | |
| download | ttarv32-master.tar.gz ttarv32-master.zip | |
+ Not great latency, but has a fairly high fmax and low resource usage
on my FPGA, so go with this for now. Likely better suited for data
path, unsure what I'll do for the control path.
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 |
