ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Verilog Asynchronous FIFO with Write/Read Pointers

Verilog

Goal -- WPM

Ready
Exercise Algorithm Area
1module async_fifo (
2// Write Interface (Domain 1)
3input wire clk_wr,
4input wire reset_wr,
5input wire wr_en,
6input wire [7:0] data_in,
7output wire full,
8
9// Read Interface (Domain 2)
10input wire clk_rd,
11input wire reset_rd,
12input wire rd_en,
13output wire [7:0] data_out,
14output wire empty
15);
16
17// FIFO Parameters
18localparam DEPTH = 8; // Number of data words in FIFO
19localparam ADDR_WIDTH = $clog2(DEPTH);
20
21// Memory for FIFO data
22reg [7:0] fifo_mem [0:DEPTH-1];
23
24// Write Pointer Logic (Domain 1)
25reg [ADDR_WIDTH:0] wr_ptr_local;
26wire [ADDR_WIDTH:0] wr_ptr_sync;
27
28always @(posedge clk_wr or posedge reset_wr) begin
29if (reset_wr) begin
30wr_ptr_local <= {ADDR_WIDTH+1{1'b0}};
31end else if (wr_en && !full) begin
32wr_ptr_local <= wr_ptr_local + 1;
33end
34end
35
36// Read Pointer Logic (Domain 2)
37reg [ADDR_WIDTH:0] rd_ptr_local;
38wire [ADDR_WIDTH:0] rd_ptr_sync;
39
40always @(posedge clk_rd or posedge reset_rd) begin
41if (reset_rd) begin
42rd_ptr_local <= {ADDR_WIDTH+1{1'b0}};
43end else if (rd_en && !empty) begin
44rd_ptr_local <= rd_ptr_local + 1;
45end
46end
47
48// Write Data Logic (Domain 1)
49always @(posedge clk_wr) begin
50if (wr_en && !full) begin
51fifo_mem[wr_ptr_local[ADDR_WIDTH-1:0]] <= data_in;
52end
53end
54
55// Read Data Logic (Domain 2)
56assign data_out = fifo_mem[rd_ptr_local[ADDR_WIDTH-1:0]];
57
58// Pointer Synchronization (Gray Code or 2-Flop Synchronizer)
59// Using 2-flop synchronizer for simplicity here.
60// For full robustness, Gray code is preferred for pointer comparison.
61
62// Sync wr_ptr_local to clk_rd domain
63reg [ADDR_WIDTH:0] wr_ptr_sync1;
64reg [ADDR_WIDTH:0] wr_ptr_sync2;
65
66always @(posedge clk_rd or posedge reset_rd) begin
67if (reset_rd) begin
68wr_ptr_sync1 <= {ADDR_WIDTH+1{1'b0}};
69wr_ptr_sync2 <= {ADDR_WIDTH+1{1'b0}};
70end else begin
71wr_ptr_sync1 <= wr_ptr_local;
72wr_ptr_sync2 <= wr_ptr_sync1;
73end
74end
75assign wr_ptr_sync = wr_ptr_sync2;
76
77// Sync rd_ptr_local to clk_wr domain
78reg [ADDR_WIDTH:0] rd_ptr_sync1;
79reg [ADDR_WIDTH:0] rd_ptr_sync2;
80
81always @(posedge clk_wr or posedge reset_wr) begin
82if (reset_wr) begin
83rd_ptr_sync1 <= {ADDR_WIDTH+1{1'b0}};
84rd_ptr_sync2 <= {ADDR_WIDTH+1{1'b0}};
85end else begin
86rd_ptr_sync1 <= rd_ptr_local;
87rd_ptr_sync2 <= rd_ptr_sync1;
88end
89end
90assign rd_ptr_sync = rd_ptr_sync2;
91
92// Empty and Full Detection Logic
93// Using the synchronized pointers for comparison.
94// The comparison logic needs to account for pointer wrap-around.
95// A common method is to compare (wr_ptr_sync - rd_ptr_sync) with DEPTH.
96// For simplicity, we use a common approach that requires one extra bit in pointers.
97
98// Full condition: wr_ptr is one ahead of rd_ptr (considering wrap-around)
99// This implies wr_ptr_sync[ADDR_WIDTH:0] == rd_ptr_sync[ADDR_WIDTH:0] + 1 (modulo 2^(ADDR_WIDTH+1))
100assign full = (wr_ptr_sync == rd_ptr_sync + 1'b1);
101
102// Empty condition: wr_ptr and rd_ptr are equal
103assign empty = (wr_ptr_sync == rd_ptr_sync);
104
105// Edge case: Writing to a full FIFO is prevented by the 'full' signal.
106// Edge case: Reading from an empty FIFO is prevented by the 'empty' signal.
107
108endmodule
Algorithm description viewbox

Verilog Asynchronous FIFO with Write/Read Pointers

Algorithm description:

This Verilog module implements an asynchronous FIFO buffer, designed to transfer data between two different clock domains. It uses independent write and read pointers and employs a two-flop synchronizer to ensure status flags (empty/full) are correctly interpreted across domains. This is a critical component in systems with diverse clock rates, preventing data loss or corruption.

Algorithm explanation:

The asynchronous FIFO uses a memory array (`fifo_mem`) to store data. It maintains separate write (`wr_ptr_local`) and read (`rd_ptr_local`) pointers, each operating under its respective clock domain (`clk_wr`, `clk_rd`). To enable correct empty/full detection, the pointers are synchronized to the opposite clock domain using two-flop synchronizers (`wr_ptr_sync`, `rd_ptr_sync`). The `full` and `empty` conditions are derived by comparing these synchronized pointers. The pointer arithmetic uses one extra bit to distinguish between full and empty states when pointers wrap around. Writing is enabled only if `!full`, and reading is enabled only if `!empty`. The space complexity is O(N*W) where N is the FIFO depth and W is the data width, plus O(1) for pointers and synchronizers. The time complexity for data to pass through the FIFO is O(1) for write and O(1) for read operations, but synchronization adds latency.

Pseudocode:

Define FIFO depth and address width.
Declare memory array for FIFO data.

Write Pointer Logic (Domain 1):
  Declare local write pointer (wr_ptr_local) with extra bit.
  Declare synchronized write pointer (wr_ptr_sync).
  On posedge clk_wr or posedge reset_wr:
    If reset_wr, clear wr_ptr_local.
    Else if wr_en and not full, increment wr_ptr_local.

Read Pointer Logic (Domain 2):
  Declare local read pointer (rd_ptr_local) with extra bit.
  Declare synchronized read pointer (rd_ptr_sync).
  On posedge clk_rd or posedge reset_rd:
    If reset_rd, clear rd_ptr_local.
    Else if rd_en and not empty, increment rd_ptr_local.

Write Data Logic (Domain 1):
  On posedge clk_wr:
    If wr_en and not full, write data_in to fifo_mem at wr_ptr_local.

Read Data Logic (Domain 2):
  Assign data_out from fifo_mem at rd_ptr_local.

Pointer Synchronization:
  Synchronize wr_ptr_local to clk_rd domain using a 2-flop synchronizer to get wr_ptr_sync.
  Synchronize rd_ptr_local to clk_wr domain using a 2-flop synchronizer to get rd_ptr_sync.

Empty and Full Detection:
  Assign full = (wr_ptr_sync == rd_ptr_sync + 1).
  Assign empty = (wr_ptr_sync == rd_ptr_sync).

Handle edge cases: Prevent write to full, prevent read from empty.