External clock recovery (Clock Gen)

To provide an audio master clock an application may use selectable oscillators, clock generation IC or, in the case of xcore.ai devices, an integrated secondary PLL, to generate fixed master clock frequencies.

It may also use an external PLL/Clock Multiplier to generate a master clock based on a reference from the xcore.

Using the internal secondary PLL on an external PLL/Clock Multiplier allows an Asynchronous mode design to lock to an external clock source from a digital stream (e.g. S/PDIF or ADAT input). lib_xua supports the Cirrus Logic CS2100 device or use of lib_sw_pll (xcore.ai only) for this purpose. Other devices may be supported via code modification.

The Clock Recovery thread (Clock Gen) is responsible for either generating the reference frequency to the CS2100 device or driving lib_sw_pll from time measurements based on the local master clock and the time of received samples. Clock Gen (via CS2100 or lib_sw_pll) generates the master clock used over the whole design. This thread also serves as a smaller buffer between ADAT and S/PDIF receiving threads and the Audio Hub thread.

When using lib_sw_pll (xcore.ai only) a further thread is instantiated which performs the sigma-delta modulation of the xcore PLL to ensure the lowest jitter over the audio band. See lib_sw_pll documentation for further details.

When running in Internal Clock mode this thread simply generates this clock using a local timer, based on the xcore’s internal 100 MHz reference clock.

When running in an external clock mode (i.e. S/PDIF Clock” or “ADAT Clock” mode) samples are received from the S/PDIF and/or ADAT receive thread. The external frequency is calculated through counting samples in a given period. Either the reference clock to the CS2100 is then generated based on the reception of these samples or the timing information is provided to lib_sw_pll to generate the phase-locked clock on-chip (xcore.ai only).

If an external stream becomes invalid, the Internal Clock timer event will fire to ensure that valid master clock generation continues regardless of cable unplugs etc. Efforts are made to ensure that the transitions between these clocks are relatively seamless. Additionally efforts are also made to try and keep the jitter on the reference clock as low as possible, regardless of activity level of the Clock Gen thread. The is achieved though the use of port times to schedule pin toggling rather than directly outputting to the port in the case of using the CS2100. For lib_sw_pll cases the last setting is kept for the sigma-delta modulator ensuring clock continuity.

The Clock Gen thread gets clock selection Get/Set commands from Endpoint 0 via the c_clk_ctl channel. This thread also records the validity of external clocks, which is also queried through the same channel from Endpoint 0. Note, the Internal Clock is always reported as being valid. It should be noted that the device always reports the current device sample rate regardless of the clock being interrogated. This results in improved user experience for most driver/operating system combinations

To inform the host of any status change, the Clock Gen thread can also cause the Decouple thread to request an interrupt packet on change of clock validity. This functionality is based on the Audio Class 2.0 status/interrupt endpoint feature.

Note

When running in Synchronous mode external digital input streams are currently not supported. Such a feature would require sample-rate conversion to covert from the S/PDIF or ADAT clock domain to the USB host clock domain. As such this thread is not used in a Synchronous mode device.