Synchronous FIFO

Posted by Liang Chen on July 14, 2021

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