OpenCores
URL https://opencores.org/ocsvn/fpga-cf/fpga-cf/trunk

Subversion Repositories fpga-cf

[/] [fpga-cf/] [trunk/] [hdl/] [boardsupport/] [v5/] [rx_elastic_buffer.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 peteralieb
//----------------------------------------------------------------------
2
// File       : rx_elastic_buffer.v
3
// Author     : Xilinx Inc.                                                                                                                                      
4
//----------------------------------------------------------------------
5
// Copyright (c) 2008 by Xilinx, Inc. All rights reserved.
6
// This text/file contains proprietary, confidential
7
// information of Xilinx, Inc., is distributed under license
8
// from Xilinx, Inc., and may be used, copied and/or
9
// disclosed only pursuant to the terms of a valid license
10
// agreement with Xilinx, Inc. Xilinx hereby grants you
11
// a license to use this text/file solely for design, simulation,
12
// implementation and creation of design files limited
13
// to Xilinx devices or technologies. Use with non-Xilinx
14
// devices or technologies is expressly prohibited and
15
// immediately terminates your license unless covered by
16
// a separate agreement.
17
//
18
// Xilinx is providing this design, code, or information
19
// "as is" solely for use in developing programs and
20
// solutions for Xilinx devices. By providing this design,
21
// code, or information as one possible implementation of
22
// this feature, application or standard, Xilinx is making no
23
// representation that this implementation is free from any
24
// claims of infringement. You are responsible for
25
// obtaining any rights you may require for your implementation.
26
// Xilinx expressly disclaims any warranty whatsoever with
27
// respect to the adequacy of the implementation, including
28
// but not limited to any warranties or representations that this
29
// implementation is free from claims of infringement, implied
30
// warranties of merchantability or fitness for a particular
31
// purpose.
32
//
33
// Xilinx products are not intended for use in life support
34
// appliances, devices, or systems. Use in such applications are
35
// expressly prohibited.
36
//
37
// This copyright and support notice must be retained as part
38
// of this text at all times. (c) Copyright 2008 Xilinx, Inc.
39
// All rights reserved.
40
//----------------------------------------------------------------------
41
// Description: This is the Receiver Elastic Buffer for the design 
42
//              example of the Virtex-5 Ethernet MAC Wrappers. 
43
//
44
//              The FIFO is created from Block Memory, is of data width
45
//              32 (2 characters wide plus status) and is of depth 64 
46
//              words.  This is twice the size of the elastic buffer in
47
//              the RocketIO which has been bypassed,
48
//
49
//              When the write clock is a few parts per million faster 
50
//              than the read clock, the occupancy of the FIFO will
51
//              increase and Idles should be removed. 
52
//              
53
//              When the read clock is a few parts per million faster 
54
//              than the write clock, the occupancy of the FIFO will
55
//              decrease and Idles should be inserted.  The logic in  
56
//              this example design will always insert as many idles as  
57
//              necessary in every Inter-frame Gap period to restore the
58
//              FIFO occupancy.
59
//
60
//              Note: the Idle /I2/ sequence is used as the clock
61
//              correction character.  This is made up from a /K28.5/
62
//              followed by a /D16.2/ character.
63
 
64
 
65
 
66
`timescale 1 ns/1 ps
67
 
68
module rx_elastic_buffer
69
  (
70
 
71
    // Signals received from the RocketIO on RXRECCLK.
72
 
73
    rxrecclk,
74
    reset,
75
    rxchariscomma_rec,
76
    rxcharisk_rec,
77
    rxdisperr_rec,
78
    rxnotintable_rec,
79
    rxrundisp_rec,
80
    rxdata_rec,
81
 
82
    // Signals reclocked onto RXUSRCLK2.
83
 
84
    rxusrclk2,
85
    rxreset,
86
    rxchariscomma_usr,
87
    rxcharisk_usr,
88
    rxdisperr_usr,
89
    rxnotintable_usr,
90
    rxrundisp_usr,
91
    rxclkcorcnt_usr,
92
    rxbuferr,
93
    rxdata_usr
94
  );
95
 
96
 
97
 
98
  // port declarations
99
 
100
  input         rxrecclk;
101
  input         reset;
102
  input         rxchariscomma_rec;
103
  input         rxcharisk_rec;
104
  input         rxdisperr_rec;
105
  input         rxnotintable_rec;
106
  input         rxrundisp_rec;
107
  input  [7:0]  rxdata_rec;
108
 
109
  input         rxusrclk2;
110
  input         rxreset;
111
  output        rxchariscomma_usr;
112
  output        rxcharisk_usr;
113
  output        rxdisperr_usr;
114
  output        rxnotintable_usr;
115
  output        rxrundisp_usr;
116
  output [2:0]  rxclkcorcnt_usr;
117
  output        rxbuferr;
118
  output [7:0]  rxdata_usr;
119
 
120
  reg           rxchariscomma_usr;
121
  reg           rxcharisk_usr;
122
  reg           rxdisperr_usr;
123
  reg           rxnotintable_usr;
124
  reg           rxrundisp_usr;
125
  reg           rxbuferr;
126
  reg    [7:0]  rxdata_usr;
127
 
128
  //--------------------------------------------------------------------
129
  // Constants to set FIFO thresholds
130
  //--------------------------------------------------------------------
131
 
132
  // FIFO occupancy over this level: clock correct to remove Idles
133
  wire   [6:0]  upper_threshold;
134
  assign upper_threshold     = 7'b1000001;
135
 
136
  // FIFO occupancy less than this level: clock correct to insert Idles
137
  wire   [6:0]  lower_threshold;
138
  assign lower_threshold     = 7'b0111111;
139
 
140
  // FIFO occupancy less than this, we consider it to be an underflow
141
  wire   [6:0]  underflow_threshold;
142
  assign underflow_threshold = 7'b0000011;
143
 
144
  // FIFO occupancy greater than this, we consider it to be an overflow
145
  wire   [6:0]  overflow_threshold;
146
  assign overflow_threshold  = 7'b1111100;
147
 
148
 
149
 
150
  //--------------------------------------------------------------------
151
  // Signal Declarations
152
  //--------------------------------------------------------------------
153
 
154
  // Write domain logic (RXRECCLK) 
155
 
156
  reg    [15:0] wr_data;               // Formatted the data word from RocketIO signals.
157
  reg    [15:0] wr_data_reg;           // wr_data registered and formatting completed.
158
  reg    [15:0] wr_data_reg_reg;       // wr_data_reg registered : to be written to the BRAM.  
159
  reg    [6:0]  next_wr_addr;          // Next FIFO write address (to reduce latency in gray code logic).
160
  reg    [6:0]  wr_addr;               // FIFO write address.
161
  wire          wr_enable;             // write enable for FIFO.
162
  reg    [6:0]  wr_addr_gray;          // wr_addr is converted to a gray code. 
163
 
164
  reg    [6:0]  wr_rd_addr_gray;       // read address pointer (gray coded) reclocked onto the write clock domain).
165
  reg    [6:0]  wr_rd_addr_gray_reg;   // read address pointer (gray coded) registered on write clock for the 2nd time.
166
  wire   [6:0]  wr_rd_addr;            // wr_rd_addr_gray converted back to binary (on the write clock domain). 
167
  reg    [6:0]  wr_occupancy;          // The occupancy of the FIFO in write clock domain.
168
  wire          filling;               // FIFO is filling up: Idles should be removed.
169
 
170
  // synthesis attribute ASYNC_REG of wr_rd_addr_gray  is "TRUE";
171
 
172
  wire          k28p5_wr;              // /K28.5/ character is detected on data prior to FIFO.
173
  wire          d16p2_wr;              // /D16.2/ character is detected on data prior to FIFO.
174
  reg    [2:0]  d16p2_wr_pipe;         // k28p5_wr registered.
175
  reg    [2:0]  k28p5_wr_pipe;         // d16p2_wr registered.
176
  reg           remove_idle;           // An Idle is removed before writing it into the FIFO.
177
  reg           remove_idle_reg;       // remove_idle registered.
178
 
179
 
180
  // Read domain logic (RXUSRCLK2) 
181
 
182
  wire   [15:0] rd_data;               // Date read out of the block RAM.
183
  reg    [15:0] rd_data_reg;           // rd_data is registered for logic pipeline.
184
  reg    [6:0]  next_rd_addr;          // Next FIFO read address (to reduce latency in gray code logic).
185
  reg    [6:0]  rd_addr;               // FIFO read address.
186
  wire          rd_enable;             // read enable for FIFO.
187
  reg    [6:0]  rd_addr_gray;          // rd_addr is converted to a gray code. 
188
 
189
  reg    [6:0]  rd_wr_addr_gray;       // write address pointer (gray coded) reclocked onto the read clock domain).
190
  reg    [6:0]  rd_wr_addr_gray_reg;   // write address pointer (gray coded) registered on read clock for the 2nd time.
191
  wire   [6:0]  rd_wr_addr;            // rd_wr_addr_gray converted back to binary (on the read clock domain). 
192
  reg    [6:0]  rd_occupancy;          // The occupancy of the FIFO in read clock domain.
193
  wire          emptying;              // FIFO is emptying: Idles should be inserted.
194
  wire          overflow;              // FIFO has filled up to overflow.
195
  wire          underflow;             // FIFO has emptied to underflow
196
 
197
  // synthesis attribute ASYNC_REG of rd_wr_addr_gray  is "TRUE";
198
 
199
  reg           even;                  // To control reading of data from upper or lower half of FIFO word.
200
  wire          k28p5_rd;              // /K28.5/ character is detected on data post FIFO.
201
  wire          d16p2_rd;              // /D16.2/ character is detected on data post FIFO.
202
  reg           insert_idle;           // An Idle is inserted whilst reading it out of the FIFO.
203
  reg           insert_idle_reg;       // insert_idle is registered.
204
  reg           rd_enable_reg;         // Read enable is registered.
205
  reg   [2:0]   rxclkcorcnt;           // derive RXCLKCORCNT to mimic RocketIO behaviour.    
206
 
207
  //--------------------------------------------------------------------
208
  // FIFO write logic (Idles are removed as necessary).
209
  //--------------------------------------------------------------------
210
 
211
  // Reclock the RocketIO data and format for storing in the BRAM.
212
  always @(posedge rxrecclk)
213
  begin : gen_wr_data
214
    if (reset === 1'b1)
215
    begin
216
      wr_data            <= 16'b0;
217
      wr_data_reg        <= 16'b0;
218
      wr_data_reg_reg    <= 16'b0;
219
    end
220
    else
221
    begin
222
 
223
      wr_data_reg_reg    <= wr_data_reg;
224
 
225
      wr_data_reg[15:14] <= wr_data[15:14];
226
      wr_data_reg[13]    <= remove_idle;
227
      wr_data_reg[12:0]  <= wr_data[12:0];
228
 
229
      // format the lower word
230
      wr_data[15:13]     <= 3'b0;   // unused
231
      wr_data[12]        <= rxchariscomma_rec;
232
      wr_data[11]        <= rxcharisk_rec;
233
      wr_data[10]        <= rxdisperr_rec;
234
      wr_data[9]         <= rxnotintable_rec;
235
      wr_data[8]         <= rxrundisp_rec;
236
      wr_data[7:0]       <= rxdata_rec[7:0];
237
 
238
    end
239
  end // gen_wr_data
240
 
241
 
242
 
243
  // Detect /K28.5/ character in upper half of the word from RocketIO
244
  assign k28p5_wr = (wr_data[7:0] == 8'b10111100 &&
245
                     wr_data[11] == 1'b1) ? 1'b1 : 1'b0;
246
 
247
  // Detect /D16.2/ character in upper half of the word from RocketIO
248
  assign d16p2_wr = (wr_data[7:0] == 8'b01010000 &&
249
                     wr_data[11] == 1'b0) ? 1'b1 : 1'b0;
250
 
251
  always @(posedge rxrecclk)
252
  begin : gen_k_d_pipe
253
    if (reset === 1'b1)
254
    begin
255
      k28p5_wr_pipe      <= 3'b000;
256
      d16p2_wr_pipe      <= 3'b000;
257
    end
258
    else
259
    begin
260
      k28p5_wr_pipe[2:1] <= k28p5_wr_pipe[1:0];
261
      d16p2_wr_pipe[2:1] <= d16p2_wr_pipe[1:0];
262
      k28p5_wr_pipe[0]   <= k28p5_wr;
263
      d16p2_wr_pipe[0]   <= d16p2_wr;
264
    end
265
  end // gen_k_d_pipe    
266
 
267
 
268
  // Create the FIFO write enable: Idles are removed by deasserting the
269
  // FIFO write_enable whilst an Idle is present on the data.
270
  always @(posedge rxrecclk)
271
  begin : gen_wr_enable
272
    if (reset === 1'b1)
273
    begin
274
      remove_idle       <= 1'b0;
275
      remove_idle_reg   <= 1'b0;
276
    end
277
    else
278
    begin
279
 
280
      remove_idle_reg <= remove_idle;
281
 
282
      // Idle removal (always leave the first /I2/ Idle, then every
283
      // alternate Idle can be removed.
284
      if (d16p2_wr == 1'b1 && k28p5_wr_pipe[0] == 1'b1 &&
285
          d16p2_wr_pipe[1] == 1'b1 && k28p5_wr_pipe[2] == 1'b1 &&
286
          filling == 1'b1 && remove_idle == 1'b0)
287
 
288
      begin
289
        remove_idle <= 1'b1;
290
      end
291
 
292
      // Else write new word on every clock edge.
293
      else
294
      begin
295
        remove_idle <= 1'b0;
296
          end
297
    end
298
  end // gen_wr_enable
299
 
300
  assign wr_enable   = ~(remove_idle | remove_idle_reg);
301
 
302
  // Create the FIFO write address pointer.
303
  always @(posedge rxrecclk)
304
  begin : gen_wr_addr
305
    if (reset === 1'b1)
306
    begin
307
      next_wr_addr <= 7'b1000001;
308
      wr_addr      <= 7'b1000000;
309
    end
310
    else if (wr_enable == 1'b1)
311
    begin
312
      next_wr_addr <= next_wr_addr + 7'b1;
313
      wr_addr      <= next_wr_addr;
314
        end
315
  end // gen_wr_addr
316
 
317
 
318
 
319
  // Convert write address pointer into a gray code
320
  always @(posedge rxrecclk)
321
  begin : wr_addrgray_bits
322
    if (reset === 1'b1)
323
      wr_addr_gray <= 7'b1100001;
324
    else
325
    begin
326
      wr_addr_gray[6] <= next_wr_addr[6];
327
      wr_addr_gray[5] <= next_wr_addr[6] ^ next_wr_addr[5];
328
      wr_addr_gray[4] <= next_wr_addr[5] ^ next_wr_addr[4];
329
      wr_addr_gray[3] <= next_wr_addr[4] ^ next_wr_addr[3];
330
      wr_addr_gray[2] <= next_wr_addr[3] ^ next_wr_addr[2];
331
      wr_addr_gray[1] <= next_wr_addr[2] ^ next_wr_addr[1];
332
      wr_addr_gray[0] <= next_wr_addr[1] ^ next_wr_addr[0];
333
    end
334
  end // wr_addrgray_bits;
335
 
336
 
337
 
338
  //--------------------------------------------------------------------
339
  // Instantiate a dual port Block RAM    
340
  //--------------------------------------------------------------------
341
 
342
  RAMB16_S18_S18 dual_port_block_ram0
343
  (
344
    .ADDRA       ({3'b0, wr_addr}),
345
    .DIA         (wr_data_reg_reg[15:0]),
346
    .DIPA        (2'b00),
347
    .DOA         (),
348
    .DOPA        (),
349
    .WEA         (wr_enable),
350
    .ENA         (1'b1),
351
    .SSRA        (1'b0),
352
    .CLKA        (rxrecclk),
353
 
354
    .ADDRB       ({3'b0, rd_addr}),
355
    .DIB         (16'b0),
356
    .DIPB        (2'b00),
357
    .DOB         (rd_data[15:0]),
358
    .DOPB        (),
359
    .WEB         (1'b0),
360
    .ENB         (1'b1),
361
    .SSRB        (rxreset),
362
    .CLKB        (rxusrclk2)
363
  );
364
 
365
 
366
  //--------------------------------------------------------------------
367
  // FIFO read logic (Idles are insterted as necessary).
368
  //--------------------------------------------------------------------
369
 
370
  // Register the BRAM data.
371
  always @(posedge rxusrclk2)
372
  begin : reg_rd_data
373
    if (rxreset == 1'b1)
374
      rd_data_reg   <= 16'b0;
375
 
376
    else if (rd_enable_reg == 1'b1)
377
      rd_data_reg   <= rd_data;
378
 
379
  end // reg_rd_data
380
 
381
  //--------------------------------------------------------------------
382
  // FIFO read logic (Idles are insterted as necessary).
383
  //--------------------------------------------------------------------
384
 
385
 
386
 
387
  // Detect /K28.5/ character in upper half of the word read from FIFO
388
  assign k28p5_rd = (rd_data_reg[7:0] == 8'b10111100 &&
389
                     rd_data_reg[11] == 1'b1) ? 1'b1 : 1'b0;
390
 
391
  // Detect /D16.2/ character in lower half of the word read from FIFO
392
  assign d16p2_rd = (rd_data[7:0] == 8'b01010000 &&
393
                     rd_data[11] == 1'b0) ? 1'b1 : 1'b0;
394
 
395
 
396
  // Create the FIFO read enable: Idles are inserted by pausing the
397
  // FIFO read_enable whilst an Idle is present on the data.
398
  always @(posedge rxusrclk2)
399
  begin : gen_rd_enable
400
    if (rxreset == 1'b1)
401
    begin
402
      even            <= 1'b1;
403
      insert_idle     <= 1'b0;
404
      insert_idle_reg <= 1'b0;
405
      rd_enable_reg   <= 1'b1;
406
    end
407
    else
408
    begin
409
 
410
      insert_idle_reg <= insert_idle;
411
      rd_enable_reg   <= rd_enable;
412
 
413
      // Repeat as many /I2/ code groups as required if nearly
414
      // empty by pausing rd_enable.
415
      if ((k28p5_rd == 1'b1 && d16p2_rd == 1'b1) && emptying == 1'b1 && insert_idle == 1'b0)
416
      begin
417
        insert_idle   <= 1'b1;
418
        even          <= 1'b0;
419
      end
420
 
421
      // Else read out a new word on every alternative clock edge.
422
      else
423
      begin
424
         insert_idle  <= 1'b0;
425
         even         <= ~(even);
426
          end
427
        end
428
  end // gen_rd_enable
429
 
430
  assign rd_enable = ~(insert_idle | insert_idle_reg);
431
 
432
 
433
  // Create the FIFO read address pointer.
434
  always @(posedge rxusrclk2)
435
  begin : gen_rd_addr
436
    if (rxreset == 1'b1)
437
    begin
438
      next_rd_addr <= 7'b0000001;
439
      rd_addr      <= 7'b0000000;
440
    end
441
    else if (rd_enable == 1'b1)
442
    begin
443
      next_rd_addr <= next_rd_addr + 7'b1;
444
      rd_addr      <= next_rd_addr;
445
    end
446
  end // gen_rd_addr
447
 
448
 
449
 
450
  // Convert read address pointer into a gray code
451
  always @(posedge rxusrclk2)
452
  begin : rd_addrgray_bits
453
    if (rxreset == 1'b1)
454
      rd_addr_gray <= 7'b0;
455
    else if (rd_enable == 1'b1)
456
    begin
457
      rd_addr_gray[6] <= next_rd_addr[6];
458
      rd_addr_gray[5] <= next_rd_addr[6] ^ next_rd_addr[5];
459
      rd_addr_gray[4] <= next_rd_addr[5] ^ next_rd_addr[4];
460
      rd_addr_gray[3] <= next_rd_addr[4] ^ next_rd_addr[3];
461
      rd_addr_gray[2] <= next_rd_addr[3] ^ next_rd_addr[2];
462
      rd_addr_gray[1] <= next_rd_addr[2] ^ next_rd_addr[1];
463
      rd_addr_gray[0] <= next_rd_addr[1] ^ next_rd_addr[0];
464
    end
465
  end // rd_addrgray_bits
466
 
467
  // Create the output data signals.
468
  always @(posedge rxusrclk2)
469
  begin : gen_mux
470
    if (rxreset == 1'b1)
471
    begin
472
      rxchariscomma_usr   <= 1'b0;
473
      rxcharisk_usr       <= 1'b0;
474
      rxdisperr_usr       <= 1'b0;
475
      rxnotintable_usr    <= 1'b0;
476
      rxrundisp_usr       <= 1'b0;
477
      rxdata_usr          <= 8'b0;
478
    end
479
    else
480
    begin
481
      if (rd_enable_reg == 1'b0 && even == 1'b0)
482
      begin
483
        rxchariscomma_usr <= 1'b0;
484
        rxcharisk_usr     <= 1'b0;
485
        rxdisperr_usr     <= 1'b0;
486
        rxnotintable_usr  <= 1'b0;
487
        rxrundisp_usr     <= rd_data_reg[8];
488
        rxdata_usr        <= 8'b01010000;
489
      end
490
      else if (rd_enable_reg == 1'b0 && even == 1'b1)
491
      begin
492
        rxchariscomma_usr <= 1'b1;
493
        rxcharisk_usr     <= 1'b1;
494
        rxdisperr_usr     <= 1'b0;
495
        rxnotintable_usr  <= 1'b0;
496
        rxrundisp_usr     <= rd_data[8];
497
        rxdata_usr        <= 8'b10111100;
498
      end
499
      else
500
      begin
501
        rxchariscomma_usr <= rd_data_reg[12];
502
        rxcharisk_usr     <= rd_data_reg[11];
503
        rxdisperr_usr     <= rd_data_reg[10];
504
        rxnotintable_usr  <= rd_data_reg[9];
505
        rxrundisp_usr     <= rd_data_reg[8];
506
        rxdata_usr        <= rd_data_reg[7:0];
507
      end
508
    end
509
  end // gen_mux
510
 
511
  // Create RocketIO style clock correction status when inserting /
512
  // removing Idles.
513
  always @(posedge rxusrclk2)
514
  begin : gen_rxclkcorcnt
515
    if (rxreset == 1'b1)
516
      rxclkcorcnt   <= 3'b0;
517
    else
518
    begin
519
      if (rd_data_reg[13] == 1'b1 && rxclkcorcnt[0] == 1'b0)
520
         rxclkcorcnt   <= 3'b001;
521
      else if (insert_idle_reg == 1'b1 && rxclkcorcnt != 3'b111)
522
         rxclkcorcnt   <= 3'b111;
523
      else
524
         rxclkcorcnt   <= 3'b000;
525
    end
526
  end // gen_rxclkcorcnt
527
 
528
  assign rxclkcorcnt_usr = rxclkcorcnt;
529
 
530
 
531
 
532
  //--------------------------------------------------------------------
533
  // Create emptying/full thresholds in read clock domain.
534
  //--------------------------------------------------------------------
535
 
536
 
537
 
538
  // Reclock the write address pointer (gray code) onto the read domain.
539
  // By reclocking the gray code, the worst case senario is that 
540
  // the reclocked value is only in error by -1, since only 1 bit at a  
541
  // time changes between gray code increments. 
542
  always @(posedge rxusrclk2)
543
  begin : reclock_wr_addrgray
544
    if (rxreset === 1'b1)
545
    begin
546
      rd_wr_addr_gray     <= 7'b1100001;
547
      rd_wr_addr_gray_reg <= 7'b1100000;
548
    end
549
    else
550
    begin
551
      rd_wr_addr_gray     <= wr_addr_gray;
552
      rd_wr_addr_gray_reg <= rd_wr_addr_gray;
553
    end
554
  end // reclock_wr_addrgray
555
 
556
 
557
 
558
  // Convert the resync'd Write Address Pointer grey code back to binary
559
  assign rd_wr_addr[6] = rd_wr_addr_gray_reg[6];
560
 
561
  assign rd_wr_addr[5] = rd_wr_addr_gray_reg[6] ^ rd_wr_addr_gray_reg[5];
562
 
563
  assign rd_wr_addr[4] = rd_wr_addr_gray_reg[6] ^ rd_wr_addr_gray_reg[5]
564
                         ^ rd_wr_addr_gray_reg[4];
565
 
566
  assign rd_wr_addr[3] = rd_wr_addr_gray_reg[6] ^ rd_wr_addr_gray_reg[5]
567
                         ^ rd_wr_addr_gray_reg[4] ^ rd_wr_addr_gray_reg[3];
568
 
569
  assign rd_wr_addr[2] = rd_wr_addr_gray_reg[6] ^ rd_wr_addr_gray_reg[5]
570
                         ^ rd_wr_addr_gray_reg[4] ^ rd_wr_addr_gray_reg[3]
571
                         ^ rd_wr_addr_gray_reg[2];
572
 
573
  assign rd_wr_addr[1] = rd_wr_addr_gray_reg[6] ^ rd_wr_addr_gray_reg[5]
574
                         ^ rd_wr_addr_gray_reg[4] ^ rd_wr_addr_gray_reg[3]
575
                         ^ rd_wr_addr_gray_reg[2] ^ rd_wr_addr_gray_reg[1];
576
 
577
  assign rd_wr_addr[0] = rd_wr_addr_gray_reg[6] ^ rd_wr_addr_gray_reg[5]
578
                         ^ rd_wr_addr_gray_reg[4] ^ rd_wr_addr_gray_reg[3]
579
                         ^ rd_wr_addr_gray_reg[2] ^ rd_wr_addr_gray_reg[1]
580
                         ^ rd_wr_addr_gray_reg[0];
581
 
582
 
583
 
584
  // Determine the occupancy of the FIFO as observed in the read domain.
585
  always @(posedge rxusrclk2)
586
  begin : gen_rd_occupancy
587
    if (rxreset === 1'b1)
588
      rd_occupancy <= 7'b1000000;
589
    else
590
      rd_occupancy <= rd_wr_addr - rd_addr;
591
  end // gen_rd_occupancy
592
 
593
 
594
 
595
  // Set emptying flag if FIFO occupancy is less than LOWER_THRESHOLD. 
596
  assign emptying = (rd_occupancy < lower_threshold) ? 1'b1 : 1'b0;
597
 
598
 
599
 
600
  // Set underflow if FIFO occupancy is less than UNDERFLOW_THRESHOLD. 
601
  assign underflow = (rd_occupancy < underflow_threshold) ? 1'b1 : 1'b0;
602
 
603
 
604
 
605
  // Set overflow if FIFO occupancy is less than OVERFLOW_THRESHOLD. 
606
  assign overflow = (rd_occupancy > overflow_threshold) ? 1'b1 : 1'b0;
607
 
608
 
609
 
610
  // If either an underflow or overflow, assert the buffer error signal.
611
  // Like the RocketIO, this will persist until a reset is issued.
612
  always @(posedge rxusrclk2)
613
  begin : gen_buffer_error
614
    if (rxreset === 1'b1)
615
      rxbuferr <= 1'b0;
616
    else if (overflow == 1'b1 || underflow == 1'b1)
617
      rxbuferr <= 1'b1;
618
  end // gen_buffer_error
619
 
620
 
621
 
622
  //--------------------------------------------------------------------
623
  // Create emptying/full thresholds in write clock domain.
624
  //--------------------------------------------------------------------
625
 
626
 
627
 
628
  // Reclock the read address pointer (gray code) onto the write domain.
629
  // By reclocking the gray code, the worst case senario is that 
630
  // the reclocked value is only in error by -1, since only 1 bit at a  
631
  // time changes between gray code increments. 
632
  always @(posedge rxrecclk)
633
  begin : reclock_rd_addrgray
634
    if (reset === 1'b1)
635
    begin
636
      wr_rd_addr_gray     <= 7'b0;
637
      wr_rd_addr_gray_reg <= 7'b0;
638
    end
639
    else
640
    begin
641
      wr_rd_addr_gray     <= rd_addr_gray;
642
      wr_rd_addr_gray_reg <= wr_rd_addr_gray;
643
    end
644
  end // reclock_rd_addrgray
645
 
646
 
647
 
648
  // Convert the resync'd Read Address Pointer grey code back to binary
649
 
650
  assign wr_rd_addr[6] = wr_rd_addr_gray_reg[6];
651
 
652
  assign wr_rd_addr[5] = wr_rd_addr_gray_reg[6] ^ wr_rd_addr_gray_reg[5];
653
 
654
  assign wr_rd_addr[4] = wr_rd_addr_gray_reg[6] ^ wr_rd_addr_gray_reg[5]
655
                         ^ wr_rd_addr_gray_reg[4];
656
 
657
  assign wr_rd_addr[3] = wr_rd_addr_gray_reg[6] ^ wr_rd_addr_gray_reg[5]
658
                         ^ wr_rd_addr_gray_reg[4] ^ wr_rd_addr_gray_reg[3];
659
 
660
  assign wr_rd_addr[2] = wr_rd_addr_gray_reg[6] ^ wr_rd_addr_gray_reg[5]
661
                         ^ wr_rd_addr_gray_reg[4] ^ wr_rd_addr_gray_reg[3]
662
                         ^ wr_rd_addr_gray_reg[2];
663
 
664
  assign wr_rd_addr[1] = wr_rd_addr_gray_reg[6] ^ wr_rd_addr_gray_reg[5]
665
                         ^ wr_rd_addr_gray_reg[4] ^ wr_rd_addr_gray_reg[3]
666
                         ^ wr_rd_addr_gray_reg[2] ^ wr_rd_addr_gray_reg[1];
667
 
668
  assign wr_rd_addr[0] = wr_rd_addr_gray_reg[6] ^ wr_rd_addr_gray_reg[5]
669
                         ^ wr_rd_addr_gray_reg[4] ^ wr_rd_addr_gray_reg[3]
670
                         ^ wr_rd_addr_gray_reg[2] ^ wr_rd_addr_gray_reg[1]
671
                         ^ wr_rd_addr_gray_reg[0];
672
 
673
 
674
 
675
  // Determine the occupancy of the FIFO as observed in the write domain.
676
  always @(posedge rxrecclk)
677
  begin : gen_wr_occupancy
678
    if (reset === 1'b1)
679
      wr_occupancy <= 7'b1000000;
680
    else
681
      wr_occupancy <= wr_addr[6:0] - wr_rd_addr[6:0];
682
  end // gen_wr_occupancy
683
 
684
 
685
 
686
  // Set filling flag if FIFO occupancy is greated than UPPER_THRESHOLD. 
687
  assign filling = (wr_occupancy > upper_threshold) ? 1'b1 : 1'b0;
688
 
689
 
690
 
691
endmodule

powered by: WebSVN 2.1.0

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