Draft preview. Lessons are being written and reviewed.

Digital Design / Module 7: Memories and FIFOs

41. Synchronous FIFO

Build the most common buffer.

Lecture coming soon

See it move

The idea

A FIFO is a queue: data comes out in the order it went in. It lets the producer and consumer run at different rates for a while. A synchronous FIFO uses one clock for both sides.

Pointers

A circular buffer needs two pointers. The write pointer marks the next slot to fill, and the read pointer marks the next slot to read. Both wrap around at the end.

Full or empty?

If the pointers are equal, the FIFO is either full or empty, and you can't tell which from the indices alone. The usual trick is one extra pointer bit:

  • All bits equal: empty.
  • Index bits equal, top bit different: full. The writer has lapped the reader.
module sync_fifo #(parameter W = 8, parameter DEPTH = 8) (
  input              clk, rst, wr, rd,
  input      [W-1:0] din,
  output     [W-1:0] dout,
  output             full, empty
);
  localparam AW = $clog2(DEPTH);
  reg [W-1:0] mem [0:DEPTH-1];
  reg [AW:0]  wp, rp;

  assign empty = (wp == rp);
  assign full  = (wp[AW-1:0] == rp[AW-1:0]) && (wp[AW] != rp[AW]);
  assign dout  = mem[rp[AW-1:0]];

  always_ff @(posedge clk)
    if (rst) begin
      wp <= '0;
      rp <= '0;
    end else begin
      if (wr && !full) begin
        mem[wp[AW-1:0]] <= din;
        wp <= wp + 1'b1;
      end
      if (rd && !empty) rp <= rp + 1'b1;
    end
endmodule

Edge cases to define and test

  • Writing when full must not overwrite data.
  • Reading when empty must not advance the pointer.
  • A simultaneous read and write at full or empty should be defined by your specification.
  • Decide whether the output is combinational, as above, or registered, which adds a cycle.

Common mistake

Using a depth that isn't a power of two with this pointer scheme. The pointers wrap naturally only at powers of two. Other depths need explicit wrap logic. Another common bug is checking full on the wrong clock cycle in the writer. Press Write until the animation refuses and look at the pointer bits.

One more to try

Key ideas

  • Read and write pointers wrap around.
  • An extra pointer bit separates full from empty.
  • Writing when full and reading when empty must be defined.

Lab: FIFO depth lab

Your exercise

Build a depth-8 FIFO and test it to overflow.

Find the bug

This code has one deliberate bug. Read the symptom, then click the line you think is wrong.

What goes wrong: The FIFO reports full straight after reset, so nothing can ever be written.

Interview questions

coreHow does the extra pointer bit help?

basicA synchronous FIFO is 32 entries deep and uses the extra-bit pointer scheme. How wide is each pointer?

basicInstead of an extra pointer bit, you could keep a count register. What are the trade-offs?

coreRight after reset, this FIFO refuses every write. Why?

assign empty = (wp == rp);
assign full  = (wp[AW-1:0] == rp[AW-1:0]);

coreIn a depth-8 FIFO with 4-bit pointers, wp = 0010 and rp = 1110. How many words are inside, and what are the flags?

coreWith the lesson's FIFO, the FIFO is full and the user asserts read and write in the same cycle. What happens? What if it is empty instead?

coreSomeone sets DEPTH = 6 but keeps 3 index bits and the same pointer logic. What happens?

advancedWhat changes if you register the FIFO's output instead of reading memory combinationally?

advancedA writer sees the FIFO's flag through two pipeline flops, so it may keep writing for two cycles after the flag rises. For a depth-16 FIFO, at what occupancy should almost_full rise?

Practise these 9 questions with animations