1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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
|