86 lines
2.3 KiB
Coq
86 lines
2.3 KiB
Coq
![]() |
module async_fifo #(
|
||
|
parameter DATA_WIDTH = 8,
|
||
|
parameter FIFO_DEPTH = 16
|
||
|
)(
|
||
|
input wr_clk,
|
||
|
input wr_rst_n,
|
||
|
input wr_en,
|
||
|
input [DATA_WIDTH-1:0] wr_data,
|
||
|
output full,
|
||
|
|
||
|
input rd_clk,
|
||
|
input rd_rst_n,
|
||
|
input rd_en,
|
||
|
output [DATA_WIDTH-1:0] rd_data,
|
||
|
output empty
|
||
|
);
|
||
|
|
||
|
reg [DATA_WIDTH-1:0] mem [FIFO_DEPTH -1 : 0];
|
||
|
reg [$clog2(FIFO_DEPTH) : 0] wr_ptr, rd_ptr;
|
||
|
|
||
|
integer i;
|
||
|
always@(posedge wr_clk or negedge wr_rst_n) begin
|
||
|
if(!wr_rst_n) begin
|
||
|
wr_ptr <= 'd0;
|
||
|
for(i=0;i<FIFO_DEPTH;i=i+1) begin
|
||
|
mem[i] <= 'd0;
|
||
|
end
|
||
|
end else if(wr_en && !full) begin
|
||
|
mem[wr_ptr[$clog2(FIFO_DEPTH)-1:0]] <= wr_data;
|
||
|
wr_ptr <= wr_ptr + 1'b1;
|
||
|
end else begin
|
||
|
wr_ptr <= wr_ptr;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always@(posedge rd_clk or negedge rd_rst_n) begin
|
||
|
if(!rd_rst_n) begin
|
||
|
rd_ptr <= 'd0;
|
||
|
end else if(rd_en && !empty) begin
|
||
|
rd_ptr <= rd_ptr + 1'b1;
|
||
|
end else begin
|
||
|
rd_ptr <= rd_ptr;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
wire [$clog2(FIFO_DEPTH):0] wr_ptr_g , rd_ptr_g;
|
||
|
|
||
|
assign wr_ptr_g = wr_ptr ^(wr_ptr >>1);
|
||
|
assign rd_ptr_g = rd_ptr ^(rd_ptr >>1);
|
||
|
|
||
|
reg [$clog2(FIFO_DEPTH):0] wr_ptr_gr , wr_ptr_grr;
|
||
|
reg [$clog2(FIFO_DEPTH):0] rd_ptr_gr , rd_ptr_grr;
|
||
|
|
||
|
always@(posedge rd_clk or negedge rd_rst_n) begin
|
||
|
if(!rd_rst_n) begin
|
||
|
wr_ptr_gr <= 0;
|
||
|
wr_ptr_grr <=0;
|
||
|
end else begin
|
||
|
wr_ptr_gr <= wr_ptr_g;
|
||
|
wr_ptr_grr <= wr_ptr_gr;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always@(posedge wr_clk or negedge wr_rst_n) begin
|
||
|
if(!wr_rst_n) begin
|
||
|
rd_ptr_gr <= 0;
|
||
|
rd_ptr_grr <=0;
|
||
|
end else begin
|
||
|
rd_ptr_gr <= rd_ptr_g;
|
||
|
rd_ptr_grr <= rd_ptr_gr;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
assign rd_data = mem[rd_ptr[$clog2(FIFO_DEPTH)-1:0]];
|
||
|
|
||
|
|
||
|
assign full = ((wr_ptr_g[$clog2(FIFO_DEPTH)] !=
|
||
|
rd_ptr_grr[$clog2(FIFO_DEPTH)]) && (wr_ptr_g[$clog2(FIFO_DEPTH)-1] !=
|
||
|
rd_ptr_grr[$clog2(FIFO_DEPTH)]-1) && (wr_ptr_g[$clog2(FIFO_DEPTH)-2:0] ==
|
||
|
rd_ptr_grr[$clog2(FIFO_DEPTH)-2 : 0])) ? 1:0;
|
||
|
|
||
|
assign empty = (rd_ptr_g[$clog2(FIFO_DEPTH) : 0] ==
|
||
|
wr_ptr_grr[$clog2(FIFO_DEPTH) :0]) ? 1:0;
|
||
|
|
||
|
endmodule
|