异步FIFO实现

Posted 绿杨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步FIFO实现相关的知识,希望对你有一定的参考价值。

  1 //-------------------------------------------
  2 // async FIFO
  3 //-----------------------------------------------
  4 
  5 `timescale  1ns/100ps
  6 
  7 module async_fifo (
  8             wr_clk,
  9             wr_reset_n,
 10             wr_en,
 11             wr_data,
 12             full,
 13             afull,
 14             rd_clk,
 15             rd_reset_n,
 16             rd_en,
 17             rd_data,
 18             empty,
 19             aempty
 20     );
 21 
 22 parameter W = 5d16;
 23 parameter DP = 10d64;
 24 parameter WR_FAST = 1b1;
 25 parameter RD_FAST = 1b1;
 26 parameter FULL_DP = DP;
 27 parameter EMPTY_DP = 1b0;
 28 
 29 parameter AW = (DP == 2)   ? 1 : 
 30               (DP == 4)   ? 2 :
 31               (DP == 8)   ? 3 :
 32               (DP == 16)  ? 4 :
 33               (DP == 32)  ? 5 :
 34               (DP == 64)  ? 6 :
 35               (DP == 128) ? 7 :
 36               (DP == 256) ? 8 :
 37               (DP == 512) ? 9 :
 38               (DP == 1024) ? 10 :
 39               (DP == 2048) ? 11 : 0;
 40 
 41 output [W-1 : 0]  rd_data;
 42 input [W-1 : 0]   wr_data;
 43 input             wr_clk, wr_reset_n, wr_en, rd_clk, rd_reset_n, rd_en;
 44 output            full, empty;
 45 output            afull, aempty;       // about full and about to empty
 46 
 47 
 48 // synopsys translate_off
 49 
 50 initial begin
 51   if (AW == 0) begin
 52      $display ("%m : ERROR!!! Fifo depth %d not in range 2 to 256", DP);
 53   end // if (AW == 0)
 54 end // initial begin
 55 
 56 // synopsys translate_on
 57 
 58 reg [W-1 : 0]    mem[DP-1 : 0];
 59 
 60 /*********************** write side ************************/
 61 reg [AW:0] sync_rd_ptr_0, sync_rd_ptr_1; 
 62 wire [AW:0] sync_rd_ptr;
 63 reg [AW:0] wr_ptr, grey_wr_ptr;
 64 reg [AW:0] grey_rd_ptr;
 65 reg full_q;
 66 wire full_c;
 67 wire afull_c;
 68 wire [AW:0] wr_ptr_inc = wr_ptr + 1b1;
 69 wire [AW:0] wr_cnt = get_cnt(wr_ptr, sync_rd_ptr);
 70 
 71 assign full_c  = (wr_cnt == FULL_DP) ? 1b1 : 1b0;
 72 assign afull_c = (wr_cnt >= FULL_DP/2 - 1) ? 1b1 : 1b0;
 73 
 74 
 75 always @(posedge wr_clk or negedge wr_reset_n) begin
 76 if (!wr_reset_n) begin
 77     wr_ptr <= 0;
 78     grey_wr_ptr <= 0;
 79     full_q <= 0;    
 80 end
 81 else if (wr_en) begin
 82     wr_ptr <= wr_ptr_inc;
 83     grey_wr_ptr <= bin2grey(wr_ptr_inc);
 84     if (wr_cnt == (FULL_DP-1)) begin
 85         full_q <= 1b1;
 86     end
 87 end
 88 else begin
 89         if (full_q && (wr_cnt<FULL_DP)) begin
 90         full_q <= 1b0;
 91         end
 92 end
 93 end
 94 
 95 assign full  = (WR_FAST == 1) ? full_c : full_q;
 96 assign afull = afull_c;
 97 
 98 always @(posedge wr_clk) begin
 99 if (wr_en) begin
100     mem[wr_ptr[AW-1:0]] <= wr_data;
101 end
102 end
103 
104 wire [AW:0] grey_rd_ptr_dly ;
105 assign #1 grey_rd_ptr_dly = grey_rd_ptr;
106 
107 // read pointer synchronizer
108 always @(posedge wr_clk or negedge wr_reset_n) begin
109 if (!wr_reset_n) begin
110     sync_rd_ptr_0 <= 0;
111     sync_rd_ptr_1 <= 0;
112 end
113 else begin
114     sync_rd_ptr_0 <= grey_rd_ptr_dly;        
115     sync_rd_ptr_1 <= sync_rd_ptr_0;
116 end
117 end
118 
119 assign sync_rd_ptr = grey2bin(sync_rd_ptr_1);
120 
121 /************************ read side *****************************/
122 reg [AW:0] sync_wr_ptr_0, sync_wr_ptr_1; 
123 wire [AW:0] sync_wr_ptr;
124 reg [AW:0] rd_ptr;
125 reg empty_q;
126 wire empty_c;
127 wire aempty_c;
128 wire [AW:0] rd_ptr_inc = rd_ptr + 1b1;
129 wire [AW:0] rd_cnt = get_cnt(sync_wr_ptr, rd_ptr);
130 
131 assign empty_c  = (rd_cnt == 0) ? 1b1 : 1b0;
132 assign aempty_c = (rd_cnt < FULL_DP/2 - 3) ? 1b1 : 1b0; //Modify
133 
134 always @(posedge rd_clk or negedge rd_reset_n) begin
135   if (!rd_reset_n) begin
136      rd_ptr <= 0;
137  grey_rd_ptr <= 0;
138  empty_q <= 1b1;
139   end
140   else begin
141      if (rd_en) begin
142         rd_ptr <= rd_ptr_inc;
143         grey_rd_ptr <= bin2grey(rd_ptr_inc);
144         if (rd_cnt==(EMPTY_DP+1)) begin
145            empty_q <= 1b1;
146         end
147      end
148      else begin
149         if (empty_q && (rd_cnt!=EMPTY_DP)) begin
150       empty_q <= 1b0;
151     end
152      end
153    end
154 end
155 
156 assign empty  = (RD_FAST == 1) ? empty_c : empty_q;
157 assign aempty = aempty_c;
158 
159 reg [W-1 : 0]  rd_data_q;
160 
161 wire [W-1 : 0] rd_data_c = mem[rd_ptr[AW-1:0]];
162 always @(posedge rd_clk) begin
163     rd_data_q <= rd_data_c;
164 end
165 assign rd_data  = (RD_FAST == 1) ? rd_data_c : rd_data_q;
166 
167 wire [AW:0] grey_wr_ptr_dly ;
168 assign #1 grey_wr_ptr_dly =  grey_wr_ptr;
169 
170 // write pointer synchronizer
171 always @(posedge rd_clk or negedge rd_reset_n) begin
172 if (!rd_reset_n) begin
173    sync_wr_ptr_0 <= 0;
174    sync_wr_ptr_1 <= 0;
175 end
176 else begin
177    sync_wr_ptr_0 <= grey_wr_ptr_dly;        
178    sync_wr_ptr_1 <= sync_wr_ptr_0;
179 end
180 end
181 assign sync_wr_ptr = grey2bin(sync_wr_ptr_1);
182 
183     
184 /************************ functions ******************************/
185 function [AW:0] bin2grey;
186 input [AW:0] bin;
187 reg [8:0] bin_8;
188 reg [8:0] grey_8;
189 begin
190     bin_8 = bin;
191     grey_8[1:0] = do_grey(bin_8[2:0]);
192     grey_8[3:2] = do_grey(bin_8[4:2]);
193     grey_8[5:4] = do_grey(bin_8[6:4]);
194     grey_8[7:6] = do_grey(bin_8[8:6]);
195     grey_8[8] = bin_8[8];
196     bin2grey = grey_8;
197 end
198 endfunction
199 
200 function [AW:0] grey2bin;
201 input [AW:0] grey;
202 reg [8:0] grey_8;
203 reg [8:0] bin_8;
204 begin
205     grey_8 = grey;
206     bin_8[8] = grey_8[8];
207     bin_8[7:6] = do_bin({bin_8[8], grey_8[7:6]});
208     bin_8[5:4] = do_bin({bin_8[6], grey_8[5:4]});
209     bin_8[3:2] = do_bin({bin_8[4], grey_8[3:2]});
210     bin_8[1:0] = do_bin({bin_8[2], grey_8[1:0]});
211     grey2bin = bin_8;
212 end
213 endfunction
214 
215 
216 function [1:0] do_grey;
217 input [2:0] bin;
218 begin
219     if (bin[2]) begin  // do reverse grey
220         case (bin[1:0]) 
221             2b00: do_grey = 2b10;
222             2b01: do_grey = 2b11;
223             2b10: do_grey = 2b01;
224             2b11: do_grey = 2b00;
225         endcase
226     end
227     else begin
228         case (bin[1:0]) 
229             2b00: do_grey = 2b00;
230             2b01: do_grey = 2b01;
231             2b10: do_grey = 2b11;
232             2b11: do_grey = 2b10;
233         endcase
234     end
235 end
236 endfunction
237 
238 function [1:0] do_bin;
239 input [2:0] grey;
240 begin
241     if (grey[2]) begin    // actually bin[2]
242         case (grey[1:0])
243             2b10: do_bin = 2b00;
244             2b11: do_bin = 2b01;
245             2b01: do_bin = 2b10;
246             2b00: do_bin = 2b11;
247         endcase
248     end
249     else begin
250         case (grey[1:0])
251             2b00: do_bin = 2b00;
252             2b01: do_bin = 2b01;
253             2b11: do_bin = 2b10;
254             2b10: do_bin = 2b11;
255         endcase
256     end
257 end
258 endfunction
259             
260 function [AW:0] get_cnt;
261 input [AW:0] wr_ptr, rd_ptr;
262 begin
263     if (wr_ptr >= rd_ptr) begin
264         get_cnt = (wr_ptr - rd_ptr);    
265     end
266     else begin
267         get_cnt = DP*2 - (rd_ptr - wr_ptr);
268     end
269 end
270 endfunction
271 
272 // synopsys translate_off
273 always @(posedge wr_clk) begin
274    if (wr_en && full) begin
275       $display($time, " %m Error! afifo overflow!");
276       // $stop;
277    end
278 end
279 
280 always @(posedge rd_clk) begin
281    if (rd_en && empty) begin
282       $display($time, " %m error! afifo underflow!");
283       // $stop;
284    end
285 end
286 // synopsys translate_on
287 
288 endmodule

 

以上是关于异步FIFO实现的主要内容,如果未能解决你的问题,请参考以下文章

异步fifo要求用verilog编写

FPGA学习之 异步FIFO

FPGA学习之 异步FIFO

FPGA学习之 异步FIFO

同步FIFO与异步FIFO的Verilog实现

如何更完整地实现一个异步FIFO-功能实现,仿真及时序约束