-
Notifications
You must be signed in to change notification settings - Fork 2
/
fifo_flex.v
150 lines (137 loc) · 4.83 KB
/
fifo_flex.v
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
/* ----------------------------------------- *
* Title : FIFO Buffer Flexible Size *
* Project : Verilog Utility Modules *
* ----------------------------------------- *
* File : fifo_flex.v *
* Author : Yigit Suoglu *
* Last Edit : 02/09/2021 *
* Licence : CERN-OHL-W *
* ----------------------------------------- *
* Description : A generic FIFO buffer with *
* flexible buffer size *
* ----------------------------------------- */
module fifo_fl#(
parameter DATA_WIDTH = 32, //Size of each data entry
parameter FIFO_LENGTH = 16, //Number of entries
parameter COUNTER_SIZE = $clog2(FIFO_LENGTH+1) //Shoud be able to fit FIFO_LENGTH, best to leave as it is
)(
input clk,
input rst,
//Flags
output fifo_empty,
output fifo_full,
output reg [COUNTER_SIZE-1:0] awaiting_count, //Number of entires waiting in the buffer
//Data in
input [DATA_WIDTH-1:0] data_i,
input push, //Add data_i to buffer, level sensitive
//Data out
output [DATA_WIDTH-1:0] data_o,
input drop //Entry at data_o is read, should be set after data_o is read, level sensitive
);
reg [DATA_WIDTH-1:0] buffer[FIFO_LENGTH-1:0];
reg [DATA_WIDTH-1:0] buffer_next[FIFO_LENGTH-1:0];
integer i;
//fifo flags
assign fifo_empty = (awaiting_count == 0);
assign fifo_full = (awaiting_count == FIFO_LENGTH);
assign data_o = buffer[0];
always@* begin //determine shifted buffer
for (i = 0; i < (FIFO_LENGTH-1); i=i+1) begin
buffer_next[i] = buffer[i+1];
end
buffer_next[FIFO_LENGTH-1] = (fifo_full & push) ? data_i : {DATA_WIDTH{1'b0}};
end
always@(posedge clk) begin //keep track of number of valid enties
if(rst) begin
awaiting_count <= {COUNTER_SIZE{1'b0}};
end else begin
if(push & ((~drop & ~fifo_full) | fifo_empty)) begin
awaiting_count <= awaiting_count + {{COUNTER_SIZE-1{1'b0}},1'b1};
end else if (drop & ~push & ~fifo_empty) begin
awaiting_count <= awaiting_count - {{COUNTER_SIZE-1{1'b0}},1'b1};
end
end
end
always@(posedge clk) begin //Handle push drop
if(rst) begin
for (i = 0; i < FIFO_LENGTH; i=i+1) begin
buffer[i] <= {DATA_WIDTH{1'b0}};
end
end else begin
if(drop) begin
for (i = 0; i < FIFO_LENGTH; i=i+1) begin
buffer[i] <= (push & ((i+1) == awaiting_count)) ? data_i : buffer_next[i];
end
end else if(push & ~fifo_full) begin
buffer[awaiting_count] <= data_i;
end
end
end
endmodule
module fifo_fe#(
parameter DATA_WIDTH = 32, //Size of each data entry
parameter FIFO_LENGTH = 16, //Number of entries
parameter COUNTER_SIZE = $clog2(FIFO_LENGTH+1) //Shoud be able to fit FIFO_LENGTH, best to leave as it is
)(
input clk,
input rst,
//Flags
output fifo_empty,
output fifo_full,
output reg [COUNTER_SIZE-1:0] awaiting_count, //Number of entires waiting in the buffer
//Data in
input [DATA_WIDTH-1:0] data_i,
input push, //Add data_i to buffer, edge sensitive
//Data out
output [DATA_WIDTH-1:0] data_o,
input drop //Entry at data_o is read, should be set after data_o is read, edge sensitive
);
reg push_d, drop_d;
wire push_posedge, drop_posedge;
reg [DATA_WIDTH-1:0] buffer[FIFO_LENGTH-1:0];
reg [DATA_WIDTH-1:0] buffer_next[FIFO_LENGTH-1:0];
integer i;
//fifo flags
assign fifo_empty = (awaiting_count == 0);
assign fifo_full = (awaiting_count == FIFO_LENGTH);
assign data_o = buffer[0];
//Edge detection
always@(posedge clk) begin
push_d <= push;
drop_d <= drop;
end
assign drop_posedge = ~drop_d & drop;
assign push_posedge = ~push_d & push;
always@* begin //determine shifted buffer
for (i = 0; i < (FIFO_LENGTH-1); i=i+1) begin
buffer_next[i] = buffer[i+1];
end
buffer_next[FIFO_LENGTH-1] = (fifo_full & push_posedge) ? data_i : {DATA_WIDTH{1'b0}};
end
always@(posedge clk) begin //keep track of number of valid enties
if(rst) begin
awaiting_count <= {COUNTER_SIZE{1'b0}};
end else begin
if(push_posedge & ((~drop_posedge & ~fifo_full) | fifo_empty)) begin
awaiting_count <= awaiting_count + {{COUNTER_SIZE-1{1'b0}},1'b1};
end else if (drop_posedge & ~push_posedge & ~fifo_empty) begin
awaiting_count <= awaiting_count - {{COUNTER_SIZE-1{1'b0}},1'b1};
end
end
end
always@(posedge clk) begin //Handle push drop
if(rst) begin
for (i = 0; i < FIFO_LENGTH; i=i+1) begin
buffer[i] <= {DATA_WIDTH{1'b0}};
end
end else begin
if(drop_posedge) begin
for (i = 0; i < FIFO_LENGTH; i=i+1) begin
buffer[i] <= (push_posedge & ((i+1) == awaiting_count)) ? data_i : buffer_next[i];
end
end else if(push_posedge & ~fifo_full) begin
buffer[awaiting_count] <= data_i;
end
end
end
endmodule