⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rx_elastic_buffer.v

📁 Xilinx Virtex5 SGMII高速串行通信例程。
💻 V
📖 第 1 页 / 共 2 页
字号:
//----------------------------------------------------------------------
// File       : rx_elastic_buffer.v
// Author     : Xilinx Inc.																	 
//----------------------------------------------------------------------
// Copyright (c) 2007 by Xilinx, Inc. All rights reserved.
// This text/file contains proprietary, confidential
// information of Xilinx, Inc., is distributed under license
// from Xilinx, Inc., and may be used, copied and/or
// disclosed only pursuant to the terms of a valid license
// agreement with Xilinx, Inc. Xilinx hereby grants you
// a license to use this text/file solely for design, simulation,
// implementation and creation of design files limited
// to Xilinx devices or technologies. Use with non-Xilinx
// devices or technologies is expressly prohibited and
// immediately terminates your license unless covered by
// a separate agreement.
//
// Xilinx is providing this design, code, or information
// "as is" solely for use in developing programs and
// solutions for Xilinx devices. By providing this design,
// code, or information as one possible implementation of
// this feature, application or standard, Xilinx is making no
// representation that this implementation is free from any
// claims of infringement. You are responsible for
// obtaining any rights you may require for your implementation.
// Xilinx expressly disclaims any warranty whatsoever with
// respect to the adequacy of the implementation, including
// but not limited to any warranties or representations that this
// implementation is free from claims of infringement, implied
// warranties of merchantability or fitness for a particular
// purpose.
//
// Xilinx products are not intended for use in life support
// appliances, devices, or systems. Use in such applications are
// expressly prohibited.
//
// This copyright and support notice must be retained as part
// of this text at all times. (c) Copyright 2007 Xilinx, Inc.
// All rights reserved.
//----------------------------------------------------------------------
// Description: This is the Receiver Elastic Buffer for the design 
//              example of the Virtex-5 Ethernet MAC Wrappers. 
//
//              The FIFO is created from Block Memory, is of data width
//              32 (2 characters wide plus status) and is of depth 64 
//              words.  This is twice the size of the elastic buffer in
//              the RocketIO which has been bypassed,
//
//              When the write clock is a few parts per million faster 
//              than the read clock, the occupancy of the FIFO will
//              increase and Idles should be removed. 
//              
//              When the read clock is a few parts per million faster 
//              than the write clock, the occupancy of the FIFO will
//              decrease and Idles should be inserted.  The logic in  
//              this example design will always insert as many idles as  
//              necessary in every Inter-frame Gap period to restore the
//              FIFO occupancy.
//
//              Note: the Idle /I2/ sequence is used as the clock
//              correction character.  This is made up from a /K28.5/
//              followed by a /D16.2/ character.

																							 
																							 
`timescale 1 ns/1 ps

module rx_elastic_buffer
  ( 

    // Signals received from the RocketIO on RXRECCLK.

    rxrecclk,
    reset,
    rxchariscomma_rec,
    rxcharisk_rec,
    rxdisperr_rec,
    rxnotintable_rec,
    rxrundisp_rec,
    rxdata_rec,

    // Signals reclocked onto RXUSRCLK2.

    rxusrclk2,
    rxreset,
    rxchariscomma_usr,
    rxcharisk_usr,
    rxdisperr_usr,
    rxnotintable_usr,
    rxrundisp_usr,
    rxclkcorcnt_usr,
    rxbuferr,
    rxdata_usr
  );



  // port declarations

  input         rxrecclk;
  input         reset;
  input         rxchariscomma_rec;
  input         rxcharisk_rec;
  input         rxdisperr_rec;
  input         rxnotintable_rec;
  input         rxrundisp_rec;
  input  [7:0]  rxdata_rec;

  input         rxusrclk2;
  input         rxreset;
  output        rxchariscomma_usr;
  output        rxcharisk_usr;
  output        rxdisperr_usr;
  output        rxnotintable_usr;
  output        rxrundisp_usr;
  output [2:0]  rxclkcorcnt_usr;
  output        rxbuferr;
  output [7:0]  rxdata_usr;

  reg           rxchariscomma_usr;
  reg           rxcharisk_usr;
  reg           rxdisperr_usr;
  reg           rxnotintable_usr;
  reg           rxrundisp_usr;
  reg           rxbuferr;
  reg    [7:0]  rxdata_usr;

  //--------------------------------------------------------------------
  // Constants to set FIFO thresholds
  //--------------------------------------------------------------------

  // FIFO occupancy over this level: clock correct to remove Idles
  wire   [6:0]  upper_threshold;        
  assign upper_threshold     = 7'b1000001;  

  // FIFO occupancy less than this level: clock correct to insert Idles
  wire   [6:0]  lower_threshold;
  assign lower_threshold     = 7'b0111111;  

  // FIFO occupancy less than this, we consider it to be an underflow
  wire   [6:0]  underflow_threshold;
  assign underflow_threshold = 7'b0000011;  

  // FIFO occupancy greater than this, we consider it to be an overflow
  wire   [6:0]  overflow_threshold;
  assign overflow_threshold  = 7'b1111100;  



  //--------------------------------------------------------------------
  // Signal Declarations
  //--------------------------------------------------------------------

  // Write domain logic (RXRECCLK) 

  reg    [15:0] wr_data;               // Formatted the data word from RocketIO signals.
  reg    [15:0] wr_data_reg;           // wr_data registered and formatting completed.
  reg    [15:0] wr_data_reg_reg;       // wr_data_reg registered : to be written to the BRAM.  
  reg    [6:0]  next_wr_addr;          // Next FIFO write address (to reduce latency in gray code logic).
  reg    [6:0]  wr_addr;               // FIFO write address.
  wire          wr_enable;             // write enable for FIFO.
  reg    [6:0]  wr_addr_gray;          // wr_addr is converted to a gray code. 

  reg    [6:0]  wr_rd_addr_gray;       // read address pointer (gray coded) reclocked onto the write clock domain).
  wire   [6:0]  wr_rd_addr;            // wr_rd_addr_gray converted back to binary (on the write clock domain). 
  reg    [6:0]  wr_occupancy;          // The occupancy of the FIFO in write clock domain.
  wire          filling;               // FIFO is filling up: Idles should be removed.

  // synthesis attribute ASYNC_REG of wr_rd_addr_gray  is "TRUE";

  wire          k28p5_wr;              // /K28.5/ character is detected on data prior to FIFO.
  wire          d16p2_wr;              // /D16.2/ character is detected on data prior to FIFO.
  reg    [2:0]  d16p2_wr_pipe;         // k28p5_wr registered.
  reg    [2:0]  k28p5_wr_pipe;         // d16p2_wr registered.
  reg           remove_idle;           // An Idle is removed before writing it into the FIFO.
  reg           remove_idle_reg;       // remove_idle registered.


  // Read domain logic (RXUSRCLK2) 

  wire   [15:0] rd_data;               // Date read out of the block RAM.
  reg    [15:0] rd_data_reg;           // rd_data is registered for logic pipeline.
  reg    [6:0]  next_rd_addr;          // Next FIFO read address (to reduce latency in gray code logic).
  reg    [6:0]  rd_addr;               // FIFO read address.
  wire          rd_enable;             // read enable for FIFO.
  reg    [6:0]  rd_addr_gray;          // rd_addr is converted to a gray code. 

  reg    [6:0]  rd_wr_addr_gray;       // write address pointer (gray coded) reclocked onto the read clock domain).
  wire   [6:0]  rd_wr_addr;            // rd_wr_addr_gray converted back to binary (on the read clock domain). 
  reg    [6:0]  rd_occupancy;          // The occupancy of the FIFO in read clock domain.
  wire          emptying;              // FIFO is emptying: Idles should be inserted.
  wire          overflow;              // FIFO has filled up to overflow.
  wire          underflow;             // FIFO has emptied to underflow

  // synthesis attribute ASYNC_REG of rd_wr_addr_gray  is "TRUE";

  reg           even;                  // To control reading of data from upper or lower half of FIFO word.
  wire          k28p5_rd;              // /K28.5/ character is detected on data post FIFO.
  wire          d16p2_rd;              // /D16.2/ character is detected on data post FIFO.
  reg           insert_idle;           // An Idle is inserted whilst reading it out of the FIFO.
  reg           insert_idle_reg;       // insert_idle is registered.
  reg           rd_enable_reg;         // Read enable is registered.
  reg   [2:0]   rxclkcorcnt;           // derive RXCLKCORCNT to mimic RocketIO behaviour.    

  //--------------------------------------------------------------------
  // FIFO write logic (Idles are removed as necessary).
  //--------------------------------------------------------------------

  // Reclock the RocketIO data and format for storing in the BRAM.
  always @(posedge rxrecclk)
  begin : gen_wr_data
    if (reset === 1'b1)
    begin
      wr_data            <= 16'b0;
      wr_data_reg        <= 16'b0;
      wr_data_reg_reg    <= 16'b0;
    end
    else
    begin

      wr_data_reg_reg    <= wr_data_reg;

      wr_data_reg[15:14] <= wr_data[15:14];
      wr_data_reg[13]    <= remove_idle;
      wr_data_reg[12:0]  <= wr_data[12:0]; 

      // format the lower word
      wr_data[15:13]     <= 3'b0;   // unused
      wr_data[12]        <= rxchariscomma_rec;
      wr_data[11]        <= rxcharisk_rec;
      wr_data[10]        <= rxdisperr_rec;
      wr_data[9]         <= rxnotintable_rec;
      wr_data[8]         <= rxrundisp_rec;
      wr_data[7:0]       <= rxdata_rec[7:0];

    end
  end // gen_wr_data



  // Detect /K28.5/ character in upper half of the word from RocketIO
  assign k28p5_wr = (wr_data[7:0] == 8'b10111100 && 
                     wr_data[11] == 1'b1) ? 1'b1 : 1'b0;   

  // Detect /D16.2/ character in upper half of the word from RocketIO
  assign d16p2_wr = (wr_data[7:0] == 8'b01010000 && 
                     wr_data[11] == 1'b0) ? 1'b1 : 1'b0;
                     
  always @(posedge rxrecclk)
  begin : gen_k_d_pipe
    if (reset === 1'b1)
    begin
      k28p5_wr_pipe      <= 3'b000;
      d16p2_wr_pipe      <= 3'b000;
    end
    else
    begin
      k28p5_wr_pipe[2:1] <= k28p5_wr_pipe[1:0];
      d16p2_wr_pipe[2:1] <= d16p2_wr_pipe[1:0];
      k28p5_wr_pipe[0]   <= k28p5_wr;
      d16p2_wr_pipe[0]   <= d16p2_wr;
    end
  end // gen_k_d_pipe    


  // Create the FIFO write enable: Idles are removed by deasserting the
  // FIFO write_enable whilst an Idle is present on the data.
  always @(posedge rxrecclk)
  begin : gen_wr_enable
    if (reset === 1'b1)
    begin
      remove_idle       <= 1'b0;
      remove_idle_reg   <= 1'b0;
    end
    else
    begin

      remove_idle_reg <= remove_idle;
       
      // Idle removal (always leave the first /I2/ Idle, then every
      // alternate Idle can be removed.
      if (d16p2_wr == 1'b1 && k28p5_wr_pipe[0] == 1'b1 &&
          d16p2_wr_pipe[1] == 1'b1 && k28p5_wr_pipe[2] == 1'b1 &&
          filling == 1'b1 && remove_idle == 1'b0)

      begin
        remove_idle <= 1'b1;
      end

      // Else write new word on every clock edge.
      else
      begin
        remove_idle <= 1'b0;
	  end
    end
  end // gen_wr_enable

  assign wr_enable   = ~(remove_idle | remove_idle_reg);
 
  // Create the FIFO write address pointer.
  always @(posedge rxrecclk)
  begin : gen_wr_addr
    if (reset === 1'b1)
    begin
      next_wr_addr <= 7'b1000001;
      wr_addr      <= 7'b1000000;
    end
    else if (wr_enable == 1'b1)
    begin
      next_wr_addr <= next_wr_addr + 7'b1;           
      wr_addr      <= next_wr_addr;
	end
  end // gen_wr_addr
		 


  // Convert write address pointer into a gray code
  always @(posedge rxrecclk)
  begin : wr_addrgray_bits
    if (reset === 1'b1)
      wr_addr_gray <= 7'b1100001;
    else
    begin
      wr_addr_gray[6] <= next_wr_addr[6];
      wr_addr_gray[5] <= next_wr_addr[6] ^ next_wr_addr[5];
      wr_addr_gray[4] <= next_wr_addr[5] ^ next_wr_addr[4];
      wr_addr_gray[3] <= next_wr_addr[4] ^ next_wr_addr[3];
      wr_addr_gray[2] <= next_wr_addr[3] ^ next_wr_addr[2];
      wr_addr_gray[1] <= next_wr_addr[2] ^ next_wr_addr[1];
      wr_addr_gray[0] <= next_wr_addr[1] ^ next_wr_addr[0];
    end
  end // wr_addrgray_bits;



  //--------------------------------------------------------------------
  // Instantiate a dual port Block RAM    
  //--------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -