| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | module async_fifo #(
|
| | parameter DATA_WIDTH = 8,
|
| | parameter ADDR_BITS = 4
|
| | )(
|
| | input wire wr_clk,
|
| | input wire wr_rst_n,
|
| | input wire [DATA_WIDTH-1:0] wr_data,
|
| | input wire wr_en,
|
| | output wire wr_full,
|
| |
|
| | input wire rd_clk,
|
| | input wire rd_rst_n,
|
| | input wire rd_en,
|
| | output wire [DATA_WIDTH-1:0] rd_data,
|
| | output wire rd_empty
|
| | );
|
| |
|
| | localparam DEPTH = 1 << ADDR_BITS;
|
| |
|
| | reg [DATA_WIDTH-1:0] mem [0:DEPTH-1];
|
| |
|
| | reg [ADDR_BITS:0] wr_bin, wr_gray;
|
| | wire [ADDR_BITS:0] wr_bin_next = wr_bin + 1;
|
| | wire [ADDR_BITS:0] wr_gray_next = wr_bin_next ^ (wr_bin_next >> 1);
|
| |
|
| | reg [ADDR_BITS:0] rd_bin, rd_gray;
|
| | wire [ADDR_BITS:0] rd_bin_next = rd_bin + 1;
|
| | wire [ADDR_BITS:0] rd_gray_next = rd_bin_next ^ (rd_bin_next >> 1);
|
| |
|
| | reg [ADDR_BITS:0] wr_gray_rd_s1, wr_gray_rd_s2;
|
| | reg [ADDR_BITS:0] rd_gray_wr_s1, rd_gray_wr_s2;
|
| |
|
| | always @(posedge wr_clk or negedge wr_rst_n)
|
| | if (!wr_rst_n) begin
|
| | wr_bin <= 0;
|
| | wr_gray <= 0;
|
| | end else if (wr_en && !wr_full) begin
|
| | mem[wr_bin[ADDR_BITS-1:0]] <= wr_data;
|
| | wr_bin <= wr_bin_next;
|
| | wr_gray <= wr_gray_next;
|
| | end
|
| |
|
| | always @(posedge rd_clk or negedge rd_rst_n)
|
| | if (!rd_rst_n) begin
|
| | rd_bin <= 0;
|
| | rd_gray <= 0;
|
| | end else if (rd_en && !rd_empty) begin
|
| | rd_bin <= rd_bin_next;
|
| | rd_gray <= rd_gray_next;
|
| | end
|
| |
|
| | always @(posedge rd_clk or negedge rd_rst_n)
|
| | if (!rd_rst_n) begin
|
| | wr_gray_rd_s1 <= 0;
|
| | wr_gray_rd_s2 <= 0;
|
| | end else begin
|
| | wr_gray_rd_s1 <= wr_gray;
|
| | wr_gray_rd_s2 <= wr_gray_rd_s1;
|
| | end
|
| |
|
| | always @(posedge wr_clk or negedge wr_rst_n)
|
| | if (!wr_rst_n) begin
|
| | rd_gray_wr_s1 <= 0;
|
| | rd_gray_wr_s2 <= 0;
|
| | end else begin
|
| | rd_gray_wr_s1 <= rd_gray;
|
| | rd_gray_wr_s2 <= rd_gray_wr_s1;
|
| | end
|
| |
|
| | assign wr_full = (wr_gray == {~rd_gray_wr_s2[ADDR_BITS:ADDR_BITS-1],
|
| | rd_gray_wr_s2[ADDR_BITS-2:0]});
|
| |
|
| | assign rd_empty = (rd_gray == wr_gray_rd_s2);
|
| |
|
| | assign rd_data = mem[rd_bin[ADDR_BITS-1:0]];
|
| |
|
| | endmodule
|
| |
|