Visible to Intel only — GUID: hly1614090807683
Ixiasoft
Visible to Intel only — GUID: hly1614090807683
Ixiasoft
4.4.3.2. PTP RX Client Flow
In this section, the acronyms PL and VL stand for Physical Lane and Virtual Lane respectively.
The following flows depict pseudo-code meant for the conceptual, illustrative purposes. For definitive software routines, refer to the design example.
- After power up or RX reset, wait until RX PCS is fully aligned.
You can monitor the status via one of the following:
- Output port:
o_rx_pcs_fully_alligned = 1'b1
- Polling via Avalon® memory-mapped interface register until it is asserted:
- For 10GE - 100GE no FEC variants and 25G FEC variants:
csr_read(phy_rxpcs_status.rx_aligned) = 1’b1
- For 50GE - 400GE FEC variants:
csr_read(rsfec_aggr_rx_stat.not_align) = 1’b0
- For 10GE - 100GE no FEC variants and 25G FEC variants:
- Output port:
- For FEC variants, configure RX FEC codeword position into the transceiver.
Attention: You must skip this step for non-FEC variants.
- Read RX FEC codeword position and FEC lane mapping for each PMA lane.
Determine mapping from a PMA lane to a FEC lane.
pl_fl_map = Speed / 25 / PL where Speed = {25, 50, 100, 200, 400} for (fl = 0; fl < FL; fl++) { rx_fec_cw_pos[fl] = csr_read(rsfec_cw_pos_rx[fl][14:0]) }
- Calculate pulse adjustments:
for (fl = 0; fl < FL; fl++) { rx_xcvr_if_pulse_adj[fl] = rx_fec_cw_pos[fl] }
- Write the pulse adjustments into the IP:
For multiple FEC lanes that interleave within single transceiver, select adjustment value from FEC lane with lowest index. You must ensure correct mapping between PMA lane and the corresponding CSR registers.
- For FGT transceiver:
for (pl = 0; pl < PL; pl++) { csr_write(ux_q_dl_ctrl_a_l<apl>.cfg_rx_lat_bit_for_async[17:0], rx_xcvr_if_pulse_adj[pl*pl_fl_map]) }
Note: There are 4 FGT quads with 4 apl lanes each. You must program registers of all active quad lanes. For information on accessing different FGT quads, refer to the User Guide. - For FHT transceiver:
for (pl = 0; pl < PL; pl++) { csr_write(rxdl_async_l<apl>.cfg_rx_lat_bit_for_async_lane<pl>[17:0], rx_xcvr_if_pulse_adj[pl*pl_fl_map]) }
Note: Both apl and pl are used in this step. For more information about the physical lanes, refer to Client Flow Glossary table in the PTP Client Flow section.
- For FGT transceiver:
- Notify soft PTP that pulse adjustments have been configured.
csr_write(ptp_rx_user_cfg_status.rx_fec_cw_pos_cfg_done, 1'b1)
- Read RX FEC codeword position and FEC lane mapping for each PMA lane.
- Wait until RX raw offset data are ready.
You can monitor the status via one of the following:
- Output port:
o_rx_ptp_offset_data_valid = 1'b1
- Polling via CSR:
csr_read(ptp_status.rx_ptp_offset_data_valid) = 1’b1
- Output port:
- Read RX raw offset data from IP:
- All variants:
rx_const_delay = csr_read(ptp_rx_lane_calc_data_constdelay[30:0]) rx_const_delay_sign = csr_read(ptp_rx_lane_calc_data_constdelay[31]) for (pl = 0; pl < PL; pl++) { rx_apulse_offset[pl] = csr_read(ptp_rx_lane<pl>_calc_data_offset[30:0]) rx_apulse_offset_sign[pl] = csr_read(ptp_rx_lane<pl>_calc_data_offset[31]) rx_apulse_wdelay[pl] = csr_read(ptp_rx_lane<pl>_calc_data_wiredelay[19:0]) rx_apulse_time[pl] = csr_read(ptp_rx_lane<pl>_calc_data_time[27:0]) }
- 10GE/25GE no FEC variants:
rx_bitslip_cnt = csr_read(bitslip_cnt.bitslip_cnt[6:0]) rx_dlpulse_alignment = csr_read(bitslip_cnt.dlpulse_alignment)
- All variants:
- Determine RX reference lane.
Skip steps 5b, 5c, and 5d for single lane 10G and 25G Ethernet modes. For these variants, use:
rx_ref_pl = 0 rx_ref_fl = 0 rx_ref_vl = 0
- Determine synchronous pulse (Alignment Marker (AM)) offsets with reference to asynchronous pulse.
- FEC variants:
for (fl = 0; fl < FL; fl++) { if ((rx_xcvr_if_pulse_adj[fl] + rx_xcvr_if_pulse_adj[fl–(fl%pl_fl_map)][4:0]) > rx_xcvr_if_pulse_adj[fl–(fl%pl_fl_map)]) { rx_spulse_offset[fl] = (rx_xcvr_if_pulse_adj[fl] – rx_xcvr_if_pulse_adj[fl–(fl%pl_fl_map)] + rx_xcvr_if_pulse_adj[fl–(fl%pl_fl_map)][4:0]) * UI13 * pl_fl_map rx_spulse_offset_sign[fl] = 1’b0; } else { rx_spulse_offset[fl] = (rx_xcvr_if_pulse_adj[fl–(fl%pl_fl_map)] – rx_xcvr_if_pulse_adj[fl] – rx_xcvr_if_pulse_adj[fl–(fl%pl_fl_map)][4:0]) * UI13 * pl_fl_map rx_spulse_offset_sign[fl] = 1’b1; } }
- 50GE/100GE no FEC variants:
for (vl = 0; vl < VL; vl++) { rx_spulse_post_am[vl] = <Refer to RX Virtual Lane Offset Calculation for No FEC Variants> rx_spulse_offset[vl] = (AM_INTERVAL – rx_spulse_post_am[vl]) * UI13 rx_spulse_offset_sign[vl] = 1’b0; }
The offset calculated in RX Virtual Lane Offset Calculation for No FEC Variants measures the bit distance from PCS internal AM to synchronous pulse of each virtual lane. To determine the bit distance from synchronous pulse to the next AM, subtract the calculated value from the AM interval.Variants AM INTERVAL in Simulation AM INTERVAL in Hardware 50GE-2 2,560 * 66 = 168,960 32,768 * 66 = 2,162,688 100GE-4 2,560 * 66 = 168,960 81,920 * 66 = 5,406,720 - For 10GE/25GE no FEC variants:
rx_spulse_offset[0] = (rx_bitslip_cnt + rx_dlpulse_alignment*33)*UI13 rx_spulse_offset_sign[0] = 1’b0;
- FEC variants:
- Detect rollover of asynchronous pulse time:
The rx_apulse_time[pl] signal represents an asynchronous pulse time of each physical lane in a 28-bit format, where bit [27:16] represent asynchronous pulse time in nanoseconds (ns) and bit [15:0] represent asynchronous pulse time in fractional nanoseconds (fns).
Two types of rollover are possible:- Natural rollover from bit 27 to bit 28 when the value reaches 28'hFFF_FFFF. Before rollover, bit [27:24] is 4'hF.
- Billion rollover when the TOD reaches one billion ns or 48'h3B9A_CA00_0000 in hex value. Before rollover, bit [27:24] is 4'h9.
Given rx_apulse_time_max is largest rx_apulse_time from all physical lanes, for (pl = 0; pl < PL; pl++){ if (rx_apulse_time_max - rx_apulse_time[pl] > 29'h01F4_0000){ if (rx_apulse_time_max[27:24] == 4'hF) { rx_apulse_time[pl] = rx_apulse_time[pl] + 29'h1000_0000 } else { rx_apulse_time[pl] = rx_apulse_time[pl] + 29'h0A00_0000 } } }
- Calculate the actual time of RX Alignment Marker (AM) at RX PMA parallel data interface:
// fl to pl map pl = fl to pl map(f) = (fl-(fl%pl_fl_map))/pl_fl_map
// vl to pl map <See PL in RX Virtual Lane Offset Calculation for No FEC Variants>
- FEC variants:
for (fl = 0; fl < FL; fl++) { local_pl = fl_to_pl_map(fl) rx_am_actual_time[fl]= (rx_apulse_time[local_pl]) + (rx_apulse_offset_sign[local_pl] ? –rx_apulse_offset[local_pl] : rx_apulse_offset[local_pl]) – (rx_apulse_wdelay[local_pl]) + (rx_spulse_offset_sign[fl] ? -rx_spulse_offset[fl] : rx_spulse_offset[fl])) }
- No FEC variants:
for (vl = 0; vl < VL; vl++) { local_pl = vl_to_pl_map(vl) rx_am_actual_time[vl] = (rx_apulse_time[local_pl]) + (rx_apulse_offset_sign[local_pl] ? –rx_apulse_offset[local_pl] : rx_apulse_offset[local_pl]) – (rx_apulse_wdelay[local_pl]) + (rx_spulse_offset_sign[vl] ? -rx_spulse_offset[vl] : rx_spulse_offset[vl]) }
- FEC variants:
- Determine RX reference lane:
- FEC variants:
rx_am_actual_time[rx_ref_fl] is maximum value out of rx_am_actual_time[FL-1:0] rx_ref_pl = fl_to_pl_map(rx_ref_fl) where rx_am_actual_time[fl] is max(rx_am_actual_time[FL-1:0])
- No FEC variants:
rx_am_actual_time[rx_ref_vl] is maximum value out of rx_am_actual_time[VL-1:0] rx_ref_pl = vl_to_pl_map(rx_ref_vl) where rx_am_actual_time[vl] is max(rx_am_actual_time[VL-1:0])
- FEC variants:
- Determine synchronous pulse (Alignment Marker (AM)) offsets with reference to asynchronous pulse.
- Calculate RX offsets:
- Calculate RX TAM adjust:
- FEC variants:
rx_tam_adjust_sim = (rx_const_delay_sign ? –rx_const_delay : rx_const_delay) + (rx_apulse_offset_sign[rx_ref_pl] ? –rx_apulse_offset[rx_ref_pl] : rx_apulse_offset[rx_ref_pl] – (rx_apulse_wdelay[rx_ref_pl]) + (rx_spulse_offset_sign[rx_ref_fl] ? -rx_spulse_offset[rx_ref_fl] : rx_spulse_offset[rx_ref_fl])
- No FEC variants:
rx_tam_adjust_sim = (rx_const_delay_sign ? –rx_const_delay : rx_const_delay) + (rx_apulse_offset_sign[rx_ref_pl] ? –rx_apulse_offset[rx_ref_pl] : rx_apulse_offset[rx_ref_pl]) – (rx_apulse_wdelay[rx_ref_pl]) + (rx_spulse_offset_sign[rx_ref_vl] ? -rx_spulse_offset[rx_ref_vl] : rx_spulse_offset[rx_ref_vl])
For hardware run with PTP Timestamp accuracy mode set to Advanced:
For routing delay adjustment information, refer to Routing Delay Adjustment for Advanced Timestamp Accuracy Mode.rx_tam_adjust = (rx_tam_adjust_sim) + (rx_routing_adj_sign[rx_ref_pl] ? – rx_routing_adj[rx_ref_pl] : rx_routing_adj[rx_ref_pl])
For all other cases:rx_tam_adjust = rx_tam_adjust_sim
Convert TAM adjust to a 32-bit 2's complement number:
rx_tam_adjust_2c = rx_tam_adjust where rx_tam_adjust is a 32-bit 2's complement number
- FEC variants:
- Calculate RX extra latency:
Convert unit of RX PMA delay from UI to nanoseconds:
rx_pma_delay_ns = rx_pma_delay_ui * UI13
RX extra latency is a negative adjustment. To indicate the negative adjustment, set the most-significant register bit to 1. Total up all extra latency together:rx_extra_latency[31] = 1 rx_extra_latency[30:0] = rx_pma_delay_ns + rx_external_phy_delay
- Calculate RX virtual lane offsets:
Attention: This step is not applicable for 10G and 25G Ethernet data rates. You must skip this step for these rates.
Using determined reference virtual lane, assign RX virtual lane offset values as described in Virtual Lane Order and Offset Values.
- For FEC KP-FEC or FEC LL-FEC variants:
for (vl = 0; vl < VL; vl++) { rx_vl_offset[vl] = [vl - (vl % PL)] / PL * 68 * UI13 }
- For FEC KR-FEC variants:
for (vl = 0; vl < VL; vl++) { rx_vl_offset[vl] = [vl - (vl % PL)] / PL * 66 * UI13 }
- For no FEC 100G Ethernet rate variants:
for (vl = 0; vl < VL; vl++) { rx_vl_offset[vl] = 2 * UI13 }
- For no FEC 50G Ethernet rate variants:
for (vl = 0; vl < VL; vl++) { rx_vl_offset[vl] = 0.5 * UI13 }
- For FEC KP-FEC or FEC LL-FEC variants:
- Calculate RX TAM adjust:
- Write the determined RX reference lane into IP:
Attention: This step is not applicable for 10G and 25G Ethernet data rates. You must skip this step for the specified rates.
csr_write(ptp_ref_lane.rx_ref_lane, rx_ref_pl)
- Write the calculated RX offsets to IP:
- Write RX virtual lane offsets:
Attention: This step is not applicable for 10G and 25G Ethernet data rates. You must skip this step for the specified rates.
for (vl = 0; vl < VL; vl++) { csr_write(rx_ptp_vl_offset_<vl>, rx_vl_offset[vl]) }
- Write RX extra latency:
csr_write(rx_ptp_extra_latency, rx_extra_latency)
- Write RX TAM adjust:
csr_write(ptp_rx_tam_adjust, rx_tam_adjust_2c)
- Write RX virtual lane offsets:
- Notify soft PTP that uses flow configuration is completed.
csr_write(ptp_rx_user_cfg_status.rx_user_cfg_done, 1'b1)
- Continue UI value measurement. Follow steps 1 through 7 mentioned in the RX UI Adjustment section.
For simulation or hardware run with 0 ppm setup, you can skip the measurement and program 0 ppm UI value defined in UI Adjustment.
- Wait until RX PTP is ready.
You can monitor the status via one of the following:
- Output port:
o_rx_ptp_ready = 1'b1
- Polling via CSR:
csr_read(ptp_status.rx_ptp_ready) = 1’b1
- Output port:
- RX PTP is up and running.
- Adjust RX UI value.
Perform the RX UI adjustment occasionally to prevent time counter drift from golden time-of-day in the system. Follow steps 1 through 8 described in RX UI Adjustment.
Note: UI measurement is a long process in simulation. Therefore, for simulation, Intel recommends skipping this step and program a 0 ppm value. For more details, refer to UI Value and PMA Delay.
- Adjust RX UI value.