forked from SJTU-YONGFU-RESEARCH-GRP/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcredit_based_fifo.v
More file actions
executable file
·208 lines (192 loc) · 8.31 KB
/
credit_based_fifo.v
File metadata and controls
executable file
·208 lines (192 loc) · 8.31 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/**
* Credit-Based FIFO
*
* This module implements a FIFO with credit-based flow control. Credits represent
* available buffer space, allowing the producer to know how much data can be
* sent without causing overflow. This is a common flow control mechanism in
* high-performance systems.
*
* Key Features:
* - Credit-based flow control: Producer tracks available buffer space
* - Credit return: Consumer returns credits when data is consumed
* - AXI-style interface: Valid/ready handshaking
* - Credit tracking: Maintains count of available credits
* - Initial credits: Configurable starting credit count
*
* Credit Mechanism:
* - Credits represent available buffer space
* - Producer consumes credit when sending data
* - Consumer returns credit when consuming data
* - Producer can only send when credits > 0
* - Prevents overflow: Producer knows available space
*
* Credit Flow:
* - Initial: credit_count = INIT_CREDITS (typically FIFO_DEPTH)
* - On write: credit_count decreases (if credit_count > 0)
* - On credit_return: credit_count increases (if credit_count < FIFO_DEPTH)
* - ready_out: High when credit_count > 0 and FIFO not full
*
* Use Cases:
* - High-performance interconnects
* - Network-on-Chip (NoC) flow control
* - PCIe credit-based flow control
* - Systems requiring backpressure management
*
* Advantages:
* - Prevents overflow: Producer knows available space
* - Low latency: Credits can be returned early
* - Efficient: Reduces unnecessary stalls
*
* @param DATA_WIDTH Width of data words (default: 8 bits)
* @param FIFO_DEPTH Depth of FIFO buffer (default: 16 entries)
* @param ADDR_WIDTH Address width (calculated as log2(FIFO_DEPTH))
* @param INIT_CREDITS Initial credit count (default: FIFO_DEPTH)
*
* @input clk Clock signal
* @input rst_n Active-low reset signal
*
* @input data_in[DATA_WIDTH-1:0] Producer data input
* @input valid_in Producer data valid
* @output ready_out Producer ready (high when credits available)
*
* @output data_out[DATA_WIDTH-1:0] Consumer data output
* @output valid_out Consumer data valid
* @input ready_in Consumer ready
*
* @input credit_return Credit return signal (pulse when consumer processes data)
* @output credits_available[ADDR_WIDTH:0] Current number of available credits
*
* @output full Full flag
* @output empty Empty flag
* @output fifo_level[ADDR_WIDTH:0] Current number of entries in FIFO
*/
module credit_based_fifo #(
parameter DATA_WIDTH = 8,
parameter FIFO_DEPTH = 16,
parameter ADDR_WIDTH = $clog2(FIFO_DEPTH),
parameter INIT_CREDITS = FIFO_DEPTH // Set initial credits to FIFO depth
) (
input wire clk,
input wire rst_n,
// Producer interface
input wire [DATA_WIDTH-1:0] data_in,
input wire valid_in,
output wire ready_out,
// Consumer interface
output reg [DATA_WIDTH-1:0] data_out,
output reg valid_out,
input wire ready_in,
// Credit interface
input wire credit_return,
output wire [ADDR_WIDTH:0] credits_available,
// Status outputs
output wire full,
output wire empty,
output wire [ADDR_WIDTH:0] fifo_level
);
// ============================================================================
// Memory Storage
// ============================================================================
// Memory array: stores FIFO data
reg [DATA_WIDTH-1:0] mem [0:FIFO_DEPTH-1];
// ============================================================================
// Pointers and Credit Counter
// ============================================================================
// Write and read pointers for FIFO management
reg [ADDR_WIDTH:0] write_ptr; // Write pointer
reg [ADDR_WIDTH:0] read_ptr; // Read pointer
// Credit counter: tracks available buffer space
// Credits represent how many data items can be accepted
reg [ADDR_WIDTH:0] credit_count;
// ============================================================================
// FIFO Status Signals
// ============================================================================
// Empty: Read and write pointers are equal
assign empty = (write_ptr == read_ptr);
// Full: FIFO level is at or near maximum
assign full = (fifo_level >= FIFO_DEPTH - 1);
// ============================================================================
// FIFO Level Calculation
// ============================================================================
// Current number of entries in FIFO
assign fifo_level = write_ptr - read_ptr;
// ============================================================================
// Credit Tracking and Flow Control
// ============================================================================
// Output current credit count
assign credits_available = credit_count;
// Producer ready: Can accept data only if:
// 1. Credits are available (credit_count > 0)
// 2. FIFO is not full
// This prevents overflow by ensuring producer knows available space
assign ready_out = (credit_count > 0) && !full;
// ============================================================================
// Write Logic
// ============================================================================
// Write data to FIFO when producer has valid data and FIFO is ready
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
write_ptr <= 0;
end else if (valid_in && ready_out) begin
// Write data to memory and advance write pointer
mem[write_ptr[ADDR_WIDTH-1:0]] <= data_in;
write_ptr <= write_ptr + 1'b1;
end
end
// ============================================================================
// Read Logic
// ============================================================================
// Read data from FIFO and provide to consumer
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
read_ptr <= 0;
valid_out <= 1'b0;
end else begin
// Provide new data if FIFO is not empty and:
// - No data currently valid, OR
// - Current data was consumed (ready_in was high)
if (!empty && (!valid_out || (valid_out && ready_in))) begin
data_out <= mem[read_ptr[ADDR_WIDTH-1:0]];
read_ptr <= read_ptr + 1'b1;
valid_out <= 1'b1;
end else if (valid_out && ready_in) begin
// Data was consumed: clear valid flag
valid_out <= 1'b0;
end
end
end
// ============================================================================
// Credit Management
// ============================================================================
// Manages credit count based on write operations and credit returns
// Credits decrease when data is written, increase when credits are returned
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// Initialize with full credits (producer can send FIFO_DEPTH items)
credit_count <= INIT_CREDITS;
end else begin
// Credit update logic based on write and credit return events
case ({valid_in && ready_out, credit_return})
2'b00: begin
// No write, no credit return: credits unchanged
credit_count <= credit_count;
end
2'b01: begin
// Credit return only: increase credits (if not at max)
// Consumer has processed data, making space available
credit_count <= (credit_count < FIFO_DEPTH) ? credit_count + 1'b1 : credit_count;
end
2'b10: begin
// Write only: decrease credits (if credits available)
// Producer has consumed a credit by writing data
credit_count <= (credit_count > 0) ? credit_count - 1'b1 : credit_count;
end
2'b11: begin
// Both write and credit return: no net change
// Credit consumed by write is immediately returned
credit_count <= credit_count;
end
endcase
end
end
endmodule