Reference: https://www.youtube.com/watch?v=GSPIRcBQUVo
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
module Sync_FIFO # (
parameter FIFO_WIDTH = 8,
FIFO_DEPTH = 64,
ADDR_WIDTH = 6
)
(
input clk,
input rst_n,
input wr_en,
input rd_en,
input [FIFO_WIDTH-1:0] data_in,
output reg [FIFO_WIDTH-1:0] data_out,
output empty,
output full
);
reg [ADDR_WIDTH:0] counter;
reg [ADDR_WIDTH-1:0] wr_ptr, rd_ptr;
reg [FIFO_WIDTH-1:0] mem [FIFO_DEPTH-1:0];
// Define flag signals
assign empty = (counter==0);
assign full = (counter==FIFO_DEPTH);
// Update counter
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
counter <= 0;
else if (wr_en && !full && rd_en && !empty)
counter <= counter;
else if (wr_en && !full)
counter <= counter + 1;
else if (rd_en && !empty)
counter <= counter - 1;
else
counter <= counter;
end
// Read from FIFO
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
data_out <= 0;
else
begin
if (rd_en && !empty)
data_out <= mem[rd_ptr];
else
data_out <= data_out;
end
end
// Write into FIFO
always @(posedge clk)
begin
if (wr_en && !full)
mem[wr_ptr] <= data_in;
else
mem[wr_ptr] <= mem[wr_ptr];
end
// Update address pointers
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
wr_ptr <= 0;
rd_ptr <= 0;
end
else
begin
if (wr_en && !full)
wr_ptr <= wr_ptr + 1;
else
wr_ptr <= wr_ptr;
if (rd_en && !empty)
rd_ptr <= rd_ptr + 1;
else
rd_ptr <= rd_ptr;
end
end
endmodule