1
1
/*
2
2
Copyright 2017 Damien Pretet ThotIP
3
-
3
+
4
4
Licensed under the Apache License, Version 2.0 (the "License");
5
5
you may not use this file except in compliance with the License.
6
6
You may obtain a copy of the License at
7
-
7
+
8
8
http://www.apache.org/licenses/LICENSE-2.0
9
-
9
+
10
10
Unless required by applicable law or agreed to in writing, software
11
11
distributed under the License is distributed on an "AS IS" BASIS,
12
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
19
20
20
module async_fifo
21
21
22
- #(
23
- parameter WIDTH = 8 ,
24
- parameter POINTER = 4
25
- )(
22
+ #(
23
+ parameter WIDTH = 8 ,
24
+ parameter POINTER = 4
25
+ )(
26
26
// Write side of the FIFO
27
- input wire wr_clk,
28
- input wire awresetn,
29
- input wire wren,
30
- input wire [WIDTH- 1 :0 ] data_in,
31
- output wire wr_full,
27
+ input wire wr_clk,
28
+ input wire awresetn,
29
+ input wire wren,
30
+ input wire [WIDTH- 1 :0 ] data_in,
31
+ output wire wr_full,
32
32
// Read side of the FIFO
33
- input wire rd_clk,
34
- input wire arresetn,
35
- input wire rden,
36
- output wire [WIDTH- 1 :0 ] data_out,
37
- output wire rd_empty
38
- );
33
+ input wire rd_clk,
34
+ input wire arresetn,
35
+ input wire rden,
36
+ output wire [WIDTH- 1 :0 ] data_out,
37
+ output wire rd_empty
38
+ );
39
39
40
40
localparam DEPTH = 1 << POINTER;
41
41
42
42
reg [POINTER- 1 : 0 ] rd_pointer, rd_sync_1, rd_sync_2;
43
43
reg [POINTER- 1 : 0 ] wr_pointer, wr_sync_1, wr_sync_2;
44
44
wire [POINTER- 1 : 0 ] rd_pointer_g;
45
45
wire [POINTER- 1 : 0 ] wr_pointer_g;
46
-
46
+
47
47
reg [WIDTH- 1 : 0 ] mem [DEPTH- 1 : 0 ];
48
-
48
+
49
49
wire [POINTER- 1 : 0 ] rd_pointer_sync;
50
50
wire [POINTER- 1 : 0 ] wr_pointer_sync;
51
-
51
+
52
52
// Write logic management
53
53
always @(posedge wr_clk or posedge awresetn) begin
54
54
if (awresetn == 1'b0 ) begin
@@ -59,13 +59,13 @@ module async_fifo
59
59
mem[wr_pointer[POINTER- 1 : 0 ]] <= data_in;
60
60
end
61
61
end
62
-
62
+
63
63
// Synchronization of read pointer with write clock
64
64
always @(posedge wr_clk) begin
65
65
rd_sync_1 <= rd_pointer_g;
66
66
rd_sync_2 <= rd_sync_1;
67
67
end
68
-
68
+
69
69
// Read logic management
70
70
always @(posedge rd_clk or posedge arresetn) begin
71
71
if (arresetn == 1'b0 ) begin
@@ -75,40 +75,40 @@ module async_fifo
75
75
rd_pointer <= rd_pointer + 1 ;
76
76
end
77
77
end
78
-
78
+
79
79
assign data_out = mem[rd_pointer[POINTER- 1 : 0 ]];
80
-
80
+
81
81
// Write pointer synchronization with read clock
82
82
always @(posedge rd_clk) begin
83
83
wr_sync_1 <= wr_pointer_g;
84
84
wr_sync_2 <= wr_sync_1;
85
85
end
86
-
86
+
87
87
// Binary pointer comparaison
88
88
assign wr_full = ((wr_pointer[POINTER- 1 : 0 ] == rd_pointer_sync[POINTER- 1 : 0 ]) &&
89
89
(wr_pointer[POINTER] != rd_pointer_sync[POINTER] ));
90
-
90
+
91
91
// Gray counter comparaison
92
92
// assign wr_full = ((wr_pointer[POINTER-2 : 0] == rd_pointer_sync[POINTER-2 : 0]) &&
93
93
// (wr_pointer[POINTER-1] != rd_pointer_sync[POINTER-1]) &&
94
94
// (wr_pointer[POINTER] != rd_pointer_sync[POINTER]));
95
-
95
+
96
96
// The FIFO is considered as empty when pointer match the same address
97
- // No more data remains to read
97
+ // No more data remains to read
98
98
assign rd_empty = ((wr_pointer_sync == rd_pointer) == 0 ) ? 1'b1 : 1'b0 ;
99
-
100
-
101
- // Convert to gray before moving the pointers
99
+
100
+
101
+ // Convert to gray before moving the pointers
102
102
// to the destination clock domain
103
103
assign wr_pointer_g = wr_pointer ^ (wr_pointer >> 1 );
104
104
assign rd_pointer_g = rd_pointer ^ (rd_pointer >> 1 );
105
-
106
-
107
- // Convert back to binary after the synchronization from
105
+
106
+
107
+ // Convert back to binary after the synchronization from
108
108
// the source domain
109
109
assign wr_pointer_sync = wr_sync_2 ^ (wr_sync_2 >> 1 ) ^
110
110
(wr_sync_2 >> 2 ) ^ (wr_sync_2 >> 3 );
111
-
111
+
112
112
assign rd_pointer_sync = rd_sync_2 ^ (rd_sync_2 >> 1 ) ^
113
113
(rd_sync_2 >> 2 ) ^ (rd_sync_2 >> 3 );
114
114
0 commit comments