qusetion on asynchronous FIFO

Status
Not open for further replies.

hover

Junior Member level 2
Joined
Jun 12, 2004
Messages
22
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,283
Location
China
Activity points
178
Hi, everyone

Recently I have written code for asynchronous FIFO.
Below is my code:


Code:
module asyn_FIFO(Data_out,FIFO_full,FIFO_empty,Data_in,write_clk,read_clk,write_to_FIFO,read_from_FIFO,reset);

parameter                 FIFO_width=8;
parameter                 FIFO_height=8;
parameter                 FIFO_ptr_width=3;

output[FIFO_width-1:0]    Data_out;
output                    FIFO_full;
output                    FIFO_empty;

input [FIFO_width-1:0]    Data_in;
input                     write_clk;
input                     read_clk;
input                     write_to_FIFO;
input                     read_from_FIFO;
input                     reset;

reg[FIFO_ptr_width-1:0]   write_addr,read_addr;
reg[FIFO_width-1:0]       Data_out;
reg[FIFO_width-1:0]       FIFO[FIFO_height-1:0];

wire                      read_synch;
wire                      write_synch;
wire[FIFO_width-1:0]      Data_middle;

integer                   i;

assign FIFO_full=((write_addr==read_addr)&&(write_to_FIFO==1));
assign FIFO_empty=((write_addr==read_addr)&&(read_from_FIFO==1));

always@(posedge write_clk or posedge reset)
  if(reset) begin
    write_addr<=3'b000;
	for(i=0;i<=FIFO_height-1;i=i+1)
	   FIFO[i]<=8'b0000_0000;
  end
  else if((write_synch)&&(!FIFO_full)) begin
        FIFO[write_addr]<=Data_middle;
	    write_addr<=write_addr+1;
  end

always@(posedge read_clk or posedge reset)
  if(reset) begin
    read_addr<=3'b000;
	Data_out<=8'b0000_0000;
  end
  else begin
    if((read_synch)&&(!FIFO_empty)) begin
	  Data_out<=FIFO[read_addr];
	  read_addr<=read_addr+1;
    end
  end

synchronizer_write s1(Data_middle,write_synch,write_clk,write_to_FIFO,reset,Data_in);
synchronizer_read  s2(read_synch,read_from_FIFO,read_clk,reset);

endmodule

   
module synchronizer_write(Data_out,write_synch,clk,Data_valid,reset,Data_in);

parameter              Data_width=8;

output[Data_width-1:0] Data_out;
output                 write_synch;

input                  clk;
input                  reset;
input                  Data_valid;
input[Data_width-1:0]  Data_in;

reg                    Data_valid_synch;
reg                    write_synch;
reg[Data_width-1:0]    Data_out;
                    
always@(posedge clk or posedge reset )
  if(reset) begin
	Data_valid_synch<=0;
	write_synch<=0;
  end
  else begin
    Data_valid_synch<=Data_valid;
	write_synch<=Data_valid_synch;
  end

always@(posedge clk or posedge reset)
  if(reset) 
    Data_out<=8'b0000_0000;
  else begin
    if(write_synch)
	  Data_out<=Data_in;
  end


endmodule

module synchronizer_read(read_synch,read_from_FIFO,clk,reset);
  
  output read_synch;
  input  read_from_FIFO;
  input  clk;
  input  reset;

  reg    meta_synch,read_synch;

  always@(posedge clk or posedge reset)
    if(reset) begin
	  meta_synch<=0;
      read_synch<=0;
	end
    else begin
	  meta_synch<=read_from_FIFO;
	  read_synch<=meta_synch;
	end

endmodule

My question is that can I use count to indicate the empty and full statuses of FIFO instead of my above approach. That is to add"count<=count+1" under code "write_addr<=write_addr+1" and "count<=count-1" under code"read_addr<=read_addr-1". But I'm afraid that count must across different domains. It will cause problem.
 

I am afraid that you cann't add"count<=count+1" under code "write_addr<=write_addr+1" and "count<=count-1" under code"read_addr<=read_addr-1". If you do so, race condition will arise and result in error.
The common way to implement a asynchorous FIFO is to use Gray code for the write address and read address. Then you can compare the two addresses to know whether the FIFO is full or empty.
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…