-
Notifications
You must be signed in to change notification settings - Fork 145
/
stream_delay.sv
134 lines (114 loc) · 4.22 KB
/
stream_delay.sv
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
// Author: Florian Zaruba, zarubaf@iis.ee.ethz.ch
// Description: Delay (or randomize) AXI-like handshaking
module stream_delay #(
parameter bit StallRandom = 0,
parameter int FixedDelay = 1,
parameter type payload_t = logic,
parameter logic [15:0] Seed = '0
)(
input logic clk_i,
input logic rst_ni,
input payload_t payload_i,
output logic ready_o,
input logic valid_i,
output payload_t payload_o,
input logic ready_i,
output logic valid_o
);
if (FixedDelay == 0 && !StallRandom) begin : gen_pass_through
assign ready_o = ready_i;
assign valid_o = valid_i;
assign payload_o = payload_i;
end else begin : gen_delay
localparam int unsigned CounterBits = 32;
typedef enum logic [1:0] {
Idle, Valid, Ready
} state_e;
state_e state_d, state_q;
logic load;
logic [CounterBits-1:0] count_out;
logic en;
logic [CounterBits-1:0] counter_load;
assign payload_o = payload_i;
always_comb begin
state_d = state_q;
valid_o = 1'b0;
ready_o = 1'b0;
load = 1'b0;
en = 1'b0;
unique case (state_q)
Idle: begin
if (valid_i) begin
load = 1'b1;
state_d = Valid;
// Just one cycle delay
if (FixedDelay == 1 || (StallRandom && counter_load == 1)) begin
state_d = Ready;
end
if (StallRandom && counter_load == 0) begin
valid_o = 1'b1;
ready_o = ready_i;
if (ready_i) state_d = Idle;
else state_d = Ready;
end
end
end
Valid: begin
en = 1'b1;
if (count_out == 0) begin
state_d = Ready;
end
end
Ready: begin
valid_o = 1'b1;
ready_o = ready_i;
if (ready_i) state_d = Idle;
end
default : /* default */;
endcase
end
if (StallRandom) begin : gen_random_stall
lfsr_16bit #(
.WIDTH ( 16 ),
.SEED ( Seed )
) i_lfsr_16bit (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.en_i ( load ),
.refill_way_oh ( ),
.refill_way_bin ( counter_load )
);
end else begin : gen_fixed_delay
assign counter_load = FixedDelay;
end
counter #(
.WIDTH ( CounterBits )
) i_counter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clear_i ( 1'b0 ),
.en_i ( en ),
.load_i ( load ),
.down_i ( 1'b1 ),
.d_i ( counter_load ),
.q_o ( count_out ),
.overflow_o ( )
);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
state_q <= Idle;
end else begin
state_q <= state_d;
end
end
end
endmodule