异步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 = 5‘d16; 23 parameter DP = 10‘d64; 24 parameter WR_FAST = 1‘b1; 25 parameter RD_FAST = 1‘b1; 26 parameter FULL_DP = DP; 27 parameter EMPTY_DP = 1‘b0; 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 + 1‘b1; 69 wire [AW:0] wr_cnt = get_cnt(wr_ptr, sync_rd_ptr); 70 71 assign full_c = (wr_cnt == FULL_DP) ? 1‘b1 : 1‘b0; 72 assign afull_c = (wr_cnt >= FULL_DP/2 - 1) ? 1‘b1 : 1‘b0; 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 <= 1‘b1; 86 end 87 end 88 else begin 89 if (full_q && (wr_cnt<FULL_DP)) begin 90 full_q <= 1‘b0; 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 + 1‘b1; 129 wire [AW:0] rd_cnt = get_cnt(sync_wr_ptr, rd_ptr); 130 131 assign empty_c = (rd_cnt == 0) ? 1‘b1 : 1‘b0; 132 assign aempty_c = (rd_cnt < FULL_DP/2 - 3) ? 1‘b1 : 1‘b0; //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 <= 1‘b1; 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 <= 1‘b1; 146 end 147 end 148 else begin 149 if (empty_q && (rd_cnt!=EMPTY_DP)) begin 150 empty_q <= 1‘b0; 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 2‘b00: do_grey = 2‘b10; 222 2‘b01: do_grey = 2‘b11; 223 2‘b10: do_grey = 2‘b01; 224 2‘b11: do_grey = 2‘b00; 225 endcase 226 end 227 else begin 228 case (bin[1:0]) 229 2‘b00: do_grey = 2‘b00; 230 2‘b01: do_grey = 2‘b01; 231 2‘b10: do_grey = 2‘b11; 232 2‘b11: do_grey = 2‘b10; 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 2‘b10: do_bin = 2‘b00; 244 2‘b11: do_bin = 2‘b01; 245 2‘b01: do_bin = 2‘b10; 246 2‘b00: do_bin = 2‘b11; 247 endcase 248 end 249 else begin 250 case (grey[1:0]) 251 2‘b00: do_bin = 2‘b00; 252 2‘b01: do_bin = 2‘b01; 253 2‘b11: do_bin = 2‘b10; 254 2‘b10: do_bin = 2‘b11; 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实现的主要内容,如果未能解决你的问题,请参考以下文章