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

Subversion Repositories rxaui_interface_and_xaui_to_rxaui_interface_adapter

[/] [rxaui_interface_and_xaui_to_rxaui_interface_adapter/] [RxPath/] [sip_rxaui_aa_detection.v] - Rev 2

Compare with Previous | Blame | View Log

//-----------------------------------------------------------------------------
// Title         : {/A/,/A/} detection
// Project       : SIP
//-----------------------------------------------------------------------------
// File          : sip_rxaui_aa_detection.v
// Author        : Lior Valency
// Created       : 11/02/2008 
// Last modified : 11/02/2008 
//-----------------------------------------------------------------------------
// Description : The purpose of this block is to detect the {/A/,/A/} pattern
// and according to this pattern send the first /A/ to lane0 and the second /A/
// to lane1.
// It implement <ReceiveFlow> algorithm describe in chapter <2.2.2> in the SPEC.
//-----------------------------------------------------------------------------
// Copyright (c) 2007  Marvell International Ltd.
//
// THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL SEMICONDUCTOR, INC.
// NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT
// OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE
// DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.
// THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESS,
// IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.
//
//------------------------------------------------------------------------------
// Modification history :
// 12/12/2007  : created
//-----------------------------------------------------------------------------
`timescale 10ps / 10ps
 
module sip_rxaui_aa_detection(/*AUTOARG*/
   // Outputs
   lane0_rx, lane1_rx, rxaui_status,
   // Inputs
   clk, reset_, serdes_mode, rx_aligned_data, serdes_rx_data
   );
 
`include "sip_rxaui_params.inc"
 
   /*AUTO_CONSTANT(MSB_LANE0 or LSB_LANE0)*/
 
   //////////////////////
   // Local parameters //
   //////////////////////
   parameter DIS_POS_A  = 10'b001100_0011;  // 0xC3
   parameter DIS_NEG_A  = 10'b110011_1100;  // 0x33C
   parameter AA_ERR_CNT_W = 2;
   parameter AA_ERR_CNT_INIT_VALUE = 2'd2;
   parameter DATA_SHIFT_W = 2;
 
   ///////////////
   // INTERFACE //
   ///////////////
 
   // General
   input                       clk;
   input 	               reset_;
 
   // Configuration
   input 		       serdes_mode;
 
   // Comma detect I/F
   input [SERDES_DATA_W-1:0]   rx_aligned_data;
 
   // Fifo I/F
   output [STD_DATA_W-1:0]     lane0_rx;
   output [STD_DATA_W-1:0]     lane1_rx;
 
   // Status
   output [STATUS_REG_W-1:0]   rxaui_status;
 
   // Serdes Interface
   input [SERDES_DATA_W-1:0]   serdes_rx_data;
 
   ///////////////////////
   // Registers & Wires //
   ///////////////////////
 
 
   ////////////////////////////////
   // Internal Registers & Wires //
   ////////////////////////////////
   reg [SERDES_DATA_W-1:0]     rx_data_shift_reg[DATA_SHIFT_W-1:0];
   reg [SERDES_DATA_W-1:0]     rx_data_shift_reg_d[DATA_SHIFT_W-1:0];
   wire [2:0] 		       detect_aa;
   wire 		       any_aa_detect;
   reg 			       pre_aa_state;
   wire 		       aa_state_d;
   reg 			       aa_state;
   wire [AA_ERR_CNT_W-1:0]     aa_staet_err_counter_d;
   reg [AA_ERR_CNT_W-1:0]      aa_staet_err_counter;
   wire 		       aa_err_counter_eq_2;
   wire [STATUS_REG_W-1:0]     rxaui_status_d; 
   reg [STATUS_REG_W-1:0]      rxaui_status; 
 
   integer 		       i;
 
   ///////////
   // Logic //
   ///////////
 
   // Search for {/A/,/A/} pattern in one of the data.
   // Option 1: (The pattern arrive in 1cc)
   // rx_data_align     : | AA | DD |
   // rx_data_align_del1: | XX | AA |
   // detect_aa:          | 0  | 110|    
   // Option 2: (The pattern arrive in 2cc)
   // rx_data_align     : | AX | DA |
   // rx_data_align_del1: | XX | AX |  
   // detect_aa:          | 0  | 101|    
   assign detect_aa[2] = (rx_data_shift_reg[0][SERDES_DATA_W-1:SERDES_DATA_W/2] == DIS_POS_A) | 
			 (rx_data_shift_reg[0][SERDES_DATA_W-1:SERDES_DATA_W/2] == DIS_NEG_A);
   assign detect_aa[1] = (rx_data_shift_reg[0][SERDES_DATA_W/2-1:0] == DIS_POS_A) | 
			 (rx_data_shift_reg[0][SERDES_DATA_W/2-1:0] == DIS_NEG_A);
   assign detect_aa[0] = (rx_aligned_data[SERDES_DATA_W/2-1:0] == DIS_POS_A) | 
			 (rx_aligned_data[SERDES_DATA_W/2-1:0] == DIS_NEG_A);
 
   // Check if any {/A/,/A/} was detected
   assign any_aa_detect = (detect_aa[0] & detect_aa[2]) | (detect_aa[2] & detect_aa[1]);
 
   // Define the state of the transmission, LSB or MSB is to lane0.
   always @(/*AUTOSENSE*/aa_state or detect_aa)
     begin
       pre_aa_state = aa_state;
       case(detect_aa[2:0])
	   3'b110:
	     pre_aa_state = LSB_LANE0;
	   3'b101,3'b111:
	     pre_aa_state = MSB_LANE0;
	   default:
	     pre_aa_state = aa_state;
       endcase // case(detect_aa)
     end // always @ (...
 
   // Check if the state of the {/A/,/A/) is change
   assign aa_state_chg = (pre_aa_state != aa_state);
 
   // Error Counter:
   // Count the number of error from the current state  
   assign aa_staet_err_counter_d = (any_aa_detect == SET) ?
				   (((aa_state_chg == UNSET) || 
				     (aa_err_counter_eq_2 == SET)) ? {AA_ERR_CNT_W{1'b0}} :
				    (aa_staet_err_counter + 2'd1)) : aa_staet_err_counter;
 
   // new aa state is latch only after 3 error are detect from the current state
   assign aa_err_counter_eq_2 = (aa_staet_err_counter == 2'd2);
   assign aa_state_d = ((aa_err_counter_eq_2 == SET) && 
			(aa_state_chg == SET)) ? pre_aa_state : aa_state;
 
   // Split the data to lane0 and lane1
   // In case working in serdes mode (Data from Serdes = 10bits, Data from
   // block 20bits), we need to use the fifo but not comma detect or AA
   // detection
   assign lane0_rx = (serdes_mode == SET) ? serdes_rx_data[SERDES_DATA_W/2-1:0] :
		     (aa_state == LSB_LANE0) ? rx_data_shift_reg[1][SERDES_DATA_W/2-1:0] :
		     rx_data_shift_reg[1][SERDES_DATA_W-1:SERDES_DATA_W/2];
   assign lane1_rx = (serdes_mode == SET) ? serdes_rx_data[SERDES_DATA_W/2-1:0] :
		     (aa_state == MSB_LANE0) ? rx_data_shift_reg[1][SERDES_DATA_W/2-1:0] :
		     rx_data_shift_reg[1][SERDES_DATA_W-1:SERDES_DATA_W/2];
 
   // Shift register implementation
   always @(rx_data_shift_reg[0] or rx_data_shift_reg[1]/*AUTOSENSE*/
	    or rx_aligned_data) begin
      for(i=0; i < DATA_SHIFT_W; i=i+1)
           if (i==1'b0) begin
              rx_data_shift_reg_d[i] = rx_aligned_data;
           end
           else begin
              rx_data_shift_reg_d[i] = rx_data_shift_reg[i-1];
           end
   end
 
   /////////////////////
   // Status Register //
   /////////////////////
 
   assign rxaui_status_d = {
			    detect_aa[2:0],                        // 8:6
			    aa_state_chg,                          // 5
			    pre_aa_state,                          // 4
			    any_aa_detect,                         // 3
			    aa_state,                              // 2
			    aa_staet_err_counter[AA_ERR_CNT_W-1:0] // 1:0  
			    };
 
 
   ////////////////
   // FF SECTION //
   ////////////////
 
   always @(posedge clk or negedge reset_)
     begin
       if(~reset_)
	 begin
	   for(i=0; i < DATA_SHIFT_W; i=i+1)
	     begin
	       rx_data_shift_reg[i] <= #1 {SERDES_DATA_W{1'b0}};
	     end
	   aa_state              <= #1 LSB_LANE0;
	   rxaui_status          <= #1 {STATUS_REG_W{1'b0}};
	   // The initial value of this is 3 after reset we are not
	   // sync with the correct lane0/lane1 and we want to sync
	   // after the first detection of {/A/,/A/}
	   aa_staet_err_counter  <= #1 AA_ERR_CNT_INIT_VALUE;
	 end
       else
	 begin
	   for(i=0; i < DATA_SHIFT_W; i=i+1)
	     begin
	       rx_data_shift_reg[i] <= #1 rx_data_shift_reg_d[i];
	     end
	   aa_state              <= #1 aa_state_d;
	   aa_staet_err_counter  <= #1 aa_staet_err_counter_d;
	   rxaui_status          <= #1 rxaui_status_d;
	 end
     end // always @ (posedge clk or negedge reset_)
 
endmodule // sip_rxaui_aa_detection
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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