354 - Is there a Verilog code example available to illustrate how to use Comma boundaries For SERDES/PCS based devices to correct for 16/20 byte shifting in FPGA Interface RX DATA?

354 - Is there a Verilog code example available to illustrate how to use Comma boundaries For SERDES/PCS based devices to correct for 16/20 byte shifting in FPGA Interface RX DATA?

For more background on 16/20 bit mode byte shifting, please refer to FAQ 355.

The principles of byte shifting in 16/20-bit mode apply to the LatticeSC , LatticeECP3 and LatticeECP2M PCS blocks in 16/20 bit data mode.
The following Verilog general piece of code illustrates how to correct for FPGA interface RX data byte shifting on an LatticeECP2M PCS in 16-bit generic 8b10 mode.
In this piece of code, a Comma (K28.5) character is expected to show in the upper byte of a 16-bit word.
The logic corrects for byte shift if the Comma occurs in the lower byte:

wire [15:0] ff_rxdata_ch0 ;       //CURRENT PCS RX DATA

wire [1:0]  ff_rx_k_cntrl_ch0 ;   //CURRENT PCS RX CONTROL

reg [15:0] ff_rxdata_ch0_reg ;    //PREVIOUS PCS RX DATA
reg [1:0]  ff_rx_k_cntrl_ch0_reg ;//PREVIOUS PCS RX CONTROL


reg [15:0] rxdata ;               //FINAL RX DATA
reg [1:0]  rxc ;                  //FINAL RX CONTROL

reg shift;                        //SELECTS WHETHER TO SHIFT BYTES OR NOT

always @ (posedge ff_rxhalfclk_ch0 or negedge reset_n) begin
   if (!reset_n)
      begin
         ff_rxdata_ch0_reg     <= 16'h0000;
         ff_rx_k_cntrl_ch0_reg <= 2'b00;
         rxdata                <= 16'h0000;
         rxc                   <= 2'b00;
         shift                 <= 0;
      end
   else
      begin
         //register data/control
         ff_rxdata_ch0_reg     <= ff_rxdata_ch0;
         ff_rx_k_cntrl_ch0_reg <= ff_rx_k_cntrl_ch0;

         //EXPECTING K28.5 on UPPER BYTE
         //DO NOT SHIFT DATA IF K28.5 is in UPPER BYTE
         if ((ff_rxdata_ch0[15:8] == 8'hBC) && (ff_rx_k_cntrl_ch0[1] == 1'b1))
            shift <= 0;
         // SHIFT DATA IF K28.5 is in LOWER BYTE
         else if ((ff_rxdata_ch0[7:0] == 8'hBC) && (ff_rx_k_cntrl_ch0[0] == 1'b1))
            shift <= 1;
         else
            shift <= shift;

         if (shift == 0) //NO SHIFTING
            begin
               rxdata <= ff_rxdata_ch0;
               rxc    <= ff_rx_k_cntrl_ch0;
            end
         else //SHIFTING
            begin
               //Replace current LSB with previous cycle MSB
               rxdata[7:0]  <= ff_rxdata_ch0_reg[15:8];
               rxc[0]       <= ff_rx_k_cntrl_ch0_reg[1];
               //Replace current MSB with current cycle LSB
               rxdata[15:8] <= ff_rxdata_ch0[7:0];
               rxc[1]       <= ff_rx_k_cntrl_ch0[0];
            end // else: !if(shift == 0)
      end // else: !if(!reset_n)
end // always @ (posedge ff_rxhalfclk_ch0 or negedge reset_n)