eth_phy_10g_rx_frame_sync_code

// Language: Verilog 2001

  

`resetall

`timescale 1ns / 1ps

`default_nettype none

  

/*

 * 10G Ethernet PHY frame sync

 */

//! Modulo que verifica la sincronización del header

module eth_phy_10g_rx_frame_sync #                  // Se ajustan los bits (slip) de la señal para corregir errores de sincronizacion o desalineaciones

(

    parameter HDR_WIDTH = 2,                        //! Ancho de encabezado

    parameter BITSLIP_HIGH_CYCLES = 1,              //! 1 ciclo de reloj para realizar un desplazamiento cuando se detecta una desalineacion alta

    parameter BITSLIP_LOW_CYCLES = 8                //! 8 ciclos de reloj para realizar un desplazamiento cuando se detecta una desalineación baja

)

(

    input  wire                  clk,               //! Señal de clock

    input  wire                  rst,               //! Señal de reinicio

  

    /*

     * SERDES interface

     */

    input  wire [HDR_WIDTH-1:0]  serdes_rx_hdr,     //! Señal de serdes sync header

    output wire                  serdes_rx_bitslip, //! Señal de serdes bitslip

  

    /*

     * Status

     */

    output wire                  rx_block_lock      //! Señal de salida que indica si se detectaron 64 sync header validos

);

  

parameter BITSLIP_MAX_CYCLES = BITSLIP_HIGH_CYCLES > BITSLIP_LOW_CYCLES ? BITSLIP_HIGH_CYCLES : BITSLIP_LOW_CYCLES; //! Determina el límite máximo de ciclos para el bitslip

parameter BITSLIP_COUNT_WIDTH = $clog2(BITSLIP_MAX_CYCLES);                                                         //! Determina la cantidad de bits necesarios para representar el número de ciclos máximos de bitslip

  

// bus width assertions

initial begin

    if (HDR_WIDTH != 2) begin

        $error("Error: HDR_WIDTH must be 2");

        $finish;

    end

end

  

localparam [1:0]

    SYNC_DATA = 2'b10,      //! Header de sincronizacion para los bloques de datos

    SYNC_CTRL = 2'b01;      //! Header de sincronizacion para los bloques de control

  

reg [5:0] sh_count_reg = 6'd0, sh_count_next;                               //! Registro que almacena la cuenta de sync headers totales recibidos. Máximo 64

reg [3:0] sh_invalid_count_reg = 4'd0, sh_invalid_count_next;               //! Registro que almacena la cuenta de sync headers inválidos recibidos. Máximo 16

reg [BITSLIP_COUNT_WIDTH-1:0] bitslip_count_reg = 0, bitslip_count_next;    //! Registro que almacena la cuenta para controlar el bitslip en la recepción de datos. Máximo 8

  

reg serdes_rx_bitslip_reg = 1'b0, serdes_rx_bitslip_next;                   //! Registro para la señal de serdes bitslip

  

reg rx_block_lock_reg = 1'b0, rx_block_lock_next;                           //! Registro para el bloque de alineacion

  

assign serdes_rx_bitslip = serdes_rx_bitslip_reg;                  

assign rx_block_lock = rx_block_lock_reg;

  
  

//! Verifica si se alineo correctamente el bloque, esto es con 64 headers validos y 0 invalidos. Una vez conseguida, la flag de alineacion se mantiene siempre y cuando haya menos de 15 encabezados invalidos en porciones de 64 en 64 headers. En caso de que llegue un encabezado invalido antes de tener la flag activa, se activa el bitslip y espera 8 encabezados validos antes de volver a contar los encabezados

always @* begin

    sh_count_next = sh_count_reg;                                           // Los registros next se inicializan con el valor actual de su correspondiente registro

    sh_invalid_count_next = sh_invalid_count_reg;

    bitslip_count_next = bitslip_count_reg;

  

    serdes_rx_bitslip_next = serdes_rx_bitslip_reg;

  

    rx_block_lock_next = rx_block_lock_reg;

  

    if (bitslip_count_reg) begin                                                        // si bitslip_count_reg>0 (ya inició la sincronizacion)

        bitslip_count_next = bitslip_count_reg-1;                                       // se decrementa en 1 la cuenta de bitslip

    end else if (serdes_rx_bitslip_reg) begin                                           // si bitslip_count_reg=0 (ya terminó la sincronización o aun no comienza) y serdes_rx_bitslip_reg>0 (si se estaba aplicando el bitslip)

        serdes_rx_bitslip_next = 1'b0;                                                  // se pone en cero para indicar que terminó la corrección de alineación de bits

        bitslip_count_next = BITSLIP_LOW_CYCLES > 0 ? BITSLIP_LOW_CYCLES-1 : 0;         // bitslip_count_next toma el valor de BITSLIP_LOW_CYCLES-1 (si es distinto a cero) para indicar cuantos ciclos de bitslip bajo se pueden realizar antes de que sea necesario realizar una correccion de desalineacion

    end else if (serdes_rx_hdr == SYNC_CTRL || serdes_rx_hdr == SYNC_DATA) begin        // si bitslip_count_reg=0 (ya terminó la sincronización o aun no comienza) y serdes_rx_bitslip_reg=0 (no se estaba aplicando el bitslip), se verifican que los encabezados sean validos

        //! Valid header

        sh_count_next = sh_count_reg + 1;                                               // se incrementa en uno el contador de bloques

        if (&sh_count_reg) begin                                                        // si todos los bits de sh_count_reg son 1 se produce un overflow

            //! Valid count overflow, reset

            sh_count_next = 0;                                                          // se reinicia el contador de bloques

            sh_invalid_count_next = 0;                                                  // se reinicia el contador de encabezados invalidos

            if (!sh_invalid_count_reg) begin                                            // si no hay encabezados invalidos

                rx_block_lock_next = 1'b1;                                              // se pone en 1 el indicador que se ha detectado un bloque valido y que se ha mantenido la sincronizacion del bloque

            end

        end

    end else begin                                                                      // si el encabezado no es valido

        //! Invalid header

        sh_count_next = sh_count_reg + 1;                                               // incrementa el contador de bloques

        sh_invalid_count_next = sh_invalid_count_reg + 1;                               // incrementa el contador de encabezados invalidos

        if (!rx_block_lock_reg || &sh_invalid_count_reg) begin                          // si no se tiene un bloque bloqueado o hay overflow del contador de encabezados invalidos

            //! Invalid count overflow, lost block lock

            sh_count_next = 0;                                                          // se reinicia el contador de bloques                                                                                                                                                                                                                                                                                                                                                                                                                  

            sh_invalid_count_next = 0;                                                  // se reinicia el contador de encabezados invalidos

            rx_block_lock_next = 1'b0;                                                  // desactiva el bloqueo e indica que se ha perdido la sincronizacion

  

            //! Slip one bit

            serdes_rx_bitslip_next = 1'b1;                                              // activa el desplazamiento de bits para intentar recuperar la sincronizacion

            bitslip_count_next = BITSLIP_HIGH_CYCLES > 0 ? BITSLIP_HIGH_CYCLES-1 : 0;   // bitslip_count_next toma el valor de BITSLIP_HIGH_CYCLES-1 (si es distinto a cero) para indicar cuantos ciclos de bitslip alto se pueden realizar antes de que sea necesario realizar una correccion de desalineacion

        end else if (&sh_count_reg) begin                                               // si hay overflow del contador de bloques

            //! Valid count overflow, reset

            sh_count_next = 0;                                                          // se reinician los contadores

            sh_invalid_count_next = 0;                  

        end

    end

end

  

always @(posedge clk) begin                                                             //! En cada flanco positivo de clock se actualizan los registros y se verifica el estado de la señal de reinicio

    sh_count_reg <= sh_count_next;

    sh_invalid_count_reg <= sh_invalid_count_next;

    bitslip_count_reg <= bitslip_count_next;

    serdes_rx_bitslip_reg <= serdes_rx_bitslip_next;

    rx_block_lock_reg <= rx_block_lock_next;

  

    if (rst) begin

        sh_count_reg <= 6'd0;

        sh_invalid_count_reg <= 4'd0;

        bitslip_count_reg <= 0;

        serdes_rx_bitslip_reg <= 1'b0;

        rx_block_lock_reg <= 1'b0;

    end

end

  

endmodule

  

`resetall