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

📄 rx_elastic_buffer.v

📁 Xilinx Virtex5 SGMII高速串行通信例程。
💻 V
📖 第 1 页 / 共 2 页
字号:
  RAMB16_S18_S18 dual_port_block_ram0
  (
    .ADDRA       ({3'b0, wr_addr}),
    .DIA         (wr_data_reg_reg[15:0]),
    .DIPA        (2'b00),
    .DOA         (),
    .DOPA        (),
    .WEA         (wr_enable),
    .ENA         (1'b1),
    .SSRA        (1'b0), 
    .CLKA        (rxrecclk),
    
    .ADDRB       ({3'b0, rd_addr}),
    .DIB         (16'b0),
    .DIPB        (2'b00),
    .DOB         (rd_data[15:0]),  
    .DOPB        (), 
    .WEB         (1'b0),
    .ENB         (1'b1),
    .SSRB        (rxreset),
    .CLKB        (rxusrclk2)       
  );


  //--------------------------------------------------------------------
  // FIFO read logic (Idles are insterted as necessary).
  //--------------------------------------------------------------------

  // Register the BRAM data.
  always @(posedge rxusrclk2)
  begin : reg_rd_data
    if (rxreset == 1'b1)
      rd_data_reg   <= 16'b0;

    else if (rd_enable_reg == 1'b1)
      rd_data_reg   <= rd_data;

  end // reg_rd_data

  //--------------------------------------------------------------------
  // FIFO read logic (Idles are insterted as necessary).
  //--------------------------------------------------------------------



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

  // Detect /D16.2/ character in lower half of the word read from FIFO
  assign d16p2_rd = (rd_data[7:0] == 8'b01010000 && 
                     rd_data[11] == 1'b0) ? 1'b1 : 1'b0;
                     

  // Create the FIFO read enable: Idles are inserted by pausing the
  // FIFO read_enable whilst an Idle is present on the data.
  always @(posedge rxusrclk2)
  begin : gen_rd_enable
    if (rxreset == 1'b1)
    begin
      even            <= 1'b1;
      insert_idle     <= 1'b0;
      insert_idle_reg <= 1'b0;
      rd_enable_reg   <= 1'b1;
    end
    else
    begin
  
      insert_idle_reg <= insert_idle;
      rd_enable_reg   <= rd_enable;
  
      // Repeat as many /I2/ code groups as required if nearly
      // empty by pausing rd_enable.
      if ((k28p5_rd == 1'b1 && d16p2_rd == 1'b1) && emptying == 1'b1 && insert_idle == 1'b0)
      begin
        insert_idle   <= 1'b1;
        even          <= 1'b0;
      end
  
      // Else read out a new word on every alternative clock edge.
      else 
      begin
         insert_idle  <= 1'b0;
         even         <= ~(even);
  	  end
  	end
  end // gen_rd_enable
  
  assign rd_enable = ~(insert_idle | insert_idle_reg);

           
  // Create the FIFO read address pointer.
  always @(posedge rxusrclk2)
  begin : gen_rd_addr
    if (rxreset == 1'b1)
    begin
      next_rd_addr <= 7'b0000001;
      rd_addr      <= 7'b0000000;
    end
    else if (rd_enable == 1'b1)
    begin
      next_rd_addr <= next_rd_addr + 7'b1;           
      rd_addr      <= next_rd_addr;
    end			  
  end // gen_rd_addr
		 


  // Convert read address pointer into a gray code
  always @(posedge rxusrclk2)
  begin : rd_addrgray_bits
    if (rxreset == 1'b1)
      rd_addr_gray <= 7'b0;
    else if (rd_enable == 1'b1)
    begin
      rd_addr_gray[6] <= next_rd_addr[6];
      rd_addr_gray[5] <= next_rd_addr[6] ^ next_rd_addr[5];
      rd_addr_gray[4] <= next_rd_addr[5] ^ next_rd_addr[4];
      rd_addr_gray[3] <= next_rd_addr[4] ^ next_rd_addr[3];
      rd_addr_gray[2] <= next_rd_addr[3] ^ next_rd_addr[2];
      rd_addr_gray[1] <= next_rd_addr[2] ^ next_rd_addr[1];
      rd_addr_gray[0] <= next_rd_addr[1] ^ next_rd_addr[0];
    end
  end // rd_addrgray_bits

  // Create the output data signals.
  always @(posedge rxusrclk2)
  begin : gen_mux
    if (rxreset == 1'b1)
    begin
      rxchariscomma_usr   <= 1'b0;
      rxcharisk_usr       <= 1'b0;
      rxdisperr_usr       <= 1'b0;
      rxnotintable_usr    <= 1'b0;
      rxrundisp_usr       <= 1'b0;
      rxdata_usr          <= 8'b0;
    end
    else
    begin
      if (rd_enable_reg == 1'b0 && even == 1'b0)
      begin			  
        rxchariscomma_usr <= 1'b0;
        rxcharisk_usr     <= 1'b0;
        rxdisperr_usr     <= 1'b0;
        rxnotintable_usr  <= 1'b0;
        rxrundisp_usr     <= rd_data_reg[8];
        rxdata_usr        <= 8'b01010000;
      end
      else if (rd_enable_reg == 1'b0 && even == 1'b1)
      begin			  
        rxchariscomma_usr <= 1'b1;
        rxcharisk_usr     <= 1'b1;
        rxdisperr_usr     <= 1'b0;
        rxnotintable_usr  <= 1'b0;
        rxrundisp_usr     <= rd_data[8];
        rxdata_usr        <= 8'b10111100;
      end			  
      else			  
      begin			  
        rxchariscomma_usr <= rd_data_reg[12];
        rxcharisk_usr     <= rd_data_reg[11];
        rxdisperr_usr     <= rd_data_reg[10];
        rxnotintable_usr  <= rd_data_reg[9];
        rxrundisp_usr     <= rd_data_reg[8];
        rxdata_usr        <= rd_data_reg[7:0];
      end			  
    end			  
  end // gen_mux

  // Create RocketIO style clock correction status when inserting /
  // removing Idles.
  always @(posedge rxusrclk2)
  begin : gen_rxclkcorcnt
    if (rxreset == 1'b1)
      rxclkcorcnt   <= 3'b0;
    else
    begin
      if (rd_data_reg[13] == 1'b1 && rxclkcorcnt[0] == 1'b0)
         rxclkcorcnt   <= 3'b001;
      else if (insert_idle_reg == 1'b1 && rxclkcorcnt != 3'b111)
         rxclkcorcnt   <= 3'b111;
      else
         rxclkcorcnt   <= 3'b000;
    end			  
  end // gen_rxclkcorcnt

  assign rxclkcorcnt_usr = rxclkcorcnt;



  //--------------------------------------------------------------------
  // Create emptying/full thresholds in read clock domain.
  //--------------------------------------------------------------------



  // Reclock the write address pointer (gray code) onto the read domain.
  // By reclocking the gray code, the worst case senario is that 
  // the reclocked value is only in error by -1, since only 1 bit at a  
  // time changes between gray code increments. 
  always @(posedge rxusrclk2)
  begin : reclock_wr_addrgray
    if (rxreset === 1'b1)
      rd_wr_addr_gray <= 7'b1100001;
    else
      rd_wr_addr_gray <= wr_addr_gray;
  end // reclock_wr_addrgray

   

  // Convert the resync'd Write Address Pointer grey code back to binary
  assign rd_wr_addr[6] = rd_wr_addr_gray[6];

  assign rd_wr_addr[5] = rd_wr_addr_gray[6] ^ rd_wr_addr_gray[5];

  assign rd_wr_addr[4] = rd_wr_addr_gray[6] ^ rd_wr_addr_gray[5] 
                         ^ rd_wr_addr_gray[4];

  assign rd_wr_addr[3] = rd_wr_addr_gray[6] ^ rd_wr_addr_gray[5] 
                         ^ rd_wr_addr_gray[4] ^ rd_wr_addr_gray[3];

  assign rd_wr_addr[2] = rd_wr_addr_gray[6] ^ rd_wr_addr_gray[5] 
                         ^ rd_wr_addr_gray[4] ^ rd_wr_addr_gray[3] 
                         ^ rd_wr_addr_gray[2];

  assign rd_wr_addr[1] = rd_wr_addr_gray[6] ^ rd_wr_addr_gray[5] 
                         ^ rd_wr_addr_gray[4] ^ rd_wr_addr_gray[3] 
                         ^ rd_wr_addr_gray[2] ^ rd_wr_addr_gray[1];

  assign rd_wr_addr[0] = rd_wr_addr_gray[6] ^ rd_wr_addr_gray[5] 
                         ^ rd_wr_addr_gray[4] ^ rd_wr_addr_gray[3] 
                         ^ rd_wr_addr_gray[2] ^ rd_wr_addr_gray[1] 
                         ^ rd_wr_addr_gray[0];



  // Determine the occupancy of the FIFO as observed in the read domain.
  always @(posedge rxusrclk2)
  begin : gen_rd_occupancy
    if (rxreset === 1'b1)
      rd_occupancy <= 7'b1000000;
    else
      rd_occupancy <= rd_wr_addr - rd_addr;
  end // gen_rd_occupancy



  // Set emptying flag if FIFO occupancy is less than LOWER_THRESHOLD. 
  assign emptying = (rd_occupancy < lower_threshold) ? 1'b1 : 1'b0;   



  // Set underflow if FIFO occupancy is less than UNDERFLOW_THRESHOLD. 
  assign underflow = (rd_occupancy < underflow_threshold) ? 1'b1 : 1'b0;   



  // Set overflow if FIFO occupancy is less than OVERFLOW_THRESHOLD. 
  assign overflow = (rd_occupancy > overflow_threshold) ? 1'b1 : 1'b0;   



  // If either an underflow or overflow, assert the buffer error signal.
  // Like the RocketIO, this will persist until a reset is issued.
  always @(posedge rxusrclk2)
  begin : gen_buffer_error
    if (rxreset === 1'b1)
      rxbuferr <= 1'b0;
    else if (overflow == 1'b1 || underflow == 1'b1)
      rxbuferr <= 1'b1;
  end // gen_buffer_error



  //--------------------------------------------------------------------
  // Create emptying/full thresholds in write clock domain.
  //--------------------------------------------------------------------



  // Reclock the read address pointer (gray code) onto the write domain.
  // By reclocking the gray code, the worst case senario is that 
  // the reclocked value is only in error by -1, since only 1 bit at a  
  // time changes between gray code increments. 
  always @(posedge rxrecclk)
  begin : reclock_rd_addrgray
    if (reset === 1'b1)
      wr_rd_addr_gray <= 7'b0;
    else
      wr_rd_addr_gray <= rd_addr_gray;
  end // reclock_rd_addrgray

   

  // Convert the resync'd Read Address Pointer grey code back to binary

  assign wr_rd_addr[6] = wr_rd_addr_gray[6];

  assign wr_rd_addr[5] = wr_rd_addr_gray[6] ^ wr_rd_addr_gray[5];

  assign wr_rd_addr[4] = wr_rd_addr_gray[6] ^ wr_rd_addr_gray[5] 
                         ^ wr_rd_addr_gray[4];

  assign wr_rd_addr[3] = wr_rd_addr_gray[6] ^ wr_rd_addr_gray[5] 
                         ^ wr_rd_addr_gray[4] ^ wr_rd_addr_gray[3];

  assign wr_rd_addr[2] = wr_rd_addr_gray[6] ^ wr_rd_addr_gray[5] 
                         ^ wr_rd_addr_gray[4] ^ wr_rd_addr_gray[3] 
                         ^ wr_rd_addr_gray[2];

  assign wr_rd_addr[1] = wr_rd_addr_gray[6] ^ wr_rd_addr_gray[5] 
                         ^ wr_rd_addr_gray[4] ^ wr_rd_addr_gray[3] 
                         ^ wr_rd_addr_gray[2] ^ wr_rd_addr_gray[1];

  assign wr_rd_addr[0] = wr_rd_addr_gray[6] ^ wr_rd_addr_gray[5] 
                         ^ wr_rd_addr_gray[4] ^ wr_rd_addr_gray[3] 
                         ^ wr_rd_addr_gray[2] ^ wr_rd_addr_gray[1] 
                         ^ wr_rd_addr_gray[0];
															   


  // Determine the occupancy of the FIFO as observed in the write domain.
  always @(posedge rxrecclk)
  begin : gen_wr_occupancy
    if (reset === 1'b1)
      wr_occupancy <= 7'b1000000;
    else
      wr_occupancy <= wr_addr[6:0] - wr_rd_addr[6:0];
  end // gen_wr_occupancy



  // Set filling flag if FIFO occupancy is greated than UPPER_THRESHOLD. 
  assign filling = (wr_occupancy > upper_threshold) ? 1'b1 : 1'b0;   



endmodule

⌨️ 快捷键说明

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