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

Subversion Repositories ethmac10g

[/] [ethmac10g/] [trunk/] [rtl/] [verilog/] [rx_engine/] [SwitchAsyncFIFO.v] - Blame information for rev 72

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 71 fisher5090
//
2
// Module SwitchAsyncFIFO
3
//
4
// the differences between this FIFO and the general one are listed below
5
//    1. because there is no any write and read acknowledgements, the user should take advantage of the status flags to generate the write and read requests.
6
//    2. after the qWFull flag has been asserted, the word can not be written into the FIFO.
7
//    3. after the qREmpty flag has been asserted, the data can not be read out from the FIFO.
8
//    4. 2 flip-flops are used to re-synchronize the addresses of the different clock domains.
9
//    5. to decrease 1 clock, the negedge of the clock is utilized by the 1st flip-flop.
10
//    6. to provide guaranteed free space information, the qRNumberLeft has been subtracted 4.
11
//
12
// Created:
13
//          by - Xinchun Liu
14
//          at - 2006-09-27
15
//
16
// revised:
17
//          by - Xinchun Liu
18
//          at - 2007-05-15
19
//    1. to decrease the clock to output time, a output register has been added.
20
//    2. 1 cycle latency has been added to the output data and empty flag.
21
//
22
`resetall
23
`timescale 1ns/10ps
24
 
25
module SwitchAsyncFIFO
26
(
27
   inReset,
28
   iWClk,
29
   iWEn,
30
   ivDataIn,
31
   qWFull,
32
   qvWCount,
33
   iRClk,
34
   iREn,
35
   ovDataOut,
36
   qREmpty,
37
   qvRNumberLeft
38
);
39
 
40
// Default address and data width
41
parameter   pDepthWidth = 5 ;
42
parameter   pWordWidth = 16 ;
43
 
44
input   inReset ;
45
input   iWClk ;
46
input iWEn ;
47
input [pWordWidth-1:0]   ivDataIn ;
48
output   qWFull ;
49
output   [pDepthWidth:0]   qvWCount ;
50
input   iRClk ;
51
input   iREn ;
52
output   [pWordWidth-1:0]   ovDataOut ;
53
output   qREmpty ;
54
output   [pDepthWidth:0]   qvRNumberLeft ;
55
 
56
wire   inReset ;
57
wire   iWClk ;
58
wire   iWEn ;
59
wire  [pWordWidth-1:0]   ivDataIn ;
60
wire   qWFull ;
61
wire  [pDepthWidth:0]   qvWCount ;
62
wire   iRClk ;
63
wire   iREn ;
64
wire  [pWordWidth-1:0]   ovDataOut ;
65
wire   qREmpty ;
66
wire  [pDepthWidth:0]   qvRNumberLeft ;
67
 
68
wire  MemWEn;
69
wire  [pDepthWidth-1:0] vWriteAddr ;
70
wire  [pDepthWidth-1:0] vReadAddr ;
71
wire   [pWordWidth-1:0] MemDataOut ;
72
 
73
DualPortRAM_ASYN #( pDepthWidth, pWordWidth ) Fifo_Storage
74
   (
75
      // Generic synchronous two-port RAM interface
76
      .WriteClock    ( iWClk ),
77
      .MemWEn        ( MemWEn ),
78
      .MemWAddr      ( vWriteAddr ),
79
      .MemDataIn     ( ivDataIn ),
80
      .ReadClock     ( iRClk ),
81
      .MemRAddr      ( vReadAddr ),
82
      .MemDataOut    ( MemDataOut )
83
    );
84
 
85
FifoControl_ASYN #( pDepthWidth, pWordWidth ) Fifo_Controller
86
   (
87
      .inReset       ( inReset ) ,
88
      .WriteClock    ( iWClk ) ,
89
      .iWEn          ( iWEn ) ,
90
      .MemWEn        ( MemWEn ) ,
91
      .vWAddr        ( vWriteAddr ) ,
92
      .qWFull        ( qWFull ) ,
93
      .qvWCount      ( qvWCount ) ,
94
      .ReadClock     ( iRClk ) ,
95
      .iREn          ( iREn ) ,
96
      .vRAddr        ( vReadAddr ) ,
97
      .qREmpty       ( qREmpty ) ,
98
      .MemDataOut    ( MemDataOut ),
99
      .qvDataOut     ( ovDataOut ),
100
      .qvRNumberLeft ( qvRNumberLeft )
101
   ) ;
102
 
103
endmodule
104
 
105
module FifoControl_ASYN
106
(
107
   inReset ,
108
   WriteClock ,
109
   iWEn ,
110
   MemWEn ,
111
   vWAddr ,
112
   qWFull ,
113
   qvWCount ,
114
   ReadClock ,
115
   iREn ,
116
   vRAddr ,
117
   qREmpty ,
118
   MemDataOut ,
119
   qvDataOut ,
120
   qvRNumberLeft
121
);
122
 
123
// Default address and data width
124
parameter   pDepthWidth = 5 ;
125
parameter   pWordWidth = 16 ;
126
 
127
input  inReset ;
128
input  WriteClock ;
129
input  iWEn ;
130
output  MemWEn ;
131
output  [pDepthWidth-1:0] vWAddr ;
132
output  qWFull ;
133
output  [pDepthWidth:0] qvWCount ;
134
input   ReadClock ;
135
input   iREn ;
136
output  [pDepthWidth-1:0] vRAddr ;
137
output  qREmpty ;
138
input   [pWordWidth-1:0]  MemDataOut ;
139
output  [pWordWidth-1:0]  qvDataOut ;
140
output  [pDepthWidth:0]   qvRNumberLeft ;
141
 
142
wire  inReset ;
143
wire  WriteClock ;
144
wire  iWEn ;
145
wire  MemWEn ;
146
wire  [pDepthWidth-1:0] vWAddr ;
147
reg   qWFull ;
148
reg   [pDepthWidth:0]   qvWCount ;
149
wire  ReadClock ;
150
wire  iREn ;
151
wire  [pDepthWidth-1:0] vRAddr ;
152
reg   qREmpty ;
153
wire  [pWordWidth-1:0]  MemDataOut ;
154
reg   [pWordWidth-1:0]  qvDataOut ;
155
reg   [pDepthWidth:0]   qvRNumberLeft ;
156
 
157
// internal variables
158
   // write clock domain
159
reg  [pDepthWidth:0] qvWAddr ;
160
reg  [pDepthWidth:0] qvNextWAddr ;
161
reg  [pDepthWidth:0] qvPreWGrayAddr ;
162
reg  [pDepthWidth:0] qvWGrayAddr ;
163
reg  [pDepthWidth:0] qvRGrayAddr_WSync1 ;
164
reg  [pDepthWidth:0] qvRGrayAddr_WSync2 ;
165
reg  [pDepthWidth:0] qvRAddr_WSync2 ;
166
   // read clock domain
167
reg  [pDepthWidth:0] qvRAddr ;
168
reg  [pDepthWidth:0] qvNextRAddr ;
169
reg  [pDepthWidth:0] qvRGrayAddr ;
170
reg  [pDepthWidth:0] qvPreWGrayAddr_RSync1 ;
171
reg  [pDepthWidth:0] qvPreWGrayAddr_RSync2 ;
172
reg  [pDepthWidth:0] qvPreWAddr_RSync2 ;
173
reg  [pDepthWidth:0] qvWGrayAddr_RSync1 ;
174
reg  [pDepthWidth:0] qvWGrayAddr_RSync2 ;
175
reg  [pDepthWidth:0] qvPointerForNumLeft ;
176
reg  [pDepthWidth:0] qvNextPointerForNumLeft ;
177
 
178
reg   qREmpty_int ;
179
wire  MemREn ;
180
 
181
assign MemREn = !qREmpty_int && ( qREmpty || iREn ) ;
182
assign MemWEn = iWEn && ( !qWFull ) ;
183
assign vWAddr = qvWAddr[pDepthWidth-1:0] ;
184
assign vRAddr = MemREn ? qvNextRAddr[pDepthWidth-1:0] : qvRAddr[pDepthWidth-1:0] ;
185
 
186
// logic
187
integer i;
188
 
189
// write clock domain
190
   // write address
191
always @ ( negedge inReset or posedge WriteClock )
192
begin
193
   if( !inReset ) begin
194
      qvWAddr <= 1 ;
195
      qvNextWAddr <= 2 ;
196
      qvPreWGrayAddr <= 0 ;
197
      qvWGrayAddr <= 1 ;
198
   end
199
   else  if( MemWEn )   begin
200
      qvWAddr <= qvNextWAddr ;
201
      qvNextWAddr <= qvNextWAddr + 1'b1 ;
202
      qvPreWGrayAddr <= qvWGrayAddr ;
203
      qvWGrayAddr <= ( qvNextWAddr >> 1 ) ^ qvNextWAddr ;
204
//      qvPreWGrayAddr <= ( qvWAddr >> 1 ) ^ qvWAddr ;
205
   end
206
end
207
   // re-synchronize the read addresses within write clock domain
208
      // the 1st synchronizing cycle
209
always @ ( negedge inReset or posedge WriteClock )  begin
210
   if( !inReset ) begin
211
      qvRGrayAddr_WSync1 <= 1 ;
212
   end
213
   else  begin
214
      qvRGrayAddr_WSync1 <= qvRGrayAddr ;
215
   end
216
end
217
      // the 2nd synchronizing cycle
218
always @ ( negedge inReset or posedge WriteClock )  begin
219
   if( !inReset ) begin
220
      qvRGrayAddr_WSync2 <= 1 ;
221
   end
222
   else  begin
223
      qvRGrayAddr_WSync2 <= qvRGrayAddr_WSync1 ;
224
   end
225
end
226
 
227
   //   to calculate the read address in write clock domain
228
always @ ( negedge inReset or posedge WriteClock )  begin   // 1 cycle delay will be added
229
   if( !inReset ) begin
230
      qvRAddr_WSync2 <= 1 ;
231
   end
232
   else  begin
233
      for( i=0; i<=pDepthWidth; i=i+1 )
234
         qvRAddr_WSync2[i] <= ^( qvRGrayAddr_WSync2 >>i ) ;   // Gray To Binary Conversion
235
   end
236
end
237
 
238
//always @ ( qvRGrayAddr_WSync2 )   // Gray To Binary Conversion
239
//   for( i=0; i<=pDepthWidth; i=i+1 )
240
//      qvRAddr_WSync2[i] = ^( qvRGrayAddr_WSync2 >>i ) ;
241
 
242
   // calculates qvWCount 
243
always @ ( negedge inReset or posedge WriteClock )  begin
244
   if( !inReset ) begin
245
      qvWCount <= 0 ;
246
   end
247
   else  begin
248
      if( MemWEn )
249
         qvWCount <= qvNextWAddr - qvRAddr_WSync2 ;
250
      else
251
         qvWCount <= qvWAddr - qvRAddr_WSync2 ;
252
   end
253
end
254
 
255
   // generates qWFull
256
always @ ( qvWCount[pDepthWidth] )
257
   qWFull <= qvWCount[pDepthWidth] ;
258
 
259
// read clock domain
260
   // read address
261
always @ ( negedge inReset or posedge ReadClock )
262
begin
263
   if( !inReset ) begin
264
      qvRAddr <= 1 ;
265
      qvNextRAddr <= 2 ;
266
      qvRGrayAddr <= 1 ;
267
      qvPointerForNumLeft <= { 1'b1, {pDepthWidth{1'b0}} } ;
268
      qvNextPointerForNumLeft <= { 1'b1, {(pDepthWidth-1){1'b0}}, 1'b1 } ;
269
   end
270
   else  if( MemREn )   begin
271
      qvRAddr <= qvNextRAddr ;
272
      qvNextRAddr <= qvNextRAddr + 1'b1 ;
273
      qvRGrayAddr <= ( qvNextRAddr >> 1 ) ^ qvNextRAddr ;
274
      qvNextPointerForNumLeft <= qvNextPointerForNumLeft + 1'b1 ;
275
      qvPointerForNumLeft <= qvNextPointerForNumLeft ;
276
//      qvPointerForNumLeft <= qvPointerForNumLeft + 1'b1 ;
277
    end
278
end
279
   // re-synchronize the write addresses within read clock domain
280
      // the 1st synchronizing cycle
281
always @ ( negedge inReset or posedge ReadClock )  begin
282
   if( !inReset ) begin
283
      qvPreWGrayAddr_RSync1 <= 0 ;
284
      qvWGrayAddr_RSync1 <= 1 ;
285
   end
286
   else  begin
287
      qvPreWGrayAddr_RSync1 <= qvPreWGrayAddr ;
288
      qvWGrayAddr_RSync1 <= qvWGrayAddr ;
289
   end
290
end
291
      // the 2nd synchronizing cycle
292
always @ ( negedge inReset or posedge ReadClock )  begin
293
   if( !inReset ) begin
294
      qvPreWGrayAddr_RSync2 <= 0 ;
295
      qvWGrayAddr_RSync2 <= 1 ;
296
   end
297
   else  begin
298
      qvPreWGrayAddr_RSync2 <= qvPreWGrayAddr_RSync1 ;
299
      qvWGrayAddr_RSync2 <= qvWGrayAddr_RSync1 ;
300
   end
301
end
302
 
303
   //   to calculate the write address in read clock domain
304
always @ ( negedge inReset or posedge ReadClock )  begin   // 1 cycle delay will be added
305
   if( !inReset ) begin
306
      qvPreWAddr_RSync2 <= 0 ;
307
   end
308
   else  begin
309
      for( i=0; i<=pDepthWidth; i=i+1 )
310
         qvPreWAddr_RSync2[i] <= ^( qvPreWGrayAddr_RSync2 >>i ) ;   // Gray To Binary Conversion
311
   end
312
end
313
//always @ ( qvPreWGrayAddr_RSync2 )   // Gray To Binary Conversion
314
//   for( i=0; i<=pDepthWidth; i=i+1 )
315
//      qvWAddr_RSync2[i] <= ^( qvPreWGrayAddr_RSync2 >>i ) ;   // Gray To Binary Conversion
316
 
317
   // calculates qvRNumberLeft
318
reg  [pDepthWidth:0] qvRNumberLeft_int ;
319
always @ ( negedge inReset or posedge ReadClock )  begin
320
   if( !inReset ) begin
321
      qvRNumberLeft_int <= { 1'b1, {pDepthWidth{1'b0}} } ;
322
   end
323
   else  begin
324
      if( MemREn )
325
         qvRNumberLeft_int <= qvNextPointerForNumLeft - qvPreWAddr_RSync2 ;
326
      else
327
         qvRNumberLeft_int <= qvPointerForNumLeft - qvPreWAddr_RSync2 ;
328
   end
329
end
330
 
331
always @ ( negedge inReset or posedge ReadClock )  begin
332
   if( !inReset ) begin
333
      qvRNumberLeft <= { 1'b1, {pDepthWidth{1'b0}} } ;
334
   end
335
   else  begin
336
      if( qvRNumberLeft_int >= 4 )  qvRNumberLeft <= qvRNumberLeft_int - 4 ;
337
      else  qvRNumberLeft <= 0 ;
338
   end
339
end
340
 
341
   // generates qREmpty_int
342
always @ ( negedge inReset or posedge ReadClock )  begin
343
   if( !inReset ) begin
344
      qREmpty_int <= 1 ;
345
   end
346
   else  begin
347
      if( ~qREmpty_int ) begin
348
         if( MemREn && ( qvRGrayAddr == qvPreWGrayAddr_RSync2 ) )
349
            qREmpty_int <= 1 ;
350
      end
351
       else  begin
352
          if( qvRGrayAddr != qvWGrayAddr_RSync2 )
353
             qREmpty_int <= 0 ;
354
      end
355
   end
356
end
357
 
358
//always @ ( qvRNumberLeft_int[pDepthWidth] )
359
//   qREmpty_int <= qvRNumberLeft_int[pDepthWidth] ;
360
 
361
always @ ( negedge inReset or posedge ReadClock )  begin
362
   if( !inReset ) begin
363
      qREmpty <= 1'b1 ;
364
   end
365
   else  begin
366
      if( qREmpty )  begin
367
         if( !qREmpty_int )   qREmpty <= 1'b0 ;
368
      end
369
      else
370
         if( qREmpty_int && iREn )   qREmpty <= 1'b1 ;
371
   end
372
end
373
 
374
always @ ( negedge inReset or posedge ReadClock )  begin
375
   if( !inReset ) begin
376
      qvDataOut <= {pWordWidth{1'b0}} ;
377
   end
378
   else  begin
379
      if( MemREn )  begin
380
         qvDataOut <= MemDataOut ;
381
      end
382
   end
383
end
384
 
385
endmodule
386
 
387
 
388
module DualPortRAM_ASYN
389
   (
390
      // Generic synchronous two-port RAM interface
391
   WriteClock ,
392
   MemWEn ,
393
   MemWAddr ,
394
   MemDataIn ,
395
   ReadClock ,
396
   MemRAddr ,
397
   MemDataOut
398
    );
399
 
400
// Default address and data width
401
parameter   pDepthWidth = 5 ;
402
parameter   pWordWidth = 16 ;
403
 
404
// Generic synchronous two-port RAM interface
405
input WriteClock ;
406
input MemWEn ;
407
input MemWAddr ;
408
input MemDataIn ;
409
input ReadClock ;
410
input  [pDepthWidth-1:0] MemRAddr ;
411
output  [pWordWidth-1:0] MemDataOut ;
412
 
413
wire  WriteClock ;
414
wire  MemWEn ;
415
wire  [pDepthWidth-1:0] MemWAddr ;
416
wire  [pWordWidth-1:0] MemDataIn ;
417
wire  ReadClock ;
418
wire  [pDepthWidth-1:0] MemRAddr ;
419
wire  [pWordWidth-1:0] MemDataOut ;
420
 
421
reg   [pWordWidth-1:0]  mem [(1<<pDepthWidth)-1:0] /*synthesis syn_ramstyle="no_rw_check"*/;
422
 
423
// RAM read and write
424
// a port for write
425
always @ ( posedge WriteClock )
426
   if( MemWEn )
427
      mem[MemWAddr] <= MemDataIn ;
428
 
429
// RAM read and write
430
//b for read
431
 
432
/* registered address */
433
reg   [pDepthWidth-1:0] qvRAddr ;
434
always @ ( posedge ReadClock )
435
   qvRAddr <= MemRAddr ;
436
 
437
assign MemDataOut = mem[qvRAddr] ;
438
 
439
endmodule

powered by: WebSVN 2.1.0

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