//------------------------------------------- // async FIFO //----------------------------------------------- `timescale 1ns/1ps module async_fifo #( parameter W = 4'd8 ) ( //timing for wr input wr_clk, input wr_reset_n, input wr_en, output full, output afull, input [W-1 : 0] wr_data, //timing for rd input rd_clk, input rd_reset_n, input rd_en, output empty, output aempty, output [W-1 : 0] rd_data ); parameter DP = 3'd4; parameter WR_FAST = 1'b1; parameter RD_FAST = 1'b1; parameter EMPTY_DP = 1'b0; parameter FULL_DP = DP; parameter AW = (DP == 2) ? 1 : (DP == 4) ? 2 : (DP == 8) ? 3 : (DP == 16) ? 4 : (DP == 32) ? 5 : (DP == 64) ? 6 : (DP == 128) ? 7 : (DP == 256) ? 8 : 0; // synopsys translate_off initial begin if (AW == 0) begin $display ("%m : ERROR!!! Fifo depth %d not in range 2 to 256", DP); end // if (AW == 0) end // initial begin // synopsys translate_on reg [W-1 : 0] mem[DP-1 : 0]; /*********************** write side ************************/ reg [AW:0] sync_rd_ptr_0, sync_rd_ptr_1; wire [AW:0] sync_rd_ptr; reg [AW:0] wr_ptr, grey_wr_ptr; reg [AW:0] grey_rd_ptr; reg full_q; wire full_c; wire afull_c; wire [AW:0] wr_ptr_inc = wr_ptr + 1'b1; wire [AW:0] wr_cnt = get_cnt(wr_ptr, sync_rd_ptr); assign full_c = (wr_cnt == FULL_DP) ? 1'b1 : 1'b0; assign afull_c = (wr_cnt == FULL_DP-1) ? 1'b1 : 1'b0; always @(posedge wr_clk or negedge wr_reset_n) begin if (!wr_reset_n) begin wr_ptr <= 0; grey_wr_ptr <= 0; full_q <= 0; end else if (wr_en) begin wr_ptr <= wr_ptr_inc; grey_wr_ptr <= bin2grey(wr_ptr_inc); if (wr_cnt == (FULL_DP-1)) begin full_q <= 1'b1; end end else begin if (full_q && (wr_cnt= rd_ptr) begin get_cnt = (wr_ptr - rd_ptr); end else begin get_cnt = DP*2 - (rd_ptr - wr_ptr); end end endfunction // synopsys translate_off always @(posedge wr_clk) begin if (wr_en && full) begin $display($time, "%m Error! afifo overflow!"); $stop; end end always @(posedge rd_clk) begin if (rd_en && empty) begin $display($time, "%m error! afifo underflow!"); $stop; end end // synopsys translate_on endmodule