-
Notifications
You must be signed in to change notification settings - Fork 2
/
fifo.v
103 lines (93 loc) · 3.11 KB
/
fifo.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
/* ----------------------------------------- *
* Title : FIFO Buffer *
* Project : Verilog Utility Modules *
* ----------------------------------------- *
* File : fifo.v *
* Author : Yigit Suoglu *
* Last Edit : 24/10/2021 *
* Licence : CERN-OHL-W *
* ----------------------------------------- *
* Description : A generic FIFO circular *
* buffer *
* ----------------------------------------- */
module fifo_cl#(
parameter DATA_WIDTH = 32, //Size of each data entry
parameter FIFO_LENGTH_SIZE = 6 //Width of number of entries
)(
input clk,
input rst,
//Flags
output fifo_empty,
output fifo_full,
output reg [FIFO_LENGTH_SIZE: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
);
localparam FIFO_LENGTH = 2 ** FIFO_LENGTH_SIZE;
reg [DATA_WIDTH-1:0] buffer[FIFO_LENGTH-1:0];
//Pointers for circular buffer
reg [FIFO_LENGTH_SIZE-1:0] read_ptr;
wire [FIFO_LENGTH_SIZE-1:0] write_ptr = read_ptr + awaiting_count[FIFO_LENGTH_SIZE-1:0];
always@(posedge clk) begin
if(rst) begin
read_ptr <= 0;
end else begin
read_ptr <= (~fifo_empty & drop) ? read_ptr + 1 : read_ptr;
end
end
always@(posedge clk) begin
if(rst) begin
awaiting_count <= 0;
end else begin
if(~fifo_full & ~drop & push) begin
awaiting_count <= awaiting_count + 1;
end else if(~fifo_empty & drop & ~push) begin
awaiting_count <= awaiting_count - 1;
end
end
end
//fifo flags
assign fifo_empty = (awaiting_count == 0);
assign fifo_full = awaiting_count[FIFO_LENGTH_SIZE];
//Handle data pins
assign data_o = buffer[read_ptr];
always@(posedge clk) begin
if(~fifo_full & push) begin
buffer[write_ptr] <= data_i;
end
end
endmodule
module fifo_ce#(
parameter DATA_WIDTH = 32, //Size of each data entry
parameter FIFO_LENGTH_SIZE = 6 //Width of number of entries
)(
input clk,
input rst,
//Flags
output fifo_empty,
output fifo_full,
output reg [FIFO_LENGTH_SIZE: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;
always@(posedge clk) begin
push_d <= push;
drop_d <= drop;
end
wire push_posedge = ~push_d & push;
wire drop_posedge = ~drop_d & drop;
fifo_cl #(.DATA_WIDTH(DATA_WIDTH), .FIFO_LENGTH_SIZE(FIFO_LENGTH_SIZE))
fifo(.clk(clk), .rst(rst),
.fifo_empty(fifo_empty), .fifo_full(fifo_full), .awaiting_count(awaiting_count),
.data_i(data_i), .push(push_posedge),
.data_o(data_o), .drop(drop_posedge));
endmodule