00001
00002
00003
00004
00005
00006 `default_nettype none
00007 `timescale 1ns / 1ps
00008
00009 (* KEEP_HIERARCHY = "TRUE" *)module async_fifo_fall (
00010 din,
00011 rd_clk,
00012 rd_en,
00013 rst,
00014 wr_clk,
00015 wr_en,
00016 almost_empty,
00017 almost_full,
00018 dout,
00019 empty,
00020 full);
00021
00022 input wire [15 : 0] din;
00023 input wire rd_clk;
00024 input wire rd_en;
00025 input wire rst;
00026 input wire wr_clk;
00027 input wire wr_en;
00028 output wire almost_empty;
00029 output wire almost_full;
00030 output wire [15 : 0] dout;
00031 output wire empty;
00032 output wire full;
00033
00034 reg [3:0] wp, rp;
00035 wire [3:0] inc_wp, inc_rp;
00036 reg [3:0] wgray, rgray;
00037 reg [3:0] rgrayd1, rgrayd2;
00038 reg [3:0] wgrayd1, wgrayd2;
00039 reg [3:0] rdbinary, wrbinary;
00040 wire wr_clk_inv;
00041
00042 assign wr_clk_inv = ~wr_clk;
00043 generate
00044 genvar i;
00045 for (i=15; i>=0; i=i-1) begin : DPRAM_GEN
00046 RAM16X1D #(
00047 .INIT(16'h000)
00048 ) RAM16X1D_inst (
00049 .WCLK(wr_clk_inv),
00050 .WE(wr_en),
00051 .A0(wp[0]),
00052 .A1(wp[1]),
00053 .A2(wp[2]),
00054 .A3(wp[3]),
00055 .D(din[i]),
00056 .SPO(),
00057 .DPRA0(rp[0]),
00058 .DPRA1(rp[1]),
00059 .DPRA2(rp[2]),
00060 .DPRA3(rp[3]),
00061 .DPO(dout[i])
00062 );
00063 end
00064 endgenerate
00065
00066 // Write Clock Domain
00067 assign inc_wp = wp + 1;
00068 always @(posedge wr_clk_inv, posedge rst) begin : WRITE_COUNTERS
00069 integer j;
00070
00071 if (rst) begin
00072 wp <= 4'h0;
00073 wgray <= 4'h0;
00074 end else begin
00075 if (wr_en) begin
00076 wp <= wp + 4'h1;
00077 wgray <= {inc_wp[3], inc_wp[2:0] ^ inc_wp[3:1]};
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 end
00088 end
00089 end
00090
00091
00092 always @(posedge wr_clk_inv, posedge rst) begin
00093 if (rst) begin
00094 rgrayd1 <= 4'h0;
00095 rgrayd2 <= 4'h0;
00096 end else begin
00097 rgrayd1 <= rgray;
00098 rgrayd2 <= rgrayd1;
00099 end
00100 end
00101
00102
00103 always @* begin : READ_GRAY2BINARY
00104 integer j;
00105
00106 for(j=3; j>=0; j=j-1) begin
00107 if (j==3)
00108 rdbinary[j] <= rgrayd2[j];
00109 else
00110 rdbinary[j] <= rgrayd2[j] ^ rdbinary[j+1];
00111 end
00112 end
00113
00114
00115 assign full = (wp == rdbinary-4'h1) ? 1'b1 : 1'b0;
00116 assign almost_full = (wp==rdbinary-4'h2) ? 1'b1 : 1'b0;
00117
00118
00119
00120 assign inc_rp = rp + 1;
00121 always @(posedge rd_clk, posedge rst) begin : READ_COUNTERS
00122 integer j;
00123
00124 if (rst) begin
00125 rp <= 4'h0;
00126 rgray <= 4'h0;
00127 end else begin
00128 if (rd_en) begin
00129 rp <= rp + 4'h1;
00130 rgray <= {inc_rp[3], inc_rp[2:0] ^ inc_rp[3:1]};
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 end
00141 end
00142 end
00143
00144
00145 always @(posedge rd_clk, posedge rst) begin
00146 if (rst) begin
00147 wgrayd1 <= 4'h0;
00148 wgrayd2 <= 4'h0;
00149 end else begin
00150 wgrayd1 <= wgray;
00151 wgrayd2 <= wgrayd1;
00152 end
00153 end
00154
00155
00156 always @* begin : WRITE_GRAY2BINARY
00157 integer j;
00158
00159 for(j=3; j>=0; j=j-1) begin
00160 if (j==3)
00161 wrbinary[j] <= wgrayd2[j];
00162 else
00163 wrbinary[j] <= wgrayd2[j] ^ wrbinary[j+1];
00164 end
00165 end
00166
00167
00168 assign empty = (wrbinary == rp) ? 1'b1 : 1'b0;
00169 assign almost_empty = (wrbinary-4'h1==rp) ? 1'b1 : 1'b0;
00170 endmodule
00171
00172