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)