ECP5 Dual Ring Wrapper

This module is a higher-level wrapper around the ecp5_quad_wrapper, providing a simplified interface to access a preconfigured HotRIO Dual Ring slave.

HotRIO Dual Ring is a network configuration in which nodes are connected by two fiber optic daisy-chains (called rings) transmitting redundant HotRIO data in opposite directions. This architecture guarantees that the master will receive data from all functional slave nodes even in the case of a fault in one node or fiber. To achieve this, the datapaths of the two rings are multiplexed at each node so that in the absence of RX data on one ring, that ring’s transmitter becomes connected to the TX stream of the other ring.

Another advantage of Dual Ring is the possibility to compute the network latency between the master and each slave node on each ring, by means of the Delay Measurement Protocol (DMP). This protocol performs the calculation by observing the difference between the arrival times of HotRIO timing flags on the two rings and comparing it with the total delay of such flags when passing through a full ring from the master TX to the master RX.

The ECP5 Dual Ring Wrapper provides all necessary modules to instantiate a minimal Dual Ring slave node:

  • ECP5 Quad Wrapper: four-channel 8b/10b transceiver, preconfigured to support bidirectional HotRIO communications on channels ch0 and ch2, while admitting manual configuration on channels ch1 and ch3.

  • HotRIO slaves: two instances of the hotrio_slave module, handling reception and transmission of HotRIO frames from/to the transceiver.

  • DMP module: one instance of dmp_module, used to calculate the network latency of the node with respect to the master on each ring.

Note

As specified above, ecp5_dual_ring_wrapper is meant to implement a HotRIO Dual Ring slave. It shall not be used to instantiate a Dual Ring master; for this purpose, use an ecp5_quad_wrapper connected to hotrio_master_tx and hotrio_master_rx on both ch0 and ch2. The ecp5_quad_wrapper documentation linked at the beginning of this page contains instructions on the instantiation of the module.

Detailed portlist

ecp5_dual_ring_wrapperhdinpstd_logic_vector(3downto 0)hdinnstd_logic_vector(3downto 0)clk_istd_logicrstn_istd_logicdual_ring_pwrup_istd_logic:= '1'dual_ring_start_address_istd_logic_vector(7downto 0)dual_ring_reset_latch_istd_logic:= '1'total_ring_delay_istd_logic_vector(15downto 0)ring_delay_valid_istd_logicdual_ring_bist_en_istd_logic:= '0'r1_tx_payload_istd_logic_vector(79downto 0)r2_tx_payload_istd_logic_vector(79downto 0)ch1_rx_pwrup_istd_logic:= '0'ch1_tx_pwrup_istd_logic:= '0'ch1_tx_idle_istd_logic:= '0'ch1_tx_data_istd_logic_vector(7downto 0) := (others...ch1_tx_kchar_istd_logic:= '0'ch1_tx_disp_correct_istd_logic:= '0'ch1_tx_force_disp_istd_logic:= '0'ch1_tx_disp_sel_istd_logic:= '0'ch1_bist_en_istd_logic:= '0'ch3_rx_pwrup_istd_logic:= '0'ch3_tx_pwrup_istd_logic:= '0'ch3_tx_idle_istd_logic:= '0'ch3_tx_data_istd_logic_vector(7downto 0) := (others...ch3_tx_kchar_istd_logic:= '0'ch3_tx_disp_correct_istd_logic:= '0'ch3_tx_force_disp_istd_logic:= '0'ch3_tx_disp_sel_istd_logic:= '0'ch3_bist_en_istd_logic:= '0'hdoutpstd_logic_vector(3downto 0)hdoutnstd_logic_vector(3downto 0)dcu0_tx_ready_ostd_logicdcu1_tx_ready_ostd_logicdual_ring_fault_ostd_logicnode_delays_ready_ostd_logicdual_ring_bist_active_ostd_logicdual_ring_bist_err_ostd_logicr1_rx_ready_ostd_logicr1_rx_sync_ostd_logicr1_time_ostd_logic_vector(63downto 0)r1_delay_ostd_logic_vector(15downto 0)r1_rx_address_ostd_logic_vector(7downto 0)r1_rx_payload_ostd_logic_vector(79downto 0)r1_new_request_ostd_logicr1_new_packet_ostd_logicr1_packet_valid_ostd_logicr1_pulse_4us_ostd_logicr1_pulse_1ms_ostd_logicr1_pulse_1s_ostd_logicdiag_r1_rx_err_ostd_logic_vector(15downto 0)diag_r1_cnt_packets_received_ostd_logic_vector(15downto 0)diag_r1_cnt_err_kchar_ostd_logic_vector(15downto 0)diag_r1_cnt_err_parity_ostd_logic_vector(15downto 0)diag_r1_cnt_err_ctc_ostd_logic_vector(15downto 0)diag_r1_cnt_ctc_events_ostd_logic_vector(15downto 0)r2_rx_ready_ostd_logicr2_rx_sync_ostd_logicr2_time_ostd_logic_vector(63downto 0)r2_delay_ostd_logic_vector(15downto 0)r2_rx_address_ostd_logic_vector(7downto 0)r2_rx_payload_ostd_logic_vector(79downto 0)r2_new_request_ostd_logicr2_new_packet_ostd_logicr2_packet_valid_ostd_logicr2_pulse_4us_ostd_logicr2_pulse_1ms_ostd_logicr2_pulse_1s_ostd_logicdiag_r2_rx_err_ostd_logic_vector(15downto 0)diag_r2_cnt_packets_received_ostd_logic_vector(15downto 0)diag_r2_cnt_err_kchar_ostd_logic_vector(15downto 0)diag_r2_cnt_err_parity_ostd_logic_vector(15downto 0)diag_r2_cnt_err_ctc_ostd_logic_vector(15downto 0)diag_r2_cnt_ctc_events_ostd_logic_vector(15downto 0)ch1_rx_clk_ostd_logicch1_rx_ready_ostd_logicdiag_ch1_rx_err_cnt_ostd_logic_vector(15downto 0)ch1_rx_data_ostd_logic_vector(7downto 0)ch1_rx_kchar_ostd_logicch1_bist_active_ostd_logicch1_bist_err_ostd_logicch3_rx_clk_ostd_logicch3_rx_ready_ostd_logicdiag_ch3_rx_err_cnt_ostd_logic_vector(15downto 0)ch3_rx_data_ostd_logic_vector(7downto 0)ch3_rx_kchar_ostd_logicch3_bist_active_ostd_logicch3_bist_err_ostd_logic

Generics

Name

Description

Type

Default

ch1_rx_enable_g

enable auxiliary channel ch1 rx

boolean

true

ch3_rx_enable_g

enable auxiliary channel ch3 rx

boolean

true

ch1_tx_enable_g

enable auxiliary channel ch1 tx

boolean

true

ch3_tx_enable_g

enable auxiliary channel ch3 tx

boolean

true

rx_invert_g

invert rx serial data inputs

bit_vector(3 downto 0)

"0000"

tx_invert_g

invert tx serial data outputs

bit_vector(3 downto 0)

"0000"

address_range_g

number of consecutive addresses belonging to this node

integer range 1 to 256

1

exchange_delay_g

number of cycles needed by the user to prepare `tx_hotrio_payload_i` after receiving `new_request_s`

integer range 0 to 9

0

reply_bit_g

if true, the msb is flipped in the tx address when the packet is a reply

boolean

false

dcu_lol_size_g

set the log2 of the no. of tx_refclk cycles over which the differences below are accumulated

positive

12

dcu_unlock_diff_g

set the min difference in no. of tx_refclk and tx_pclk rising edges to consider the txpll unlocked

positive

2

dcu_lock_diff_g

set the max difference in no. of tx_refclk and tx_pclk rising edges to consider lock recovered

positive

1

rx_serdes_rst_bits_g

log2 of the no. of clock cycles to wait to change state after lock of the cdr

positive

10

rx_pcs_rst_bits_g

log2 of the no. of clock cycles to wait to change state after release of the serdes rx reset

positive

10

rx_pcs_lock_bits_g

log2 of the no. of consecutive clock cycles with locked cdr before considering the rx channel ready

positive

11

rx_pcs_lol_bits_g

log2 of the no. of consecutive clock cycles with unlocked cdr before restarting the rx reset sequence

positive

20

rx_err_cnt_bits_g

log2 of the no. of rx errors every 2^17 cycles at which a rx pcs reset is issued

positive

3

tx_serdes_rst_bits_g

log2 of the no. of clock cycles to wait to change state after lock of the txpll

positive

2

tx_pcs_rst_bits_g

log2 of the no. of clock cycles to wait to change state after release of the serdes tx reset

positive

3

tx_pcs_lock_bits_g

log2 of the no. of consecutive clock cyles with locked txpll before considering the tx dual ready. must be higher than `dcu_lol_size_g`

positive

14

tx_pcs_lol_bits_g

log2 of the no. of consecutive clock cycles with unlocked txpll before restarting the tx reset sequence. must be higher than `dcu_lol_size_g`

positive

15

bist_k_counter_bits_g

log2 of the no. of full bist ramps between two replacements of the d0.0 with k28.5

positive

1

Input signals


IN ports

Name

Description

Type

hdinp

serial stream input for the four channels (true ports)

std_logic_vector(3 downto 0)

hdinn

serial stream input for the four channels (complement ports)

std_logic_vector(3 downto 0)

clk_i

system clock of the fpga, to be shared by all tx and rx references. frequency must be 125 mhz

std_logic

rstn_i

active low reset synchronous with `clk_i`. acts on both duals of the quad

std_logic

dual_ring_pwrup_i

power up channels ch0 and ch2 used by the dual ring. requires both `dcun_serdes_pwrup_i` to be high

std_logic := '1'

dual_ring_start_address_i

first hotrio address in the range this node needs to reply to

std_logic_vector(7 downto 0)

dual_ring_reset_latch_i

when high, dual ring switching logic will be deactivated if rx ready is high in both rings

std_logic := '1'

total_ring_delay_i

data travel time over a full ring from master tx to master rx, expressed in 125 mhz clock cycles

std_logic_vector(15 downto 0)

ring_delay_valid_i

one-cycle pulse notifying the dmp (delay measurement protocol) module that it should read `total_ring_delay_i` and recalculate node latencies

std_logic

dual_ring_bist_en_i

enable bist for ch0 and ch2

std_logic := '0'

r1_tx_payload_i

hotrio payload to be sent on the first ring when an address in this node's range is received

std_logic_vector(79 downto 0)

r2_tx_payload_i

hotrio payload to be sent on the second ring when an address in this node's range is received

std_logic_vector(79 downto 0)

ch1_rx_pwrup_i

ch1 rx power-up

std_logic := '0'

ch1_tx_pwrup_i

ch1 tx power-up

std_logic := '0'

ch1_tx_idle_i

disable serial output of ch1

std_logic := '0'

ch1_tx_data_i

ch1 tx data

std_logic_vector(7 downto 0) := (others => '0')

ch1_tx_kchar_i

ch1 tx k-character flag

std_logic := '0'

ch1_tx_disp_correct_i

fix the disparity for ethernet communications. only use while sending the data character of idle2

std_logic := '0'

ch1_tx_force_disp_i

force the disparity in the ch1_tx_disp_sel input

std_logic := '0'

ch1_tx_disp_sel_i

select the disparity to be used in the tx data (if forced)

std_logic := '0'

ch1_bist_en_i

enable bist for ch1

std_logic := '0'

ch3_rx_pwrup_i

ch3 rx power-up

std_logic := '0'

ch3_tx_pwrup_i

ch3 tx power-up

std_logic := '0'

ch3_tx_idle_i

disable serial output of ch3

std_logic := '0'

ch3_tx_data_i

ch3 tx data

std_logic_vector(7 downto 0) := (others => '0')

ch3_tx_kchar_i

ch3 tx k-character flag

std_logic := '0'

ch3_tx_disp_correct_i

fix the disparity for ethernet communications. only use while sending the data character of idle2

std_logic := '0'

ch3_tx_force_disp_i

force the disparity in the ch3_tx_disp_sel input

std_logic := '0'

ch3_tx_disp_sel_i

select the disparity to be used in the tx data (if forced)

std_logic := '0'

ch3_bist_en_i

enable bist for ch3

std_logic := '0'

Output signals


OUT ports

Name

Description

Type

hdoutp

serial stream outputs for the four channels (true ports)

std_logic_vector(3 downto 0)

hdoutn

serial stream outputs for the four channels (complement ports)

std_logic_vector(3 downto 0)

dcu0_tx_ready_o

common tx ready signal for dual 0

std_logic

dcu1_tx_ready_o

common tx ready signal for dual 1

std_logic

dual_ring_fault_o

high when dual ring switching logic is active. triggered by rx ready going low on any ring and reset by `dual_ring_reset_latch_i` if both rx ready are high

std_logic

node_delays_ready_o

high when valid latencies are ready on the `r1_delay_o` and `r2_delay_o` ports

std_logic

dual_ring_bist_active_o

signals that the bist initialization has been received on both rings

std_logic

dual_ring_bist_err_o

pulses high when an error is detected in the received bist on any ring

std_logic

r1_rx_ready_o

ch0 rx ready signal

std_logic

r1_rx_sync_o

synchronization flag for the hotrio slave of the first ring

std_logic

r1_time_o

64-bit timestamp received via hotrio on the first ring

std_logic_vector(63 downto 0)

r1_delay_o

latency of this node with respect to the hotrio master on the first ring

std_logic_vector(15 downto 0)

r1_rx_address_o

hotrio address received on the first ring

std_logic_vector(7 downto 0)

r1_rx_payload_o

hotrio payload received on the first ring

std_logic_vector(79 downto 0)

r1_new_request_o

high for one cycle when new data is available on `r1_rx_address_o`

std_logic

r1_new_packet_o

high for one cycle when new data is available on `r1_rx_payload_o`

std_logic

r1_packet_valid_o

high at the same time as `r1_new_packet_o` if parity check succeeded on the new packet

std_logic

r1_pulse_4us_o

high for one cycle every four microseconds

std_logic

r1_pulse_1ms_o

high for one cycle every millisecond

std_logic

r1_pulse_1s_o

high for one cycle every second

std_logic

diag_r1_rx_err_o

number of running disparity and code violation errors received on the first ring since last pcs reset

std_logic_vector(15 downto 0)

diag_r1_cnt_packets_received_o

number of hotrio packets received on the first ring since last reset

std_logic_vector(15 downto 0)

diag_r1_cnt_err_kchar_o

number of misplaced special characters received on the first ring since last reset

std_logic_vector(15 downto 0)

diag_r1_cnt_err_parity_o

number of hotrio packets with one or more parity errors received on the first ring since last reset

std_logic_vector(15 downto 0)

diag_r1_cnt_err_ctc_o

number of ctc fifo overrun and/or underrun errors on the first ring since last reset

std_logic_vector(15 downto 0)

diag_r1_cnt_ctc_events_o

number of ctc activations (insertion and/or drops) on the first ring since last reset. these are not errors

std_logic_vector(15 downto 0)

r2_rx_ready_o

ch0 rx ready signal

std_logic

r2_rx_sync_o

synchronization flag for the hotrio slave of the second ring

std_logic

r2_time_o

64-bit timestamp received via hotrio on the second ring

std_logic_vector(63 downto 0)

r2_delay_o

latency of this node with respect to the hotrio master on the second ring

std_logic_vector(15 downto 0)

r2_rx_address_o

hotrio address received on the second ring

std_logic_vector(7 downto 0)

r2_rx_payload_o

hotrio payload received on the second ring

std_logic_vector(79 downto 0)

r2_new_request_o

high for one cycle when new data is available on `r2_rx_address_o`

std_logic

r2_new_packet_o

high for one cycle when new data is available on `r2_rx_payload_o`

std_logic

r2_packet_valid_o

high at the same time as `r2_new_packet_o` if parity check succeeded on the new packet

std_logic

r2_pulse_4us_o

high for one cycle every four microseconds

std_logic

r2_pulse_1ms_o

high for one cycle every millisecond

std_logic

r2_pulse_1s_o

high for one cycle every second

std_logic

diag_r2_rx_err_o

number of running disparity and code violation errors received on the second ring since last pcs reset

std_logic_vector(15 downto 0)

diag_r2_cnt_packets_received_o

number of hotrio packets received on the second ring since last reset

std_logic_vector(15 downto 0)

diag_r2_cnt_err_kchar_o

number of misplaced special characters received on the second ring since last reset

std_logic_vector(15 downto 0)

diag_r2_cnt_err_parity_o

number of hotrio packets with one or more parity errors received on the second ring since last reset

std_logic_vector(15 downto 0)

diag_r2_cnt_err_ctc_o

number of ctc fifo overrun and/or underrun errors on the second ring since last reset

std_logic_vector(15 downto 0)

diag_r2_cnt_ctc_events_o

number of ctc activations (insertion and/or drops) on the second ring since last reset. these are not errors

std_logic_vector(15 downto 0)

ch1_rx_clk_o

ch1 recovered clock (if locked)

std_logic

ch1_rx_ready_o

ch1 rx ready signal

std_logic

diag_ch1_rx_err_cnt_o

number of running disparity and code violation errors received on ch1 since last pcs reset

std_logic_vector(15 downto 0)

ch1_rx_data_o

ch1 rx data

std_logic_vector(7 downto 0)

ch1_rx_kchar_o

ch1 rx k-character flag

std_logic

ch1_bist_active_o

signals that the bist initialization has been received

std_logic

ch1_bist_err_o

pulses high when an error is detected in the received bist

std_logic

ch3_rx_clk_o

ch3 recovered clock (if locked)

std_logic

ch3_rx_ready_o

ch3 rx ready signal

std_logic

diag_ch3_rx_err_cnt_o

number of running disparity and code violation errors received on ch3 since last pcs reset

std_logic_vector(15 downto 0)

ch3_rx_data_o

ch3 rx data

std_logic_vector(7 downto 0)

ch3_rx_kchar_o

ch3 rx k-character flag

std_logic

ch3_bist_active_o

signals that the bist initialization has been received

std_logic

ch3_bist_err_o

pulses high when an error is detected in the received bist

std_logic

Configuring the Dual Ring Wrapper

This section provides guidance in the instantiation of the ecp5_dual_ring_wrapper module and in the selection of the appropriate options for the application. Several settings, both in the generic map and in the port map, are equal to those of the ecp5_quad_wrapper module, and they are explained in its document. These include:

  • Generics to invert channels.

  • Generics to change the size of SerDes/PCS reset counters.

  • Ports to power up/down the channels not involved in Dual Ring (ch1 and ch3), and to control their running disparity and Built-in Self Test (BIST).

Here onwards, only the parts of module configuration that differ from the ecp5_quad_wrapper will be discussed.

Fixed options

With respect to the Quad Wrapper, this module is partially preconfigured. As a result, some options that were selectable in the Quad Wrapper cannot be changed in the Dual Ring Wrapper. These include the following:

  • Both Duals of the 8b/10b transceiver are always instantiated, as they are needed to provide access to channels ch0 and ch2 for Dual Ring. As such, the hdinp and hdinn ports always have width 4 in the Dual Ring Wrapper, even if ch1 and ch3 are unused.

  • Line rates for the two Duals cannot be changed and they are set to 125 MHz, the HotRIO transmission frequency.

  • Direct link mode cannot be enabled for any Dual. Internally, the TX reference clock of the Duals are both connected to the same clock net, provided by the user on the clk_i port.

Clocking

While the Quad Wrapper has a clock input for each Dual, the Dual Ring Wrapper only has one clock input, shared by both Duals. All data inputs to the Dual Ring Wrapper, including TX data for all channels, the module’s reset, and configuration ports, should be provided synchronously with this clock input, clk_i.

clk_i must be a stable 125 MHz clock and must not be derived from a clock output of the module itself.

Enabling and disabling channels

Channels involved in Dual Ring (ch0 and ch2) cannot be permanently disabled in the generic map. The two auxiliary channels (ch1 and ch3) can be freely configured, as they are general-purpose Quad Wrapper channels. By default they are enabled, but if they are not needed by the application they can be disabled by setting the corresponding chN_rx_enable_g and/or chN_tx_enable_g generics to false. This will cause the channel-specific logic to be omitted inside the Dual Ring Wrapper, resulting in lower resource utilization and potentially easier timing closure.

Enabled auxiliary channels can still be powered up or down at runtime using the chN_rx_pwrup_i and chN_tx_pwrup_i ports. Dual Ring channels can also be powered up or down, but they are always both in the same powerup status, controlled by the dual_ring_pwrup_i port.

HotRIO slave options

The Dual Ring Wrapper includes HotRIO slave settings both in the generic list and in the port list. These options always take effect in both HotRIO slave instances in the Dual Ring symmetrically.

  • The generics can be used to set the number of addresses belonging to the node, the delay between receiving an address in the node’s range and sampling the TX payload to be sent as a reply, and whether a reply should have the MSB of the address set to 1 or left unchanged.

  • In the port list, the first of the consecutive addresses belonging to this node can be selected at runtime through the dual_ring_start_address_i port. This setting should not be modified while one of the HotRIO slaves of this module is actively replying to a HotRIO packet that belongs to the current address range.

Enabling and disabling BIST on Dual Ring channels

Built-In Self Test is provided for all channels of the Quad. However, Dual Ring channels cannot be independently set to BIST mode. BIST can be enabled in both rings simultaneously by asserting dual_ring_bist_en_i.

When BIST is enabled, the HotRIO slaves are bypassed and their flags and counters should be ignored. Both Dual Ring channels will send BIST data on their transmitters, and their receivers will be directly connected to the BIST checker. The two usual BIST flags, “active” and “err”, are taken from each checker and combined to produce a single set of flags according to the following rules:

  • dual_ring_bist_active_o is high if both “active” flags are high (AND gate)

  • dual_ring_bist_err_o is high if any “err” flag is high (OR gate)

The Built-In Self Test can be considered passed only if dual_ring_bist_active_o is steady high and dual_ring_bist_err_o is steady low.

Exchanging data with Dual Ring channels

While auxiliary channels have 8-bit data ports for RX and TX, Dual Ring channels are designed to exchange HotRIO packets. As such, they have 80-bit payload TX and RX ports and an 8-bit RX address port, as well as the full set of flags and diagnostic counters of the hotrio_slave module.

There are also two additional outputs providing timing information to the node:

  • rN_time_o provides the 64-bit timestamp sent by the master node.

  • rN_delay_o provides the network latency calculated by the DMP, measured in 125 MHz clock periods.

Configuring DMP

As mentioned in the introduction of this document, the HotRIO Delay Measurement Protocol requires information on the total delay of a full ring to be able to calculate the delay between the master and the current node.

This information can be provided in several ways. The suggested approach is to provide it through the register tree via sideband communication. When the register dedicated to the total ring delay is written by the STM32-G0, its update flag can be connected to ring_delay_valid_i to notify the presence of new valid data on total_ring_delay_i.

DMP delays will be recalculated every time a new total ring delay is provided to the aforementioned ports.