From 46b2687d70cf2b4d260e4c508183e4184c08ce63 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 17 Feb 2023 15:52:43 +0800 Subject: [PATCH] RTIO/SYS Clock merge Co-authored-by: mwojcik Co-committed-by: mwojcik --- flake.lock | 46 +++---- src/gateware/kasli_soc.py | 177 ++++++++++++-------------- src/gateware/test_dma.py | 4 +- src/gateware/zc706.py | 210 ++++++++++++++++--------------- src/gateware/zynq_clocking.py | 122 ++++++++++++++++++ src/libboard_artiq/src/lib.rs | 25 ---- src/runtime/src/main.rs | 5 +- src/runtime/src/rtio_clocking.rs | 58 ++++----- src/satman/src/main.rs | 34 ++--- 9 files changed, 377 insertions(+), 304 deletions(-) create mode 100644 src/gateware/zynq_clocking.py diff --git a/flake.lock b/flake.lock index 0d552783..609f5ef7 100644 --- a/flake.lock +++ b/flake.lock @@ -11,11 +11,11 @@ "src-pythonparser": "src-pythonparser" }, "locked": { - "lastModified": 1672816435, - "narHash": "sha256-cH2i+1eoJ+K9rAxctVjUR5oNWi54USjbtXPYj5a0j7A=", - "ref": "refs/heads/master", - "rev": "1be7e2a2e1d142802a52792865b19c8874fd0e9d", - "revCount": 8257, + "lastModified": 1673758995, + "narHash": "sha256-Nl00lPjySWyui12fGhU6/BiBZZVScI19ux3I+EGT4YM=", + "ref": "master", + "rev": "e9c65abebe8ce6912479b0a7334a813ae581458b", + "revCount": 8305, "type": "git", "url": "https://github.com/m-labs/artiq.git" }, @@ -68,11 +68,11 @@ "mozilla-overlay": { "flake": false, "locked": { - "lastModified": 1664789696, - "narHash": "sha256-UGWJHQShiwLCr4/DysMVFrYdYYHcOqAOVsWNUu+l6YU=", + "lastModified": 1672878308, + "narHash": "sha256-0+fl6PHokhtSV+w58z2QD2rTf8QhcOGsT9o4LwHHZHE=", "owner": "mozilla", "repo": "nixpkgs-mozilla", - "rev": "80627b282705101e7b38e19ca6e8df105031b072", + "rev": "d38863db88e100866b3e494a651ee4962b762fcc", "type": "github" }, "original": { @@ -115,11 +115,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1669735802, - "narHash": "sha256-qtG/o/i5ZWZLmXw108N2aPiVsxOcidpHJYNkT45ry9Q=", + "lastModified": 1673345971, + "narHash": "sha256-4DfFcKLRfVUTyuGrGNNmw37IeIZSoku9tgTVmu/iD98=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "731cc710aeebecbf45a258e977e8b68350549522", + "rev": "54644f409ab471e87014bb305eac8c50190bcf48", "type": "github" }, "original": { @@ -144,11 +144,11 @@ ] }, "locked": { - "lastModified": 1669369686, - "narHash": "sha256-YHez+S3PTUgtuliUNB5WM+RXcj8RKLbHVRvOgELSkwU=", + "lastModified": 1673433867, + "narHash": "sha256-a7Oq35YoDzPtISbqAsaT+2/v15HZ7G1q0ukXmKWdb7Q=", "owner": "m-labs", "repo": "sipyco", - "rev": "98db6eacb084c2c5280fb653bee3d313e3ca6df8", + "rev": "38f8f4185d7db6b68bd7f71546da9077b1e2561c", "type": "github" }, "original": { @@ -160,11 +160,11 @@ "src-migen": { "flake": false, "locked": { - "lastModified": 1662111470, - "narHash": "sha256-IPyhoFZLhY8d3jHB8jyvGdbey7V+X5eCzBZYSrJ18ec=", + "lastModified": 1673433200, + "narHash": "sha256-ribBG06gsucz5oBS+O6aL8s2oJjx+qfl+vXmspts8gg=", "owner": "m-labs", "repo": "migen", - "rev": "639e66f4f453438e83d86dc13491b9403bbd8ec6", + "rev": "f3e9145c9825514a1b4225378936569da4df8e12", "type": "github" }, "original": { @@ -176,11 +176,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1669779825, - "narHash": "sha256-l3lyy6dmbivo9Tppb08KHSyU89ZZG1CCcSjPlNRD210=", - "ref": "master", - "rev": "2c255775f732a41ba1a512ab3d2547af4e25f674", - "revCount": 2435, + "lastModified": 1671158014, + "narHash": "sha256-50w0K2E2ympYrG1Tte/HVbsp4FS2U+yohqZByXTOo4I=", + "ref": "refs/heads/master", + "rev": "26f039f9f6931a20a04ccd0f0a5402f67f553916", + "revCount": 2436, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" @@ -218,7 +218,7 @@ "locked": { "lastModified": 1669819016, "narHash": "sha256-WvNMUekL4Elc55RdqX8XP43QPnBrK8Rbd0bsoI61E5U=", - "ref": "refs/heads/master", + "ref": "master", "rev": "67dbb5932fa8ff5f143983476f741f945871d286", "revCount": 624, "type": "git", diff --git a/src/gateware/kasli_soc.py b/src/gateware/kasli_soc.py index 36dfad96..d33e4e96 100755 --- a/src/gateware/kasli_soc.py +++ b/src/gateware/kasli_soc.py @@ -14,8 +14,8 @@ from misoc.integration import cpu_interface from artiq.coredevice import jsondesc from artiq.gateware import rtio, eem_7series +from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path from artiq.gateware.rtio.phy import ttl_simple -from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier from artiq.gateware.drtio.transceiver import gtx_7series from artiq.gateware.drtio.siphaser import SiPhaser7Series from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer @@ -25,57 +25,9 @@ import dma import analyzer import acpki import drtio_aux_controller +import zynq_clocking -class RTIOCRG(Module, AutoCSR): - def __init__(self, platform): - self.pll_reset = CSRStorage(reset=1) - self.pll_locked = CSRStatus() - self.clock_domains.cd_rtio = ClockDomain() - self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) - clk_synth = platform.request("cdr_clk_clean_fabric") - clk_synth_se = Signal() - platform.add_period_constraint(clk_synth.p, 8.0) - self.specials += [ - Instance("IBUFGDS", - p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="FALSE", - i_I=clk_synth.p, i_IB=clk_synth.n, o_O=clk_synth_se), - ] - - pll_locked = Signal() - rtio_clk = Signal() - rtiox4_clk = Signal() - fb_clk = Signal() - self.specials += [ - Instance("PLLE2_ADV", - p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, - p_BANDWIDTH="HIGH", - p_REF_JITTER1=0.001, - p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0, - i_CLKIN2=clk_synth_se, - # Warning: CLKINSEL=0 means CLKIN2 is selected - i_CLKINSEL=0, - - # VCO @ 1.5GHz when using 125MHz input - p_CLKFBOUT_MULT=12, p_DIVCLK_DIVIDE=1, - i_CLKFBIN=fb_clk, - i_RST=self.pll_reset.storage, - - o_CLKFBOUT=fb_clk, - - p_CLKOUT0_DIVIDE=3, p_CLKOUT0_PHASE=0.0, - o_CLKOUT0=rtiox4_clk, - - p_CLKOUT1_DIVIDE=12, p_CLKOUT1_PHASE=0.0, - o_CLKOUT1=rtio_clk), - Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk), - Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), - - AsyncResetSynchronizer(self.cd_rtio, ~pll_locked), - MultiReg(pll_locked, self.pll_locked.status) - ] - - eem_iostandard_dict = { 0: "LVDS_25", 1: "LVDS_25", @@ -109,6 +61,23 @@ class SMAClkinForward(Module): ] +class GTP125BootstrapClock(Module): + def __init__(self, platform): + self.clock_domains.cd_bootstrap = ClockDomain(reset_less=True) + self.cd_bootstrap.clk.attr.add("keep") + + bootstrap_125 = platform.request("clk125_gtp") + bootstrap_se = Signal() + platform.add_period_constraint(bootstrap_125.p, 8.0) + self.specials += [ + Instance("IBUFDS_GTE2", + p_CLKSWING_CFG="0b11", + i_CEB=0, + i_I=bootstrap_125.p, i_IB=bootstrap_125.n, o_O=bootstrap_se), + Instance("BUFG", i_I=bootstrap_se, o_O=self.cd_bootstrap.clk) + ] + + class GenericStandalone(SoCCore): def __init__(self, description, acpki=False): self.acpki = acpki @@ -121,23 +90,30 @@ class GenericStandalone(SoCCore): ident = description["variant"] if self.acpki: ident = "acpki_" + ident - SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident) - - platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]") - platform.add_platform_command("set_input_jitter clk_fpga_0 0.24") + SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident, ps_cd_sys=False) self.submodules += SMAClkinForward(self.platform) self.rustc_cfg["has_si5324"] = None self.rustc_cfg["si5324_soft_reset"] = None + clk_synth = platform.request("cdr_clk_clean_fabric") + clk_synth_se = Signal() + platform.add_period_constraint(clk_synth.p, 8.0) + + self.specials += Instance("IBUFGDS", + p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="FALSE", + i_I=clk_synth.p, i_IB=clk_synth.n, o_O=clk_synth_se) + fix_serdes_timing_path(platform) + self.submodules.bootstrap = GTP125BootstrapClock(self.platform) + + + self.submodules.sys_crg = zynq_clocking.SYSCRG(self.platform, self.ps7, clk_synth_se) + platform.add_false_path_constraints( + self.bootstrap.cd_bootstrap.clk, self.sys_crg.cd_sys.clk) + self.csr_devices.append("sys_crg") self.crg = self.ps7 # HACK for eem_7series to find the clock - self.submodules.rtio_crg = RTIOCRG(self.platform) - self.csr_devices.append("rtio_crg") - self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.) - self.platform.add_false_path_constraints( - self.ps7.cd_sys.clk, - self.rtio_crg.cd_rtio.clk) + self.crg.cd_sys = self.sys_crg.cd_sys self.rtio_channels = [] has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"]) @@ -153,7 +129,7 @@ class GenericStandalone(SoCCore): self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.rtio_channels.append(rtio.LogChannel()) - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) self.submodules.rtio_core = rtio.Core(self.rtio_tsc, self.rtio_channels) self.csr_devices.append("rtio_core") @@ -189,13 +165,12 @@ class GenericStandalone(SoCCore): self.add_csr_group("grabber", self.grabber_csr_group) for grabber in self.grabber_csr_group: self.platform.add_false_path_constraints( - self.rtio_crg.cd_rtio.clk, getattr(self, grabber).deserializer.cd_cl.clk) + self.sys_crg.cd_sys.clk, getattr(self, grabber).deserializer.cd_cl.clk) class GenericMaster(SoCCore): def __init__(self, description, acpki=False): - sys_clk_freq = 125e6 - rtio_clk_freq = description["rtio_frequency"] + clk_freq = description["rtio_frequency"] self.acpki = acpki self.rustc_cfg = dict() @@ -207,10 +182,7 @@ class GenericMaster(SoCCore): ident = description["variant"] if self.acpki: ident = "acpki_" + ident - SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident) - - platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]") - platform.add_platform_command("set_input_jitter clk_fpga_0 0.24") + SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident, ps_cd_sys=False) self.submodules += SMAClkinForward(self.platform) @@ -219,12 +191,25 @@ class GenericMaster(SoCCore): self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("clk_gtp"), pads=data_pads, - sys_clk_freq=sys_clk_freq) + clk_freq=clk_freq) self.csr_devices.append("drtio_transceiver") + txout_buf = Signal() + gtx0 = self.drtio_transceiver.gtxs[0] + self.specials += Instance("BUFG", i_I=gtx0.txoutclk, o_O=txout_buf) + + self.submodules.bootstrap = GTP125BootstrapClock(self.platform) + self.submodules.sys_crg = zynq_clocking.SYSCRG( + self.platform, + self.ps7, + txout_buf, + clk_sw=gtx0.tx_init.done) + self.csr_devices.append("sys_crg") self.crg = self.ps7 # HACK for eem_7series to find the clock - self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) - self.csr_devices.append("rtio_crg") + self.crg.cd_sys = self.sys_crg.cd_sys + platform.add_false_path_constraints( + self.bootstrap.cd_bootstrap.clk, self.sys_crg.cd_sys.clk) + fix_serdes_timing_path(platform) self.rustc_cfg["has_si5324"] = None self.rustc_cfg["si5324_soft_reset"] = None @@ -243,7 +228,7 @@ class GenericMaster(SoCCore): self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.rtio_channels.append(rtio.LogChannel()) - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) drtio_csr_group = [] drtioaux_csr_group = [] @@ -319,8 +304,7 @@ class GenericMaster(SoCCore): class GenericSatellite(SoCCore): def __init__(self, description, acpki=False): - sys_clk_freq = 125e6 - rtio_clk_freq = description["rtio_frequency"] + clk_freq = description["rtio_frequency"] self.acpki = acpki self.rustc_cfg = dict() @@ -332,24 +316,32 @@ class GenericSatellite(SoCCore): ident = description["variant"] if self.acpki: ident = "acpki_" + ident - SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident) + SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident, ps_cd_sys=False) - platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]") - platform.add_platform_command("set_input_jitter clk_fpga_0 0.24") - - self.crg = self.ps7 # HACK for eem_7series to find the clock - self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) - self.csr_devices.append("rtio_crg") - self.rustc_cfg["has_rtio_crg"] = None - data_pads = [platform.request("sfp", i) for i in range(4)] self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("clk_gtp"), pads=data_pads, - sys_clk_freq=sys_clk_freq) + clk_freq=clk_freq) self.csr_devices.append("drtio_transceiver") + txout_buf = Signal() + gtx0 = self.drtio_transceiver.gtxs[0] + self.specials += Instance("BUFG", i_I=gtx0.txoutclk, o_O=txout_buf) + + self.submodules.bootstrap = GTP125BootstrapClock(self.platform) + self.submodules.sys_crg = zynq_clocking.SYSCRG( + self.platform, + self.ps7, + txout_buf, + clk_sw=gtx0.tx_init.done) + platform.add_false_path_constraints( + self.bootstrap.cd_bootstrap.clk, self.sys_crg.cd_sys.clk) + self.csr_devices.append("sys_crg") + self.crg = self.ps7 # HACK for eem_7series to find the clock + self.crg.cd_sys = self.sys_crg.cd_sys + self.rtio_channels = [] has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"]) if has_grabber: @@ -364,7 +356,7 @@ class GenericSatellite(SoCCore): self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.rtio_channels.append(rtio.LogChannel()) - self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) drtioaux_csr_group = [] drtioaux_memory_group = [] @@ -435,7 +427,7 @@ class GenericSatellite(SoCCore): self.submodules.cri_con = rtio.CRIInterconnectShared( [self.drtiosat.cri], [self.local_io.cri] + self.drtio_cri, - mode="sync", enable_routing=True) + enable_routing=True) self.csr_devices.append("cri_con") self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) @@ -444,31 +436,22 @@ class GenericSatellite(SoCCore): self.submodules.rtio_moninj = rtio.MonInj(self.rtio_channels) self.csr_devices.append("rtio_moninj") - rtio_clk_period = 1e9/rtio_clk_freq - self.rustc_cfg["rtio_frequency"] = str(rtio_clk_freq/1e6) + rtio_clk_period = 1e9/clk_freq + self.rustc_cfg["rtio_frequency"] = str(clk_freq/1e6) self.submodules.siphaser = SiPhaser7Series( si5324_clkin=platform.request("cdr_clk"), rx_synchronizer=self.rx_synchronizer, ultrascale=False, rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) self.csr_devices.append("siphaser") self.rustc_cfg["has_si5324"] = None self.rustc_cfg["has_siphaser"] = None self.rustc_cfg["si5324_soft_reset"] = None gtx0 = self.drtio_transceiver.gtxs[0] - platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period) - platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period) platform.add_false_path_constraints( - self.crg.cd_sys.clk, gtx0.txoutclk, gtx0.rxoutclk) - for gtx in self.drtio_transceiver.gtxs[1:]: - platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, gtx.rxoutclk) if has_grabber: self.rustc_cfg["has_grabber"] = None diff --git a/src/gateware/test_dma.py b/src/gateware/test_dma.py index 03816645..456205f5 100644 --- a/src/gateware/test_dma.py +++ b/src/gateware/test_dma.py @@ -168,7 +168,7 @@ class FullStackTB(Module): bus = axi.Interface(ws*8) self.memory = AXIMemorySim(bus, sequence) self.submodules.dut = dma.DMA(bus) - self.submodules.tsc = rtio.TSC("async") + self.submodules.tsc = rtio.TSC() self.submodules.rtio = rtio.Core(self.tsc, rtio_channels) self.comb += self.dut.cri.connect(self.rtio.cri) @@ -229,7 +229,7 @@ class TestDMA(unittest.TestCase): do_dma(tb.dut, 0), monitor(), (None for _ in range(70)), tb.memory.ar(), tb.memory.r() - ]}, {"sys": 8, "rsys": 8, "rtio": 8, "rio": 8, "rio_phy": 8}) + ]}, {"sys": 8, "rsys": 8, "rio": 8, "rio_phy": 8}) correct_changes = [(timestamp + 11, channel) for channel, timestamp, _, _ in test_writes_full_stack] diff --git a/src/gateware/zc706.py b/src/gateware/zc706.py index 6bb7b4c2..13f7feec 100755 --- a/src/gateware/zc706.py +++ b/src/gateware/zc706.py @@ -15,7 +15,7 @@ from misoc.cores import gpio from artiq.gateware import rtio, nist_clock, nist_qc2 from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2 -from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier, fix_serdes_timing_path +from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path from artiq.gateware.drtio.transceiver import gtx_7series from artiq.gateware.drtio.siphaser import SiPhaser7Series from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer @@ -25,50 +25,7 @@ import dma import analyzer import acpki import drtio_aux_controller - - -class RTIOCRG(Module, AutoCSR): - def __init__(self, platform, rtio_internal_clk): - self.clock_sel = CSRStorage() - self.pll_reset = CSRStorage(reset=1) - self.pll_locked = CSRStatus() - self.clock_domains.cd_rtio = ClockDomain() - self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) - - rtio_external_clk = Signal() - user_sma_clock = platform.request("user_sma_clock") - platform.add_period_constraint(user_sma_clock.p, 8.0) - self.specials += Instance("IBUFDS", - i_I=user_sma_clock.p, i_IB=user_sma_clock.n, - o_O=rtio_external_clk) - - pll_locked = Signal() - rtio_clk = Signal() - rtiox4_clk = Signal() - self.specials += [ - Instance("PLLE2_ADV", - p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, - - p_REF_JITTER1=0.01, - p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0, - i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk, - # Warning: CLKINSEL=0 means CLKIN2 is selected - i_CLKINSEL=~self.clock_sel.storage, - - # VCO @ 1GHz when using 125MHz input - p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1, - i_CLKFBIN=self.cd_rtio.clk, - i_RST=self.pll_reset.storage, - - o_CLKFBOUT=rtio_clk, - - p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0, - o_CLKOUT0=rtiox4_clk), - Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk), - Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), - AsyncResetSynchronizer(self.cd_rtio, ~pll_locked), - MultiReg(pll_locked, self.pll_locked.status) - ] +import zynq_clocking class SMAClkinForward(Module): @@ -84,6 +41,37 @@ class SMAClkinForward(Module): ] +class CLK200BootstrapClock(Module): + def __init__(self, platform, freq=125e6): + self.clock_domains.cd_bootstrap = ClockDomain(reset_less=True) + self.cd_bootstrap.clk.attr.add("keep") + + clk200 = platform.request("clk200") + clk200_se = Signal() + + pll_fb = Signal() + pll_clkout = Signal() + assert freq in [125e6, 100e6] + divide = int(1e9/freq) + self.specials += [ + Instance("IBUFDS", + i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se), + Instance("PLLE2_BASE", + p_CLKIN1_PERIOD=5.0, + i_CLKIN1=clk200_se, + i_CLKFBIN=pll_fb, + o_CLKFBOUT=pll_fb, + + # VCO @ 1GHz + p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1, + + # 125MHz/100MHz for bootstrap + p_CLKOUT1_DIVIDE=divide, p_CLKOUT1_PHASE=0.0, o_CLKOUT1=pll_clkout, + ), + Instance("BUFG", i_I=pll_clkout, o_O=self.cd_bootstrap.clk) + ] + + # The NIST backplanes require setting VADJ to 3.3V by reprogramming the power supply. # This also changes the I/O standard for some on-board LEDs. leds_fmc33 = [ @@ -135,9 +123,6 @@ def prepare_zc706_platform(platform): platform.toolchain.bitstream_commands.extend([ "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", ]) - platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]") - platform.add_platform_command("set_input_jitter clk_fpga_0 0.24") - class ZC706(SoCCore): def __init__(self, acpki=False): @@ -150,18 +135,37 @@ class ZC706(SoCCore): ident = self.__class__.__name__ if self.acpki: ident = "acpki_" + ident - SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident) + SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident, ps_cd_sys=False) - self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk) - self.csr_devices.append("rtio_crg") - self.rustc_cfg["has_rtio_crg_clock_sel"] = None - self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.) - self.platform.add_false_path_constraints( - self.ps7.cd_sys.clk, - self.rtio_crg.cd_rtio.clk) + platform.add_extension(si5324_fmc33) + self.comb += platform.request("si5324_33").rst_n.eq(1) + + cdr_clk = Signal() + cdr_clk_buf = Signal() + si5324_out = platform.request("si5324_clkout") + platform.add_period_constraint(si5324_out.p, 8.0) + self.specials += [ + Instance("IBUFDS_GTE2", + i_CEB=0, + i_I=si5324_out.p, i_IB=si5324_out.n, + o_O=cdr_clk, + p_CLKCM_CFG="0b1", + p_CLKRCV_TRST="0b1", + p_CLKSWING_CFG="0b11"), + Instance("BUFG", i_I=cdr_clk, o_O=cdr_clk_buf) + ] + self.rustc_cfg["has_si5324"] = None + self.rustc_cfg["si5324_as_synthesizer"] = None + self.rustc_cfg["si5324_soft_reset"] = None + + self.submodules.bootstrap = CLK200BootstrapClock(platform) + self.submodules.sys_crg = zynq_clocking.SYSCRG(self.platform, self.ps7, cdr_clk_buf) + platform.add_false_path_constraints( + self.bootstrap.cd_bootstrap.clk, self.sys_crg.cd_sys.clk) + self.csr_devices.append("sys_crg") def add_rtio(self, rtio_channels): - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) self.csr_devices.append("rtio_core") @@ -198,20 +202,17 @@ class _MasterBase(SoCCore): self.acpki = acpki self.rustc_cfg = dict() + clk_freq = 100e6 if drtio100mhz else 125e6 + platform = zc706.Platform() prepare_zc706_platform(platform) ident = self.__class__.__name__ if self.acpki: ident = "acpki_" + ident - SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident) + SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident, ps_cd_sys=False) platform.add_extension(si5324_fmc33) - self.sys_clk_freq = 125e6 - rtio_clk_freq = 100e6 if drtio100mhz else self.sys_clk_freq - - platform = self.platform - self.comb += platform.request("sfp_tx_disable_n").eq(1) data_pads = [ platform.request("sfp"), @@ -224,11 +225,23 @@ class _MasterBase(SoCCore): self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), pads=data_pads, - sys_clk_freq=self.sys_clk_freq, - rtio_clk_freq=rtio_clk_freq) + clk_freq=clk_freq) self.csr_devices.append("drtio_transceiver") - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) + txout_buf = Signal() + gtx0 = self.drtio_transceiver.gtxs[0] + self.specials += Instance("BUFG", i_I=gtx0.txoutclk, o_O=txout_buf) + self.submodules.bootstrap = CLK200BootstrapClock(platform, clk_freq) + self.submodules.sys_crg = zynq_clocking.SYSCRG( + self.platform, + self.ps7, + txout_buf, + clk_sw=gtx0.tx_init.done, + freq=clk_freq) + platform.add_false_path_constraints( + self.bootstrap.cd_bootstrap.clk, self.sys_crg.cd_sys.clk) + self.csr_devices.append("sys_crg") drtio_csr_group = [] drtioaux_csr_group = [] @@ -271,28 +284,20 @@ class _MasterBase(SoCCore): self.rustc_cfg["has_si5324"] = None self.rustc_cfg["si5324_as_synthesizer"] = None - rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq # Constrain TX & RX timing for the first transceiver channel # (First channel acts as master for phase alignment for all channels' TX) - gtx0 = self.drtio_transceiver.gtxs[0] - platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period) - platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period) platform.add_false_path_constraints( - self.ps7.cd_sys.clk, gtx0.txoutclk, gtx0.rxoutclk) # Constrain RX timing for the each transceiver channel # (Each channel performs single-lane phase alignment for RX) for gtx in self.drtio_transceiver.gtxs[1:]: - platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period) platform.add_false_path_constraints( - self.ps7.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk) + gtx0.txoutclk, gtx.rxoutclk) - self.submodules.rtio_crg = RTIOClockMultiplier(self.sys_clk_freq) - self.csr_devices.append("rtio_crg") - fix_serdes_timing_path(self.platform) + fix_serdes_timing_path(platform) def add_rtio(self, rtio_channels): - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) self.csr_devices.append("rtio_core") @@ -314,7 +319,7 @@ class _MasterBase(SoCCore): self.submodules.cri_con = rtio.CRIInterconnectShared( [self.rtio.cri, self.rtio_dma.cri], [self.rtio_core.cri] + self.drtio_cri, - mode="sync", enable_routing=True) + enable_routing=True) self.csr_devices.append("cri_con") self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) @@ -333,19 +338,17 @@ class _SatelliteBase(SoCCore): self.acpki = acpki self.rustc_cfg = dict() + clk_freq = 100e6 if drtio100mhz else 125e6 + platform = zc706.Platform() prepare_zc706_platform(platform) ident = self.__class__.__name__ if self.acpki: ident = "acpki_" + ident - SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident) + SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident, ps_cd_sys=False) platform.add_extension(si5324_fmc33) - self.sys_clk_freq = 125e6 - rtio_clk_freq = 100e6 if drtio100mhz else self.sys_clk_freq - platform = self.platform - # SFP self.comb += platform.request("sfp_tx_disable_n").eq(0) data_pads = [ @@ -353,16 +356,33 @@ class _SatelliteBase(SoCCore): platform.request("user_sma_mgt") ] - self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), pads=data_pads, - sys_clk_freq=self.sys_clk_freq, - rtio_clk_freq=rtio_clk_freq) + clk_freq=clk_freq) self.csr_devices.append("drtio_transceiver") + txout_buf = Signal() + txout_buf.attr.add("keep") + gtx0 = self.drtio_transceiver.gtxs[0] + self.specials += Instance( + "BUFG", + i_I=gtx0.txoutclk, + o_O=txout_buf) + self.submodules.bootstrap = CLK200BootstrapClock(platform, clk_freq) + self.submodules.sys_crg = zynq_clocking.SYSCRG( + self.platform, + self.ps7, + txout_buf, + clk_sw=gtx0.tx_init.done, + freq=clk_freq) + platform.add_false_path_constraints( + self.bootstrap.cd_bootstrap.clk, self.sys_crg.cd_sys.clk) + self.csr_devices.append("sys_crg") + drtioaux_csr_group = [] drtioaux_memory_group = [] drtiorep_csr_group = [] @@ -420,7 +440,7 @@ class _SatelliteBase(SoCCore): ultrascale=False, rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq) platform.add_false_path_constraints( - self.ps7.cd_sys.clk, self.siphaser.mmcm_freerun_output) + self.sys_crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) self.csr_devices.append("siphaser") self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324_33").rst_n) self.csr_devices.append("si5324_rst_n") @@ -430,23 +450,15 @@ class _SatelliteBase(SoCCore): rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq # Constrain TX & RX timing for the first transceiver channel # (First channel acts as master for phase alignment for all channels' TX) - gtx0 = self.drtio_transceiver.gtxs[0] - platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period) - platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period) platform.add_false_path_constraints( - self.ps7.cd_sys.clk, gtx0.txoutclk, gtx0.rxoutclk) # Constrain RX timing for the each transceiver channel # (Each channel performs single-lane phase alignment for RX) for gtx in self.drtio_transceiver.gtxs[1:]: - platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period) platform.add_false_path_constraints( - self.ps7.cd_sys.clk, gtx.rxoutclk) + self.sys_crg.cd_sys.clk, gtx.rxoutclk) - self.submodules.rtio_crg = RTIOClockMultiplier(self.sys_clk_freq) - self.csr_devices.append("rtio_crg") - self.rustc_cfg["has_rtio_crg"] = None - fix_serdes_timing_path(self.platform) + fix_serdes_timing_path(platform) def add_rtio(self, rtio_channels): self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) @@ -468,7 +480,7 @@ class _SatelliteBase(SoCCore): self.submodules.cri_con = rtio.CRIInterconnectShared( [self.drtiosat.cri], [self.local_io.cri] + self.drtio_cri, - mode="sync", enable_routing=True) + enable_routing=True) self.csr_devices.append("cri_con") self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) @@ -616,6 +628,7 @@ class _NIST_QC2_RTIO: class NIST_CLOCK(ZC706, _NIST_CLOCK_RTIO): def __init__(self, acpki, drtio100mhz): ZC706.__init__(self, acpki) + self.submodules += SMAClkinForward(self.platform) _NIST_CLOCK_RTIO.__init__(self) class NIST_CLOCK_Master(_MasterBase, _NIST_CLOCK_RTIO): @@ -631,6 +644,7 @@ class NIST_CLOCK_Satellite(_SatelliteBase, _NIST_CLOCK_RTIO): class NIST_QC2(ZC706, _NIST_QC2_RTIO): def __init__(self, acpki, drtio100mhz): ZC706.__init__(self, acpki) + self.submodules += SMAClkinForward(self.platform) _NIST_QC2_RTIO.__init__(self) class NIST_QC2_Master(_MasterBase, _NIST_QC2_RTIO): diff --git a/src/gateware/zynq_clocking.py b/src/gateware/zynq_clocking.py new file mode 100644 index 00000000..72bb894f --- /dev/null +++ b/src/gateware/zynq_clocking.py @@ -0,0 +1,122 @@ +from migen import * +from migen.genlib.cdc import MultiReg +from migen.genlib.resetsync import AsyncResetSynchronizer +from misoc.interconnect.csr import * + + +class ClockSwitchFSM(Module): + def __init__(self): + self.i_clk_sw = Signal() + + self.o_clk_sw = Signal() + self.o_reset = Signal() + + ### + + i_switch = Signal() + o_switch = Signal() + reset = Signal() + + # at 125MHz bootstrap cd, will get around 0.5ms + delay_counter = Signal(16, reset=0xFFFF) + + # register to prevent glitches + self.sync.bootstrap += [ + self.o_clk_sw.eq(o_switch), + self.o_reset.eq(reset), + ] + + self.o_clk_sw.attr.add("no_retiming") + self.o_reset.attr.add("no_retiming") + self.i_clk_sw.attr.add("no_retiming") + i_switch.attr.add("no_retiming") + + self.specials += MultiReg(self.i_clk_sw, i_switch, "bootstrap") + + fsm = ClockDomainsRenamer("bootstrap")(FSM(reset_state="START")) + + self.submodules += fsm + + fsm.act("START", + If(i_switch & ~o_switch, + NextState("RESET_START")) + ) + + fsm.act("RESET_START", + reset.eq(1), + If(delay_counter == 0, + NextValue(delay_counter, 0xFFFF), + NextState("CLOCK_SWITCH") + ).Else( + NextValue(delay_counter, delay_counter-1), + ) + ) + + fsm.act("CLOCK_SWITCH", + reset.eq(1), + NextValue(o_switch, 1), + NextValue(delay_counter, delay_counter-1), + If(delay_counter == 0, + NextState("END")) + ) + fsm.act("END", + NextValue(o_switch, 1), + reset.eq(0)) + + +class SYSCRG(Module, AutoCSR): + def __init__(self, platform, ps7, main_clk, clk_sw=None, freq=125e6): + # assumes bootstrap clock is same freq as main and sys output + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) + + self.current_clock = CSRStatus() + + self.cd_sys.clk.attr.add("keep") + + bootstrap_clk = ClockSignal("bootstrap") + + period = 1e9/freq + + pll_locked = Signal() + pll_sys = Signal() + pll_sys4x = Signal() + fb_clk = Signal() + + self.submodules.clk_sw_fsm = ClockSwitchFSM() + + if clk_sw is None: + self.clock_switch = CSRStorage() + self.comb += self.clk_sw_fsm.i_clk_sw.eq(self.clock_switch.storage) + else: + self.comb += self.clk_sw_fsm.i_clk_sw.eq(clk_sw) + + self.specials += [ + Instance("PLLE2_ADV", + p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, + p_BANDWIDTH="HIGH", + p_REF_JITTER1=0.001, + p_CLKIN1_PERIOD=period, i_CLKIN1=main_clk, + p_CLKIN2_PERIOD=period, i_CLKIN2=bootstrap_clk, + i_CLKINSEL=self.clk_sw_fsm.o_clk_sw, + + # VCO @ 1.5GHz when using 125MHz input + # 1.2GHz for 100MHz (zc706) + p_CLKFBOUT_MULT=12, p_DIVCLK_DIVIDE=1, + i_CLKFBIN=fb_clk, + i_RST=self.clk_sw_fsm.o_reset, + + o_CLKFBOUT=fb_clk, + + p_CLKOUT0_DIVIDE=3, p_CLKOUT0_PHASE=0.0, + o_CLKOUT0=pll_sys4x, + + p_CLKOUT1_DIVIDE=12, p_CLKOUT1_PHASE=0.0, + o_CLKOUT1=pll_sys), + Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk), + Instance("BUFG", i_I=pll_sys4x, o_O=self.cd_sys4x.clk), + + AsyncResetSynchronizer(self.cd_sys, ~pll_locked), + ] + + self.comb += self.current_clock.status.eq(self.clk_sw_fsm.o_clk_sw) diff --git a/src/libboard_artiq/src/lib.rs b/src/libboard_artiq/src/lib.rs index b85481c6..454a819d 100644 --- a/src/libboard_artiq/src/lib.rs +++ b/src/libboard_artiq/src/lib.rs @@ -29,8 +29,6 @@ pub mod drtioaux_async; pub mod mem; use core::{cmp, str}; -use libboard_zynq::slcr; -use libregister::RegisterW; pub fn identifier_read(buf: &mut [u8]) -> &str { unsafe { @@ -44,26 +42,3 @@ pub fn identifier_read(buf: &mut [u8]) -> &str { str::from_utf8_unchecked(&buf[..len as usize]) } } - -pub fn init_gateware() { - // Set up PS->PL clocks - slcr::RegisterBlock::unlocked(|slcr| { - // As we are touching the mux, the clock may glitch, so reset the PL. - slcr.fpga_rst_ctrl.write( - slcr::FpgaRstCtrl::zeroed() - .fpga0_out_rst(true) - .fpga1_out_rst(true) - .fpga2_out_rst(true) - .fpga3_out_rst(true) - ); - slcr.fpga0_clk_ctrl.write( - slcr::Fpga0ClkCtrl::zeroed() - .src_sel(slcr::PllSource::IoPll) - .divisor0(8) - .divisor1(1) - ); - slcr.fpga_rst_ctrl.write( - slcr::FpgaRstCtrl::zeroed() - ); - }); -} \ No newline at end of file diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index a925be98..fe47a04b 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -21,7 +21,7 @@ use nb; use void::Void; use libconfig::Config; use libcortex_a9::l2c::enable_l2_cache; -use libboard_artiq::{logger, identifier_read, init_gateware, pl}; +use libboard_artiq::{logger, identifier_read, pl}; const ASYNC_ERROR_COLLISION: u8 = 1 << 0; const ASYNC_ERROR_BUSY: u8 = 1 << 1; @@ -111,7 +111,6 @@ pub fn main_core0() { ram::init_alloc_core0(); gic::InterruptController::gic(mpcore::RegisterBlock::mpcore()).enable_interrupts(); - init_gateware(); info!("gateware ident: {}", identifier_read(&mut [0; 64])); i2c::init(); @@ -142,7 +141,7 @@ pub fn main_core0() { Config::new_dummy() } }; - + rtio_clocking::init(&mut timer, &cfg); task::spawn(report_async_rtio_errors()); diff --git a/src/runtime/src/rtio_clocking.rs b/src/runtime/src/rtio_clocking.rs index de0f4724..5340e6df 100644 --- a/src/runtime/src/rtio_clocking.rs +++ b/src/runtime/src/rtio_clocking.rs @@ -66,41 +66,26 @@ fn get_rtio_clock_cfg(cfg: &Config) -> RtioClock { res } - -fn init_rtio(timer: &mut GlobalTimer, _clk: RtioClock) { - #[cfg(has_rtio_crg_clock_sel)] - let clock_sel = match _clk { - RtioClock::Ext0_Bypass => { - info!("Using bypassed external clock"); - 1 - }, - RtioClock::Int_125 => { - info!("Using internal RTIO clock"); - 0 - }, - _ => { - warn!("rtio_clock setting '{:?}' is not supported. Using default internal RTIO clock instead", _clk); - 0 - } - }; - +#[cfg(not(has_drtio))] +fn init_rtio(timer: &mut GlobalTimer) { + info!("Switching SYS clocks..."); unsafe { - pl::csr::rtio_crg::pll_reset_write(1); - #[cfg(has_rtio_crg_clock_sel)] - pl::csr::rtio_crg::clock_sel_write(clock_sel); - pl::csr::rtio_crg::pll_reset_write(0); - } - timer.delay_ms(1); - let locked = unsafe { pl::csr::rtio_crg::pll_locked_read() != 0 }; - if locked { - info!("RTIO PLL locked"); - } else { - panic!("RTIO PLL failed to lock"); + pl::csr::sys_crg::clock_switch_write(1); } + // if it's not locked, it will hang at the CSR. + timer.delay_ms(20); // wait for CPLL/QPLL/SYS PLL lock + let clk = unsafe { pl::csr::sys_crg::current_clock_read() }; + if clk == 1 { + info!("SYS CLK switched successfully"); + } else { + panic!("SYS CLK did not switch"); + } unsafe { pl::csr::rtio_core::reset_phy_write(1); } + info!("SYS PLL locked"); + } #[cfg(has_drtio)] @@ -109,8 +94,16 @@ fn init_drtio(timer: &mut GlobalTimer) unsafe { pl::csr::drtio_transceiver::stable_clkin_write(1); } - timer.delay_ms(2); // wait for CPLL/QPLL lock + + timer.delay_ms(20); // wait for CPLL/QPLL/SYS PLL lock + let clk = unsafe { pl::csr::sys_crg::current_clock_read() }; + if clk == 1 { + info!("SYS CLK switched successfully"); + } else { + panic!("SYS CLK did not switch"); + } unsafe { + pl::csr::rtio_core::reset_phy_write(1); pl::csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); } } @@ -249,9 +242,10 @@ pub fn init(timer: &mut GlobalTimer, cfg: &Config) { _ => setup_si5324(i2c, timer, clk), } } + #[cfg(has_drtio)] init_drtio(timer); - init_rtio(timer, clk); - + #[cfg(not(has_drtio))] + init_rtio(timer); } \ No newline at end of file diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index 76a2f589..de66c1ab 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -22,7 +22,7 @@ use libboard_zynq::{i2c::I2c, timer::GlobalTimer, time::Milliseconds, print, pri use libsupport_zynq::ram; #[cfg(has_si5324)] use libboard_artiq::si5324; -use libboard_artiq::{pl::csr, drtio_routing, drtioaux, logger, identifier_read, init_gateware}; +use libboard_artiq::{pl::csr, drtio_routing, drtioaux, logger, identifier_read}; use libcortex_a9::{spin_lock_yield, interrupt_handler, regs::{MPIDR, SP}, notify_spin_lock, asm, l2c::enable_l2_cache}; use libregister::{RegisterW, RegisterR}; @@ -390,25 +390,6 @@ fn drtiosat_process_errors() { } } - -#[cfg(has_rtio_crg)] -fn init_rtio_crg(timer: &mut GlobalTimer) { - unsafe { - csr::rtio_crg::pll_reset_write(0); - } - timer.delay_us(150); - let locked = unsafe { csr::rtio_crg::pll_locked_read() != 0 }; - if !locked { - error!("RTIO clock failed"); - } - else { - info!("RTIO PLL locked"); - } -} - -#[cfg(not(has_rtio_crg))] -fn init_rtio_crg(_timer: &mut GlobalTimer) { } - fn hardware_tick(ts: &mut u64, timer: &mut GlobalTimer) { let now = timer.get_time(); let mut ts_ms = Milliseconds(*ts); @@ -458,8 +439,6 @@ pub extern fn main_core0() -> i32 { buffer_logger.set_uart_log_level(log::LevelFilter::Info); buffer_logger.register(); log::set_max_level(log::LevelFilter::Info); - - init_gateware(); info!("ARTIQ satellite manager starting..."); info!("gateware ident {}", identifier_read(&mut [0; 64])); @@ -472,15 +451,22 @@ pub extern fn main_core0() -> i32 { #[cfg(has_si5324)] si5324::setup(&mut i2c, &SI5324_SETTINGS, si5324::Input::Ckin1, &mut timer).expect("cannot initialize Si5324"); + timer.delay_us(100_000); + info!("Switching SYS clocks..."); unsafe { csr::drtio_transceiver::stable_clkin_write(1); } - timer.delay_us(1500); // wait for CPLL/QPLL lock + timer.delay_us(20_000); // wait for CPLL/QPLL/MMCM lock + let clk = unsafe { csr::sys_crg::current_clock_read() }; + if clk == 1 { + info!("SYS CLK switched successfully"); + } else { + panic!("SYS CLK did not switch"); + } unsafe { csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); } - init_rtio_crg(&mut timer); #[cfg(has_drtio_routing)] let mut repeaters = [repeater::Repeater::default(); csr::DRTIOREP.len()];