-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathfifo.v
More file actions
112 lines (102 loc) · 3.69 KB
/
fifo.v
File metadata and controls
112 lines (102 loc) · 3.69 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
/* ----------------------------------------- *
* Title : FIFO Buffer *
* Project : Verilog Utility Modules *
* ----------------------------------------- *
* File : fifo.v *
* Author : Yigit Suoglu *
* Last Edit : 14/11/2025 *
* Licence : CERN-OHL-W *
* ----------------------------------------- *
* Description : A generic FIFO circular *
* buffer *
* ----------------------------------------- */
//Level sensetive push/drop
module fifo_cl#(
parameter DATA_WIDTH = 32, //Size of each data entry
parameter FIFO_DEPTH = 64 //Max number of buffer entries
)(
input clk,
input rst,
//Flags
output fifo_empty,
output fifo_full,
output reg [$clog2(FIFO_DEPTH):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_SIZE = $clog2(FIFO_DEPTH);
localparam FIFO_DEPTH_POW2 = ((FIFO_DEPTH & (FIFO_DEPTH - 1)) == 0);
localparam WRITE_PTR_SUM_SIZE = FIFO_DEPTH_POW2 ? FIFO_LENGTH_SIZE - 1 : FIFO_LENGTH_SIZE;
reg [DATA_WIDTH-1:0] buffer[FIFO_DEPTH-1:0];
//Pointers for circular buffer
reg [FIFO_LENGTH_SIZE-1:0] read_ptr;
wire [FIFO_LENGTH_SIZE-1:0] read_ptr_overflow = FIFO_DEPTH_POW2 ? 0 : read_ptr == (FIFO_DEPTH-1);
wire [WRITE_PTR_SUM_SIZE:0] write_ptr_pre = awaiting_count[FIFO_LENGTH_SIZE-1:0] + read_ptr;
wire write_ptr_overflow = FIFO_DEPTH_POW2 ? 0 : write_ptr_pre > (FIFO_DEPTH-1);
wire [FIFO_LENGTH_SIZE-1:0] write_ptr = write_ptr_overflow ? write_ptr_pre - FIFO_DEPTH : write_ptr_pre;
always@(posedge clk) begin
if(rst) begin
read_ptr <= 0;
end else begin
read_ptr <= (~fifo_empty & drop) ?
read_ptr_overflow ? 0 : 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_DEPTH);
//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
//edge sensetive push/drop
module fifo_ce#(
parameter DATA_WIDTH = 32, //Size of each data entry
parameter FIFO_DEPTH = 64 //Max number of buffer entries
)(
input clk,
input rst,
//Flags
output fifo_empty,
output fifo_full,
output reg [$clog2(FIFO_DEPTH):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_DEPTH(FIFO_DEPTH))
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