diff --git a/.gitignore b/.gitignore
index 979a2930..0cffca23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,7 @@ build/
.build*
*.pyc
xscope.xmt
+
+# Traces
+*.gtkw
+*.vcd
diff --git a/tests/test_sync.py b/tests/test_sync.py
new file mode 100644
index 00000000..45c9ae22
--- /dev/null
+++ b/tests/test_sync.py
@@ -0,0 +1,49 @@
+import pytest
+import Pyxsim
+from Pyxsim import testers
+import os
+import sys
+
+
+@pytest.fixture()
+def test_file(request):
+ return str(request.node.fspath)
+
+
+def do_test(test_file, options, capfd):
+
+ testname, _ = os.path.splitext(os.path.basename(test_file))
+
+ binary = f"{testname}/bin/{testname}.xe"
+
+ tester = testers.ComparisonTester(open("pass.expect"))
+
+ loopback_args = (
+ "-port tile[0] XS1_PORT_1M 1 0 -port tile[0] XS1_PORT_1I 1 0 "
+ + "-port tile[0] XS1_PORT_1N 1 0 -port tile[0] XS1_PORT_1J 1 0 "
+ + "-port tile[0] XS1_PORT_1O 1 0 -port tile[0] XS1_PORT_1K 1 0 "
+ + "-port tile[0] XS1_PORT_1P 1 0 -port tile[0] XS1_PORT_1L 1 0 "
+ + "-port tile[0] XS1_PORT_1A 1 0 -port tile[0] XS1_PORT_1B 1 0 "
+ )
+
+
+ max_cycles = 15000000 # enough to reach the 10 skip + 100 test in sim at 48kHz
+
+ simargs = [
+ "--max-cycles",
+ str(max_cycles),
+ "--plugin",
+ "LoopbackPort.dll",
+ loopback_args,
+ ]
+
+ result = Pyxsim.run_on_simulator(binary, tester=tester, simargs=simargs, capfd=capfd, instTracing=options.enabletracing, vcdTracing=options.enablevcdtracing)
+
+ return result
+
+
+def test_sync(test_file, options, capfd):
+
+ result = do_test(test_file, options, capfd)
+
+ assert result
diff --git a/tests/test_sync/Makefile b/tests/test_sync/Makefile
new file mode 100644
index 00000000..e175efba
--- /dev/null
+++ b/tests/test_sync/Makefile
@@ -0,0 +1,9 @@
+
+XCC_FLAGS = -O3 -g -DXUD_CORE_CLOCK=600 -save-temps -DUSB_TILE=tile[0] -DLOCAL_CLOCK_INCREMENT=10000 -DLOCAL_CLOCK_MARGIN=100
+
+TARGET = test_xs3_600.xn
+
+USED_MODULES = lib_xua lib_xud lib_logging
+
+XMOS_MAKE_PATH ?= ../..
+-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/tests/test_sync/src/debug_conf.h b/tests/test_sync/src/debug_conf.h
new file mode 100644
index 00000000..aadb0014
--- /dev/null
+++ b/tests/test_sync/src/debug_conf.h
@@ -0,0 +1,9 @@
+// Copyright 2016-2021 XMOS LIMITED.
+// This Software is subject to the terms of the XMOS Public Licence: Version 1.
+#ifndef __debug_conf_h__
+#define __debug_conf_h__
+
+#define DEBUG_PRINT_ENABLE_MAIN 1
+#define DEBUG_PRINT_ENABLE_AUDIO_IO 0
+
+#endif // __debug_conf_h__
diff --git a/tests/test_sync/src/main.xc b/tests/test_sync/src/main.xc
new file mode 100644
index 00000000..12c6509d
--- /dev/null
+++ b/tests/test_sync/src/main.xc
@@ -0,0 +1,160 @@
+// Copyright 2022 XMOS LIMITED.
+// This Software is subject to the terms of the XMOS Public Licence: Version 1.
+
+/* Simples test to ensure reference clock to CS2100 device continues when SOF clock not available
+ * Note, this test uses "nice" numbers and it doesn't check for graceful change over from internal to SOF clock
+ */
+
+#include "platform.h"
+#include "xua.h"
+#include "uac_hwresources.h"
+#include "print.h"
+
+#define EP_COUNT_IN 3
+#define EP_COUNT_OUT 3
+
+out port p_pll_ref = XS1_PORT_1A;
+in port p_off_mclk = XS1_PORT_1M;
+in port p_pll_loop = XS1_PORT_1B;
+
+/* Purely for debug/viewing on VCD */
+out port p_test = XS1_PORT_1C;
+
+/* To speed this test up we divide all delays by 10. This is also the case for the delays in the clock generation code */
+#define SOF_PERIOD_TICKS (12500/10)
+
+void exit(int);
+
+void delay(unsigned d)
+{
+ timer t;
+ unsigned time;
+ t :> time;
+ t when timerafter(time + d) :> int x;
+}
+
+/* From lib_xud */
+void SetupEndpoints(chanend c_ep_out[], int noEpOut, chanend c_ep_in[], int noEpIn, XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[]);
+
+void AudioHwInit()
+{
+ return;
+}
+
+void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode,
+ unsigned sampRes_DAC, unsigned sampRes_ADC)
+{
+ return;
+}
+
+void driveSofs(chanend c_sof, int count)
+{
+ static int sof = 0;
+ for(int i = 0; i < count; i++)
+ {
+ outuint(c_sof, sof++);
+ delay(SOF_PERIOD_TICKS);
+ }
+}
+
+void fake_xud(chanend c_out[], chanend c_in[], chanend c_sof)
+{
+ timer t;
+ unsigned time;
+
+ p_test <: 1;
+
+ /* Makes traces a bit nicer to look at */
+ t :> time;
+ t when timerafter(SOF_PERIOD_TICKS * 2) :> int x;
+
+ /* Endpoint type tables */
+ XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_ISO, XUD_EPTYPE_DIS};
+ XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_ISO, XUD_EPTYPE_ISO};
+
+ SetupEndpoints(c_out, EP_COUNT_OUT, c_in, EP_COUNT_IN, epTypeTableOut, epTypeTableIn);
+
+ driveSofs(c_sof, 24);
+
+ p_test <: 0;
+ /* Sim missing SOFs */
+ delay(SOF_PERIOD_TICKS*8);
+ p_test <: 1;
+
+ driveSofs(c_sof, 16);
+
+ p_test <: 0;
+}
+
+extern XUD_BusSpeed_t g_curUsbSpeed;
+
+#define MARGIN (1500/10)
+#define EXPECTED_PERIOD (100000/10) // Test runs as HS - so 8 * 125000
+
+void checker()
+{
+ timer t;
+ unsigned t0, t1;
+ unsigned x = 0;
+
+ int fail = 0;
+
+ p_pll_loop when pinseq(1) :> x;
+ p_pll_loop when pinseq(0) :> x;
+ p_pll_loop when pinseq(1) :> x;
+
+ for(int i = 0; i < 8; i++)
+ {
+ p_pll_loop when pinsneq(x) :> x;
+ t :> t0;
+ p_pll_loop when pinsneq(x) :> x;
+ t :> t1;
+
+ int period = t1-t0;
+
+ if(period > (EXPECTED_PERIOD + MARGIN))
+ {
+ printstr("Period too long: ");
+ printintln(period);
+ fail = 1;
+ }
+ else if(period < (EXPECTED_PERIOD - MARGIN))
+ {
+ printstr("Period too short: ");
+ printintln(period);
+ fail = 1;
+ }
+ }
+ if(!fail)
+ printstrln("PASS");
+
+ exit(0);
+}
+
+
+int main()
+{
+ chan c_out[EP_COUNT_OUT];
+ chan c_in[EP_COUNT_IN];
+ chan c_sof;
+ chan c_aud_ctl;
+
+ interface pll_ref_if i_pll_ref;
+
+ par
+ {
+ PllRefPinTask(i_pll_ref, p_pll_ref);
+
+ {
+ g_curUsbSpeed = XUD_SPEED_HS;
+ XUA_Buffer_Ep(c_out[1], /* USB Audio Out*/
+ c_in[1], /* USB Audio In */
+ c_sof, c_aud_ctl, p_off_mclk, i_pll_ref
+ );
+ }
+
+ fake_xud(c_out, c_in, c_sof);
+
+ checker();
+ }
+}
diff --git a/tests/test_sync/src/test_xs3_600.xn b/tests/test_sync/src/test_xs3_600.xn
new file mode 100644
index 00000000..20e8eeb6
--- /dev/null
+++ b/tests/test_sync/src/test_xs3_600.xn
@@ -0,0 +1,24 @@
+
+
+
+ tileref tile[2]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/test_sync/src/usb_device.h b/tests/test_sync/src/usb_device.h
new file mode 100644
index 00000000..1f5aaa89
--- /dev/null
+++ b/tests/test_sync/src/usb_device.h
@@ -0,0 +1,25 @@
+// Copyright 2016-2021 XMOS LIMITED.
+// This Software is subject to the terms of the XMOS Public Licence: Version 1.
+#ifndef __usb_device_h__
+#define __usb_device_h__
+
+#include
+#include
+#include "usb_std_requests.h"
+#include "xud.h"
+
+XUD_Result_t USB_GetSetupPacket(XUD_ep ep_out, XUD_ep ep_in, REFERENCE_PARAM(USB_SetupPacket_t, sp));
+
+XUD_Result_t USB_StandardRequests(XUD_ep ep_out, XUD_ep ep_in,
+ NULLABLE_ARRAY_OF(unsigned char, devDesc_hs), int devDescLength_hs,
+ NULLABLE_ARRAY_OF(unsigned char, cfgDesc_hs), int cfgDescLength_hs,
+ NULLABLE_ARRAY_OF(unsigned char, devDesc_fs), int devDescLength_fs,
+ NULLABLE_ARRAY_OF(unsigned char, cfgDesc_fs), int cfgDescLength_fs,
+#ifdef __XC__
+ char * unsafe strDescs[],
+#else
+ char * strDescs[],
+#endif
+ int strDescsLength, REFERENCE_PARAM(USB_SetupPacket_t, sp), XUD_BusSpeed_t usbBusSpeed);
+
+#endif // __usb_device_h__
diff --git a/tests/test_sync/src/xua_conf.h b/tests/test_sync/src/xua_conf.h
new file mode 100644
index 00000000..616262b7
--- /dev/null
+++ b/tests/test_sync/src/xua_conf.h
@@ -0,0 +1,44 @@
+// Copyright 2016-2022 XMOS LIMITED.
+// This Software is subject to the terms of the XMOS Public Licence: Version 1.
+#ifndef _XUA_CONF_H_
+#define _XUA_CONF_H_
+
+#define NUM_USB_CHAN_OUT (2)
+#define NUM_USB_CHAN_IN (2)
+#define I2S_CHANS_DAC (2)
+#define I2S_CHANS_ADC (2)
+
+#define XUA_SYNCMODE XUA_SYNCMODE_SYNC
+#define UAC_FORCE_FEEDBACK_EP (0)
+
+#define EXCLUDE_USB_AUDIO_MAIN
+#define XUA_NUM_PDM_MICS 0
+#define XUD_TILE 1
+#define AUDIO_IO_TILE 0
+#define MIXER 0
+
+#ifndef MCLK_441
+#define MCLK_441 (512 * 44100)
+#endif
+
+#ifndef MCLK_48
+#define MCLK_48 (512 * 48000)
+#endif
+
+#define MIN_FREQ (44100)
+#define MAX_FREQ (192000)
+#define SPDIF_TX_INDEX 0
+#define VENDOR_STR "XMOS"
+#define VENDOR_ID 0x20B1
+#define PRODUCT_STR_A2 "Test device"
+#define PRODUCT_STR_A1 "Test device"
+#define PID_AUDIO_1 1
+#define PID_AUDIO_2 2
+#define AUDIO_CLASS 2
+#define AUDIO_CLASS_FALLBACK 0
+#define BCD_DEVICE 0x1234
+#define XUA_DFU_EN 0
+#define MIC_DUAL_ENABLED 1 //Use single thread, dual PDM mic
+#define XUA_MIC_FRAME_SIZE 240
+
+#endif