OpenCores
URL https://opencores.org/ocsvn/sdr_ctrl/sdr_ctrl/trunk

Subversion Repositories sdr_ctrl

[/] [sdr_ctrl/] [trunk/] [rtl/] [lib/] [async_fifo.v] - Blame information for rev 31

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 31 dinesha
/*********************************************************************
2
 
3
  ASYNC FIFO
4
 
5
  This file is part of the sdram controller project
6
  http://www.opencores.org/cores/sdr_ctrl/
7
 
8
  Description: ASYNC FIFO
9
 
10
  To Do:
11
    nothing
12
 
13
  Author(s):  Dinesh Annayya, dinesha@opencores.org
14
 
15
 Copyright (C) 2000 Authors and OPENCORES.ORG
16
 
17
 This source file may be used and distributed without
18
 restriction provided that this copyright statement is not
19
 removed from the file and that any derivative work contains
20
 the original copyright notice and the associated disclaimer.
21
 
22
 This source file is free software; you can redistribute it
23
 and/or modify it under the terms of the GNU Lesser General
24
 Public License as published by the Free Software Foundation;
25
 either version 2.1 of the License, or (at your option) any
26
later version.
27
 
28
 This source is distributed in the hope that it will be
29
 useful, but WITHOUT ANY WARRANTY; without even the implied
30
 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
31
 PURPOSE.  See the GNU Lesser General Public License for more
32
 details.
33
 
34
 You should have received a copy of the GNU Lesser General
35
 Public License along with this source; if not, download it
36
 from http://www.opencores.org/lgpl.shtml
37
 
38
*******************************************************************/
39
 
40
//-------------------------------------------
41
// async FIFO
42
//-----------------------------------------------
43
`timescale  1ns/1ps
44
 
45
module async_fifo (wr_clk,
46
                   wr_reset_n,
47
                   wr_en,
48
                   wr_data,
49
                   full,                 // sync'ed to wr_clk
50
                   afull,                 // sync'ed to wr_clk
51
                   rd_clk,
52
                   rd_reset_n,
53
                   rd_en,
54
                   empty,                // sync'ed to rd_clk
55
                   aempty,                // sync'ed to rd_clk
56
                   rd_data);
57
 
58
   parameter W = 4'd8;
59
   parameter DP = 3'd4;
60
   parameter WR_FAST = 1'b1;
61
   parameter RD_FAST = 1'b1;
62
   parameter FULL_DP = DP;
63
   parameter EMPTY_DP = 1'b0;
64
 
65
   parameter AW = (DP == 2)   ? 1 :
66
                  (DP == 4)   ? 2 :
67
                  (DP == 8)   ? 3 :
68
                  (DP == 16)  ? 4 :
69
                  (DP == 32)  ? 5 :
70
                  (DP == 64)  ? 6 :
71
                  (DP == 128) ? 7 :
72
                  (DP == 256) ? 8 : 0;
73
 
74
   output [W-1 : 0]  rd_data;
75
   input [W-1 : 0]   wr_data;
76
   input             wr_clk, wr_reset_n, wr_en, rd_clk, rd_reset_n,
77
                     rd_en;
78
   output            full, empty;
79
   output            afull, aempty;       // about full and about to empty
80
 
81
 
82
   // synopsys translate_off
83
 
84
   initial begin
85
      if (AW == 0) begin
86
         $display ("%m : ERROR!!! Fifo depth %d not in range 2 to 256", DP);
87
      end // if (AW == 0)
88
   end // initial begin
89
 
90
   // synopsys translate_on
91
 
92
   reg [W-1 : 0]    mem[DP-1 : 0];
93
 
94
   /*********************** write side ************************/
95
   reg [AW:0] sync_rd_ptr_0, sync_rd_ptr_1;
96
   wire [AW:0] sync_rd_ptr;
97
   reg [AW:0] wr_ptr, grey_wr_ptr;
98
   reg [AW:0] grey_rd_ptr;
99
   reg full_q;
100
   wire full_c;
101
   wire afull_c;
102
   wire [AW:0] wr_ptr_inc = wr_ptr + 1'b1;
103
   wire [AW:0] wr_cnt = get_cnt(wr_ptr, sync_rd_ptr);
104
 
105
   assign full_c  = (wr_cnt == FULL_DP) ? 1'b1 : 1'b0;
106
   assign afull_c = (wr_cnt == FULL_DP-1) ? 1'b1 : 1'b0;
107
 
108
 
109
   always @(posedge wr_clk or negedge wr_reset_n) begin
110
        if (!wr_reset_n) begin
111
                wr_ptr <= 0;
112
                grey_wr_ptr <= 0;
113
                full_q <= 0;
114
        end
115
        else if (wr_en) begin
116
                wr_ptr <= wr_ptr_inc;
117
                grey_wr_ptr <= bin2grey(wr_ptr_inc);
118
                if (wr_cnt == (FULL_DP-1)) begin
119
                        full_q <= 1'b1;
120
                end
121
        end
122
        else begin
123
                if (full_q && (wr_cnt<FULL_DP)) begin
124
                        full_q <= 1'b0;
125
                end
126
        end
127
    end
128
 
129
    assign full  = (WR_FAST == 1) ? full_c : full_q;
130
    assign afull = afull_c;
131
 
132
    always @(posedge wr_clk) begin
133
        if (wr_en) begin
134
                mem[wr_ptr[AW-1:0]] <= wr_data;
135
        end
136
    end
137
 
138
    wire [AW:0] grey_rd_ptr_dly ;
139
    assign #1 grey_rd_ptr_dly = grey_rd_ptr;
140
 
141
    // read pointer synchronizer
142
    always @(posedge wr_clk or negedge wr_reset_n) begin
143
        if (!wr_reset_n) begin
144
                sync_rd_ptr_0 <= 0;
145
                sync_rd_ptr_1 <= 0;
146
        end
147
        else begin
148
                sync_rd_ptr_0 <= grey_rd_ptr_dly;
149
                sync_rd_ptr_1 <= sync_rd_ptr_0;
150
        end
151
    end
152
 
153
    assign sync_rd_ptr = grey2bin(sync_rd_ptr_1);
154
 
155
   /************************ read side *****************************/
156
   reg [AW:0] sync_wr_ptr_0, sync_wr_ptr_1;
157
   wire [AW:0] sync_wr_ptr;
158
   reg [AW:0] rd_ptr;
159
   reg empty_q;
160
   wire empty_c;
161
   wire aempty_c;
162
   wire [AW:0] rd_ptr_inc = rd_ptr + 1'b1;
163
   wire [AW:0] sync_wr_ptr_dec = sync_wr_ptr - 1'b1;
164
   wire [AW:0] rd_cnt = get_cnt(sync_wr_ptr, rd_ptr);
165
 
166
   assign empty_c  = (rd_cnt == 0) ? 1'b1 : 1'b0;
167
   assign aempty_c = (rd_cnt == 1) ? 1'b1 : 1'b0;
168
 
169
   always @(posedge rd_clk or negedge rd_reset_n) begin
170
      if (!rd_reset_n) begin
171
         rd_ptr <= 0;
172
         grey_rd_ptr <= 0;
173
         empty_q <= 1'b1;
174
      end
175
      else begin
176
         if (rd_en) begin
177
            rd_ptr <= rd_ptr_inc;
178
            grey_rd_ptr <= bin2grey(rd_ptr_inc);
179
            if (rd_cnt==(EMPTY_DP+1)) begin
180
               empty_q <= 1'b1;
181
            end
182
         end
183
         else begin
184
            if (empty_q && (rd_cnt!=EMPTY_DP)) begin
185
              empty_q <= 1'b0;
186
            end
187
         end
188
       end
189
    end
190
 
191
    assign empty  = (RD_FAST == 1) ? empty_c : empty_q;
192
    assign aempty = aempty_c;
193
 
194
    assign rd_data = mem[rd_ptr[AW-1:0]];
195
 
196
    wire [AW:0] grey_wr_ptr_dly ;
197
    assign #1 grey_wr_ptr_dly =  grey_wr_ptr;
198
 
199
    // write pointer synchronizer
200
    always @(posedge rd_clk or negedge rd_reset_n) begin
201
        if (!rd_reset_n) begin
202
           sync_wr_ptr_0 <= 0;
203
           sync_wr_ptr_1 <= 0;
204
        end
205
        else begin
206
           sync_wr_ptr_0 <= grey_wr_ptr_dly;
207
           sync_wr_ptr_1 <= sync_wr_ptr_0;
208
        end
209
    end
210
    assign sync_wr_ptr = grey2bin(sync_wr_ptr_1);
211
 
212
 
213
/************************ functions ******************************/
214
function [AW:0] bin2grey;
215
input [AW:0] bin;
216
reg [8:0] bin_8;
217
reg [8:0] grey_8;
218
begin
219
        bin_8 = bin;
220
        grey_8[1:0] = do_grey(bin_8[2:0]);
221
        grey_8[3:2] = do_grey(bin_8[4:2]);
222
        grey_8[5:4] = do_grey(bin_8[6:4]);
223
        grey_8[7:6] = do_grey(bin_8[8:6]);
224
        grey_8[8] = bin_8[8];
225
        bin2grey = grey_8;
226
end
227
endfunction
228
 
229
function [AW:0] grey2bin;
230
input [AW:0] grey;
231
reg [8:0] grey_8;
232
reg [8:0] bin_8;
233
begin
234
        grey_8 = grey;
235
        bin_8[8] = grey_8[8];
236
        bin_8[7:6] = do_bin({bin_8[8], grey_8[7:6]});
237
        bin_8[5:4] = do_bin({bin_8[6], grey_8[5:4]});
238
        bin_8[3:2] = do_bin({bin_8[4], grey_8[3:2]});
239
        bin_8[1:0] = do_bin({bin_8[2], grey_8[1:0]});
240
        grey2bin = bin_8;
241
end
242
endfunction
243
 
244
 
245
function [1:0] do_grey;
246
input [2:0] bin;
247
begin
248
        if (bin[2]) begin  // do reverse grey
249
                case (bin[1:0])
250
                        2'b00: do_grey = 2'b10;
251
                        2'b01: do_grey = 2'b11;
252
                        2'b10: do_grey = 2'b01;
253
                        2'b11: do_grey = 2'b00;
254
                endcase
255
        end
256
        else begin
257
                case (bin[1:0])
258
                        2'b00: do_grey = 2'b00;
259
                        2'b01: do_grey = 2'b01;
260
                        2'b10: do_grey = 2'b11;
261
                        2'b11: do_grey = 2'b10;
262
                endcase
263
        end
264
end
265
endfunction
266
 
267
function [1:0] do_bin;
268
input [2:0] grey;
269
begin
270
        if (grey[2]) begin      // actually bin[2]
271
                case (grey[1:0])
272
                        2'b10: do_bin = 2'b00;
273
                        2'b11: do_bin = 2'b01;
274
                        2'b01: do_bin = 2'b10;
275
                        2'b00: do_bin = 2'b11;
276
                endcase
277
        end
278
        else begin
279
                case (grey[1:0])
280
                        2'b00: do_bin = 2'b00;
281
                        2'b01: do_bin = 2'b01;
282
                        2'b11: do_bin = 2'b10;
283
                        2'b10: do_bin = 2'b11;
284
                endcase
285
        end
286
end
287
endfunction
288
 
289
function [AW:0] get_cnt;
290
input [AW:0] wr_ptr, rd_ptr;
291
begin
292
        if (wr_ptr >= rd_ptr) begin
293
                get_cnt = (wr_ptr - rd_ptr);
294
        end
295
        else begin
296
                get_cnt = DP*2 - (rd_ptr - wr_ptr);
297
        end
298
end
299
endfunction
300
 
301
// synopsys translate_off
302
always @(posedge wr_clk) begin
303
   if (wr_en && full) begin
304
      $display($time, "%m Error! afifo overflow!");
305
      $stop;
306
   end
307
end
308
 
309
always @(posedge rd_clk) begin
310
   if (rd_en && empty) begin
311
      $display($time, "%m error! afifo underflow!");
312
      $stop;
313
   end
314
end
315
// synopsys translate_on
316
 
317
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.