From 1eb87164be8dad5e82f27083f007cabd41ad36b6 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 28 Oct 2022 16:47:56 +0800 Subject: [PATCH 01/16] kasli: remove rtiocrg, use rtio/sys merge --- artiq/gateware/targets/kasli.py | 63 ++------------------------------- 1 file changed, 2 insertions(+), 61 deletions(-) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 7ed52052b..f080b4fd0 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -27,59 +27,6 @@ from artiq.gateware.drtio import * from artiq.build_soc import * -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) - - if platform.hw_rev == "v2.0": - clk_synth = platform.request("cdr_clk_clean_fabric") - else: - clk_synth = platform.request("si5324_clkout_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) - ] - - class SMAClkinForward(Module): def __init__(self, platform): sma_clkin = platform.request("sma_clkin") @@ -118,6 +65,8 @@ class StandaloneBase(MiniSoC, AMPSoC): integrated_sram_size=8192, ethmac_nrxslots=4, ethmac_ntxslots=4, + clk_freq=kwargs.get("rtio_frequency", 125.0e6), + rtio_sys_merge=True, **kwargs) AMPSoC.__init__(self) add_identifier(self, gateware_identifier_str=gateware_identifier_str) @@ -136,8 +85,6 @@ class StandaloneBase(MiniSoC, AMPSoC): self.config["SI5324_SOFT_RESET"] = None def add_rtio(self, rtio_channels, sed_lanes=8): - self.submodules.rtio_crg = _RTIOCRG(self.platform) - self.csr_devices.append("rtio_crg") fix_serdes_timing_path(self.platform) self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels, lane_count=sed_lanes) @@ -157,10 +104,6 @@ class StandaloneBase(MiniSoC, AMPSoC): self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) self.csr_devices.append("rtio_moninj") - self.platform.add_false_path_constraints( - self.crg.cd_sys.clk, - self.rtio_crg.cd_rtio.clk) - self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.csr_devices.append("rtio_analyzer") @@ -247,8 +190,6 @@ class SUServo(StandaloneBase): self.add_rtio(self.rtio_channels) pads = self.platform.lookup_request("sampler3_adc_data_p") - self.platform.add_false_path_constraints( - pads.clkout, self.rtio_crg.cd_rtio.clk) self.platform.add_false_path_constraints( pads.clkout, self.crg.cd_sys.clk) From a6856a5e4adc3abc424c92c671b44f9033721dd3 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 28 Oct 2022 16:50:10 +0800 Subject: [PATCH 02/16] rtio: remove rtio clock, use sys instead --- artiq/gateware/rtio/cdc.py | 2 +- artiq/gateware/rtio/core.py | 23 ++++++++----------- artiq/gateware/rtio/cri.py | 10 ++------ artiq/gateware/rtio/input_collector.py | 6 ++--- artiq/gateware/rtio/phy/fastino.py | 2 +- artiq/gateware/rtio/phy/grabber.py | 10 ++++---- artiq/gateware/rtio/phy/phaser.py | 4 ++-- artiq/gateware/rtio/phy/ttl_serdes_7series.py | 6 ++--- .../rtio/phy/ttl_serdes_ultrascale.py | 8 +++---- artiq/gateware/rtio/sed/core.py | 4 ++-- artiq/gateware/rtio/tsc.py | 2 +- artiq/gateware/rtio/xilinx_clocking.py | 2 +- 12 files changed, 33 insertions(+), 46 deletions(-) diff --git a/artiq/gateware/rtio/cdc.py b/artiq/gateware/rtio/cdc.py index bd0b11d37..cc0201969 100644 --- a/artiq/gateware/rtio/cdc.py +++ b/artiq/gateware/rtio/cdc.py @@ -15,7 +15,7 @@ class GrayCodeTransfer(Module): # convert to Gray code value_gray_rtio = Signal(width, reset_less=True) - self.sync.rtio += value_gray_rtio.eq(self.i ^ self.i[1:]) + self.sync += value_gray_rtio.eq(self.i ^ self.i[1:]) # transfer to system clock domain value_gray_sys = Signal(width) value_gray_rtio.attr.add("no_retiming") diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 0b26a1126..7b3b6d6fa 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -24,7 +24,7 @@ class Core(Module, AutoCSR): self.sequence_error_channel = CSRStatus(16) # Clocking/Reset - # Create rsys, rio and rio_phy domains based on sys and rtio + # Create rio and rio_phy domains based on sys # with reset controlled by CSR. # # The `rio` CD contains logic that is reset with `core.reset()`. @@ -40,20 +40,15 @@ class Core(Module, AutoCSR): cmd_reset.eq(self.reset.re), cmd_reset_phy.eq(self.reset_phy.re) ] - cmd_reset.attr.add("no_retiming") - cmd_reset_phy.attr.add("no_retiming") - self.clock_domains.cd_rsys = ClockDomain() self.clock_domains.cd_rio = ClockDomain() self.clock_domains.cd_rio_phy = ClockDomain() self.comb += [ - self.cd_rsys.clk.eq(ClockSignal()), - self.cd_rsys.rst.eq(cmd_reset), - self.cd_rio.clk.eq(ClockSignal("rtio")), - self.cd_rio_phy.clk.eq(ClockSignal("rtio")) + self.cd_rio.clk.eq(ClockSignal()), + self.cd_rio.rst.eq(cmd_reset), + self.cd_rio_phy.clk.eq(ClockSignal()), + self.cd_rio_phy.rst.eq(cmd_reset_phy) ] - self.specials += AsyncResetSynchronizer(self.cd_rio, cmd_reset) - self.specials += AsyncResetSynchronizer(self.cd_rio_phy, cmd_reset_phy) # TSC chan_fine_ts_width = max(max(rtlink.get_fine_ts_width(channel.interface.o) @@ -65,7 +60,7 @@ class Core(Module, AutoCSR): # Outputs/Inputs quash_channels = [n for n, c in enumerate(channels) if isinstance(c, LogChannel)] - outputs = SED(channels, tsc.glbl_fine_ts_width, "async", + outputs = SED(channels, tsc.glbl_fine_ts_width, "sync", quash_channels=quash_channels, lane_count=lane_count, fifo_depth=fifo_depth, interface=self.cri) @@ -73,14 +68,14 @@ class Core(Module, AutoCSR): self.comb += outputs.coarse_timestamp.eq(tsc.coarse_ts) self.sync += outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts_sys + 16) - inputs = InputCollector(tsc, channels, "async", + inputs = InputCollector(tsc, channels, "sync", quash_channels=quash_channels, interface=self.cri) self.submodules += inputs # Asychronous output errors - o_collision_sync = BlindTransfer("rio", "rsys", data_width=16) - o_busy_sync = BlindTransfer("rio", "rsys", data_width=16) + o_collision_sync = BlindTransfer("rio", "sys", data_width=16) + o_busy_sync = BlindTransfer("rio", "sys", data_width=16) self.submodules += o_collision_sync, o_busy_sync o_collision = Signal() o_busy = Signal() diff --git a/artiq/gateware/rtio/cri.py b/artiq/gateware/rtio/cri.py index c735b9e5f..8b38f4529 100644 --- a/artiq/gateware/rtio/cri.py +++ b/artiq/gateware/rtio/cri.py @@ -155,10 +155,8 @@ class CRIDecoder(Module): if enable_routing: self.specials.routing_table = Memory(slave_bits, 256) - if mode == "async": + if mode == "async" or mode == "sync": rtp_decoder = self.routing_table.get_port() - elif mode == "sync": - rtp_decoder = self.routing_table.get_port(clock_domain="rtio") else: raise ValueError self.specials += rtp_decoder @@ -199,12 +197,8 @@ class CRISwitch(Module, AutoCSR): # # # - if mode == "async": + if mode == "async" or mode == "sync": selected = self.selected.storage - elif mode == "sync": - self.selected.storage.attr.add("no_retiming") - selected = Signal.like(self.selected.storage) - self.specials += MultiReg(self.selected.storage, selected, "rtio") else: raise ValueError diff --git a/artiq/gateware/rtio/input_collector.py b/artiq/gateware/rtio/input_collector.py index a68f5a7ff..a65fe6d9d 100644 --- a/artiq/gateware/rtio/input_collector.py +++ b/artiq/gateware/rtio/input_collector.py @@ -36,9 +36,9 @@ class InputCollector(Module): sync_io = self.sync sync_cri = self.sync elif mode == "async": - fifo_factory = lambda *args: ClockDomainsRenamer({"write": "rio", "read": "rsys"})(AsyncFIFO(*args)) + fifo_factory = lambda *args: ClockDomainsRenamer({"write": "rio", "read": "sys"})(AsyncFIFO(*args)) sync_io = self.sync.rio - sync_cri = self.sync.rsys + sync_cri = self.sync.sys else: raise ValueError @@ -85,7 +85,7 @@ class InputCollector(Module): if mode == "sync": overflow_trigger = overflow_io elif mode == "async": - overflow_transfer = BlindTransfer("rio", "rsys") + overflow_transfer = BlindTransfer("rio", "sys") self.submodules += overflow_transfer self.comb += overflow_transfer.i.eq(overflow_io) overflow_trigger = overflow_transfer.o diff --git a/artiq/gateware/rtio/phy/fastino.py b/artiq/gateware/rtio/phy/fastino.py index 474bab0f3..9fcc71390 100644 --- a/artiq/gateware/rtio/phy/fastino.py +++ b/artiq/gateware/rtio/phy/fastino.py @@ -120,7 +120,7 @@ class Fastino(Module): ), ] - self.sync.rtio += [ + self.sync += [ self.rtlink.i.stb.eq(self.rtlink.o.stb & self.rtlink.o.address[-1]), self.rtlink.i.data.eq( diff --git a/artiq/gateware/rtio/phy/grabber.py b/artiq/gateware/rtio/phy/grabber.py index 520450c76..f0783fa42 100644 --- a/artiq/gateware/rtio/phy/grabber.py +++ b/artiq/gateware/rtio/phy/grabber.py @@ -21,14 +21,12 @@ class Synchronizer(Module): # # # - for count in counts_in: - count.attr.add("no_retiming") - self.specials += [MultiReg(i, o, "rtio") for i, o in zip(counts_in, self.counts)] + self.comb += [o.eq(i) for i, o in zip(counts_in, self.counts)] - ps = PulseSynchronizer("cl", "rtio") + ps = PulseSynchronizer("cl", "sys") self.submodules += ps self.comb += ps.i.eq(roi_engines[0].out.update) - self.sync.rtio += self.update.eq(ps.o) + self.sync += self.update.eq(ps.o) class Serializer(Module): @@ -85,7 +83,7 @@ class Grabber(Module): roi_engine.cfg.x1, roi_engine.cfg.y1]): roi_boundary = Signal.like(target) roi_boundary.attr.add("no_retiming") - self.sync.rtio += If(self.config.o.stb & (self.config.o.address == 4*n+offset), + self.sync += If(self.config.o.stb & (self.config.o.address == 4*n+offset), roi_boundary.eq(self.config.o.data)) self.specials += MultiReg(roi_boundary, target, "cl") diff --git a/artiq/gateware/rtio/phy/phaser.py b/artiq/gateware/rtio/phy/phaser.py index 557a65d74..94a5400d5 100644 --- a/artiq/gateware/rtio/phy/phaser.py +++ b/artiq/gateware/rtio/phy/phaser.py @@ -10,7 +10,7 @@ class Phy(Module): self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=32, address_width=4, enable_replace=True)) - self.sync.rtio += [ + self.sync += [ If(self.rtlink.o.stb, Array(regs)[self.rtlink.o.address].eq(self.rtlink.o.data) ) @@ -70,7 +70,7 @@ class Base(Module): self.comb += self.serializer.payload.eq(Cat(header.raw_bits(), body)) re_dly = Signal(3) # stage, send, respond - self.sync.rtio += [ + self.sync += [ header.type.eq(1), # body type is baseband data If(self.serializer.stb, self.ch0.dds.stb.eq(1), # synchronize diff --git a/artiq/gateware/rtio/phy/ttl_serdes_7series.py b/artiq/gateware/rtio/phy/ttl_serdes_7series.py index 841032c63..1f467d565 100644 --- a/artiq/gateware/rtio/phy/ttl_serdes_7series.py +++ b/artiq/gateware/rtio/phy/ttl_serdes_7series.py @@ -19,7 +19,7 @@ class _OSERDESE2_8X(Module): p_INIT_OQ=0b11111111 if invert else 0b00000000, o_OQ=self.ser_out, o_TQ=self.t_out, i_RST=ResetSignal("rio_phy"), - i_CLK=ClockSignal("rtiox4"), + i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("rio_phy"), i_D1=o[0] ^ invert, i_D2=o[1] ^ invert, i_D3=o[2] ^ invert, i_D4=o[3] ^ invert, i_D5=o[4] ^ invert, i_D6=o[5] ^ invert, i_D7=o[6] ^ invert, i_D8=o[7] ^ invert, @@ -43,8 +43,8 @@ class _ISERDESE2_8X(Module): o_Q1=i[7], o_Q2=i[6], o_Q3=i[5], o_Q4=i[4], o_Q5=i[3], o_Q6=i[2], o_Q7=i[1], o_Q8=i[0], i_D=self.ser_in, - i_CLK=ClockSignal("rtiox4"), - i_CLKB=~ClockSignal("rtiox4"), + i_CLK=ClockSignal("sys4x"), + i_CLKB=~ClockSignal("sys4x"), i_CE1=1, i_RST=ResetSignal("rio_phy"), i_CLKDIV=ClockSignal("rio_phy")) diff --git a/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py b/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py index 0dbe613ac..3cc0f02ef 100644 --- a/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py +++ b/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py @@ -18,8 +18,8 @@ class _OSERDESE3(Module): p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=self.ser_out, o_T_OUT=self.t_out, - i_RST=ResetSignal("rtio"), - i_CLK=ClockSignal("rtiox"), i_CLKDIV=ClockSignal("rtio"), + i_RST=ResetSignal("sys"), + i_CLK=ClockSignal("rtiox"), i_CLKDIV=ClockSignal("sys"), i_D=self.o, i_T=self.t_in) @@ -39,11 +39,11 @@ class _ISERDESE3(Module): p_DATA_WIDTH=dw, i_D=self.ser_in, - i_RST=ResetSignal("rtio"), + i_RST=ResetSignal("sys"), i_FIFO_RD_EN=0, i_CLK=ClockSignal("rtiox"), i_CLK_B=ClockSignal("rtiox"), # locally inverted - i_CLKDIV=ClockSignal("rtio"), + i_CLKDIV=ClockSignal("sys"), o_Q=Cat(*[self.i[i] for i in reversed(range(dw))])) diff --git a/artiq/gateware/rtio/sed/core.py b/artiq/gateware/rtio/sed/core.py index 7d0b0de4e..2b3611854 100644 --- a/artiq/gateware/rtio/sed/core.py +++ b/artiq/gateware/rtio/sed/core.py @@ -20,8 +20,8 @@ class SED(Module): gates_cdr = lambda x: x output_driver_cdr = lambda x: x elif mode == "async": - lane_dist_cdr = ClockDomainsRenamer("rsys") - fifos_cdr = ClockDomainsRenamer({"write": "rsys", "read": "rio"}) + lane_dist_cdr = ClockDomainsRenamer("sys") + fifos_cdr = ClockDomainsRenamer({"write": "sys", "read": "rio"}) gates_cdr = ClockDomainsRenamer("rio") output_driver_cdr = ClockDomainsRenamer("rio") else: diff --git a/artiq/gateware/rtio/tsc.py b/artiq/gateware/rtio/tsc.py index e93744553..d12c69044 100644 --- a/artiq/gateware/rtio/tsc.py +++ b/artiq/gateware/rtio/tsc.py @@ -30,7 +30,7 @@ class TSC(Module): # # # - self.sync.rtio += If(self.load, + self.sync += If(self.load, self.coarse_ts.eq(self.load_value) ).Else( self.coarse_ts.eq(self.coarse_ts + 1) diff --git a/artiq/gateware/rtio/xilinx_clocking.py b/artiq/gateware/rtio/xilinx_clocking.py index 57e6683c4..20e0c36c6 100644 --- a/artiq/gateware/rtio/xilinx_clocking.py +++ b/artiq/gateware/rtio/xilinx_clocking.py @@ -17,7 +17,7 @@ class RTIOClockMultiplier(Module, AutoCSR): self.specials += [ Instance("MMCME2_BASE", p_CLKIN1_PERIOD=1e9/rtio_clk_freq, - i_CLKIN1=ClockSignal("rtio"), + i_CLKIN1=ClockSignal("sys"), i_RST=self.pll_reset.storage, o_LOCKED=pll_locked, From 458bd8a9278ba3b388019f69e5bdf5ea167371a1 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 28 Oct 2022 16:51:41 +0800 Subject: [PATCH 03/16] kasli_generic: remove rtio clockdomain reference --- artiq/gateware/targets/kasli_generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gateware/targets/kasli_generic.py b/artiq/gateware/targets/kasli_generic.py index bb822f41e..a356aaba1 100755 --- a/artiq/gateware/targets/kasli_generic.py +++ b/artiq/gateware/targets/kasli_generic.py @@ -64,7 +64,7 @@ class GenericStandalone(StandaloneBase): 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.crg.cd_sys.clk, getattr(self, grabber).deserializer.cd_cl.clk) class GenericMaster(MasterBase): From f8eb695c0f8a6423e36403ce7339f8a4b854483c Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 28 Oct 2022 16:53:08 +0800 Subject: [PATCH 04/16] dma test: no more rsys or rtio domains --- artiq/gateware/test/rtio/test_dma.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/gateware/test/rtio/test_dma.py b/artiq/gateware/test/rtio/test_dma.py index c5d220a9f..a8ccac564 100644 --- a/artiq/gateware/test/rtio/test_dma.py +++ b/artiq/gateware/test/rtio/test_dma.py @@ -203,11 +203,11 @@ class TestDMA(unittest.TestCase): run_simulation(tb[32], {"sys": [ do_dma(tb[32].dut, 0), monitor(32), (None for _ in range(70)), - ]}, {"sys": 8, "rsys": 8, "rtio": 8, "rio": 8, "rio_phy": 8}) + ]}, {"sys": 8, "sys": 8, "rio": 8, "rio_phy": 8}) run_simulation(tb[64], {"sys": [ do_dma(tb[64].dut, 0), monitor(64), (None for _ in range(70)), - ]}, {"sys": 8, "rsys": 8, "rtio": 8, "rio": 8, "rio_phy": 8}) + ]}, {"sys": 8, "sys": 8, "rio": 8, "rio_phy": 8}) correct_changes = [(timestamp + 11, channel) for channel, timestamp, _, _ in test_writes_full_stack] From 5cd57e8688226ae1e1b642d7dcfdc84c01868288 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 28 Oct 2022 17:31:34 +0800 Subject: [PATCH 05/16] rtio_clocking: switch clocks and reboot --- artiq/firmware/runtime/rtio_clocking.rs | 72 +++++++++++++++++-------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index f0330b4d9..1c61437d9 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -1,8 +1,10 @@ use board_misoc::config; #[cfg(si5324_as_synthesizer)] use board_artiq::si5324; +#[cfg(any(soc_platform = "kasli", has_drtio))] +use board_misoc::csr; #[cfg(has_drtio)] -use board_misoc::{csr, clock}; +use board_misoc::clock; #[derive(Debug, PartialEq)] #[allow(non_camel_case_types)] @@ -54,9 +56,9 @@ fn get_rtio_clock_cfg() -> RtioClock { return RtioClock::Ext0_Synth0_125to125; #[cfg(all(rtio_frequency = "125.0", not(si5324_ext_ref)))] return RtioClock::Int_125; - #[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref)))] + #[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref), not(soc_platform = "kasli")))] return RtioClock::Int_150; - #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))] + #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref), not(soc_platform = "kasli")))] return RtioClock::Int_100; //in case nothing is set return RtioClock::Int_125; @@ -134,7 +136,7 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { } }, RtioClock::Ext0_Synth0_100to125 => { // 125MHz output, from 100MHz CLKINx reference, 586 Hz loop bandwidth - info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + info!("using 100MHz reference to make 125MHz RTIO clock with PLL"); si5324::FrequencySettings { n1_hs : 10, nc1_ls : 4, @@ -147,7 +149,7 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { } }, RtioClock::Ext0_Synth0_125to125 => { // 125MHz output, from 125MHz CLKINx reference, 606 Hz loop bandwidth - info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + info!("using 125MHz reference to make 125MHz RTIO clock with PLL"); si5324::FrequencySettings { n1_hs : 5, nc1_ls : 8, @@ -197,7 +199,7 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { bwsel : 4, crystal_ref: true } - } + }, _ => { // 125MHz output like above, default (if chosen option is not supported) warn!("rtio_clock setting '{:?}' is not supported. Falling back to default internal 125MHz RTIO clock.", cfg); si5324::FrequencySettings { @@ -225,26 +227,50 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { si5324::setup(&si5324_settings, si5324_ref_input).expect("cannot initialize Si5324"); } +#[cfg(si5324_as_synthesizer)] +fn setup_si5324(clock_cfg: RtioClock) { + #[cfg(soc_platform = "kasli")] + { + let switched = unsafe { + csr::crg::switch_done_read() + }; + if switched == 1 { + info!("Clocking has already been set up."); + return; + } + } + #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))] + let si5324_ext_input = si5324::Input::Ckin1; + #[cfg(all(soc_platform = "kasli", not(hw_rev = "v2.0")))] + let si5324_ext_input = si5324::Input::Ckin2; + #[cfg(soc_platform = "metlino")] + let si5324_ext_input = si5324::Input::Ckin2; + #[cfg(soc_platform = "kc705")] + let si5324_ext_input = si5324::Input::Ckin2; + match clock_cfg { + RtioClock::Ext0_Bypass => { + info!("using external RTIO clock with PLL bypass"); + si5324::bypass(si5324_ext_input).expect("cannot bypass Si5324") + }, + _ => setup_si5324_as_synthesizer(clock_cfg), + } + + // switch sysclk source to si5324 + #[cfg(soc_platform = "kasli")] + { + // excessive dots will be cut off by the reboot + info!("Switching sys clock, rebooting.................."); + unsafe { + csr::crg::clock_sel_write(1); + } + } +} + + pub fn init() { let clock_cfg = get_rtio_clock_cfg(); #[cfg(si5324_as_synthesizer)] - { - #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))] - let si5324_ext_input = si5324::Input::Ckin1; - #[cfg(all(soc_platform = "kasli", not(hw_rev = "v2.0")))] - let si5324_ext_input = si5324::Input::Ckin2; - #[cfg(soc_platform = "metlino")] - let si5324_ext_input = si5324::Input::Ckin2; - #[cfg(soc_platform = "kc705")] - let si5324_ext_input = si5324::Input::Ckin2; - match clock_cfg { - RtioClock::Ext0_Bypass => { - info!("using external RTIO clock with PLL bypass"); - si5324::bypass(si5324_ext_input).expect("cannot bypass Si5324") - }, - _ => setup_si5324_as_synthesizer(clock_cfg), - } - } + setup_si5324(clock_cfg); #[cfg(has_drtio)] { From af0b94bb348c40875e7032b8dd50098de922b377 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 28 Oct 2022 17:32:12 +0800 Subject: [PATCH 06/16] rtio_clock: remove 150MHz support --- artiq/firmware/runtime/rtio_clocking.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index 1c61437d9..8c44cca4f 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -12,7 +12,6 @@ pub enum RtioClock { Default, Int_125, Int_100, - Int_150, Ext0_Bypass, Ext0_Synth0_10to125, Ext0_Synth0_100to125, @@ -25,7 +24,6 @@ fn get_rtio_clock_cfg() -> RtioClock { let res = match result { Ok("int_125") => RtioClock::Int_125, Ok("int_100") => RtioClock::Int_100, - Ok("int_150") => RtioClock::Int_150, Ok("ext0_bypass") => RtioClock::Ext0_Bypass, Ok("ext0_bypass_125") => RtioClock::Ext0_Bypass, Ok("ext0_bypass_100") => RtioClock::Ext0_Bypass, @@ -56,8 +54,6 @@ fn get_rtio_clock_cfg() -> RtioClock { return RtioClock::Ext0_Synth0_125to125; #[cfg(all(rtio_frequency = "125.0", not(si5324_ext_ref)))] return RtioClock::Int_125; - #[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref), not(soc_platform = "kasli")))] - return RtioClock::Int_150; #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref), not(soc_platform = "kasli")))] return RtioClock::Int_100; //in case nothing is set @@ -161,19 +157,6 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { crystal_ref: false } }, - RtioClock::Int_150 => { // 150MHz output, from crystal - info!("using internal 150MHz RTIO clock"); - si5324::FrequencySettings { - n1_hs : 9, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 33732, - n31 : 7139, - n32 : 7139, - bwsel : 3, - crystal_ref: true - } - }, RtioClock::Int_100 => { // 100MHz output, from crystal. Also used as reference for Sayma HMC830. info!("using internal 100MHz RTIO clock"); si5324::FrequencySettings { From ad000609ced68ab84457265bd5b12b28429cf0a4 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Mon, 31 Oct 2022 15:25:51 +0800 Subject: [PATCH 07/16] simplify tsc with no rtio/sys clk distinction --- artiq/gateware/rtio/cdc.py | 2 +- artiq/gateware/rtio/core.py | 2 +- artiq/gateware/rtio/tsc.py | 24 +----------------------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/artiq/gateware/rtio/cdc.py b/artiq/gateware/rtio/cdc.py index cc0201969..bd0b11d37 100644 --- a/artiq/gateware/rtio/cdc.py +++ b/artiq/gateware/rtio/cdc.py @@ -15,7 +15,7 @@ class GrayCodeTransfer(Module): # convert to Gray code value_gray_rtio = Signal(width, reset_less=True) - self.sync += value_gray_rtio.eq(self.i ^ self.i[1:]) + self.sync.rtio += value_gray_rtio.eq(self.i ^ self.i[1:]) # transfer to system clock domain value_gray_sys = Signal(width) value_gray_rtio.attr.add("no_retiming") diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 7b3b6d6fa..66144ceca 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -66,7 +66,7 @@ class Core(Module, AutoCSR): interface=self.cri) self.submodules += outputs self.comb += outputs.coarse_timestamp.eq(tsc.coarse_ts) - self.sync += outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts_sys + 16) + self.sync += outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16) inputs = InputCollector(tsc, channels, "sync", quash_channels=quash_channels, diff --git a/artiq/gateware/rtio/tsc.py b/artiq/gateware/rtio/tsc.py index d12c69044..f2c316047 100644 --- a/artiq/gateware/rtio/tsc.py +++ b/artiq/gateware/rtio/tsc.py @@ -1,8 +1,5 @@ from migen import * -from artiq.gateware.rtio.cdc import GrayCodeTransfer - - class TSC(Module): def __init__(self, mode, glbl_fine_ts_width=0): self.glbl_fine_ts_width = glbl_fine_ts_width @@ -11,22 +8,10 @@ class TSC(Module): self.coarse_ts = Signal(64 - glbl_fine_ts_width) self.full_ts = Signal(64) - # in sys domain - # monotonic, may lag behind the counter in the IO clock domain, but - # not be ahead of it. - self.coarse_ts_sys = Signal.like(self.coarse_ts) - self.full_ts_sys = Signal(64) - - # in rtio domain self.load = Signal() self.load_value = Signal.like(self.coarse_ts) - if mode == "async": - self.full_ts_cri = self.full_ts_sys - elif mode == "sync": - self.full_ts_cri = self.full_ts - else: - raise ValueError + self.full_ts_cri = self.full_ts # # # @@ -35,14 +20,7 @@ class TSC(Module): ).Else( self.coarse_ts.eq(self.coarse_ts + 1) ) - coarse_ts_cdc = GrayCodeTransfer(len(self.coarse_ts)) # from rtio to sys - self.submodules += coarse_ts_cdc - self.comb += [ - coarse_ts_cdc.i.eq(self.coarse_ts), - self.coarse_ts_sys.eq(coarse_ts_cdc.o) - ] self.comb += [ self.full_ts.eq(self.coarse_ts << glbl_fine_ts_width), - self.full_ts_sys.eq(self.coarse_ts_sys << glbl_fine_ts_width) ] From 17efc28dbe8664cb0dd7f2f767ef3ae8636b0c7e Mon Sep 17 00:00:00 2001 From: Spaqin Date: Sat, 17 Dec 2022 15:39:54 +0800 Subject: [PATCH 08/16] DRTIO: RTIO/SYS clock merge --- artiq/firmware/runtime/rtio_clocking.rs | 51 +++++++----- artiq/firmware/satman/main.rs | 34 ++++++-- artiq/gateware/drtio/aux_controller.py | 31 +++---- artiq/gateware/drtio/core.py | 19 ++--- artiq/gateware/drtio/link_layer.py | 24 ++---- artiq/gateware/drtio/rt_controller_master.py | 2 +- .../gateware/drtio/rt_controller_repeater.py | 12 +-- artiq/gateware/drtio/rt_packet_master.py | 55 +++++-------- artiq/gateware/drtio/rt_packet_repeater.py | 28 +++---- artiq/gateware/drtio/rx_synchronizer.py | 4 +- artiq/gateware/drtio/siphaser.py | 19 ++--- .../drtio/transceiver/clock_aligner.py | 6 +- .../gateware/drtio/transceiver/gtp_7series.py | 38 +++------ artiq/gateware/drtio/wrpll/core.py | 2 +- artiq/gateware/rtio/phy/phaser.py | 4 +- artiq/gateware/targets/kasli.py | 82 ++++++++++++------- .../test/drtio/test_aux_controller.py | 2 +- artiq/gateware/test/drtio/test_full_stack.py | 8 +- .../test/drtio/test_rt_packet_repeater.py | 2 +- artiq/gateware/test/drtio/test_switching.py | 6 +- 20 files changed, 210 insertions(+), 219 deletions(-) diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index 8c44cca4f..6af4ea3e9 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -1,10 +1,7 @@ use board_misoc::config; #[cfg(si5324_as_synthesizer)] use board_artiq::si5324; -#[cfg(any(soc_platform = "kasli", has_drtio))] -use board_misoc::csr; -#[cfg(has_drtio)] -use board_misoc::clock; +use board_misoc::{csr, clock}; #[derive(Debug, PartialEq)] #[allow(non_camel_case_types)] @@ -212,15 +209,12 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { #[cfg(si5324_as_synthesizer)] fn setup_si5324(clock_cfg: RtioClock) { - #[cfg(soc_platform = "kasli")] - { - let switched = unsafe { - csr::crg::switch_done_read() - }; - if switched == 1 { - info!("Clocking has already been set up."); - return; - } + let switched = unsafe { + csr::crg::switch_done_read() + }; + if switched == 1 { + info!("Clocking has already been set up."); + return; } #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))] let si5324_ext_input = si5324::Input::Ckin1; @@ -239,12 +233,14 @@ fn setup_si5324(clock_cfg: RtioClock) { } // switch sysclk source to si5324 - #[cfg(soc_platform = "kasli")] + #[cfg(not(has_drtio))] { - // excessive dots will be cut off by the reboot - info!("Switching sys clock, rebooting.................."); + info!("Switching sys clock, rebooting..."); + // delay for clean UART log, wait until UART FIFO is empty + clock::spin_us(1300); unsafe { csr::crg::clock_sel_write(1); + loop {} } } } @@ -257,15 +253,28 @@ pub fn init() { #[cfg(has_drtio)] { - unsafe { - csr::drtio_transceiver::stable_clkin_write(1); + let switched = unsafe { + csr::crg::switch_done_read() + }; + if switched == 0 { + info!("Switching sys clock, rebooting..."); + clock::spin_us(500); // delay for clean UART log + unsafe { + // clock switch and reboot will begin after TX is initialized + // and TX will be initialized after this + csr::drtio_transceiver::stable_clkin_write(1); + } + loop {} } - clock::spin_us(1500); // wait for CPLL/QPLL lock - unsafe { - csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); + else { + // enable TX after the reboot, with stable clock + unsafe { + csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); + } } } + #[cfg(has_rtio_crg)] { #[cfg(has_rtio_clock_switch)] diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 10beb6695..7ac232827 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -465,6 +465,30 @@ const SI5324_SETTINGS: si5324::FrequencySettings crystal_ref: true }; +fn sysclk_setup() { + let switched = unsafe { + csr::crg::switch_done_read() + }; + if switched == 1 { + info!("Clocking has already been set up."); + return; + } + else { + #[cfg(has_si5324)] + si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324"); + #[cfg(has_wrpll)] + wrpll::init(); + info!("Switching sys clock, rebooting..."); + // delay for clean UART log, wait until UART FIFO is empty + clock::spin_us(1300); + unsafe { + csr::drtio_transceiver::stable_clkin_write(1); + } + loop {} + } +} + + #[no_mangle] pub extern fn main() -> i32 { extern { @@ -517,21 +541,15 @@ pub extern fn main() -> i32 { io_expander1.service().unwrap(); } - #[cfg(has_si5324)] - si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324"); - #[cfg(has_wrpll)] - wrpll::init(); + sysclk_setup(); - unsafe { - csr::drtio_transceiver::stable_clkin_write(1); - } - clock::spin_us(1500); // wait for CPLL/QPLL lock #[cfg(not(has_jdcg))] unsafe { csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); } #[cfg(has_wrpll)] wrpll::diagnostics(); + init_rtio_crg(); #[cfg(has_hmc830_7043)] diff --git a/artiq/gateware/drtio/aux_controller.py b/artiq/gateware/drtio/aux_controller.py index 051a03a20..5f91b1f45 100644 --- a/artiq/gateware/drtio/aux_controller.py +++ b/artiq/gateware/drtio/aux_controller.py @@ -22,8 +22,7 @@ class Transmitter(Module, AutoCSR): self.aux_tx = CSR() self.specials.mem = Memory(mem_dw, max_packet//(mem_dw//8)) - converter = ClockDomainsRenamer("rtio")( - stream.Converter(mem_dw, ll_dw)) + converter = stream.Converter(mem_dw, ll_dw) self.submodules += converter # when continuously fed, the Converter outputs data continuously @@ -36,7 +35,7 @@ class Transmitter(Module, AutoCSR): seen_eop_rst = Signal() frame_r = Signal() seen_eop = Signal() - self.sync.rtio += [ + self.sync += [ If(link_layer.tx_aux_ack, frame_r.eq(link_layer.tx_aux_frame), If(frame_r & ~link_layer.tx_aux_frame, seen_eop.eq(1)) @@ -44,13 +43,9 @@ class Transmitter(Module, AutoCSR): If(seen_eop_rst, seen_eop.eq(0)) ] - mem_port = self.mem.get_port(clock_domain="rtio") + mem_port = self.mem.get_port() self.specials += mem_port - self.aux_tx_length.storage.attr.add("no_retiming") - tx_length = Signal(bits_for(max_packet)) - self.specials += MultiReg(self.aux_tx_length.storage, tx_length, "rtio") - frame_counter_nbits = bits_for(max_packet) - log2_int(mem_dw//8) frame_counter = Signal(frame_counter_nbits) frame_counter_next = Signal(frame_counter_nbits) @@ -66,35 +61,33 @@ class Transmitter(Module, AutoCSR): mem_port.adr.eq(frame_counter_next), converter.sink.data.eq(mem_port.dat_r) ] - self.sync.rtio += frame_counter.eq(frame_counter_next) - start_tx = PulseSynchronizer("sys", "rtio") - tx_done = PulseSynchronizer("rtio", "sys") - self.submodules += start_tx, tx_done - self.comb += start_tx.i.eq(self.aux_tx.re) + tx_done = Signal() self.sync += [ - If(tx_done.o, self.aux_tx.w.eq(0)), - If(self.aux_tx.re, self.aux_tx.w.eq(1)) + frame_counter.eq(frame_counter_next), + If(self.aux_tx.re, self.aux_tx.w.eq(1)), + If(tx_done, self.aux_tx.w.eq(0)) ] - fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE")) + fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", frame_counter_rst.eq(1), seen_eop_rst.eq(1), - If(start_tx.o, NextState("TRANSMIT")) + If(self.aux_tx.re, NextState("TRANSMIT")) ) fsm.act("TRANSMIT", converter.sink.stb.eq(1), If(converter.sink.ack, frame_counter_ce.eq(1) ), - If(frame_counter_next == tx_length, NextState("WAIT_INTERFRAME")) + If(frame_counter_next == self.aux_tx_length.storage, + NextState("WAIT_INTERFRAME")) ) fsm.act("WAIT_INTERFRAME", If(seen_eop, - tx_done.i.eq(1), + tx_done.eq(1), NextState("IDLE") ) ) diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index 6311456e4..e8ca07e3f 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -2,7 +2,6 @@ from types import SimpleNamespace from migen import * from migen.genlib.resetsync import AsyncResetSynchronizer -from migen.genlib.cdc import PulseSynchronizer from misoc.interconnect.csr import * from artiq.gateware.rtio import cri, rtlink @@ -31,7 +30,6 @@ class TransceiverInterface(AutoCSR): def __init__(self, channel_interfaces): self.stable_clkin = CSRStorage() self.txenable = CSRStorage(len(channel_interfaces)) - self.clock_domains.cd_rtio = ClockDomain() for i in range(len(channel_interfaces)): name = "rtio_rx" + str(i) setattr(self.clock_domains, "cd_"+name, ClockDomain(name=name)) @@ -65,7 +63,7 @@ class SyncRTIO(Module): enable_spread=False, report_buffer_space=True, interface=self.cri)) self.comb += self.outputs.coarse_timestamp.eq(tsc.coarse_ts) - self.sync.rtio += self.outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16) + self.sync += self.outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16) self.submodules.inputs = ClockDomainsRenamer("rio")( InputCollector(tsc, channels, "sync", interface=self.cri)) @@ -86,8 +84,8 @@ class DRTIOSatellite(Module): self.clock_domains.cd_rio = ClockDomain() self.clock_domains.cd_rio_phy = ClockDomain() self.comb += [ - self.cd_rio.clk.eq(ClockSignal("rtio")), - self.cd_rio_phy.clk.eq(ClockSignal("rtio")) + self.cd_rio.clk.eq(ClockSignal("sys")), + self.cd_rio_phy.clk.eq(ClockSignal("sys")) ] reset = Signal() reset_phy = Signal() @@ -125,9 +123,9 @@ class DRTIOSatellite(Module): rx_rt_frame_perm=rx_synchronizer.resync(self.link_layer.rx_rt_frame_perm), rx_rt_data=rx_synchronizer.resync(self.link_layer.rx_rt_data) ) - self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "rtio") - self.submodules.rt_packet = ClockDomainsRenamer("rtio")( - rt_packet_satellite.RTPacketSatellite(link_layer_sync, interface=self.cri)) + self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "sys") + self.submodules.rt_packet = rt_packet_satellite.RTPacketSatellite( + link_layer_sync, interface=self.cri) self.comb += self.rt_packet.reset.eq(self.cd_rio.rst) self.comb += [ @@ -135,12 +133,9 @@ class DRTIOSatellite(Module): tsc.load_value.eq(self.rt_packet.tsc_load_value) ] - ps_tsc_load = PulseSynchronizer("rtio", "sys") - self.submodules += ps_tsc_load - self.comb += ps_tsc_load.i.eq(self.rt_packet.tsc_load) self.sync += [ If(self.tsc_loaded.re, self.tsc_loaded.w.eq(0)), - If(ps_tsc_load.o, self.tsc_loaded.w.eq(1)) + If(self.rt_packet.tsc_load, self.tsc_loaded.w.eq(1)) ] self.submodules.rt_errors = rt_errors_satellite.RTErrorsSatellite( diff --git a/artiq/gateware/drtio/link_layer.py b/artiq/gateware/drtio/link_layer.py index a4779e912..367830067 100644 --- a/artiq/gateware/drtio/link_layer.py +++ b/artiq/gateware/drtio/link_layer.py @@ -232,7 +232,7 @@ class LinkLayer(Module, AutoCSR): # receiver locked, comma aligned, receiving valid 8b10b symbols self.rx_ready = Signal() - tx = ClockDomainsRenamer("rtio")(LinkLayerTX(encoder)) + tx = LinkLayerTX(encoder) rx = ClockDomainsRenamer("rtio_rx")(LinkLayerRX(decoders)) self.submodules += tx, rx @@ -256,31 +256,23 @@ class LinkLayer(Module, AutoCSR): rx_up = Signal() rx_up_r = Signal() - self.sync.rtio += rx_up_r.eq(rx_up) + self.sync += rx_up_r.eq(rx_up) rx_up_rx = Signal() rx_up_r.attr.add("no_retiming") self.specials += [ MultiReg(rx_up_r, rx_up_rx, "rtio_rx"), MultiReg(rx_up_r, self.rx_up.status)] - tx_force_aux_zero_rtio = Signal() - tx_force_rt_zero_rtio = Signal() - self.tx_force_aux_zero.storage.attr.add("no_retiming") - self.tx_force_rt_zero.storage.attr.add("no_retiming") - self.specials += [ - MultiReg(self.tx_force_aux_zero.storage, tx_force_aux_zero_rtio, "rtio"), - MultiReg(self.tx_force_rt_zero.storage, tx_force_rt_zero_rtio, "rtio")] - rx_disable_rx = Signal() self.rx_disable.storage.attr.add("no_retiming") self.specials += MultiReg(self.rx_disable.storage, rx_disable_rx, "rtio_rx") self.comb += [ - tx.aux_frame.eq(self.tx_aux_frame | tx_force_aux_zero_rtio), - tx.aux_data.eq(Mux(tx_force_aux_zero_rtio, 0, self.tx_aux_data)), + tx.aux_frame.eq(self.tx_aux_frame | self.tx_force_aux_zero.storage), + tx.aux_data.eq(Mux(self.tx_force_aux_zero.storage, 0, self.tx_aux_data)), self.tx_aux_ack.eq(tx.aux_ack), - tx.rt_frame.eq(self.tx_rt_frame | tx_force_rt_zero_rtio), - tx.rt_data.eq(Mux(tx_force_rt_zero_rtio, 0, self.tx_rt_data)) + tx.rt_frame.eq(self.tx_rt_frame | self.tx_force_rt_zero.storage), + tx.rt_data.eq(Mux(self.tx_force_rt_zero.storage, 0, self.tx_rt_data)) ] # we register those to improve timing margins, as the data may need # to be recaptured by RXSynchronizer. @@ -294,10 +286,10 @@ class LinkLayer(Module, AutoCSR): self.rx_rt_data.eq(rx.rt_data) ] - wait_scrambler = ClockDomainsRenamer("rtio")(WaitTimer(15)) + wait_scrambler = WaitTimer(15) self.submodules += wait_scrambler - fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="WAIT_RX_READY")) + fsm = FSM(reset_state="WAIT_RX_READY") self.submodules += fsm fsm.act("WAIT_RX_READY", diff --git a/artiq/gateware/drtio/rt_controller_master.py b/artiq/gateware/drtio/rt_controller_master.py index fdd340be8..3ed22dbe7 100644 --- a/artiq/gateware/drtio/rt_controller_master.py +++ b/artiq/gateware/drtio/rt_controller_master.py @@ -108,7 +108,7 @@ class RTController(Module): cond_underflow = Signal() self.comb += cond_underflow.eq((self.cri.o_timestamp[tsc.glbl_fine_ts_width:] - - self.csrs.underflow_margin.storage[tsc.glbl_fine_ts_width:]) < tsc.coarse_ts_sys) + - self.csrs.underflow_margin.storage[tsc.glbl_fine_ts_width:]) < tsc.coarse_ts) # buffer space buffer_space = Memory(16, 256) diff --git a/artiq/gateware/drtio/rt_controller_repeater.py b/artiq/gateware/drtio/rt_controller_repeater.py index 0fe10d1de..53b2b1b07 100644 --- a/artiq/gateware/drtio/rt_controller_repeater.py +++ b/artiq/gateware/drtio/rt_controller_repeater.py @@ -15,15 +15,11 @@ class RTController(Module, AutoCSR): self.command_missed_chan_sel = CSRStatus(24) self.buffer_space_timeout_dest = CSRStatus(8) - self.specials += MultiReg(self.reset.storage, rt_packet.reset, "rtio") + self.sync += rt_packet.reset.eq(self.reset.storage) set_time_stb = Signal() - set_time_ack = Signal() - self.submodules += CrossDomainRequest("rtio", - set_time_stb, set_time_ack, None, - rt_packet.set_time_stb, rt_packet.set_time_ack, None) self.sync += [ - If(set_time_ack, set_time_stb.eq(0)), + If(rt_packet.set_time_stb, set_time_stb.eq(0)), If(self.set_time.re, set_time_stb.eq(1)) ] self.comb += self.set_time.w.eq(set_time_stb) @@ -31,10 +27,10 @@ class RTController(Module, AutoCSR): errors = [ (rt_packet.err_unknown_packet_type, "rtio_rx", None, None), (rt_packet.err_packet_truncated, "rtio_rx", None, None), - (rt_packet.err_command_missed, "rtio", + (rt_packet.err_command_missed, "sys", Cat(rt_packet.command_missed_cmd, rt_packet.command_missed_chan_sel), Cat(self.command_missed_cmd.status, self.command_missed_chan_sel.status)), - (rt_packet.err_buffer_space_timeout, "rtio", + (rt_packet.err_buffer_space_timeout, "sys", rt_packet.buffer_space_destination, self.buffer_space_timeout_dest.status) ] diff --git a/artiq/gateware/drtio/rt_packet_master.py b/artiq/gateware/drtio/rt_packet_master.py index 4fd26f85d..70d44ecaf 100644 --- a/artiq/gateware/drtio/rt_packet_master.py +++ b/artiq/gateware/drtio/rt_packet_master.py @@ -2,7 +2,7 @@ from migen import * from migen.genlib.fsm import * -from migen.genlib.fifo import AsyncFIFO +from migen.genlib.fifo import SyncFIFO from migen.genlib.cdc import BlindTransfer from artiq.gateware.rtio.cdc import GrayCodeTransfer @@ -76,8 +76,8 @@ class RTPacketMaster(Module): assert len(link_layer.tx_rt_data) % 8 == 0 ws = len(link_layer.tx_rt_data) tx_plm = get_m2s_layouts(ws) - tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath( - link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)) + tx_dp = TransmitDatapath( + link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm) self.submodules += tx_dp rx_plm = get_s2m_layouts(ws) rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath( @@ -85,8 +85,7 @@ class RTPacketMaster(Module): self.submodules += rx_dp # Write FIFO and extra data count - sr_fifo = ClockDomainsRenamer({"write": "sys", "read": "rtio"})( - AsyncFIFO(1+64+24+8+512, sr_fifo_depth)) + sr_fifo = SyncFIFO(1+64+24+8+512, sr_fifo_depth) self.submodules += sr_fifo sr_notwrite_d = Signal() sr_timestamp_d = Signal(64) @@ -106,7 +105,7 @@ class RTPacketMaster(Module): sr_buf_re = Signal() self.comb += sr_fifo.re.eq(sr_fifo.readable & (~sr_buf_readable | sr_buf_re)) - self.sync.rtio += \ + self.sync += \ If(sr_fifo.re, sr_buf_readable.eq(1), ).Elif(sr_buf_re, @@ -120,7 +119,7 @@ class RTPacketMaster(Module): sr_extra_data_cnt = Signal(8) sr_data = Signal(512) - self.sync.rtio += If(sr_fifo.re, + self.sync += If(sr_fifo.re, sr_notwrite.eq(sr_notwrite_d), sr_timestamp.eq(sr_timestamp_d), sr_chan_sel.eq(sr_chan_sel_d), @@ -131,11 +130,11 @@ class RTPacketMaster(Module): sr_extra_data_d = Signal(512) self.comb += sr_extra_data_d.eq(sr_data_d[short_data_len:]) for i in range(512//ws): - self.sync.rtio += If(sr_fifo.re, + self.sync += If(sr_fifo.re, If(sr_extra_data_d[ws*i:ws*(i+1)] != 0, sr_extra_data_cnt.eq(i+1))) sr_extra_data = Signal(512) - self.sync.rtio += If(sr_fifo.re, sr_extra_data.eq(sr_extra_data_d)) + self.sync += If(sr_fifo.re, sr_extra_data.eq(sr_extra_data_d)) extra_data_ce = Signal() extra_data_last = Signal() @@ -146,7 +145,7 @@ class RTPacketMaster(Module): for i in range(512//ws)}), extra_data_last.eq(extra_data_counter == sr_extra_data_cnt) ] - self.sync.rtio += \ + self.sync += \ If(extra_data_ce, extra_data_counter.eq(extra_data_counter + 1), ).Else( @@ -160,18 +159,6 @@ class RTPacketMaster(Module): buffer_space_not, buffer_space, self.buffer_space_not, self.buffer_space_not_ack, self.buffer_space) - set_time_stb = Signal() - set_time_ack = Signal() - self.submodules += CrossDomainRequest("rtio", - self.set_time_stb, self.set_time_ack, None, - set_time_stb, set_time_ack, None) - - echo_stb = Signal() - echo_ack = Signal() - self.submodules += CrossDomainRequest("rtio", - self.echo_stb, self.echo_ack, None, - echo_stb, echo_ack, None) - read_not = Signal() read_no_event = Signal() read_is_overflow = Signal() @@ -199,14 +186,14 @@ class RTPacketMaster(Module): ] # TX FSM - tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE")) + tx_fsm = FSM(reset_state="IDLE") self.submodules += tx_fsm echo_sent_now = Signal() - self.sync.rtio += self.echo_sent_now.eq(echo_sent_now) + self.sync += self.echo_sent_now.eq(echo_sent_now) tsc_value = Signal(64) tsc_value_load = Signal() - self.sync.rtio += If(tsc_value_load, tsc_value.eq(self.tsc_value)) + self.sync += If(tsc_value_load, tsc_value.eq(self.tsc_value)) tx_fsm.act("IDLE", # Ensure 2 cycles between frames on the link. @@ -223,10 +210,10 @@ class RTPacketMaster(Module): NextState("WRITE") ) ).Else( - If(echo_stb, + If(self.echo_stb, echo_sent_now.eq(1), NextState("ECHO") - ).Elif(set_time_stb, + ).Elif(self.set_time_stb, tsc_value_load.eq(1), NextState("SET_TIME") ) @@ -273,14 +260,14 @@ class RTPacketMaster(Module): tx_fsm.act("ECHO", tx_dp.send("echo_request"), If(tx_dp.packet_last, - echo_ack.eq(1), + self.echo_ack.eq(1), NextState("IDLE") ) ) tx_fsm.act("SET_TIME", tx_dp.send("set_time", timestamp=tsc_value), If(tx_dp.packet_last, - set_time_ack.eq(1), + self.set_time_ack.eq(1), NextState("IDLE") ) ) @@ -334,16 +321,14 @@ class RTPacketMaster(Module): # packet counters tx_frame_r = Signal() packet_cnt_tx = Signal(32) - self.sync.rtio += [ + self.sync += [ tx_frame_r.eq(link_layer.tx_rt_frame), If(link_layer.tx_rt_frame & ~tx_frame_r, packet_cnt_tx.eq(packet_cnt_tx + 1)) ] - cdc_packet_cnt_tx = GrayCodeTransfer(32) - self.submodules += cdc_packet_cnt_tx + self.comb += [ - cdc_packet_cnt_tx.i.eq(packet_cnt_tx), - self.packet_cnt_tx.eq(cdc_packet_cnt_tx.o) + self.packet_cnt_tx.eq(packet_cnt_tx) ] rx_frame_r = Signal() @@ -353,7 +338,7 @@ class RTPacketMaster(Module): If(link_layer.rx_rt_frame & ~rx_frame_r, packet_cnt_rx.eq(packet_cnt_rx + 1)) ] - cdc_packet_cnt_rx = ClockDomainsRenamer({"rtio": "rtio_rx"})( + cdc_packet_cnt_rx = ClockDomainsRenamer({"rtio": "sys", "sys": "rtio_rx"})( GrayCodeTransfer(32)) self.submodules += cdc_packet_cnt_rx self.comb += [ diff --git a/artiq/gateware/drtio/rt_packet_repeater.py b/artiq/gateware/drtio/rt_packet_repeater.py index 9374d1a18..728c24ae8 100644 --- a/artiq/gateware/drtio/rt_packet_repeater.py +++ b/artiq/gateware/drtio/rt_packet_repeater.py @@ -38,8 +38,8 @@ class RTPacketRepeater(Module): assert len(link_layer.tx_rt_data) % 8 == 0 ws = len(link_layer.tx_rt_data) tx_plm = get_m2s_layouts(ws) - tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath( - link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)) + tx_dp = TransmitDatapath( + link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm) self.submodules += tx_dp rx_plm = get_s2m_layouts(ws) rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath( @@ -49,7 +49,7 @@ class RTPacketRepeater(Module): # TSC sync tsc_value = Signal(64) tsc_value_load = Signal() - self.sync.rtio += If(tsc_value_load, tsc_value.eq(tsc.coarse_ts)) + self.sync += If(tsc_value_load, tsc_value.eq(tsc.coarse_ts)) # CRI buffer stage 1 cb0_loaded = Signal() @@ -60,7 +60,7 @@ class RTPacketRepeater(Module): cb0_chan_sel = Signal(24) cb0_o_address = Signal(8) cb0_o_data = Signal(512) - self.sync.rtio += [ + self.sync += [ If(self.reset | cb0_ack, cb0_loaded.eq(0), cb0_cmd.eq(cri.commands["nop"]) @@ -91,7 +91,7 @@ class RTPacketRepeater(Module): cb_chan_sel = Signal(24) cb_o_address = Signal(8) cb_o_data = Signal(512) - self.sync.rtio += [ + self.sync += [ If(self.reset | cb_ack, cb_loaded.eq(0), cb_cmd.eq(cri.commands["nop"]) @@ -112,11 +112,11 @@ class RTPacketRepeater(Module): wb_extra_data_a = Signal(512) self.comb += wb_extra_data_a.eq(self.cri.o_data[short_data_len:]) for i in range(512//ws): - self.sync.rtio += If(self.cri.cmd == cri.commands["write"], + self.sync += If(self.cri.cmd == cri.commands["write"], If(wb_extra_data_a[ws*i:ws*(i+1)] != 0, wb_extra_data_cnt.eq(i+1))) wb_extra_data = Signal(512) - self.sync.rtio += If(self.cri.cmd == cri.commands["write"], + self.sync += If(self.cri.cmd == cri.commands["write"], wb_extra_data.eq(wb_extra_data_a)) extra_data_ce = Signal() @@ -128,7 +128,7 @@ class RTPacketRepeater(Module): for i in range(512//ws)}), extra_data_last.eq(extra_data_counter == wb_extra_data_cnt) ] - self.sync.rtio += \ + self.sync += \ If(extra_data_ce, extra_data_counter.eq(extra_data_counter + 1), ).Else( @@ -136,19 +136,19 @@ class RTPacketRepeater(Module): ) # Buffer space - self.sync.rtio += If(self.cri.cmd == cri.commands["get_buffer_space"], + self.sync += If(self.cri.cmd == cri.commands["get_buffer_space"], self.buffer_space_destination.eq(self.cri.chan_sel[16:])) rx_buffer_space_not = Signal() rx_buffer_space = Signal(16) buffer_space_not = Signal() buffer_space_not_ack = Signal() - self.submodules += CrossDomainNotification("rtio_rx", "rtio", + self.submodules += CrossDomainNotification("rtio_rx", "sys", rx_buffer_space_not, rx_buffer_space, buffer_space_not, buffer_space_not_ack, self.cri.o_buffer_space) - timeout_counter = ClockDomainsRenamer("rtio")(WaitTimer(8191)) + timeout_counter = WaitTimer(8191) self.submodules += timeout_counter # Read @@ -163,7 +163,7 @@ class RTPacketRepeater(Module): rtio_read_is_overflow = Signal() rtio_read_data = Signal(32) rtio_read_timestamp = Signal(64) - self.submodules += CrossDomainNotification("rtio_rx", "rtio", + self.submodules += CrossDomainNotification("rtio_rx", "sys", read_not, Cat(read_no_event, read_is_overflow, read_data, read_timestamp), @@ -183,7 +183,7 @@ class RTPacketRepeater(Module): i_status_wait_event, i_status_overflow, cb0_loaded | cb_loaded)) load_read_reply = Signal() - self.sync.rtio += [ + self.sync += [ If(load_read_reply, i_status_wait_event.eq(0), i_status_overflow.eq(0), @@ -200,7 +200,7 @@ class RTPacketRepeater(Module): ] # TX and CRI FSM - tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE")) + tx_fsm = FSM(reset_state="IDLE") self.submodules += tx_fsm tx_fsm.act("IDLE", diff --git a/artiq/gateware/drtio/rx_synchronizer.py b/artiq/gateware/drtio/rx_synchronizer.py index 90fddb97c..055d1d70b 100644 --- a/artiq/gateware/drtio/rx_synchronizer.py +++ b/artiq/gateware/drtio/rx_synchronizer.py @@ -17,7 +17,7 @@ class GenericRXSynchronizer(Module): return synchronized def do_finalize(self): - eb = ElasticBuffer(sum(len(s[0]) for s in self.signals), 4, "rtio_rx", "rtio") + eb = ElasticBuffer(sum(len(s[0]) for s in self.signals), 4, "rtio_rx", "sys") self.submodules += eb self.comb += [ eb.din.eq(Cat(*[s[0] for s in self.signals])), @@ -57,6 +57,6 @@ class XilinxRXSynchronizer(Module): self.specials += [ Instance("FD", i_C=ClockSignal("rtio_rx"), i_D=din[i], o_Q=inter[i], attr={hu_set, ("RLOC", "X0Y{}".format(i))}), - Instance("FD", i_C=ClockSignal("rtio"), i_D=inter[i], o_Q=dout[i], + Instance("FD", i_C=ClockSignal("sys"), i_D=inter[i], o_Q=dout[i], attr={hu_set, ("RLOC", "X1Y{}".format(i))}) ] diff --git a/artiq/gateware/drtio/siphaser.py b/artiq/gateware/drtio/siphaser.py index 5237b7453..c4054c127 100644 --- a/artiq/gateware/drtio/siphaser.py +++ b/artiq/gateware/drtio/siphaser.py @@ -1,23 +1,23 @@ from migen import * -from migen.genlib.cdc import MultiReg, PulseSynchronizer +from migen.genlib.cdc import MultiReg from misoc.interconnect.csr import * -# This code assumes 125/62.5MHz reference clock and 100MHz, 125MHz or 150MHz RTIO +# This code assumes 125/62.5MHz reference clock and 100MHz or 125MHz RTIO # frequency. class SiPhaser7Series(Module, AutoCSR): def __init__(self, si5324_clkin, rx_synchronizer, - ref_clk=None, ref_div2=False, ultrascale=False, rtio_clk_freq=150e6): + ref_clk=None, ref_div2=False, ultrascale=False, rtio_clk_freq=125e6): self.switch_clocks = CSRStorage() self.phase_shift = CSR() self.phase_shift_done = CSRStatus(reset=1) self.error = CSR() - assert rtio_clk_freq in (100e6, 125e6, 150e6) + assert rtio_clk_freq in (100e6, 125e6) - # 125MHz/62.5MHz reference clock to 100MHz/125MHz/150MHz. VCO @ 750MHz. + # 125MHz/62.5MHz reference clock to 100MHz/125MHz. VCO @ 750MHz. # Used to provide a startup clock to the transceiver through the Si, # we do not use the crystal reference so that the PFD (f3) frequency # can be high. @@ -97,17 +97,14 @@ class SiPhaser7Series(Module, AutoCSR): toggle_out = rx_synchronizer.resync(toggle_in) toggle_out_expected = Signal() - self.sync.rtio += toggle_out_expected.eq(~toggle_out) + self.sync += toggle_out_expected.eq(~toggle_out) error = Signal() - error_clear = PulseSynchronizer("sys", "rtio") - self.submodules += error_clear - self.sync.rtio += [ + self.sync += [ If(toggle_out != toggle_out_expected, error.eq(1)), - If(error_clear.o, error.eq(0)) + If(self.error.re, error.eq(0)) ] self.specials += MultiReg(error, self.error.w) - self.comb += error_clear.i.eq(self.error.re) # expose MMCM outputs - used for clock constraints self.mmcm_freerun_output = mmcm_freerun_output diff --git a/artiq/gateware/drtio/transceiver/clock_aligner.py b/artiq/gateware/drtio/transceiver/clock_aligner.py index 9d17d2b77..b0649a148 100644 --- a/artiq/gateware/drtio/transceiver/clock_aligner.py +++ b/artiq/gateware/drtio/transceiver/clock_aligner.py @@ -33,7 +33,7 @@ class BruteforceClockAligner(Module): check_counter = Signal(max=check_max_val+1) check = Signal() reset_check_counter = Signal() - self.sync.rtio_tx += [ + self.sync += [ check.eq(0), If(reset_check_counter, check_counter.eq(check_max_val) @@ -47,7 +47,7 @@ class BruteforceClockAligner(Module): ) ] - checks_reset = PulseSynchronizer("rtio_tx", "rtio_rx") + checks_reset = PulseSynchronizer("sys", "rtio_rx") self.submodules += checks_reset comma_n = ~comma & 0b1111111111 @@ -76,7 +76,7 @@ class BruteforceClockAligner(Module): ) ] - fsm = ClockDomainsRenamer("rtio_tx")(FSM(reset_state="WAIT_COMMA")) + fsm = FSM(reset_state="WAIT_COMMA") self.submodules += fsm fsm.act("WAIT_COMMA", diff --git a/artiq/gateware/drtio/transceiver/gtp_7series.py b/artiq/gateware/drtio/transceiver/gtp_7series.py index 5da42b22b..75c31a486 100644 --- a/artiq/gateware/drtio/transceiver/gtp_7series.py +++ b/artiq/gateware/drtio/transceiver/gtp_7series.py @@ -20,8 +20,7 @@ class GTPSingle(Module): self.stable_clkin = Signal() self.txenable = Signal() - self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")( - Encoder(2, True)) + self.submodules.encoder = encoder = Encoder(2, True) self.submodules.decoders = decoders = [ClockDomainsRenamer("rtio_rx")( (Decoder(True))) for _ in range(2)] self.rx_ready = Signal() @@ -33,10 +32,11 @@ class GTPSingle(Module): # # # - # TX generates RTIO clock, init must be in system domain - self.submodules.tx_init = tx_init = GTPTXInit(sys_clk_freq, mode) - # RX receives restart commands from RTIO domain - rx_init = ClockDomainsRenamer("rtio_tx")(GTPRXInit(rtio_clk_freq)) + # TX generates RTIO clock, init must be in bootstrap domain + self.submodules.tx_init = tx_init = ClockDomainsRenamer("bootstrap")( + GTPTXInit(125e6, mode)) + # RX receives restart commands from SYS domain + rx_init = GTPRXInit(rtio_clk_freq) self.submodules += rx_init self.comb += [ @@ -367,7 +367,7 @@ class GTPSingle(Module): # Channel - DRP Ports i_DRPADDR=rx_init.drpaddr, - i_DRPCLK=ClockSignal("rtio_tx"), + i_DRPCLK=ClockSignal("sys"), i_DRPDI=rx_init.drpdi, o_DRPDO=rx_init.drpdo, i_DRPEN=rx_init.drpen, @@ -566,8 +566,8 @@ class GTPSingle(Module): i_PMARSVDIN1 =0b0, # Transmit Ports - FPGA TX Interface Ports i_TXDATA =Cat(txdata[:8], txdata[10:18]), - i_TXUSRCLK =ClockSignal("rtio_tx"), - i_TXUSRCLK2 =ClockSignal("rtio_tx"), + i_TXUSRCLK =ClockSignal("sys"), + i_TXUSRCLK2 =ClockSignal("sys"), # Transmit Ports - PCI Express Ports i_TXELECIDLE =0, @@ -665,19 +665,10 @@ class GTPSingle(Module): raise ValueError self.specials += Instance("GTPE2_CHANNEL", **gtp_params) - # tx clocking - tx_reset_deglitched = Signal() - tx_reset_deglitched.attr.add("no_retiming") - self.sync += tx_reset_deglitched.eq(~tx_init.done) - self.clock_domains.cd_rtio_tx = ClockDomain() - if mode == "master" or mode == "single": - self.specials += Instance("BUFG", i_I=self.txoutclk, o_O=self.cd_rtio_tx.clk) - self.specials += AsyncResetSynchronizer(self.cd_rtio_tx, tx_reset_deglitched) - # rx clocking rx_reset_deglitched = Signal() rx_reset_deglitched.attr.add("no_retiming") - self.sync.rtio_tx += rx_reset_deglitched.eq(~rx_init.done) + self.sync += rx_reset_deglitched.eq(~rx_init.done) self.clock_domains.cd_rtio_rx = ClockDomain() self.specials += [ Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk), @@ -727,7 +718,6 @@ class GTP(Module, TransceiverInterface): # # # - rtio_tx_clk = Signal() channel_interfaces = [] for i in range(nchannels): if nchannels == 1: @@ -735,10 +725,6 @@ class GTP(Module, TransceiverInterface): else: mode = "master" if i == master else "slave" gtp = GTPSingle(qpll_channel, data_pads[i], sys_clk_freq, rtio_clk_freq, mode) - if mode == "slave": - self.comb += gtp.cd_rtio_tx.clk.eq(rtio_tx_clk) - else: - self.comb += rtio_tx_clk.eq(gtp.cd_rtio_tx.clk) self.gtps.append(gtp) setattr(self.submodules, "gtp"+str(i), gtp) channel_interface = ChannelInterface(gtp.encoder, gtp.decoders) @@ -754,10 +740,6 @@ class GTP(Module, TransceiverInterface): gtp.txenable.eq(self.txenable.storage[n]) ] - self.comb += [ - self.cd_rtio.clk.eq(self.gtps[master].cd_rtio_tx.clk), - self.cd_rtio.rst.eq(reduce(or_, [gtp.cd_rtio_tx.rst for gtp in self.gtps])) - ] for i in range(nchannels): self.comb += [ getattr(self, "cd_rtio_rx" + str(i)).clk.eq(self.gtps[i].cd_rtio_rx.clk), diff --git a/artiq/gateware/drtio/wrpll/core.py b/artiq/gateware/drtio/wrpll/core.py index 52bc91ab7..3003d4848 100644 --- a/artiq/gateware/drtio/wrpll/core.py +++ b/artiq/gateware/drtio/wrpll/core.py @@ -9,7 +9,7 @@ from artiq.gateware.drtio.wrpll import thls, filters class FrequencyCounter(Module, AutoCSR): - def __init__(self, timer_width=23, counter_width=23, domains=["helper", "rtio", "rtio_rx0"]): + def __init__(self, timer_width=23, counter_width=23, domains=["helper", "sys", "rtio_rx0"]): for domain in domains: name = "counter_" + domain counter = CSRStatus(counter_width, name=name) diff --git a/artiq/gateware/rtio/phy/phaser.py b/artiq/gateware/rtio/phy/phaser.py index 94a5400d5..d4771d9ed 100644 --- a/artiq/gateware/rtio/phy/phaser.py +++ b/artiq/gateware/rtio/phy/phaser.py @@ -105,7 +105,7 @@ class MiqroChannel(Module): self.pulse.eq(pulse), self.rtlink.o.busy.eq(stb & ~self.ack), ] - self.sync.rtio += [ + self.sync += [ If(~stb, dt.eq(dt + 2), ), @@ -162,7 +162,7 @@ class Miqro(Module): ] re_dly = Signal(3) # stage, send, respond - self.sync.rtio += [ + self.sync += [ header.type.eq(3), # body type is miqro pulse data If(self.serializer.stb, header.we.eq(0), diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index f080b4fd0..9adfac0a2 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -17,7 +17,7 @@ from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.amp import AMPSoC from artiq.gateware import rtio from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, edge_counter -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 import eem from artiq.gateware.drtio.transceiver import gtp_7series from artiq.gateware.drtio.siphaser import SiPhaser7Series @@ -76,6 +76,23 @@ class StandaloneBase(MiniSoC, AMPSoC): self.platform.request("error_led"))) self.csr_devices.append("error_led") self.submodules += SMAClkinForward(self.platform) + cdr_clk_out = self.platform.request("cdr_clk_clean") + else: + cdr_clk_out = self.platform.request("si5324_clkout") + + cdr_clk = Signal() + cdr_clk_buf = Signal() + self.platform.add_period_constraint(cdr_clk_out, 8.) + + self.specials += [ + Instance("IBUFDS_GTE2", + i_CEB=0, + i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n, + o_O=cdr_clk), + Instance("BUFG", i_I=cdr_clk, o_O=cdr_clk_buf) + ] + + self.crg.configure(cdr_clk_buf) i2c = self.platform.request("i2c") self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) @@ -218,6 +235,8 @@ class MasterBase(MiniSoC, AMPSoC): integrated_sram_size=8192, ethmac_nrxslots=4, ethmac_ntxslots=4, + clk_freq=rtio_clk_freq, + rtio_sys_merge=True, **kwargs) AMPSoC.__init__(self) add_identifier(self, gateware_identifier_str=gateware_identifier_str) @@ -256,8 +275,6 @@ class MasterBase(MiniSoC, AMPSoC): sys_clk_freq=self.clk_freq, rtio_clk_freq=rtio_clk_freq) self.csr_devices.append("drtio_transceiver") - self.sync += self.disable_cdr_clk_ibuf.eq( - ~self.drtio_transceiver.stable_clkin.storage) if enable_sata: sfp_channels = self.drtio_transceiver.channels[1:] @@ -307,8 +324,14 @@ class MasterBase(MiniSoC, AMPSoC): rtio_clk_period = 1e9/rtio_clk_freq gtp = self.drtio_transceiver.gtps[0] + + txout_buf = Signal() + self.specials += Instance("BUFG", i_I=gtp.txoutclk, o_O=txout_buf) + self.crg.configure(txout_buf, clk_sw=gtp.tx_init.done) + platform.add_period_constraint(gtp.txoutclk, rtio_clk_period) platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period) + platform.add_false_path_constraints( self.crg.cd_sys.clk, gtp.txoutclk, gtp.rxoutclk) @@ -317,8 +340,6 @@ class MasterBase(MiniSoC, AMPSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtp.rxoutclk) - self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) - self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) def add_rtio(self, rtio_channels, sed_lanes=8): @@ -350,19 +371,18 @@ class MasterBase(MiniSoC, AMPSoC): # Never running out of stupid features, GTs on A7 make you pack # unrelated transceiver PLLs into one GTPE2_COMMON yourself. def create_qpll(self): - # The GTP acts up if you send any glitch to its - # clock input, even while the PLL is held in reset. - self.disable_cdr_clk_ibuf = Signal(reset=1) - self.disable_cdr_clk_ibuf.attr.add("no_retiming") if self.platform.hw_rev == "v2.0": - cdr_clk_clean = self.platform.request("cdr_clk_clean") + cdr_clk_out = self.platform.request("cdr_clk_clean") else: - cdr_clk_clean = self.platform.request("si5324_clkout") - cdr_clk_clean_buf = Signal() + cdr_clk_out = self.platform.request("si5324_clkout") + + cdr_clk = Signal() + self.platform.add_period_constraint(cdr_clk_out, 8.) + self.specials += Instance("IBUFDS_GTE2", - i_CEB=self.disable_cdr_clk_ibuf, - i_I=cdr_clk_clean.p, i_IB=cdr_clk_clean.n, - o_O=cdr_clk_clean_buf) + i_CEB=0, + i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n, + o_O=cdr_clk) # Note precisely the rules Xilinx made up: # refclksel=0b001 GTREFCLK0 selected # refclksel=0b010 GTREFCLK1 selected @@ -377,7 +397,8 @@ class MasterBase(MiniSoC, AMPSoC): fbdiv=4, fbdiv_45=5, refclk_div=1) - qpll = QPLL(cdr_clk_clean_buf, qpll_drtio_settings, + + qpll = QPLL(cdr_clk, qpll_drtio_settings, self.crg.clk125_buf, qpll_eth_settings) self.submodules += qpll self.drtio_qpll_channel, self.ethphy_qpll_channel = qpll.channels @@ -400,6 +421,8 @@ class SatelliteBase(BaseSoC): cpu_bus_width=cpu_bus_width, sdram_controller_type="minicon", l2_size=128*1024, + clk_freq=rtio_clk_freq, + rtio_sys_merge=True, **kwargs) add_identifier(self, gateware_identifier_str=gateware_identifier_str) @@ -410,23 +433,24 @@ class SatelliteBase(BaseSoC): self.platform.request("error_led"))) self.csr_devices.append("error_led") - disable_cdr_clk_ibuf = Signal(reset=1) - disable_cdr_clk_ibuf.attr.add("no_retiming") if self.platform.hw_rev == "v2.0": - cdr_clk_clean = self.platform.request("cdr_clk_clean") + cdr_clk_out = self.platform.request("cdr_clk_clean") else: - cdr_clk_clean = self.platform.request("si5324_clkout") - cdr_clk_clean_buf = Signal() + cdr_clk_out = self.platform.request("si5324_clkout") + + cdr_clk = Signal() + self.platform.add_period_constraint(cdr_clk_out, 8.) + self.specials += Instance("IBUFDS_GTE2", - i_CEB=disable_cdr_clk_ibuf, - i_I=cdr_clk_clean.p, i_IB=cdr_clk_clean.n, - o_O=cdr_clk_clean_buf) + i_CEB=0, + i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n, + o_O=cdr_clk) qpll_drtio_settings = QPLLSettings( refclksel=0b001, fbdiv=4, fbdiv_45=5, refclk_div=1) - qpll = QPLL(cdr_clk_clean_buf, qpll_drtio_settings) + qpll = QPLL(cdr_clk, qpll_drtio_settings) self.submodules += qpll drtio_data_pads = [] @@ -445,8 +469,6 @@ class SatelliteBase(BaseSoC): sys_clk_freq=self.clk_freq, rtio_clk_freq=rtio_clk_freq) self.csr_devices.append("drtio_transceiver") - self.sync += disable_cdr_clk_ibuf.eq( - ~self.drtio_transceiver.stable_clkin.storage) if enable_sata: sfp_channels = self.drtio_transceiver.channels[1:] @@ -542,6 +564,10 @@ class SatelliteBase(BaseSoC): self.config["SI5324_SOFT_RESET"] = None gtp = self.drtio_transceiver.gtps[0] + txout_buf = Signal() + self.specials += Instance("BUFG", i_I=gtp.txoutclk, o_O=txout_buf) + self.crg.configure(txout_buf, clk_sw=gtp.tx_init.done) + platform.add_period_constraint(gtp.txoutclk, rtio_clk_period) platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period) platform.add_false_path_constraints( @@ -555,8 +581,6 @@ class SatelliteBase(BaseSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtp.rxoutclk) - self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) - self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) def add_rtio(self, rtio_channels, sed_lanes=8): diff --git a/artiq/gateware/test/drtio/test_aux_controller.py b/artiq/gateware/test/drtio/test_aux_controller.py index 68c9f3bbd..6c65307ed 100644 --- a/artiq/gateware/test/drtio/test_aux_controller.py +++ b/artiq/gateware/test/drtio/test_aux_controller.py @@ -36,7 +36,7 @@ class TB(Module): def __init__(self, nwords, dw): self.submodules.link_layer = Loopback(nwords) self.submodules.aux_controller = ClockDomainsRenamer( - {"rtio": "sys", "rtio_rx": "sys"})(DRTIOAuxController(self.link_layer, dw)) + {"rtio_rx": "sys"})(DRTIOAuxController(self.link_layer, dw)) class TestAuxController(unittest.TestCase): diff --git a/artiq/gateware/test/drtio/test_full_stack.py b/artiq/gateware/test/drtio/test_full_stack.py index 02535b7e6..7cafe16a1 100644 --- a/artiq/gateware/test/drtio/test_full_stack.py +++ b/artiq/gateware/test/drtio/test_full_stack.py @@ -144,7 +144,7 @@ class OutputsTestbench: class TestFullStack(unittest.TestCase): - clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5, + clocks = {"sys": 8, "rtio_rx": 5, "rio": 5, "rio_phy": 5} def test_pulses(self): @@ -169,7 +169,7 @@ class TestFullStack(unittest.TestCase): yield from tb.sync() run_simulation(tb.dut, - {"sys": test(), "rtio": tb.check_ttls(ttl_changes)}, self.clocks) + {"sys": test()}, self.clocks) self.assertEqual(ttl_changes, correct_ttl_changes) def test_underflow(self): @@ -214,7 +214,7 @@ class TestFullStack(unittest.TestCase): yield from tb.sync() run_simulation(tb.dut, - {"sys": test(), "rtio": tb.check_ttls(ttl_changes)}, self.clocks) + {"sys": test()}, self.clocks) self.assertEqual(ttl_changes, correct_ttl_changes) def test_write_underflow(self): @@ -284,7 +284,7 @@ class TestFullStack(unittest.TestCase): yield dut.phy2.rtlink.i.stb.eq(0) run_simulation(dut, - {"sys": test(), "rtio": generate_input()}, self.clocks) + {"sys": test()}, self.clocks) def test_echo(self): dut = DUT(2) diff --git a/artiq/gateware/test/drtio/test_rt_packet_repeater.py b/artiq/gateware/test/drtio/test_rt_packet_repeater.py index 9c73af625..21a28ae47 100644 --- a/artiq/gateware/test/drtio/test_rt_packet_repeater.py +++ b/artiq/gateware/test/drtio/test_rt_packet_repeater.py @@ -12,7 +12,7 @@ def create_dut(nwords): pt = PacketInterface("s2m", nwords*8) pr = PacketInterface("m2s", nwords*8) ts = Signal(64) - dut = ClockDomainsRenamer({"rtio": "sys", "rtio_rx": "sys"})( + dut = ClockDomainsRenamer({"rtio_rx": "sys"})( RTPacketRepeater( SimpleNamespace(coarse_ts=ts), SimpleNamespace( diff --git a/artiq/gateware/test/drtio/test_switching.py b/artiq/gateware/test/drtio/test_switching.py index dddfb9bd2..1f7876ade 100644 --- a/artiq/gateware/test/drtio/test_switching.py +++ b/artiq/gateware/test/drtio/test_switching.py @@ -130,7 +130,7 @@ class Testbench: class TestSwitching(unittest.TestCase): - clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5, + clocks = {"sys": 8, "rtio_rx": 5, "rio": 5, "rio_phy": 5} def test_outputs(self): @@ -183,7 +183,7 @@ class TestSwitching(unittest.TestCase): current_request = (packet_type, field_dict, trailer) run_simulation(tb.dut, - {"sys": test(), "rtio": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks) + {"sys": test(), "sys": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks) def test_inputs(self): @@ -244,4 +244,4 @@ class TestSwitching(unittest.TestCase): current_request = (packet_type, field_dict, trailer) run_simulation(tb.dut, - {"sys": test(), "rtio": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks) + {"sys": test(), "sys": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks) From 3838dfc1d108cf3c08984bfd455f94365819f526 Mon Sep 17 00:00:00 2001 From: Spaqin Date: Fri, 6 Jan 2023 07:13:38 +0800 Subject: [PATCH 09/16] DRTIO: RTIO/SYS clock merge, KC705 --- artiq/firmware/runtime/rtio_clocking.rs | 33 +--- artiq/firmware/satman/main.rs | 13 -- .../gateware/drtio/transceiver/gtx_7series.py | 65 +++---- .../drtio/transceiver/gtx_7series_init.py | 10 +- artiq/gateware/targets/kc705.py | 161 ++++++++---------- 5 files changed, 102 insertions(+), 180 deletions(-) diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index 6af4ea3e9..52ab35915 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -63,40 +63,12 @@ fn get_rtio_clock_cfg() -> RtioClock { #[cfg(has_rtio_crg)] pub mod crg { - #[cfg(has_rtio_clock_switch)] - use super::RtioClock; use board_misoc::{clock, csr}; pub fn check() -> bool { unsafe { csr::rtio_crg::pll_locked_read() != 0 } } - #[cfg(has_rtio_clock_switch)] - pub fn init(clk: RtioClock) -> bool { - let clk_sel: u8 = match clk { - RtioClock::Ext0_Bypass => { - info!("Using 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 - } - }; - unsafe { - csr::rtio_crg::pll_reset_write(1); - csr::rtio_crg::clock_sel_write(clk_sel); - csr::rtio_crg::pll_reset_write(0); - } - clock::spin_us(150); - return check() - } - - #[cfg(not(has_rtio_clock_switch))] pub fn init() -> bool { info!("Using internal RTIO clock"); unsafe { @@ -223,7 +195,7 @@ fn setup_si5324(clock_cfg: RtioClock) { #[cfg(soc_platform = "metlino")] let si5324_ext_input = si5324::Input::Ckin2; #[cfg(soc_platform = "kc705")] - let si5324_ext_input = si5324::Input::Ckin2; + let si5324_ext_input = si5324::Input::Ckin1; match clock_cfg { RtioClock::Ext0_Bypass => { info!("using external RTIO clock with PLL bypass"); @@ -277,9 +249,6 @@ pub fn init() { #[cfg(has_rtio_crg)] { - #[cfg(has_rtio_clock_switch)] - let result = crg::init(clock_cfg); - #[cfg(not(has_rtio_clock_switch))] let result = crg::init(); if !result { error!("RTIO clock failed"); diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 7ac232827..366aa1d5b 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -426,19 +426,6 @@ fn hardware_tick(ts: &mut u64) { } } -#[cfg(all(has_si5324, rtio_frequency = "150.0"))] -const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 6, - nc1_ls : 6, - n2_hs : 10, - n2_ls : 270, - n31 : 75, - n32 : 75, - bwsel : 4, - crystal_ref: true -}; - #[cfg(all(has_si5324, rtio_frequency = "125.0"))] const SI5324_SETTINGS: si5324::FrequencySettings = si5324::FrequencySettings { diff --git a/artiq/gateware/drtio/transceiver/gtx_7series.py b/artiq/gateware/drtio/transceiver/gtx_7series.py index 3d96971ca..fe901d90c 100644 --- a/artiq/gateware/drtio/transceiver/gtx_7series.py +++ b/artiq/gateware/drtio/transceiver/gtx_7series.py @@ -1,5 +1,6 @@ from migen import * from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.genlib.cdc import MultiReg from misoc.cores.code_8b10b import Encoder, Decoder from misoc.interconnect.csr import * @@ -16,13 +17,12 @@ class GTX_20X(Module): # * GTX PLL frequency @ 2.5GHz # * GTX line rate (TX & RX) @ 2.5Gb/s # * GTX TX/RX USRCLK @ 125MHz == coarse RTIO frequency - def __init__(self, refclk, pads, sys_clk_freq, rtio_clk_freq=125e6, tx_mode="single", rx_mode="single"): + def __init__(self, refclk, pads, clk_freq=125e6, tx_mode="single", rx_mode="single"): assert tx_mode in ["single", "master", "slave"] assert rx_mode in ["single", "master", "slave"] self.txenable = Signal() - self.submodules.encoder = ClockDomainsRenamer("rtio_tx")( - Encoder(2, True)) + self.submodules.encoder = Encoder(2, True) self.submodules.decoders = [ClockDomainsRenamer("rtio_rx")( (Decoder(True))) for _ in range(2)] self.rx_ready = Signal() @@ -36,11 +36,11 @@ class GTX_20X(Module): cpllreset = Signal() cplllock = Signal() - # TX generates RTIO clock, init must be in system domain - self.submodules.tx_init = tx_init = GTXInit(sys_clk_freq, False, mode=tx_mode) - # RX receives restart commands from RTIO domain - self.submodules.rx_init = rx_init = ClockDomainsRenamer("rtio_tx")( - GTXInit(rtio_clk_freq, True, mode=rx_mode)) + # TX generates SYS clock, init must be in bootstrap domain + self.submodules.tx_init = tx_init = ClockDomainsRenamer("bootstrap")( + GTXInit(clk_freq, False, mode=tx_mode)) + # RX receives restart commands from SYS domain + self.submodules.rx_init = rx_init = GTXInit(clk_freq, True, mode=rx_mode) self.comb += [ cpllreset.eq(tx_init.cpllreset), tx_init.cplllock.eq(cplllock), @@ -113,8 +113,8 @@ class GTX_20X(Module): i_TXCHARDISPMODE=Cat(txdata[9], txdata[19]), i_TXCHARDISPVAL=Cat(txdata[8], txdata[18]), i_TXDATA=Cat(txdata[:8], txdata[10:18]), - i_TXUSRCLK=ClockSignal("rtio_tx"), - i_TXUSRCLK2=ClockSignal("rtio_tx"), + i_TXUSRCLK=ClockSignal("sys"), + i_TXUSRCLK2=ClockSignal("sys"), # TX electrical i_TXBUFDIFFCTRL=0b100, @@ -247,19 +247,10 @@ class GTX_20X(Module): p_ES_EYE_SCAN_EN="TRUE", # Must be TRUE for GTX ) - # TX clocking - tx_reset_deglitched = Signal() - tx_reset_deglitched.attr.add("no_retiming") - self.sync += tx_reset_deglitched.eq(~tx_init.done) - self.clock_domains.cd_rtio_tx = ClockDomain() - if tx_mode == "single" or tx_mode == "master": - self.specials += Instance("BUFG", i_I=self.txoutclk, o_O=self.cd_rtio_tx.clk) - self.specials += AsyncResetSynchronizer(self.cd_rtio_tx, tx_reset_deglitched) - # RX clocking rx_reset_deglitched = Signal() rx_reset_deglitched.attr.add("no_retiming") - self.sync.rtio += rx_reset_deglitched.eq(~rx_init.done) + self.sync += rx_reset_deglitched.eq(~rx_init.done) self.clock_domains.cd_rtio_rx = ClockDomain() if rx_mode == "single" or rx_mode == "master": self.specials += Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk), @@ -271,7 +262,7 @@ class GTX_20X(Module): self.decoders[1].input.eq(rxdata[10:]) ] - clock_aligner = BruteforceClockAligner(0b0101111100, rtio_clk_freq) + clock_aligner = BruteforceClockAligner(0b0101111100, clk_freq) self.submodules += clock_aligner self.comb += [ clock_aligner.rxdata.eq(rxdata), @@ -282,17 +273,18 @@ class GTX_20X(Module): class GTX(Module, TransceiverInterface): - def __init__(self, clock_pads, pads, sys_clk_freq, rtio_clk_freq=125e6, master=0): + def __init__(self, clock_pads, pads, clk_freq=125e6, master=0): self.nchannels = nchannels = len(pads) self.gtxs = [] - self.rtio_clk_freq = rtio_clk_freq + self.rtio_clk_freq = clk_freq # # # refclk = Signal() - stable_clkin_n = Signal() + + clk_enable = Signal() self.specials += Instance("IBUFDS_GTE2", - i_CEB=stable_clkin_n, + i_CEB=~clk_enable, i_I=clock_pads.p, i_IB=clock_pads.n, o_O=refclk, @@ -301,7 +293,6 @@ class GTX(Module, TransceiverInterface): p_CLKSWING_CFG="0b11" ) - rtio_tx_clk = Signal() channel_interfaces = [] for i in range(nchannels): if nchannels == 1: @@ -309,12 +300,7 @@ class GTX(Module, TransceiverInterface): else: mode = "master" if i == master else "slave" # Note: RX phase alignment is to be done on individual lanes, not multi-lane. - gtx = GTX_20X(refclk, pads[i], sys_clk_freq, rtio_clk_freq=rtio_clk_freq, tx_mode=mode, rx_mode="single") - # Fan-out (to slave) / Fan-in (from master) of the TXUSRCLK - if mode == "slave": - self.comb += gtx.cd_rtio_tx.clk.eq(rtio_tx_clk) - else: - self.comb += rtio_tx_clk.eq(gtx.cd_rtio_tx.clk) + gtx = GTX_20X(refclk, pads[i], clk_freq, tx_mode=mode, rx_mode="single") self.gtxs.append(gtx) setattr(self.submodules, "gtx"+str(i), gtx) channel_interface = ChannelInterface(gtx.encoder, gtx.decoders) @@ -326,15 +312,16 @@ class GTX(Module, TransceiverInterface): TransceiverInterface.__init__(self, channel_interfaces) for n, gtx in enumerate(self.gtxs): self.comb += [ - stable_clkin_n.eq(~self.stable_clkin.storage), - gtx.txenable.eq(self.txenable.storage[n]) + gtx.txenable.eq(self.txenable.storage[n]), + gtx.tx_init.stable_clkin.eq(clk_enable) ] + # rx_init is in SYS domain, rather than bootstrap + self.specials += MultiReg(clk_enable, gtx.rx_init.stable_clkin) + + # stable_clkin resets after reboot since it's in SYS domain + # still need to keep clk_enable high after this + self.sync.bootstrap += clk_enable.eq(self.stable_clkin.storage | self.gtxs[0].tx_init.done) - # Connect master's `rtio_tx` clock to `rtio` clock - self.comb += [ - self.cd_rtio.clk.eq(self.gtxs[master].cd_rtio_tx.clk), - self.cd_rtio.rst.eq(reduce(or_, [gtx.cd_rtio_tx.rst for gtx in self.gtxs])) - ] # Connect slave i's `rtio_rx` clock to `rtio_rxi` clock for i in range(nchannels): self.comb += [ diff --git a/artiq/gateware/drtio/transceiver/gtx_7series_init.py b/artiq/gateware/drtio/transceiver/gtx_7series_init.py index 70c69a19c..5552c308f 100644 --- a/artiq/gateware/drtio/transceiver/gtx_7series_init.py +++ b/artiq/gateware/drtio/transceiver/gtx_7series_init.py @@ -11,11 +11,13 @@ class GTXInit(Module): # Choose between Auto Mode and Manual Mode for TX/RX phase alignment with buffer bypassed: # * Auto Mode: When only single lane is involved, as suggested by Xilinx (AR59612) # * Manual Mode: When only multi-lane is involved, as suggested by Xilinx (AR59612) - def __init__(self, sys_clk_freq, rx, mode="single"): + def __init__(self, clk_freq, rx, mode="single"): assert isinstance(rx, bool) assert mode in ["single", "master", "slave"] self.mode = mode + self.stable_clkin = Signal() + self.done = Signal() self.restart = Signal() @@ -83,13 +85,13 @@ class GTXInit(Module): # After configuration, transceiver resets have to stay low for # at least 500ns (see AR43482) - startup_cycles = ceil(500*sys_clk_freq/1000000000) + startup_cycles = ceil(500*clk_freq/1000000000) startup_timer = WaitTimer(startup_cycles) self.submodules += startup_timer # PLL reset should be 1 period of refclk # (i.e. 1/(125MHz) for the case of RTIO @ 125MHz) - pll_reset_cycles = ceil(sys_clk_freq/125e6) + pll_reset_cycles = ceil(clk_freq/125e6) pll_reset_timer = WaitTimer(pll_reset_cycles) self.submodules += pll_reset_timer @@ -108,7 +110,7 @@ class GTXInit(Module): startup_fsm.act("INITIAL", startup_timer.wait.eq(1), - If(startup_timer.done, NextState("RESET_ALL")) + If(startup_timer.done & self.stable_clkin, NextState("RESET_ALL")) ) startup_fsm.act("RESET_ALL", gtXxreset.eq(1), diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index e04088a92..3ad5f5bdf 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -24,65 +24,20 @@ from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer from artiq.gateware.drtio import * from artiq.build_soc import * - -class _RTIOCRG(Module, AutoCSR): - def __init__(self, platform, rtio_internal_clk, use_sma=True): - 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) - - # 100 MHz when using 125MHz input - self.clock_domains.cd_ext_clkout = ClockDomain(reset_less=True) - platform.add_period_constraint(self.cd_ext_clkout.clk, 5.0) - if use_sma: - ext_clkout = platform.request("user_sma_gpio_p_33") - self.sync.ext_clkout += ext_clkout.eq(~ext_clkout) - - rtio_external_clk = Signal() - if use_sma: - 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() - ext_clkout_clk = Signal() +class SMAClkinForward(Module): + def __init__(self, platform): + sma_clkin = platform.request("user_sma_clock") + sma_clkin_se = Signal() + sma_clkin_buffered = Signal() + cdr_clk_se = Signal() + cdr_clk = platform.request("si5324_clkin_33") 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, - - p_CLKOUT1_DIVIDE=5, p_CLKOUT1_PHASE=0.0, - o_CLKOUT1=ext_clkout_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), - Instance("BUFG", i_I=ext_clkout_clk, o_O=self.cd_ext_clkout.clk), - - AsyncResetSynchronizer(self.cd_rtio, ~pll_locked), - MultiReg(pll_locked, self._pll_locked.status) + Instance("IBUFDS", i_I=sma_clkin.p, i_IB=sma_clkin.n, o_O=sma_clkin_se), + Instance("BUFG", i_I=sma_clkin_se, o_O=sma_clkin_buffered), + Instance("ODDR", i_C=sma_clkin_buffered, i_CE=1, i_D1=0, i_D2=1, o_Q=cdr_clk_se), + Instance("OBUFDS", i_I=cdr_clk_se, o_O=cdr_clk.p, o_OB=cdr_clk.n) ] - # The default voltage for these signals on KC705 is 2.5V, and the Migen platform # follows this default. But since the SMAs are on the same bank as the DDS, # which is set to 3.3V by reprogramming the KC705 power ICs, we need to @@ -138,6 +93,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): integrated_sram_size=8192, ethmac_nrxslots=4, ethmac_ntxslots=4, + rtio_sys_merge=True, **kwargs) AMPSoC.__init__(self) add_identifier(self, gateware_identifier_str=gateware_identifier_str) @@ -149,6 +105,31 @@ class _StandaloneBase(MiniSoC, AMPSoC): if isinstance(self.platform.toolchain, XilinxISEToolchain): self.platform.toolchain.bitgen_opt += " -g compress" + self.platform.add_extension(_reprogrammed3v3_io) + + cdr_clk_out = self.platform.request("si5324_clkout") + cdr_clk = Signal() + cdr_clk_buf = Signal() + + self.config["HAS_SI5324"] = None + self.config["SI5324_AS_SYNTHESIZER"] = None + self.submodules.si5324_rst_n = gpio.GPIOOut(self.platform.request("si5324_33").rst_n) + self.csr_devices.append("si5324_rst_n") + self.specials += [ + Instance("IBUFDS_GTE2", + i_CEB=0, + i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n, + o_O=cdr_clk, + p_CLKCM_CFG=1, + p_CLKRCV_TRST=1, + p_CLKSWING_CFG="2'b11"), + Instance("BUFG", i_I=cdr_clk, o_O=cdr_clk_buf) + ] + + self.crg.configure(cdr_clk_buf) + + self.submodules += SMAClkinForward(self.platform) + self.submodules.timer1 = timer.Timer() self.csr_devices.append("timer1") self.interrupt_devices.append("timer1") @@ -158,7 +139,6 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.platform.request("user_led", 1))) self.csr_devices.append("leds") - self.platform.add_extension(_reprogrammed3v3_io) self.platform.add_extension(_ams101_dac) i2c = self.platform.request("i2c") @@ -169,9 +149,6 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.config["HAS_DDS"] = None def add_rtio(self, rtio_channels): - self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk) - self.csr_devices.append("rtio_crg") - self.config["HAS_RTIO_CLOCK_SWITCH"] = None self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) self.csr_devices.append("rtio_core") @@ -187,11 +164,6 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) self.csr_devices.append("rtio_moninj") - self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.) - self.platform.add_false_path_constraints( - self.crg.cd_sys.clk, - self.rtio_crg.cd_rtio.clk) - self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.csr_devices.append("rtio_analyzer") @@ -208,6 +180,7 @@ class _MasterBase(MiniSoC, AMPSoC): mem_map.update(MiniSoC.mem_map) def __init__(self, gateware_identifier_str=None, drtio_100mhz=False, **kwargs): + clk_freq = 100e6 if drtio_100mhz else 125e6 MiniSoC.__init__(self, cpu_type="vexriscv", cpu_bus_width=64, @@ -216,6 +189,8 @@ class _MasterBase(MiniSoC, AMPSoC): integrated_sram_size=8192, ethmac_nrxslots=4, ethmac_ntxslots=4, + clk_freq=clk_freq, + rtio_sys_merge=True, **kwargs) AMPSoC.__init__(self) add_identifier(self, gateware_identifier_str=gateware_identifier_str) @@ -236,14 +211,11 @@ class _MasterBase(MiniSoC, AMPSoC): platform.request("sfp"), platform.request("user_sma_mgt") ] - rtio_clk_freq = 100e6 if drtio_100mhz else 125e6 - # 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), pads=data_pads, - sys_clk_freq=self.clk_freq, - rtio_clk_freq=rtio_clk_freq) + clk_freq=self.clk_freq) self.csr_devices.append("drtio_transceiver") self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) @@ -292,29 +264,31 @@ class _MasterBase(MiniSoC, AMPSoC): self.config["HAS_SI5324"] = None self.config["SI5324_AS_SYNTHESIZER"] = None - self.comb += [ - platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), - platform.request("user_sma_clock_n").eq(ClockSignal("rtio")) - ] - 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] + + txout_buf = Signal() + self.specials += Instance("BUFG", i_I=gtx0.txoutclk, o_O=txout_buf) + self.crg.configure(txout_buf, clk_sw=gtx0.tx_init.done) + + self.comb += [ + platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), + platform.request("user_sma_clock_n").eq(gtx0.txoutclk) + ] + 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) + self.crg.cd_sys.clk, 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.crg.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk) + self.crg.cd_sys.clk, gtx.rxoutclk) - self.submodules.rtio_crg = RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) - self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) def add_rtio(self, rtio_channels): @@ -345,12 +319,15 @@ class _SatelliteBase(BaseSoC): mem_map.update(BaseSoC.mem_map) def __init__(self, gateware_identifier_str=None, sma_as_sat=False, drtio_100mhz=False, **kwargs): + clk_freq = 100e6 if drtio_100mhz else 125e6 BaseSoC.__init__(self, cpu_type="vexriscv", cpu_bus_width=64, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, + clk_freq=clk_freq, + rtio_sys_merge=True, **kwargs) add_identifier(self, gateware_identifier_str=gateware_identifier_str) @@ -372,14 +349,13 @@ class _SatelliteBase(BaseSoC): if sma_as_sat: data_pads = data_pads[::-1] - rtio_clk_freq = 100e6 if drtio_100mhz else 125e6 + rtio_clk_freq = clk_freq # 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), pads=data_pads, - sys_clk_freq=self.clk_freq, - rtio_clk_freq=rtio_clk_freq) + clk_freq=self.clk_freq) self.csr_devices.append("drtio_transceiver") self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) @@ -432,6 +408,7 @@ class _SatelliteBase(BaseSoC): self.submodules.siphaser = SiPhaser7Series( si5324_clkin=platform.request("si5324_clkin_33"), rx_synchronizer=self.rx_synchronizer, + ref_clk=ClockSignal("bootstrap"), ultrascale=False, rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq) platform.add_false_path_constraints( @@ -445,20 +422,22 @@ class _SatelliteBase(BaseSoC): self.config["I2C_BUS_COUNT"] = 1 self.config["HAS_SI5324"] = None - self.comb += [ - platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), - platform.request("user_sma_clock_n").eq(ClockSignal("rtio")) - ] - 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] + + txout_buf = Signal() + self.specials += Instance("BUFG", i_I=gtx0.txoutclk, o_O=txout_buf) + self.crg.configure(txout_buf, clk_sw=gtx0.tx_init.done) + + self.comb += [ + platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), + platform.request("user_sma_clock_n").eq(gtx0.txoutclk) + ] + 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) # 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:]: @@ -466,8 +445,6 @@ class _SatelliteBase(BaseSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtx.rxoutclk) - self.submodules.rtio_crg = RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) - self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) def add_rtio(self, rtio_channels): From 5da9794895e04214c11da9bf03b42e73671cad7c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Jan 2023 17:41:12 +0800 Subject: [PATCH 10/16] remove Sayma and Metlino support --- artiq/coredevice/ad9154_reg.py | 2996 ----------------- artiq/coredevice/ad9154_spi.py | 23 - artiq/coredevice/basemod_att.py | 79 - artiq/coredevice/sawg.py | 372 -- artiq/coredevice/shiftreg.py | 54 - artiq/coredevice/spline.py | 228 -- artiq/examples/kasli_sawgmaster/device_db.py | 184 - .../kasli_sawgmaster/repository/basemod.py | 25 - .../repository/sines_2sayma.py | 37 - .../repository/sines_urukul_sayma.py | 89 - artiq/examples/metlino_sayma_ttl/device_db.py | 102 - .../metlino_sayma_ttl/repository/demo.py | 129 - artiq/examples/sayma_master/device_db.py | 173 - .../examples/sayma_master/repository/demo.py | 41 - artiq/firmware/libboard_artiq/ad9154.rs | 549 --- artiq/firmware/libboard_artiq/ad9154_reg.rs | 826 ----- artiq/firmware/libboard_artiq/hmc830_7043.rs | 419 --- artiq/firmware/libboard_artiq/lib.rs | 7 - artiq/firmware/libboard_artiq/si5324.rs | 6 - artiq/firmware/libboard_artiq/wrpll.rs | 2 - artiq/firmware/libboard_misoc/net_settings.rs | 4 - artiq/firmware/libboard_misoc/spiflash.rs | 2 +- artiq/firmware/runtime/main.rs | 2 +- artiq/firmware/runtime/rtio_clocking.rs | 6 +- artiq/firmware/satman/jdac_common.rs | 74 - artiq/firmware/satman/jdcg.rs | 589 ---- artiq/firmware/satman/main.rs | 104 - artiq/frontend/artiq_flash.py | 138 +- .../drtio/transceiver/gth_ultrascale.py | 704 ---- .../drtio/transceiver/gth_ultrascale_init.py | 157 - artiq/gateware/dsp/__init__.py | 0 artiq/gateware/dsp/accu.py | 112 - artiq/gateware/dsp/fir.py | 172 - artiq/gateware/dsp/sawg.py | 220 -- artiq/gateware/dsp/spline.py | 47 - artiq/gateware/dsp/tools.py | 69 - artiq/gateware/fmcdio_vhdci_eem.py | 29 - artiq/gateware/jesd204_tools.py | 290 -- artiq/gateware/rtio/phy/sawg.py | 39 - artiq/gateware/targets/metlino.py | 180 - artiq/gateware/targets/sayma_amc.py | 462 --- artiq/gateware/targets/sayma_rtm.py | 280 -- artiq/gateware/test/dsp/__init__.py | 0 artiq/gateware/test/dsp/fir.py | 112 - artiq/gateware/test/dsp/test_accu.py | 46 - artiq/gateware/test/dsp/test_satadd.py | 71 - artiq/gateware/test/dsp/test_sawg.py | 36 - artiq/gateware/test/dsp/test_sawg_fe.py | 255 -- artiq/gateware/test/dsp/test_sawg_phy.py | 70 - artiq/gateware/test/dsp/test_spline.py | 31 - artiq/gateware/test/dsp/tools.py | 49 - artiq/test/test_coefficients.py | 49 - doc/manual/core_drivers_reference.rst | 25 - doc/manual/utilities.rst | 3 - flake.nix | 14 +- 55 files changed, 12 insertions(+), 10770 deletions(-) delete mode 100644 artiq/coredevice/ad9154_reg.py delete mode 100644 artiq/coredevice/ad9154_spi.py delete mode 100644 artiq/coredevice/basemod_att.py delete mode 100644 artiq/coredevice/sawg.py delete mode 100644 artiq/coredevice/shiftreg.py delete mode 100644 artiq/coredevice/spline.py delete mode 100644 artiq/examples/kasli_sawgmaster/device_db.py delete mode 100644 artiq/examples/kasli_sawgmaster/repository/basemod.py delete mode 100644 artiq/examples/kasli_sawgmaster/repository/sines_2sayma.py delete mode 100644 artiq/examples/kasli_sawgmaster/repository/sines_urukul_sayma.py delete mode 100644 artiq/examples/metlino_sayma_ttl/device_db.py delete mode 100644 artiq/examples/metlino_sayma_ttl/repository/demo.py delete mode 100644 artiq/examples/sayma_master/device_db.py delete mode 100644 artiq/examples/sayma_master/repository/demo.py delete mode 100644 artiq/firmware/libboard_artiq/ad9154.rs delete mode 100644 artiq/firmware/libboard_artiq/ad9154_reg.rs delete mode 100644 artiq/firmware/libboard_artiq/hmc830_7043.rs delete mode 100644 artiq/firmware/satman/jdac_common.rs delete mode 100644 artiq/firmware/satman/jdcg.rs delete mode 100644 artiq/gateware/drtio/transceiver/gth_ultrascale.py delete mode 100644 artiq/gateware/drtio/transceiver/gth_ultrascale_init.py delete mode 100644 artiq/gateware/dsp/__init__.py delete mode 100644 artiq/gateware/dsp/accu.py delete mode 100644 artiq/gateware/dsp/fir.py delete mode 100644 artiq/gateware/dsp/sawg.py delete mode 100644 artiq/gateware/dsp/spline.py delete mode 100644 artiq/gateware/dsp/tools.py delete mode 100644 artiq/gateware/fmcdio_vhdci_eem.py delete mode 100644 artiq/gateware/jesd204_tools.py delete mode 100644 artiq/gateware/rtio/phy/sawg.py delete mode 100755 artiq/gateware/targets/metlino.py delete mode 100755 artiq/gateware/targets/sayma_amc.py delete mode 100755 artiq/gateware/targets/sayma_rtm.py delete mode 100644 artiq/gateware/test/dsp/__init__.py delete mode 100644 artiq/gateware/test/dsp/fir.py delete mode 100644 artiq/gateware/test/dsp/test_accu.py delete mode 100644 artiq/gateware/test/dsp/test_satadd.py delete mode 100644 artiq/gateware/test/dsp/test_sawg.py delete mode 100644 artiq/gateware/test/dsp/test_sawg_fe.py delete mode 100644 artiq/gateware/test/dsp/test_sawg_phy.py delete mode 100644 artiq/gateware/test/dsp/test_spline.py delete mode 100644 artiq/gateware/test/dsp/tools.py delete mode 100644 artiq/test/test_coefficients.py diff --git a/artiq/coredevice/ad9154_reg.py b/artiq/coredevice/ad9154_reg.py deleted file mode 100644 index a7d414e96..000000000 --- a/artiq/coredevice/ad9154_reg.py +++ /dev/null @@ -1,2996 +0,0 @@ -# auto-generated, do not edit -from artiq.language.core import portable -from artiq.language.types import TInt32 - -AD9154_SPI_INTFCONFA = 0x000 -# default: 0x00, access: R/W -@portable -def AD9154_SOFTRESET_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_SOFTRESET_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_LSBFIRST_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_LSBFIRST_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ADDRINC_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_ADDRINC_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SDOACTIVE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_SDOACTIVE_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SDOACTIVE_M_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_SDOACTIVE_M_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ADDRINC_M_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_ADDRINC_M_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_LSBFIRST_M_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_LSBFIRST_M_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SOFTRESET_M_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_SOFTRESET_M_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_CHIPTYPE = 0x003 - -AD9154_PRODIDL = 0x004 - -AD9154_PRODIDH = 0x005 - -AD9154_CHIPGRADE = 0x006 -# default: 0x02, access: R -@portable -def AD9154_DEV_REVISION_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x00, access: R -@portable -def AD9154_PROD_GRADE_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_SPI_PAGEINDX = 0x008 - -AD9154_PWRCNTRL0 = 0x011 -# default: 0x01, access: R/W -@portable -def AD9154_PD_DAC3_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_PD_DAC3_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_DAC2_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_PD_DAC2_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_DAC1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_PD_DAC1_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_DAC0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_PD_DAC0_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_PD_BG_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_PD_BG_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_TXENMASK1 = 0x012 -# default: 0x00, access: R/W -@portable -def AD9154_DACA_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_DACA_MASK_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_DACB_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_DACB_MASK_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_PWRCNTRL3 = 0x013 -# default: 0x00, access: R/W -@portable -def AD9154_SPI_TXEN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_SPI_TXEN_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ENA_SPI_TXEN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_ENA_SPI_TXEN_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_PA_CTRL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_SPI_PA_CTRL_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ENA_PA_CTRL_FROM_SPI_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_ENA_PA_CTRL_FROM_SPI_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ENA_PA_CTRL_FROM_BLSM_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_ENA_PA_CTRL_FROM_BLSM_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_ENA_PA_CTRL_FROM_TXENSM_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_ENA_PA_CTRL_FROM_TXENSM_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ENA_PA_CTRL_FROM_PARROT_ERR_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_ENA_PA_CTRL_FROM_PARROT_ERR_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_GROUP_DLY = 0x014 -# default: 0x08, access: R/W -@portable -def AD9154_COARSE_GROUP_DELAY_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_COARSE_GROUP_DELAY_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x08, access: R/W -@portable -def AD9154_GROUP_DELAY_RESERVED_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 4 - -@portable -def AD9154_GROUP_DELAY_RESERVED_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_IRQEN_STATUSMODE0 = 0x01f -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_LANEFIFOERR_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_IRQEN_SMODE_LANEFIFOERR_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SERPLLLOCK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_IRQEN_SMODE_SERPLLLOCK_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SERPLLLOST_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_IRQEN_SMODE_SERPLLLOST_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_DACPLLLOCK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_IRQEN_SMODE_DACPLLLOCK_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_DACPLLLOST_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_IRQEN_SMODE_DACPLLLOST_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - - -AD9154_IRQEN_STATUSMODE1 = 0x020 -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_PRBS0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_IRQEN_SMODE_PRBS0_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_PRBS1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_IRQEN_SMODE_PRBS1_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_PRBS2_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_IRQEN_SMODE_PRBS2_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_PRBS3_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_IRQEN_SMODE_PRBS3_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - - -AD9154_IRQEN_STATUSMODE2 = 0x021 -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_TRIP0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_IRQEN_SMODE_SYNC_TRIP0_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_WLIM0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_IRQEN_SMODE_SYNC_WLIM0_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_ROTATE0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_IRQEN_SMODE_SYNC_ROTATE0_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_LOCK0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_IRQEN_SMODE_SYNC_LOCK0_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_NCO_ALIGN0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_IRQEN_SMODE_NCO_ALIGN0_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_BLNKDONE0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_IRQEN_SMODE_BLNKDONE0_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_PDPERR0_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_IRQEN_SMODE_PDPERR0_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_IRQEN_STATUSMODE3 = 0x022 -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_TRIP1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_IRQEN_SMODE_SYNC_TRIP1_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_WLIM1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_IRQEN_SMODE_SYNC_WLIM1_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_ROTATE1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_IRQEN_SMODE_SYNC_ROTATE1_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_SYNC_LOCK1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_IRQEN_SMODE_SYNC_LOCK1_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_NCO_ALIGN1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_IRQEN_SMODE_NCO_ALIGN1_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_BLNKDONE1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_IRQEN_SMODE_BLNKDONE1_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_IRQEN_SMODE_PDPERR1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_IRQEN_SMODE_PDPERR1_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_IRQ_STATUS0 = 0x023 -# default: 0x00, access: R -@portable -def AD9154_LANEFIFOERR_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SERPLLLOCK_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SERPLLLOST_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_DACPLLLOCK_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_DACPLLLOST_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - - -AD9154_IRQ_STATUS1 = 0x024 -# default: 0x00, access: R -@portable -def AD9154_PRBS0_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_PRBS1_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_PRBS2_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_PRBS3_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - - -AD9154_IRQ_STATUS2 = 0x025 -# default: 0x00, access: R -@portable -def AD9154_SYNC_TRIP0_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_WLIM0_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_ROTATE0_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_LOCK0_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_NCO_ALIGN0_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_BLNKDONE0_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_PDPERR0_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_IRQ_STATUS3 = 0x026 -# default: 0x00, access: R -@portable -def AD9154_SYNC_TRIP1_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_WLIM1_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_ROTATE1_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_LOCK1_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_NCO_ALIGN1_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_BLNKDONE1_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_PDPERR1_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_JESD_CHECKS = 0x030 -# default: 0x00, access: R -@portable -def AD9154_ERR_INTSUPP_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_ERR_SUBCLASS_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_ERR_KUNSUPP_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_ERR_JESDBAD_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_ERR_WINLIMIT_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_ERR_DLYOVER_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - - -AD9154_SYNC_ERRWINDOW = 0x034 - -AD9154_SYNC_LASTERR_L = 0x038 - -AD9154_SYNC_LASTERR_H = 0x039 -# default: 0x00, access: R -@portable -def AD9154_LASTERROR_H_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_LASTOVER_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_LASTUNDER_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_SYNC_CONTROL = 0x03a -# default: 0x00, access: R/W -@portable -def AD9154_SYNCMODE_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_SYNCMODE_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x00, access: R/W -@portable -def AD9154_SYNCCLRLAST_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_SYNCCLRLAST_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SYNCCLRSTKY_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_SYNCCLRSTKY_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SYNCARM_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_SYNCARM_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SYNCENABLE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_SYNCENABLE_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_SYNC_STATUS = 0x03b -# default: 0x00, access: R -@portable -def AD9154_SYNC_TRIP_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_WLIM_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_ROTATE_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_LOCK_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SYNC_BUSY_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_SYNC_CURRERR_L = 0x03c - -AD9154_SYNC_CURRERR_H = 0x03d -# default: 0x00, access: R -@portable -def AD9154_CURRERROR_H_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_CURROVER_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_CURRUNDER_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DACGAIN0_I = 0x040 - -AD9154_DACGAIN1_I = 0x041 - -AD9154_DACGAIN0_Q = 0x042 - -AD9154_DACGAIN1_Q = 0x043 - -AD9154_GROUPDELAY_COMP_I = 0x044 - -AD9154_GROUPDELAY_COMP_Q = 0x045 - -AD9154_GROUPDELAY_COMP_BYP = 0x046 -# default: 0x01, access: R/W -@portable -def AD9154_GROUPCOMP_BYPQ_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_GROUPCOMP_BYPQ_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_GROUPCOMP_BYPI_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_GROUPCOMP_BYPI_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - - -AD9154_MIX_MODE = 0x04a - -AD9154_NCOALIGN_MODE = 0x050 -# default: 0x00, access: R/W -@portable -def AD9154_NCO_ALIGN_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_NCO_ALIGN_MODE_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x00, access: R -@portable -def AD9154_NCO_ALIGN_FAIL_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_NCO_ALIGN_PASS_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_NCO_ALIGN_MTCH_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_NCO_ALIGN_ARM_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_NCO_ALIGN_ARM_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_NCOKEY_ILSB = 0x051 - -AD9154_NCOKEY_IMSB = 0x052 - -AD9154_NCOKEY_QLSB = 0x053 - -AD9154_NCOKEY_QMSB = 0x054 - -AD9154_PDP_THRES0 = 0x060 - -AD9154_PDP_THRES1 = 0x061 - -AD9154_PDP_AVG_TIME = 0x062 -# default: 0x00, access: R/W -@portable -def AD9154_PDP_AVG_TIME__SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_PDP_AVG_TIME__GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x00, access: R/W -@portable -def AD9154_PA_BUS_SWAP_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_PA_BUS_SWAP_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_PDP_ENABLE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_PDP_ENABLE_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_PDP_POWER0 = 0x063 - -AD9154_PDP_POWER1 = 0x064 - -AD9154_CLKCFG0 = 0x080 -# default: 0x00, access: R/W -@portable -def AD9154_REF_CLKDIV_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_REF_CLKDIV_EN_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_RF_SYNC_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_RF_SYNC_EN_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_DUTY_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_DUTY_EN_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_CLK_REC_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_PD_CLK_REC_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_SERDES_PCLK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_PD_SERDES_PCLK_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_CLK_DIG_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_PD_CLK_DIG_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_CLK23_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_PD_CLK23_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_CLK01_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_PD_CLK01_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_SYSREF_ACTRL0 = 0x081 -# default: 0x00, access: R/W -@portable -def AD9154_HYS_CNTRL1_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_HYS_CNTRL1_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_SYSREF_RISE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_SYSREF_RISE_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_HYS_ON_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_HYS_ON_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PD_SYSREF_BUFFER_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_PD_SYSREF_BUFFER_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - - -AD9154_SYSREF_ACTRL1 = 0x082 - -AD9154_DACPLLCNTRL = 0x083 -# default: 0x00, access: R/W -@portable -def AD9154_ENABLE_DACPLL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_ENABLE_DACPLL_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_RECAL_DACPLL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_RECAL_DACPLL_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DACPLLSTATUS = 0x084 -# default: 0x00, access: R -@portable -def AD9154_DACPLL_LOCK_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_VCO_CAL_PROGRESS_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_CP_CAL_VALID_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_CP_OVERRANGE_L_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_CP_OVERRANGE_H_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x3 - - -AD9154_DACINTEGERWORD0 = 0x085 - -AD9154_DACLOOPFILT1 = 0x087 -# default: 0x08, access: R/W -@portable -def AD9154_LF_C1_WORD_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_LF_C1_WORD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x08, access: R/W -@portable -def AD9154_LF_C2_WORD_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 4 - -@portable -def AD9154_LF_C2_WORD_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_DACLOOPFILT2 = 0x088 -# default: 0x08, access: R/W -@portable -def AD9154_LF_C3_WORD_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_LF_C3_WORD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x08, access: R/W -@portable -def AD9154_LF_R1_WORD_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 4 - -@portable -def AD9154_LF_R1_WORD_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_DACLOOPFILT3 = 0x089 -# default: 0x08, access: R/W -@portable -def AD9154_LF_R3_WORD_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_LF_R3_WORD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x00, access: R/W -@portable -def AD9154_LF_BYPASS_C1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_LF_BYPASS_C1_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_LF_BYPASS_C2_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_LF_BYPASS_C2_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_LF_BYPASS_R1_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_LF_BYPASS_R1_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_LF_BYPASS_R3_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_LF_BYPASS_R3_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DACCPCNTRL = 0x08a -# default: 0x20, access: R/W -@portable -def AD9154_CP_CURRENT_SET(x: TInt32) -> TInt32: - return (x & 0x3f) << 0 - -@portable -def AD9154_CP_CURRENT_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3f - -# default: 0x00, access: R/W -@portable -def AD9154_VT_FORCE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_VT_FORCE_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_DACLOGENCNTRL = 0x08b -# default: 0x00, access: R/W -@portable -def AD9154_LODIVMODE_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_LODIVMODE_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_LO_POWER_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 4 - -@portable -def AD9154_LO_POWER_MODE_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x3 - - -AD9154_DACLDOCNTRL1 = 0x08c -# default: 0x00, access: R/W -@portable -def AD9154_REFDIVMODE_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_REFDIVMODE_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x00, access: R/W -@portable -def AD9154_LDO_BYPASS_FLT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_LDO_BYPASS_FLT_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_LDO_REF_SEL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_LDO_REF_SEL_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DACLDOCNTRL2 = 0x08d -# default: 0x03, access: R/W -@portable -def AD9154_LDO_VDROP_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_LDO_VDROP_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x02, access: R/W -@portable -def AD9154_LDO_SEL_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 2 - -@portable -def AD9154_LDO_SEL_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x7 - -# default: 0x01, access: R/W -@portable -def AD9154_LDO_INRUSH_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 5 - -@portable -def AD9154_LDO_INRUSH_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_LDO_BYPASS_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_LDO_BYPASS_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DATA_FORMAT = 0x110 -# default: 0x00, access: R/W -@portable -def AD9154_BINARY_FORMAT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_BINARY_FORMAT_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DATAPATH_CTRL = 0x111 -# default: 0x00, access: R/W -@portable -def AD9154_I_TO_Q_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_I_TO_Q_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SEL_SIDEBAND_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_SEL_SIDEBAND_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_MODULATION_TYPE_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 2 - -@portable -def AD9154_MODULATION_TYPE_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_PHASE_ADJ_ENABLE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_PHASE_ADJ_ENABLE_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_DIG_GAIN_ENABLE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_DIG_GAIN_ENABLE_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_INVSINC_ENABLE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_INVSINC_ENABLE_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_INTERP_MODE = 0x112 - -AD9154_NCO_FTW_UPDATE = 0x113 -# default: 0x00, access: R/W -@portable -def AD9154_FTW_UPDATE_REQ_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_FTW_UPDATE_REQ_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_FTW_UPDATE_ACK_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - - -AD9154_FTW0 = 0x114 - -AD9154_FTW1 = 0x115 - -AD9154_FTW2 = 0x116 - -AD9154_FTW3 = 0x117 - -AD9154_FTW4 = 0x118 - -AD9154_FTW5 = 0x119 - -AD9154_NCO_PHASE_OFFSET0 = 0x11a - -AD9154_NCO_PHASE_OFFSET1 = 0x11b - -AD9154_PHASE_ADJ0 = 0x11c - -AD9154_PHASE_ADJ1 = 0x11d - -AD9154_TXEN_SM_0 = 0x11f -# default: 0x01, access: R/W -@portable -def AD9154_TXEN_SM_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_TXEN_SM_EN_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_GP_PA_CTRL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_GP_PA_CTRL_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_GP_PA_ON_INVERT_SET(x: TInt32) -> TInt32: - return (x & 0x0) << 2 - -@portable -def AD9154_GP_PA_ON_INVERT_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x0 - -# default: 0x00, access: R/W -@portable -def AD9154_RISE_COUNTERS_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 4 - -@portable -def AD9154_RISE_COUNTERS_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x3 - -# default: 0x02, access: R/W -@portable -def AD9154_FALL_COUNTERS_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 6 - -@portable -def AD9154_FALL_COUNTERS_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x3 - - -AD9154_TXEN_RISE_COUNT_0 = 0x121 - -AD9154_TXEN_RISE_COUNT_1 = 0x122 - -AD9154_TXEN_FALL_COUNT_0 = 0x123 - -AD9154_TXEN_FALL_COUNT_1 = 0x124 - -AD9154_DEVICE_CONFIG_REG_0 = 0x12d - -AD9154_DIE_TEMP_CTRL0 = 0x12f -# default: 0x00, access: R/W -@portable -def AD9154_AUXADC_ENABLE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_AUXADC_ENABLE_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x10, access: R/W -@portable -def AD9154_AUXADC_RESERVED_SET(x: TInt32) -> TInt32: - return (x & 0x7f) << 1 - -@portable -def AD9154_AUXADC_RESERVED_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x7f - - -AD9154_DIE_TEMP0 = 0x132 - -AD9154_DIE_TEMP1 = 0x133 - -AD9154_DIE_TEMP_UPDATE = 0x134 - -AD9154_DC_OFFSET_CTRL = 0x135 - -AD9154_IPATH_DC_OFFSET_1PART0 = 0x136 - -AD9154_IPATH_DC_OFFSET_1PART1 = 0x137 - -AD9154_QPATH_DC_OFFSET_1PART0 = 0x138 - -AD9154_QPATH_DC_OFFSET_1PART1 = 0x139 - -AD9154_IPATH_DC_OFFSET_2PART = 0x13a - -AD9154_QPATH_DC_OFFSET_2PART = 0x13b - -AD9154_IDAC_DIG_GAIN0 = 0x13c - -AD9154_IDAC_DIG_GAIN1 = 0x13d - -AD9154_QDAC_DIG_GAIN0 = 0x13e - -AD9154_QDAC_DIG_GAIN1 = 0x13f - -AD9154_GAIN_RAMP_UP_STEP0 = 0x140 - -AD9154_GAIN_RAMP_UP_STEP1 = 0x141 - -AD9154_GAIN_RAMP_DOWN_STEP0 = 0x142 - -AD9154_GAIN_RAMP_DOWN_STEP1 = 0x143 - -AD9154_DEVICE_CONFIG_REG_1 = 0x146 - -AD9154_BSM_STAT = 0x147 -# default: 0x00, access: R -@portable -def AD9154_SOFTBLANKRB_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x3 - - -AD9154_PRBS = 0x14b -# default: 0x00, access: R/W -@portable -def AD9154_PRBS_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_PRBS_EN_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_PRBS_RESET_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_PRBS_RESET_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_PRBS_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_PRBS_MODE_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_PRBS_GOOD_I_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_PRBS_GOOD_Q_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_PRBS_ERROR_I = 0x14c - -AD9154_PRBS_ERROR_Q = 0x14d - -AD9154_DACPLLT0 = 0x1b0 -# default: 0x01, access: R/W -@portable -def AD9154_LOGEN_PD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_LOGEN_PD_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_LDO_PD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_LDO_PD_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SYNTH_PD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_SYNTH_PD_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_VCO_PD_ALC_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_VCO_PD_ALC_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_VCO_PD_PTAT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_VCO_PD_PTAT_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_VCO_PD_IN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_VCO_PD_IN_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DACPLLT1 = 0x1b1 -# default: 0x00, access: R/W -@portable -def AD9154_PFD_EDGE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_PFD_EDGE_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_PFD_DELAY_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 2 - -@portable -def AD9154_PFD_DELAY_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x3 - - -AD9154_DACPLLT2 = 0x1b2 -# default: 0x00, access: R/W -@portable -def AD9154_EXT_ALC_WORD_SET(x: TInt32) -> TInt32: - return (x & 0x7f) << 0 - -@portable -def AD9154_EXT_ALC_WORD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7f - -# default: 0x00, access: R/W -@portable -def AD9154_EXT_ALC_WORD_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_EXT_ALC_WORD_EN_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DACPLLT3 = 0x1b3 -# default: 0x00, access: W -@portable -def AD9154_EXT_BAND1_SET(x: TInt32) -> TInt32: - return (x & 0xff) << 0 - - -AD9154_DACPLLT4 = 0x1b4 -# default: 0x00, access: R/W -@portable -def AD9154_EXT_BAND2_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_EXT_BAND2_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_EXT_BAND_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_EXT_BAND_EN_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x0f, access: R/W -@portable -def AD9154_VCO_CAL_OFFSET_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 3 - -@portable -def AD9154_VCO_CAL_OFFSET_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0xf - -# default: 0x00, access: R/W -@portable -def AD9154_BYP_LOAD_DELAY_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_BYP_LOAD_DELAY_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_DACPLLT5 = 0x1b5 - -AD9154_DACPLLT6 = 0x1b6 - -AD9154_DACPLLT7 = 0x1b7 - -AD9154_DACPLLT8 = 0x1b8 - -AD9154_DACPLLT9 = 0x1b9 - -AD9154_DACPLLTA = 0x1ba - -AD9154_DACPLLTB = 0x1bb -# default: 0x04, access: R/W -@portable -def AD9154_VCO_BIAS_REF_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_VCO_BIAS_REF_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x01, access: R/W -@portable -def AD9154_VCO_BIAS_TCF_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 3 - -@portable -def AD9154_VCO_BIAS_TCF_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x3 - - -AD9154_DACPLLTC = 0x1bc - -AD9154_DACPLLTD = 0x1bd - -AD9154_DACPLLTE = 0x1be - -AD9154_DACPLLTF = 0x1bf - -AD9154_DACPLLT10 = 0x1c0 - -AD9154_DACPLLT11 = 0x1c1 - -AD9154_DACPLLT15 = 0x1c2 - -AD9154_DACPLLT16 = 0x1c3 - -AD9154_DACPLLT17 = 0x1c4 - -AD9154_DACPLLT18 = 0x1c5 - -AD9154_MASTER_PD = 0x200 - -AD9154_PHY_PD = 0x201 - -AD9154_GENERIC_PD = 0x203 -# default: 0x00, access: R/W -@portable -def AD9154_PD_SYNCOUT1B_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_PD_SYNCOUT1B_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_PD_SYNCOUT0B_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_PD_SYNCOUT0B_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - - -AD9154_CDR_RESET = 0x206 - -AD9154_CDR_OPERATING_MODE_REG_0 = 0x230 -# default: 0x00, access: R/W -@portable -def AD9154_CDR_OVERSAMP_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_CDR_OVERSAMP_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x02, access: R/W -@portable -def AD9154_CDR_RESERVED_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 2 - -@portable -def AD9154_CDR_RESERVED_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x7 - -# default: 0x01, access: R/W -@portable -def AD9154_ENHALFRATE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_ENHALFRATE_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - - -AD9154_EQ_BIAS_REG = 0x268 -# default: 0x22, access: R/W -@portable -def AD9154_EQ_BIAS_RESERVED_SET(x: TInt32) -> TInt32: - return (x & 0x3f) << 0 - -@portable -def AD9154_EQ_BIAS_RESERVED_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3f - -# default: 0x01, access: R/W -@portable -def AD9154_EQ_POWER_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 6 - -@portable -def AD9154_EQ_POWER_MODE_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x3 - - -AD9154_SERDESPLL_ENABLE_CNTRL = 0x280 -# default: 0x00, access: R/W -@portable -def AD9154_ENABLE_SERDESPLL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_ENABLE_SERDESPLL_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_RECAL_SERDESPLL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_RECAL_SERDESPLL_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - - -AD9154_PLL_STATUS = 0x281 -# default: 0x00, access: R -@portable -def AD9154_SERDES_PLL_LOCK_RB_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SERDES_CURRENTS_READY_RB_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SERDES_VCO_CAL_IN_PROGRESS_RB_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SERDES_PLL_CAL_VALID_RB_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SERDES_PLL_OVERRANGE_L_RB_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_SERDES_PLL_OVERRANGE_H_RB_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - - -AD9154_LDO_FILTER_1 = 0x284 - -AD9154_LDO_FILTER_2 = 0x285 - -AD9154_LDO_FILTER_3 = 0x286 - -AD9154_CP_CURRENT_SPI = 0x287 -# default: 0x3f, access: R/W -@portable -def AD9154_SPI_CP_CURRENT_SET(x: TInt32) -> TInt32: - return (x & 0x3f) << 0 - -@portable -def AD9154_SPI_CP_CURRENT_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3f - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_SERDES_LOGEN_POWER_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_SPI_SERDES_LOGEN_POWER_MODE_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_REF_CLK_DIVIDER_LDO = 0x289 -# default: 0x00, access: R/W -@portable -def AD9154_SPI_CDR_OVERSAMP_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_SPI_CDR_OVERSAMP_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_LDO_BYPASS_FILT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_SPI_LDO_BYPASS_FILT_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_LDO_REF_SEL_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_SPI_LDO_REF_SEL_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - - -AD9154_VCO_LDO = 0x28a - -AD9154_PLL_RD_REG = 0x28b -# default: 0x01, access: R/W -@portable -def AD9154_SPI_SERDES_LOGEN_PD_CORE_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_SPI_SERDES_LOGEN_PD_CORE_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_SERDES_LDO_PD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_SPI_SERDES_LDO_PD_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_SYN_PD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_SPI_SYN_PD_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_VCO_PD_ALC_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_SPI_VCO_PD_ALC_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_VCO_PD_PTAT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_SPI_VCO_PD_PTAT_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_VCO_PD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_SPI_VCO_PD_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_ALC_VARACTOR = 0x290 -# default: 0x03, access: R/W -@portable -def AD9154_SPI_VCO_VARACTOR_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_SPI_VCO_VARACTOR_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x08, access: R/W -@portable -def AD9154_SPI_INIT_ALC_VALUE_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 4 - -@portable -def AD9154_SPI_INIT_ALC_VALUE_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_VCO_OUTPUT = 0x291 -# default: 0x09, access: R/W -@portable -def AD9154_SPI_VCO_OUTPUT_LEVEL_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_SPI_VCO_OUTPUT_LEVEL_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x04, access: R/W -@portable -def AD9154_SPI_VCO_OUTPUT_RESERVED_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 4 - -@portable -def AD9154_SPI_VCO_OUTPUT_RESERVED_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_CP_CONFIG = 0x294 -# default: 0x00, access: R/W -@portable -def AD9154_SPI_CP_TEST_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_SPI_CP_TEST_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_CP_CAL_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_SPI_CP_CAL_EN_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_CP_FORCE_CALBITS_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_SPI_CP_FORCE_CALBITS_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_CP_OFFSET_OFF_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_SPI_CP_OFFSET_OFF_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_CP_ENABLE_MACHINE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_SPI_CP_ENABLE_MACHINE_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_CP_DITHER_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_SPI_CP_DITHER_MODE_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_CP_HALF_VCO_CAL_CLK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_SPI_CP_HALF_VCO_CAL_CLK_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_VCO_BIAS_1 = 0x296 -# default: 0x04, access: R/W -@portable -def AD9154_SPI_VCO_BIAS_REF_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_SPI_VCO_BIAS_REF_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_VCO_BIAS_TCF_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 3 - -@portable -def AD9154_SPI_VCO_BIAS_TCF_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x3 - - -AD9154_VCO_BIAS_2 = 0x297 -# default: 0x00, access: R/W -@portable -def AD9154_SPI_PRESCALE_BIAS_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_SPI_PRESCALE_BIAS_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_LAST_ALC_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_SPI_LAST_ALC_EN_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_PRESCALE_BYPASS_R_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_SPI_PRESCALE_BYPASS_R_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_VCO_COMP_BYPASS_BIASR_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_SPI_VCO_COMP_BYPASS_BIASR_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_VCO_BYPASS_DAC_R_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_SPI_VCO_BYPASS_DAC_R_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - - -AD9154_VCO_PD_OVERRIDES = 0x299 -# default: 0x00, access: R/W -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_VCO_BUF_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_VCO_BUF_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_CAL_TCF_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_CAL_TCF_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_TCF_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_TCF_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - - -AD9154_VCO_CAL = 0x29a -# default: 0x02, access: R/W -@portable -def AD9154_SPI_FB_CLOCK_ADV_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_SPI_FB_CLOCK_ADV_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x03, access: R/W -@portable -def AD9154_SPI_VCO_CAL_COUNT_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 2 - -@portable -def AD9154_SPI_VCO_CAL_COUNT_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x3 - -# default: 0x07, access: R/W -@portable -def AD9154_SPI_VCO_CAL_ALC_WAIT_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 4 - -@portable -def AD9154_SPI_VCO_CAL_ALC_WAIT_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x7 - -# default: 0x01, access: R/W -@portable -def AD9154_SPI_VCO_CAL_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_SPI_VCO_CAL_EN_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_CP_LEVEL_DETECT = 0x29c -# default: 0x07, access: R/W -@portable -def AD9154_SPI_CP_LEVEL_THRESHOLD_HIGH_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_SPI_CP_LEVEL_THRESHOLD_HIGH_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x02, access: R/W -@portable -def AD9154_SPI_CP_LEVEL_THRESHOLD_LOW_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 3 - -@portable -def AD9154_SPI_CP_LEVEL_THRESHOLD_LOW_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x7 - -# default: 0x00, access: R/W -@portable -def AD9154_SPI_CP_LEVEL_DET_PD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_SPI_CP_LEVEL_DET_PD_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_VCO_VARACTOR_CTRL_0 = 0x29f -# default: 0x03, access: R/W -@portable -def AD9154_SPI_VCO_VARACTOR_OFFSET_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_SPI_VCO_VARACTOR_OFFSET_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x03, access: R/W -@portable -def AD9154_SPI_VCO_VARACTOR_REF_TCF_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 4 - -@portable -def AD9154_SPI_VCO_VARACTOR_REF_TCF_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x7 - - -AD9154_VCO_VARACTOR_CTRL_1 = 0x2a0 -# default: 0x08, access: R/W -@portable -def AD9154_SPI_VCO_VARACTOR_REF_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_SPI_VCO_VARACTOR_REF_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - - -AD9154_TERM_BLK1_CTRLREG0 = 0x2a7 - -AD9154_TERM_BLK2_CTRLREG0 = 0x2ae - -AD9154_GENERAL_JRX_CTRL_0 = 0x300 -# default: 0x00, access: R/W -@portable -def AD9154_LINK_EN_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -@portable -def AD9154_LINK_EN_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_LINK_PAGE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -@portable -def AD9154_LINK_PAGE_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_LINK_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_LINK_MODE_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_CHECKSUM_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_CHECKSUM_MODE_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_GENERAL_JRX_CTRL_1 = 0x301 - -AD9154_DYN_LINK_LATENCY_0 = 0x302 - -AD9154_DYN_LINK_LATENCY_1 = 0x303 - -AD9154_LMFC_DELAY_0 = 0x304 - -AD9154_LMFC_DELAY_1 = 0x305 - -AD9154_LMFC_VAR_0 = 0x306 - -AD9154_LMFC_VAR_1 = 0x307 - -AD9154_XBAR_LN_0_1 = 0x308 -# default: 0x00, access: R/W -@portable -def AD9154_LOGICAL_LANE0_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_LOGICAL_LANE0_SRC_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x01, access: R/W -@portable -def AD9154_LOGICAL_LANE1_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 3 - -@portable -def AD9154_LOGICAL_LANE1_SRC_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x7 - - -AD9154_XBAR_LN_2_3 = 0x309 -# default: 0x02, access: R/W -@portable -def AD9154_LOGICAL_LANE2_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_LOGICAL_LANE2_SRC_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x03, access: R/W -@portable -def AD9154_LOGICAL_LANE3_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 3 - -@portable -def AD9154_LOGICAL_LANE3_SRC_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x7 - - -AD9154_XBAR_LN_4_5 = 0x30a -# default: 0x04, access: R/W -@portable -def AD9154_LOGICAL_LANE4_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_LOGICAL_LANE4_SRC_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x05, access: R/W -@portable -def AD9154_LOGICAL_LANE5_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 3 - -@portable -def AD9154_LOGICAL_LANE5_SRC_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x7 - - -AD9154_XBAR_LN_6_7 = 0x30b -# default: 0x06, access: R/W -@portable -def AD9154_LOGICAL_LANE6_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -@portable -def AD9154_LOGICAL_LANE6_SRC_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x7 - -# default: 0x07, access: R/W -@portable -def AD9154_LOGICAL_LANE7_SRC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 3 - -@portable -def AD9154_LOGICAL_LANE7_SRC_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x7 - - -AD9154_FIFO_STATUS_REG_0 = 0x30c - -AD9154_FIFO_STATUS_REG_1 = 0x30d - -AD9154_SYNCB_GEN_1 = 0x312 -# default: 0x00, access: R/W -@portable -def AD9154_SYNCB_ERR_DUR_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 4 - -@portable -def AD9154_SYNCB_ERR_DUR_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x7 - - -AD9154_SERDES_SPI_REG = 0x314 - -AD9154_PHY_PRBS_TEST_EN = 0x315 - -AD9154_PHY_PRBS_TEST_CTRL = 0x316 -# default: 0x00, access: R/W -@portable -def AD9154_PHY_TEST_RESET_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_PHY_TEST_RESET_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_PHY_TEST_START_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_PHY_TEST_START_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_PHY_PRBS_PAT_SEL_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 2 - -@portable -def AD9154_PHY_PRBS_PAT_SEL_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_PHY_SRC_ERR_CNT_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 4 - -@portable -def AD9154_PHY_SRC_ERR_CNT_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x7 - - -AD9154_PHY_PRBS_TEST_THRESHOLD_LOBITS = 0x317 - -AD9154_PHY_PRBS_TEST_THRESHOLD_MIDBITS = 0x318 - -AD9154_PHY_PRBS_TEST_THRESHOLD_HIBITS = 0x319 - -AD9154_PHY_PRBS_TEST_ERRCNT_LOBITS = 0x31a - -AD9154_PHY_PRBS_TEST_ERRCNT_MIDBITS = 0x31b - -AD9154_PHY_PRBS_TEST_ERRCNT_HIBITS = 0x31c - -AD9154_PHY_PRBS_TEST_STATUS = 0x31d - -AD9154_SHORT_TPL_TEST_0 = 0x32c -# default: 0x00, access: R/W -@portable -def AD9154_SHORT_TPL_TEST_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -@portable -def AD9154_SHORT_TPL_TEST_EN_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SHORT_TPL_TEST_RESET_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_SHORT_TPL_TEST_RESET_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_SHORT_TPL_DAC_SEL_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 2 - -@portable -def AD9154_SHORT_TPL_DAC_SEL_GET(x: TInt32) -> TInt32: - return (x >> 2) & 0x3 - -# default: 0x00, access: R/W -@portable -def AD9154_SHORT_TPL_SP_SEL_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 4 - -@portable -def AD9154_SHORT_TPL_SP_SEL_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x3 - - -AD9154_SHORT_TPL_TEST_1 = 0x32d - -AD9154_SHORT_TPL_TEST_2 = 0x32e - -AD9154_SHORT_TPL_TEST_3 = 0x32f - -AD9154_DEVICE_CONFIG_REG_2 = 0x333 - -AD9154_JESD_BIT_INVERSE_CTRL = 0x334 - -AD9154_DID_REG = 0x400 - -AD9154_BID_REG = 0x401 -# default: 0x00, access: R -@portable -def AD9154_BID_RD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x00, access: R -@portable -def AD9154_ADJCNT_RD_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_LID0_REG = 0x402 -# default: 0x00, access: R -@portable -def AD9154_LID0_RD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R -@portable -def AD9154_PHADJ_RD_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R -@portable -def AD9154_ADJDIR_RD_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_SCR_L_REG = 0x403 -# default: 0x00, access: R -@portable -def AD9154_L_1_RD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R -@portable -def AD9154_SCR_RD_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_F_REG = 0x404 - -AD9154_K_REG = 0x405 - -AD9154_M_REG = 0x406 - -AD9154_CS_N_REG = 0x407 -# default: 0x00, access: R -@portable -def AD9154_N_1_RD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R -@portable -def AD9154_CS_RD_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x3 - - -AD9154_NP_REG = 0x408 -# default: 0x00, access: R -@portable -def AD9154_NP_1_RD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R -@portable -def AD9154_SUBCLASSV_RD_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x7 - - -AD9154_S_REG = 0x409 -# default: 0x00, access: R -@portable -def AD9154_S_1_RD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R -@portable -def AD9154_JESDV_RD_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x7 - - -AD9154_HD_CF_REG = 0x40a -# default: 0x00, access: R -@portable -def AD9154_CF_RD_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R -@portable -def AD9154_HD_RD_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_RES1_REG = 0x40b - -AD9154_RES2_REG = 0x40c - -AD9154_CHECKSUM0_REG = 0x40d - -AD9154_COMPSUM0_REG = 0x40e - -AD9154_LID1_REG = 0x412 - -AD9154_CHECKSUM1_REG = 0x415 - -AD9154_COMPSUM1_REG = 0x416 - -AD9154_LID2_REG = 0x41a - -AD9154_CHECKSUM2_REG = 0x41d - -AD9154_COMPSUM2_REG = 0x41e - -AD9154_LID3_REG = 0x422 - -AD9154_CHECKSUM3_REG = 0x425 - -AD9154_COMPSUM3_REG = 0x426 - -AD9154_LID4_REG = 0x42a - -AD9154_CHECKSUM4_REG = 0x42d - -AD9154_COMPSUM4_REG = 0x42e - -AD9154_LID5_REG = 0x432 - -AD9154_CHECKSUM5_REG = 0x435 - -AD9154_COMPSUM5_REG = 0x436 - -AD9154_LID6_REG = 0x43a - -AD9154_CHECKSUM6_REG = 0x43d - -AD9154_COMPSUM6_REG = 0x43e - -AD9154_LID7_REG = 0x442 - -AD9154_CHECKSUM7_REG = 0x445 - -AD9154_COMPSUM7_REG = 0x446 - -AD9154_ILS_DID = 0x450 - -AD9154_ILS_BID = 0x451 -# default: 0x00, access: R/W -@portable -def AD9154_BID_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 0 - -@portable -def AD9154_BID_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0xf - -# default: 0x00, access: R/W -@portable -def AD9154_ADJCNT_SET(x: TInt32) -> TInt32: - return (x & 0xf) << 4 - -@portable -def AD9154_ADJCNT_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0xf - - -AD9154_ILS_LID0 = 0x452 -# default: 0x00, access: R/W -@portable -def AD9154_LID0_SET(x: TInt32) -> TInt32: - return (x & 0x1f) << 0 - -@portable -def AD9154_LID0_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R/W -@portable -def AD9154_PHADJ_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_PHADJ_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ADJDIR_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_ADJDIR_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - - -AD9154_ILS_SCR_L = 0x453 -# default: 0x03, access: R/W -@portable -def AD9154_L_1_SET(x: TInt32) -> TInt32: - return (x & 0x1f) << 0 - -@portable -def AD9154_L_1_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x01, access: R/W -@portable -def AD9154_SCR_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_SCR_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_ILS_F = 0x454 - -AD9154_ILS_K = 0x455 - -AD9154_ILS_M = 0x456 - -AD9154_ILS_CS_N = 0x457 -# default: 0x0f, access: R/W -@portable -def AD9154_N_1_SET(x: TInt32) -> TInt32: - return (x & 0x1f) << 0 - -@portable -def AD9154_N_1_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x00, access: R/W -@portable -def AD9154_CS_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 6 - -@portable -def AD9154_CS_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x3 - - -AD9154_ILS_NP = 0x458 -# default: 0x0f, access: R/W -@portable -def AD9154_NP_1_SET(x: TInt32) -> TInt32: - return (x & 0x1f) << 0 - -@portable -def AD9154_NP_1_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x01, access: R/W -@portable -def AD9154_SUBCLASSV_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 5 - -@portable -def AD9154_SUBCLASSV_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x7 - - -AD9154_ILS_S = 0x459 -# default: 0x00, access: R/W -@portable -def AD9154_S_1_SET(x: TInt32) -> TInt32: - return (x & 0x1f) << 0 - -@portable -def AD9154_S_1_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x01, access: R/W -@portable -def AD9154_JESDV_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 5 - -@portable -def AD9154_JESDV_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x7 - - -AD9154_ILS_HD_CF = 0x45a -# default: 0x00, access: R/W -@portable -def AD9154_CF_SET(x: TInt32) -> TInt32: - return (x & 0x1f) << 0 - -@portable -def AD9154_CF_GET(x: TInt32) -> TInt32: - return (x >> 0) & 0x1f - -# default: 0x01, access: R/W -@portable -def AD9154_HD_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_HD_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_ILS_RES1 = 0x45b - -AD9154_ILS_RES2 = 0x45c - -AD9154_ILS_CHECKSUM = 0x45d - -AD9154_ERRCNTRMON = 0x46b -# default: 0x00, access: W -@portable -def AD9154_CNTRSEL_SET(x: TInt32) -> TInt32: - return (x & 0x3) << 0 - -# default: 0x00, access: W -@portable -def AD9154_LANESEL_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 4 - - -AD9154_LANEDESKEW = 0x46c - -AD9154_BADDISPARITY = 0x46d -# default: 0x00, access: W -@portable -def AD9154_LANE_ADDR_DIS_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -# default: 0x00, access: W -@portable -def AD9154_RST_ERR_CNTR_DIS_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -# default: 0x00, access: W -@portable -def AD9154_DISABLE_ERR_CNTR_DIS_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -# default: 0x00, access: W -@portable -def AD9154_RST_IRQ_DIS_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - - -AD9154_NIT_W = 0x46e -# default: 0x00, access: W -@portable -def AD9154_LANE_ADDR_NIT_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -# default: 0x00, access: W -@portable -def AD9154_RST_ERR_CNTR_NIT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -# default: 0x00, access: W -@portable -def AD9154_DISABLE_ERR_CNTR_NIT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -# default: 0x00, access: W -@portable -def AD9154_RST_IRQ_NIT_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - - -AD9154_UNEXPECTEDCONTROL_W = 0x46f -# default: 0x00, access: W -@portable -def AD9154_LANE_ADDR_UCC_SET(x: TInt32) -> TInt32: - return (x & 0x7) << 0 - -# default: 0x00, access: W -@portable -def AD9154_RST_ERR_CNTR_UCC_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -# default: 0x00, access: W -@portable -def AD9154_DISABLE_ERR_CNTR_UCC_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -# default: 0x00, access: W -@portable -def AD9154_RST_IRQ_UCC_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - - -AD9154_CODEGRPSYNCFLG = 0x470 - -AD9154_FRAMESYNCFLG = 0x471 - -AD9154_GOODCHKSUMFLG = 0x472 - -AD9154_INITLANESYNCFLG = 0x473 - -AD9154_CTRLREG1 = 0x476 - -AD9154_CTRLREG2 = 0x477 -# default: 0x00, access: R/W -@portable -def AD9154_THRESHOLD_MASK_EN_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_THRESHOLD_MASK_EN_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_ILAS_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_ILAS_MODE_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_KVAL = 0x478 - -AD9154_IRQVECTOR_MASK = 0x47a -# default: 0x00, access: W -@portable -def AD9154_CODEGRPSYNC_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 0 - -# default: 0x00, access: W -@portable -def AD9154_BADCHECKSUM_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 2 - -# default: 0x00, access: W -@portable -def AD9154_INITIALLANESYNC_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -# default: 0x00, access: W -@portable -def AD9154_UCC_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -# default: 0x00, access: W -@portable -def AD9154_NIT_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -# default: 0x00, access: W -@portable -def AD9154_BADDIS_MASK_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - - -AD9154_SYNCASSERTIONMASK = 0x47b -# default: 0x01, access: R/W -@portable -def AD9154_CMM_ENABLE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 3 - -@portable -def AD9154_CMM_ENABLE_GET(x: TInt32) -> TInt32: - return (x >> 3) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_CMM_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 4 - -@portable -def AD9154_CMM_GET(x: TInt32) -> TInt32: - return (x >> 4) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_UCC_S_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 5 - -@portable -def AD9154_UCC_S_GET(x: TInt32) -> TInt32: - return (x >> 5) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_NIT_S_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 6 - -@portable -def AD9154_NIT_S_GET(x: TInt32) -> TInt32: - return (x >> 6) & 0x1 - -# default: 0x00, access: R/W -@portable -def AD9154_BADDIS_S_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 7 - -@portable -def AD9154_BADDIS_S_GET(x: TInt32) -> TInt32: - return (x >> 7) & 0x1 - - -AD9154_ERRORTHRES = 0x47c - -AD9154_LANEENABLE = 0x47d - -AD9154_RAMP_ENA = 0x47e - -AD9154_DIG_TEST0 = 0x520 -# default: 0x00, access: R/W -@portable -def AD9154_DC_TEST_MODE_SET(x: TInt32) -> TInt32: - return (x & 0x1) << 1 - -@portable -def AD9154_DC_TEST_MODE_GET(x: TInt32) -> TInt32: - return (x >> 1) & 0x1 - - -AD9154_DC_TEST_VALUEI0 = 0x521 - -AD9154_DC_TEST_VALUEI1 = 0x522 - -AD9154_DC_TEST_VALUEQ0 = 0x523 - -AD9154_DC_TEST_VALUEQ1 = 0x524 diff --git a/artiq/coredevice/ad9154_spi.py b/artiq/coredevice/ad9154_spi.py deleted file mode 100644 index d83a85ff6..000000000 --- a/artiq/coredevice/ad9154_spi.py +++ /dev/null @@ -1,23 +0,0 @@ -from artiq.language.core import kernel - - -class AD9154: - """Kernel interface to AD9154 registers, using non-realtime SPI.""" - - def __init__(self, dmgr, spi_device, chip_select): - self.core = dmgr.get("core") - self.bus = dmgr.get(spi_device) - self.chip_select = chip_select - - @kernel - def setup_bus(self, div=16): - self.bus.set_config_mu(0, 24, div, self.chip_select) - - @kernel - def write(self, addr, data): - self.bus.write((addr << 16) | (data<< 8)) - - @kernel - def read(self, addr): - self.write((1 << 15) | addr, 0) - return self.bus.read() diff --git a/artiq/coredevice/basemod_att.py b/artiq/coredevice/basemod_att.py deleted file mode 100644 index 5015324ff..000000000 --- a/artiq/coredevice/basemod_att.py +++ /dev/null @@ -1,79 +0,0 @@ -from artiq.language.core import kernel, portable, delay -from artiq.language.units import us, ms -from artiq.coredevice.shiftreg import ShiftReg - - -@portable -def to_mu(att): - return round(att*2.0) ^ 0x3f - -@portable -def from_mu(att_mu): - return 0.5*(att_mu ^ 0x3f) - - -class BaseModAtt: - def __init__(self, dmgr, rst_n, clk, le, mosi, miso): - self.rst_n = dmgr.get(rst_n) - self.shift_reg = ShiftReg(dmgr, - clk=clk, ser=mosi, latch=le, ser_in=miso, n=8*4) - - @kernel - def reset(self): - # HMC's incompetence in digital design and interfaces means that - # the HMC542 needs a level low on RST_N and then a rising edge - # on Latch Enable. Their "latch" isn't a latch but a DFF. - # Of course, it also powers up with a random attenuation, and - # that cannot be fixed with simple pull-ups/pull-downs. - self.rst_n.off() - self.shift_reg.latch.off() - delay(1*us) - self.shift_reg.latch.on() - delay(1*us) - self.shift_reg.latch.off() - self.rst_n.on() - delay(1*us) - - @kernel - def set_mu(self, att0, att1, att2, att3): - """ - Sets the four attenuators on BaseMod. - The values are in half decibels, between 0 (no attenuation) - and 63 (31.5dB attenuation). - """ - word = ( - (att0 << 2) | - (att1 << 10) | - (att2 << 18) | - (att3 << 26) - ) - self.shift_reg.set(word) - - @kernel - def get_mu(self): - """ - Retrieves the current settings of the four attenuators on BaseMod. - """ - word = self.shift_reg.get() - att0 = (word >> 2) & 0x3f - att1 = (word >> 10) & 0x3f - att2 = (word >> 18) & 0x3f - att3 = (word >> 26) & 0x3f - return att0, att1, att2, att3 - - @kernel - def set(self, att0, att1, att2, att3): - """ - Sets the four attenuators on BaseMod. - The values are in decibels. - """ - self.set_mu(to_mu(att0), to_mu(att1), to_mu(att2), to_mu(att3)) - - @kernel - def get(self): - """ - Retrieves the current settings of the four attenuators on BaseMod. - The values are in decibels. - """ - att0, att1, att2, att3 = self.get_mu() - return from_mu(att0), from_mu(att1), from_mu(att2), from_mu(att3) diff --git a/artiq/coredevice/sawg.py b/artiq/coredevice/sawg.py deleted file mode 100644 index 0a5905fa7..000000000 --- a/artiq/coredevice/sawg.py +++ /dev/null @@ -1,372 +0,0 @@ -""" -Driver for the Smart Arbitrary Waveform Generator (SAWG) on RTIO. - -The SAWG is an "improved DDS" built in gateware and interfacing to -high-speed DACs. - -Output event replacement is supported except on the configuration channel. -""" - - -from artiq.language.types import TInt32, TFloat -from numpy import int32, int64 -from artiq.language.core import kernel -from artiq.coredevice.spline import Spline -from artiq.coredevice.rtio import rtio_output - - -# sawg.Config addresses -_SAWG_DIV = 0 -_SAWG_CLR = 1 -_SAWG_IQ_EN = 2 -# _SAWF_PAD = 3 # reserved -_SAWG_OUT_MIN = 4 -_SAWG_OUT_MAX = 5 -_SAWG_DUC_MIN = 6 -_SAWG_DUC_MAX = 7 - - -class Config: - """SAWG configuration. - - Exposes the configurable quantities of a single SAWG channel. - - Access to the configuration registers for a SAWG channel can not - be concurrent. There must be at least :attr:`_rtio_interval` machine - units of delay between accesses. Replacement is not supported and will be - lead to an ``RTIOCollision`` as this is likely a programming error. - All methods therefore advance the timeline by the duration of one - configuration register transfer. - - :param channel: RTIO channel number of the channel. - :param core: Core device. - """ - kernel_invariants = {"channel", "core", "_out_scale", "_duc_scale", - "_rtio_interval"} - - def __init__(self, channel, core, cordic_gain=1.): - self.channel = channel - self.core = core - # normalized DAC output - self._out_scale = (1 << 15) - 1. - # normalized DAC output including DUC cordic gain - self._duc_scale = self._out_scale/cordic_gain - # configuration channel access interval - self._rtio_interval = int64(3*self.core.ref_multiplier) - - @kernel - def set_div(self, div: TInt32, n: TInt32=0): - """Set the spline evolution divider and current counter value. - - The divider and the spline evolution are synchronized across all - spline channels within a SAWG channel. The DDS/DUC phase accumulators - always evolves at full speed. - - .. note:: The spline evolution divider has not been tested extensively - and is currently considered a technological preview only. - - :param div: Spline evolution divider, such that - ``t_sawg_spline/t_rtio_coarse = div + 1``. Default: ``0``. - :param n: Current value of the counter. Default: ``0``. - """ - rtio_output((self.channel << 8) | _SAWG_DIV, div | (n << 16)) - delay_mu(self._rtio_interval) - - @kernel - def set_clr(self, clr0: TInt32, clr1: TInt32, clr2: TInt32): - """Set the accumulator clear mode for the three phase accumulators. - - When the ``clr`` bit for a given DDS/DUC phase accumulator is - set, that phase accumulator will be cleared with every phase offset - RTIO command and the output phase of the DDS/DUC will be - exactly the phase RTIO value ("absolute phase update mode"). - - .. math:: - q^\prime(t) = p^\prime + (t - t^\prime) f^\prime - - In turn, when the bit is cleared, the phase RTIO channels - determine a phase offset to the current (carrier-) value of the - DDS/DUC phase accumulator. This "relative phase update mode" is - sometimes also called “continuous phase mode”. - - .. math:: - q^\prime(t) = q(t^\prime) + (p^\prime - p) + - (t - t^\prime) f^\prime - - Where: - - * :math:`q`, :math:`q^\prime`: old/new phase accumulator - * :math:`p`, :math:`p^\prime`: old/new phase offset - * :math:`f^\prime`: new frequency - * :math:`t^\prime`: timestamp of setting new :math:`p`, :math:`f` - * :math:`t`: running time - - :param clr0: Auto-clear phase accumulator of the ``phase0``/ - ``frequency0`` DUC. Default: ``True`` - :param clr1: Auto-clear phase accumulator of the ``phase1``/ - ``frequency1`` DDS. Default: ``True`` - :param clr2: Auto-clear phase accumulator of the ``phase2``/ - ``frequency2`` DDS. Default: ``True`` - """ - rtio_output((self.channel << 8) | _SAWG_CLR, clr0 | - (clr1 << 1) | (clr2 << 2)) - delay_mu(self._rtio_interval) - - @kernel - def set_iq_en(self, i_enable: TInt32, q_enable: TInt32): - """Enable I/Q data on this DAC channel. - - Every pair of SAWG channels forms a buddy pair. - The ``iq_en`` configuration controls which DDS data is emitted to the - DACs. - - Refer to the documentation of :class:`SAWG` for a mathematical - description of ``i_enable`` and ``q_enable``. - - .. note:: Quadrature data from the buddy channel is currently - a technological preview only. The data is ignored in the SAWG - gateware and not added to the DAC output. - This is equivalent to the ``q_enable`` switch always being ``0``. - - :param i_enable: Controls adding the in-phase - DUC-DDS data of *this* SAWG channel to *this* DAC channel. - Default: ``1``. - :param q_enable: controls adding the quadrature - DUC-DDS data of this SAWG's *buddy* channel to *this* DAC - channel. Default: ``0``. - """ - rtio_output((self.channel << 8) | _SAWG_IQ_EN, i_enable | - (q_enable << 1)) - delay_mu(self._rtio_interval) - - @kernel - def set_duc_max_mu(self, limit: TInt32): - """Set the digital up-converter (DUC) I and Q data summing junctions - upper limit. In machine units. - - The default limits are chosen to reach maximum and minimum DAC output - amplitude. - - For a description of the limiter functions in normalized units see: - - .. seealso:: :meth:`set_duc_max` - """ - rtio_output((self.channel << 8) | _SAWG_DUC_MAX, limit) - delay_mu(self._rtio_interval) - - @kernel - def set_duc_min_mu(self, limit: TInt32): - """.. seealso:: :meth:`set_duc_max_mu`""" - rtio_output((self.channel << 8) | _SAWG_DUC_MIN, limit) - delay_mu(self._rtio_interval) - - @kernel - def set_out_max_mu(self, limit: TInt32): - """.. seealso:: :meth:`set_duc_max_mu`""" - rtio_output((self.channel << 8) | _SAWG_OUT_MAX, limit) - delay_mu(self._rtio_interval) - - @kernel - def set_out_min_mu(self, limit: TInt32): - """.. seealso:: :meth:`set_duc_max_mu`""" - rtio_output((self.channel << 8) | _SAWG_OUT_MIN, limit) - delay_mu(self._rtio_interval) - - @kernel - def set_duc_max(self, limit: TFloat): - """Set the digital up-converter (DUC) I and Q data summing junctions - upper limit. - - Each of the three summing junctions has a saturating adder with - configurable upper and lower limits. The three summing junctions are: - - * At the in-phase input to the ``phase0``/``frequency0`` fast DUC, - after the anti-aliasing FIR filter. - * At the quadrature input to the ``phase0``/``frequency0`` - fast DUC, after the anti-aliasing FIR filter. The in-phase and - quadrature data paths both use the same limits. - * Before the DAC, where the following three data streams - are added together: - - * the output of the ``offset`` spline, - * (optionally, depending on ``i_enable``) the in-phase output - of the ``phase0``/``frequency0`` fast DUC, and - * (optionally, depending on ``q_enable``) the quadrature - output of the ``phase0``/``frequency0`` fast DUC of the - buddy channel. - - Refer to the documentation of :class:`SAWG` for a mathematical - description of the summing junctions. - - :param limit: Limit value ``[-1, 1]``. The output of the limiter will - never exceed this limit. The default limits are the full range - ``[-1, 1]``. - - .. seealso:: - * :meth:`set_duc_max`: Upper limit of the in-phase and quadrature - inputs to the DUC. - * :meth:`set_duc_min`: Lower limit of the in-phase and quadrature - inputs to the DUC. - * :meth:`set_out_max`: Upper limit of the DAC output. - * :meth:`set_out_min`: Lower limit of the DAC output. - """ - self.set_duc_max_mu(int32(round(limit*self._duc_scale))) - - @kernel - def set_duc_min(self, limit: TFloat): - """.. seealso:: :meth:`set_duc_max`""" - self.set_duc_min_mu(int32(round(limit*self._duc_scale))) - - @kernel - def set_out_max(self, limit: TFloat): - """.. seealso:: :meth:`set_duc_max`""" - self.set_out_max_mu(int32(round(limit*self._out_scale))) - - @kernel - def set_out_min(self, limit: TFloat): - """.. seealso:: :meth:`set_duc_max`""" - self.set_out_min_mu(int32(round(limit*self._out_scale))) - - -class SAWG: - """Smart arbitrary waveform generator channel. - The channel is parametrized as: :: - - oscillators = exp(2j*pi*(frequency0*t + phase0))*( - amplitude1*exp(2j*pi*(frequency1*t + phase1)) + - amplitude2*exp(2j*pi*(frequency2*t + phase2))) - - output = (offset + - i_enable*Re(oscillators) + - q_enable*Im(buddy_oscillators)) - - This parametrization can be viewed as two complex (quadrature) oscillators - (``frequency1``/``phase1`` and ``frequency2``/``phase2``) that are - executing and sampling at the coarse RTIO frequency. They can represent - frequencies within the first Nyquist zone from ``-f_rtio_coarse/2`` to - ``f_rtio_coarse/2``. - - .. note:: The coarse RTIO frequency ``f_rtio_coarse`` is the inverse of - ``ref_period*multiplier``. Both are arguments of the ``Core`` device, - specified in the device database ``device_db.py``. - - The sum of their outputs is then interpolated by a factor of - :attr:`parallelism` (2, 4, 8 depending on the bitstream) using a - finite-impulse-response (FIR) anti-aliasing filter (more accurately - a half-band filter). - - The filter is followed by a configurable saturating limiter. - - After the limiter, the data is shifted in frequency using a complex - digital up-converter (DUC, ``frequency0``/``phase0``) running at - :attr:`parallelism` times the coarse RTIO frequency. The first Nyquist - zone of the DUC extends from ``-f_rtio_coarse*parallelism/2`` to - ``f_rtio_coarse*parallelism/2``. Other Nyquist zones are usable depending - on the interpolation/modulation options configured in the DAC. - - The real/in-phase data after digital up-conversion can be offset using - another spline interpolator ``offset``. - - The ``i_enable``/``q_enable`` switches enable emission of quadrature - signals for later analog quadrature mixing distinguishing upper and lower - sidebands and thus doubling the bandwidth. They can also be used to emit - four-tone signals. - - .. note:: Quadrature data from the buddy channel is currently - ignored in the SAWG gateware and not added to the DAC output. - This is equivalent to the ``q_enable`` switch always being ``0``. - - The configuration channel and the nine - :class:`artiq.coredevice.spline.Spline` interpolators are accessible as - attributes: - - * :attr:`config`: :class:`Config` - * :attr:`offset`, :attr:`amplitude1`, :attr:`amplitude2`: in units - of full scale - * :attr:`phase0`, :attr:`phase1`, :attr:`phase2`: in units of turns - * :attr:`frequency0`, :attr:`frequency1`, :attr:`frequency2`: in units - of Hz - - .. note:: The latencies (pipeline depths) of the nine data channels (i.e. - all except :attr:`config`) are matched. Equivalent channels (e.g. - :attr:`phase1` and :attr:`phase2`) are exactly matched. Channels of - different type or functionality (e.g. :attr:`offset` vs - :attr:`amplitude1`, DDS vs DUC, :attr:`phase0` vs :attr:`phase1`) are - only matched to within one coarse RTIO cycle. - - :param channel_base: RTIO channel number of the first channel (amplitude). - The configuration channel and frequency/phase/amplitude channels are - then assumed to be successive channels. - :param parallelism: Number of output samples per coarse RTIO clock cycle. - :param core_device: Name of the core device that this SAWG is on. - """ - kernel_invariants = {"channel_base", "core", "parallelism", - "amplitude1", "frequency1", "phase1", - "amplitude2", "frequency2", "phase2", - "frequency0", "phase0", "offset"} - - def __init__(self, dmgr, channel_base, parallelism, core_device="core"): - self.core = dmgr.get(core_device) - self.channel_base = channel_base - self.parallelism = parallelism - width = 16 - time_width = 16 - cordic_gain = 1.646760258057163 # Cordic(width=16, guard=None).gain - head_room = 1.001 - self.config = Config(channel_base, self.core, cordic_gain) - self.offset = Spline(width, time_width, channel_base + 1, - self.core, 2.*head_room) - self.amplitude1 = Spline(width, time_width, channel_base + 2, - self.core, 2*head_room*cordic_gain**2) - self.frequency1 = Spline(3*width, time_width, channel_base + 3, - self.core, 1/self.core.coarse_ref_period) - self.phase1 = Spline(width, time_width, channel_base + 4, - self.core, 1.) - self.amplitude2 = Spline(width, time_width, channel_base + 5, - self.core, 2*head_room*cordic_gain**2) - self.frequency2 = Spline(3*width, time_width, channel_base + 6, - self.core, 1/self.core.coarse_ref_period) - self.phase2 = Spline(width, time_width, channel_base + 7, - self.core, 1.) - self.frequency0 = Spline(2*width, time_width, channel_base + 8, - self.core, - parallelism/self.core.coarse_ref_period) - self.phase0 = Spline(width, time_width, channel_base + 9, - self.core, 1.) - - @kernel - def reset(self): - """Re-establish initial conditions. - - This clears all spline interpolators, accumulators and configuration - settings. - - This method advances the timeline by the time required to perform all - 7 writes to the configuration channel, plus 9 coarse RTIO cycles. - """ - self.config.set_div(0, 0) - self.config.set_clr(1, 1, 1) - self.config.set_iq_en(1, 0) - self.config.set_duc_min(-1.) - self.config.set_duc_max(1.) - self.config.set_out_min(-1.) - self.config.set_out_max(1.) - self.frequency0.set_mu(0) - coarse_cycle = int64(self.core.ref_multiplier) - delay_mu(coarse_cycle) - self.frequency1.set_mu(0) - delay_mu(coarse_cycle) - self.frequency2.set_mu(0) - delay_mu(coarse_cycle) - self.phase0.set_mu(0) - delay_mu(coarse_cycle) - self.phase1.set_mu(0) - delay_mu(coarse_cycle) - self.phase2.set_mu(0) - delay_mu(coarse_cycle) - self.amplitude1.set_mu(0) - delay_mu(coarse_cycle) - self.amplitude2.set_mu(0) - delay_mu(coarse_cycle) - self.offset.set_mu(0) - delay_mu(coarse_cycle) diff --git a/artiq/coredevice/shiftreg.py b/artiq/coredevice/shiftreg.py deleted file mode 100644 index 79000eba3..000000000 --- a/artiq/coredevice/shiftreg.py +++ /dev/null @@ -1,54 +0,0 @@ -from artiq.language.core import kernel, delay -from artiq.language.units import us - - -class ShiftReg: - """Driver for shift registers/latch combos connected to TTLs""" - kernel_invariants = {"dt", "n"} - - def __init__(self, dmgr, clk, ser, latch, n=32, dt=10*us, ser_in=None): - self.core = dmgr.get("core") - self.clk = dmgr.get(clk) - self.ser = dmgr.get(ser) - self.latch = dmgr.get(latch) - self.n = n - self.dt = dt - if ser_in is not None: - self.ser_in = dmgr.get(ser_in) - - @kernel - def set(self, data): - """Sets the values of the latch outputs. This does not - advance the timeline and the waveform is generated before - `now`.""" - delay(-2*(self.n + 1)*self.dt) - for i in range(self.n): - if (data >> (self.n-i-1)) & 1 == 0: - self.ser.off() - else: - self.ser.on() - self.clk.off() - delay(self.dt) - self.clk.on() - delay(self.dt) - self.clk.off() - self.latch.on() - delay(self.dt) - self.latch.off() - delay(self.dt) - - @kernel - def get(self): - delay(-2*(self.n + 1)*self.dt) - data = 0 - for i in range(self.n): - data <<= 1 - self.ser_in.sample_input() - if self.ser_in.sample_get(): - data |= 1 - delay(self.dt) - self.clk.on() - delay(self.dt) - self.clk.off() - delay(self.dt) - return data diff --git a/artiq/coredevice/spline.py b/artiq/coredevice/spline.py deleted file mode 100644 index 9f8310d1e..000000000 --- a/artiq/coredevice/spline.py +++ /dev/null @@ -1,228 +0,0 @@ -from numpy import int32, int64 -from artiq.language.core import kernel, portable, delay -from artiq.coredevice.rtio import rtio_output, rtio_output_wide -from artiq.language.types import TInt32, TInt64, TFloat - - -class Spline: - r"""Spline interpolating RTIO channel. - - One knot of a polynomial basis spline (B-spline) :math:`u(t)` - is defined by the coefficients :math:`u_n` up to order :math:`n = k`. - If the coefficients are evaluated starting at time :math:`t_0`, - the output :math:`u(t)` for :math:`t > t_0, t_0` is: - - .. math:: - u(t) &= \sum_{n=0}^k \frac{u_n}{n!} (t - t_0)^n \\ - &= u_0 + u_1 (t - t_0) + \frac{u_2}{2} (t - t_0)^2 + \dots - - This class contains multiple methods to convert spline knot data from SI - to machine units and multiple methods that set the current spline - coefficient data. None of these advance the timeline. The :meth:`smooth` - method is the only method that advances the timeline. - - :param width: Width in bits of the quantity that this spline controls - :param time_width: Width in bits of the time counter of this spline - :param channel: RTIO channel number - :param core_device: Core device that this spline is attached to - :param scale: Scale for conversion between machine units and physical - units; to be given as the "full scale physical value". - """ - - kernel_invariants = {"channel", "core", "scale", "width", - "time_width", "time_scale"} - - def __init__(self, width, time_width, channel, core_device, scale=1.): - self.core = core_device - self.channel = channel - self.width = width - self.scale = float((int64(1) << width) / scale) - self.time_width = time_width - self.time_scale = float((1 << time_width) * - core_device.coarse_ref_period) - - @portable(flags={"fast-math"}) - def to_mu(self, value: TFloat) -> TInt32: - """Convert floating point ``value`` from physical units to 32 bit - integer machine units.""" - return int32(round(value*self.scale)) - - @portable(flags={"fast-math"}) - def from_mu(self, value: TInt32) -> TFloat: - """Convert 32 bit integer ``value`` from machine units to floating - point physical units.""" - return value/self.scale - - @portable(flags={"fast-math"}) - def to_mu64(self, value: TFloat) -> TInt64: - """Convert floating point ``value`` from physical units to 64 bit - integer machine units.""" - return int64(round(value*self.scale)) - - @kernel - def set_mu(self, value: TInt32): - """Set spline value (machine units). - - :param value: Spline value in integer machine units. - """ - rtio_output(self.channel << 8, value) - - @kernel(flags={"fast-math"}) - def set(self, value: TFloat): - """Set spline value. - - :param value: Spline value relative to full-scale. - """ - if self.width > 32: - l = [int32(0)] * 2 - self.pack_coeff_mu([self.to_mu64(value)], l) - rtio_output_wide(self.channel << 8, l) - else: - rtio_output(self.channel << 8, self.to_mu(value)) - - @kernel - def set_coeff_mu(self, value): # TList(TInt32) - """Set spline raw values. - - :param value: Spline packed raw values. - """ - rtio_output_wide(self.channel << 8, value) - - @portable(flags={"fast-math"}) - def pack_coeff_mu(self, coeff, packed): # TList(TInt64), TList(TInt32) - """Pack coefficients into RTIO data - - :param coeff: TList(TInt64) list of machine units spline coefficients. - Lowest (zeroth) order first. The coefficient list is zero-extended - by the RTIO gateware. - :param packed: TList(TInt32) list for packed RTIO data. Must be - pre-allocated. Length in bits is - ``n*width + (n - 1)*n//2*time_width`` - """ - pos = 0 - for i in range(len(coeff)): - wi = self.width + i*self.time_width - ci = coeff[i] - while wi != 0: - j = pos//32 - used = pos - 32*j - avail = 32 - used - if avail > wi: - avail = wi - cij = int32(ci) - if avail != 32: - cij &= (1 << avail) - 1 - packed[j] |= cij << used - ci >>= avail - wi -= avail - pos += avail - - @portable(flags={"fast-math"}) - def coeff_to_mu(self, coeff, coeff64): # TList(TFloat), TList(TInt64) - """Convert a floating point list of coefficients into a 64 bit - integer (preallocated). - - :param coeff: TList(TFloat) list of coefficients in physical units. - :param coeff64: TList(TInt64) preallocated list of coefficients in - machine units. - """ - for i in range(len(coeff)): - vi = coeff[i] * self.scale - for j in range(i): - vi *= self.time_scale - ci = int64(round(vi)) - coeff64[i] = ci - # artiq.wavesynth.coefficients.discrete_compensate: - if i == 2: - coeff64[1] += ci >> self.time_width + 1 - elif i == 3: - coeff64[2] += ci >> self.time_width - coeff64[1] += ci // 6 >> 2*self.time_width - - def coeff_as_packed_mu(self, coeff64): - """Pack 64 bit integer machine units coefficients into 32 bit integer - RTIO data list. - - This is a host-only method that can be used to generate packed - spline coefficient data to be frozen into kernels at compile time. - """ - n = len(coeff64) - width = n*self.width + (n - 1)*n//2*self.time_width - packed = [int32(0)] * ((width + 31)//32) - self.pack_coeff_mu(coeff64, packed) - return packed - - def coeff_as_packed(self, coeff): - """Convert floating point spline coefficients into 32 bit integer - packed data. - - This is a host-only method that can be used to generate packed - spline coefficient data to be frozen into kernels at compile time. - """ - coeff64 = [int64(0)] * len(coeff) - self.coeff_to_mu(coeff, coeff64) - return self.coeff_as_packed_mu(coeff64) - - @kernel(flags={"fast-math"}) - def set_coeff(self, coeff): # TList(TFloat) - """Set spline coefficients. - - Missing coefficients (high order) are zero-extended byt the RTIO - gateware. - - If more coefficients are supplied than the gateware supports the extra - coefficients are ignored. - - :param value: List of floating point spline coefficients, - lowest order (constant) coefficient first. Units are the - unit of this spline's value times increasing powers of 1/s. - """ - n = len(coeff) - coeff64 = [int64(0)] * n - self.coeff_to_mu(coeff, coeff64) - width = n*self.width + (n - 1)*n//2*self.time_width - packed = [int32(0)] * ((width + 31)//32) - self.pack_coeff_mu(coeff64, packed) - self.set_coeff_mu(packed) - - @kernel(flags={"fast-math"}) - def smooth(self, start: TFloat, stop: TFloat, duration: TFloat, - order: TInt32): - """Initiate an interpolated value change. - - For zeroth order (step) interpolation, the step is at - ``start + duration/2``. - - First order interpolation corresponds to a linear value ramp from - ``start`` to ``stop`` over ``duration``. - - The third order interpolation is constrained to have zero first - order derivative at both `start` and `stop`. - - For first order and third order interpolation (linear and cubic) - the interpolator needs to be stopped explicitly at the stop time - (e.g. by setting spline coefficient data or starting a new - :meth:`smooth` interpolation). - - This method advances the timeline by ``duration``. - - :param start: Initial value of the change. In physical units. - :param stop: Final value of the change. In physical units. - :param duration: Duration of the interpolation. In physical units. - :param order: Order of the interpolation. Only 0, 1, - and 3 are valid: step, linear, cubic. - """ - if order == 0: - delay(duration/2.) - self.set_coeff([stop]) - delay(duration/2.) - elif order == 1: - self.set_coeff([start, (stop - start)/duration]) - delay(duration) - elif order == 3: - v2 = 6.*(stop - start)/(duration*duration) - self.set_coeff([start, 0., v2, -2.*v2/duration]) - delay(duration) - else: - raise ValueError("Invalid interpolation order. " - "Supported orders are: 0, 1, 3.") diff --git a/artiq/examples/kasli_sawgmaster/device_db.py b/artiq/examples/kasli_sawgmaster/device_db.py deleted file mode 100644 index 1c555fdea..000000000 --- a/artiq/examples/kasli_sawgmaster/device_db.py +++ /dev/null @@ -1,184 +0,0 @@ -core_addr = "192.168.1.70" - -device_db = { - "core": { - "type": "local", - "module": "artiq.coredevice.core", - "class": "Core", - "arguments": {"host": core_addr, "ref_period": 1/(8*150e6)} - }, - "core_log": { - "type": "controller", - "host": "::1", - "port": 1068, - "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr - }, - "core_moninj": { - "type": "controller", - "host": "::1", - "port_proxy": 1383, - "port": 1384, - "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr - }, - "core_cache": { - "type": "local", - "module": "artiq.coredevice.cache", - "class": "CoreCache" - }, - "core_dma": { - "type": "local", - "module": "artiq.coredevice.dma", - "class": "CoreDMA" - }, -} - -device_db.update( - spi_urukul0={ - "type": "local", - "module": "artiq.coredevice.spi2", - "class": "SPIMaster", - "arguments": {"channel": 0} - }, - ttl_urukul0_io_update={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 1} - }, - ttl_urukul0_sw0={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 2} - }, - ttl_urukul0_sw1={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 3} - }, - ttl_urukul0_sw2={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 4} - }, - ttl_urukul0_sw3={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 5} - }, - urukul0_cpld={ - "type": "local", - "module": "artiq.coredevice.urukul", - "class": "CPLD", - "arguments": { - "spi_device": "spi_urukul0", - "io_update_device": "ttl_urukul0_io_update", - "refclk": 150e6, - "clk_sel": 2 - } - } -) - -for i in range(4): - device_db["urukul0_ch" + str(i)] = { - "type": "local", - "module": "artiq.coredevice.ad9910", - "class": "AD9910", - "arguments": { - "pll_n": 16, # 600MHz sample rate - "pll_vco": 2, - "chip_select": 4 + i, - "cpld_device": "urukul0_cpld", - "sw_device": "ttl_urukul0_sw" + str(i) - } - } - -""" -artiq_route routing.bin init -artiq_route routing.bin set 0 0 -artiq_route routing.bin set 1 1 0 -artiq_route routing.bin set 2 1 1 0 -artiq_route routing.bin set 3 2 0 -artiq_route routing.bin set 4 2 1 0 -artiq_coremgmt -D kasli config write -f routing_table routing.bin -""" - -for sayma in range(2): - amc_base = 0x010000 + sayma*0x020000 - rtm_base = 0x020000 + sayma*0x020000 - for i in range(4): - device_db["led" + str(4*sayma+i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": amc_base + i} - } - for i in range(2): - device_db["ttl_mcx" + str(2*sayma+i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLInOut", - "arguments": {"channel": amc_base + 4 + i} - } - for i in range(8): - device_db["sawg" + str(8*sayma+i)] = { - "type": "local", - "module": "artiq.coredevice.sawg", - "class": "SAWG", - "arguments": {"channel_base": amc_base + 6 + i*10, "parallelism": 4} - } - for basemod in range(2): - for i in range(4): - device_db["sawg_sw" + str(8*sayma+4*basemod+i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": rtm_base + basemod*9 + i} - } - att_idx = 2*sayma + basemod - device_db["basemod_att_rst_n"+str(att_idx)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": rtm_base + basemod*9 + 4} - } - device_db["basemod_att_clk"+str(att_idx)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": rtm_base + basemod*9 + 5} - } - device_db["basemod_att_le"+str(att_idx)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": rtm_base + basemod*9 + 6} - } - device_db["basemod_att_mosi"+str(att_idx)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": rtm_base + basemod*9 + 7} - } - device_db["basemod_att_miso"+str(att_idx)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLInOut", - "arguments": {"channel": rtm_base + basemod*9 + 8} - } - device_db["basemod_att"+str(att_idx)] = { - "type": "local", - "module": "artiq.coredevice.basemod_att", - "class": "BaseModAtt", - "arguments": { - "rst_n": "basemod_att_rst_n"+str(att_idx), - "clk": "basemod_att_clk"+str(att_idx), - "le": "basemod_att_le"+str(att_idx), - "mosi": "basemod_att_mosi"+str(att_idx), - "miso": "basemod_att_miso"+str(att_idx), - } - } - diff --git a/artiq/examples/kasli_sawgmaster/repository/basemod.py b/artiq/examples/kasli_sawgmaster/repository/basemod.py deleted file mode 100644 index 3ca9a1c86..000000000 --- a/artiq/examples/kasli_sawgmaster/repository/basemod.py +++ /dev/null @@ -1,25 +0,0 @@ -from artiq.experiment import * - - -class BaseMod(EnvExperiment): - def build(self): - self.setattr_device("core") - self.basemods = [self.get_device("basemod_att0"), self.get_device("basemod_att1")] - self.rfsws = [self.get_device("sawg_sw"+str(i)) for i in range(8)] - - @kernel - def run(self): - self.core.reset() - for basemod in self.basemods: - self.core.break_realtime() - delay(10*ms) - basemod.reset() - delay(10*ms) - basemod.set(0.0, 0.0, 0.0, 0.0) - delay(10*ms) - print(basemod.get_mu()) - - self.core.break_realtime() - for rfsw in self.rfsws: - rfsw.on() - delay(1*ms) diff --git a/artiq/examples/kasli_sawgmaster/repository/sines_2sayma.py b/artiq/examples/kasli_sawgmaster/repository/sines_2sayma.py deleted file mode 100644 index 3a8204941..000000000 --- a/artiq/examples/kasli_sawgmaster/repository/sines_2sayma.py +++ /dev/null @@ -1,37 +0,0 @@ -from artiq.experiment import * - - -class Sines2Sayma(EnvExperiment): - def build(self): - self.setattr_device("core") - self.sawgs = [self.get_device("sawg"+str(i)) for i in range(16)] - - @kernel - def drtio_is_up(self): - for i in range(5): - if not self.core.get_rtio_destination_status(i): - return False - return True - - @kernel - def run(self): - while True: - print("waiting for DRTIO ready...") - while not self.drtio_is_up(): - pass - print("OK") - - self.core.reset() - - for sawg in self.sawgs: - delay(1*ms) - sawg.reset() - - for sawg in self.sawgs: - delay(1*ms) - sawg.amplitude1.set(.4) - # Do not use a sub-multiple of oscilloscope sample rates. - sawg.frequency0.set(9*MHz) - - while self.drtio_is_up(): - pass diff --git a/artiq/examples/kasli_sawgmaster/repository/sines_urukul_sayma.py b/artiq/examples/kasli_sawgmaster/repository/sines_urukul_sayma.py deleted file mode 100644 index dfd8e46c9..000000000 --- a/artiq/examples/kasli_sawgmaster/repository/sines_urukul_sayma.py +++ /dev/null @@ -1,89 +0,0 @@ -from artiq.experiment import * - - -class SinesUrukulSayma(EnvExperiment): - def build(self): - self.setattr_device("core") - self.setattr_device("urukul0_cpld") - - # Urukul clock output syntonized to the RTIO clock. - # Can be used as HMC830 reference on Sayma RTM. - # When using this reference, Sayma must be recalibrated every time Urukul - # is rebooted, as Urukul is not synchronized to the Kasli. - self.urukul_hmc_ref = self.get_device("urukul0_ch3") - - # Urukul measurement channels - compare with SAWG outputs. - # When testing sync, do not reboot Urukul, as it is not - # synchronized to the Kasli. - self.urukul_meas = [self.get_device("urukul0_ch" + str(i)) for i in range(3)] - # The same waveform is output on all first 4 SAWG channels (first DAC). - self.sawgs = [self.get_device("sawg"+str(i)) for i in range(4)] - self.basemod = self.get_device("basemod_att0") - self.rfsws = [self.get_device("sawg_sw"+str(i)) for i in range(4)] - - - # DRTIO destinations: - # 0: local - # 1: Sayma AMC - # 2: Sayma RTM - @kernel - def drtio_is_up(self): - for i in range(3): - if not self.core.get_rtio_destination_status(i): - return False - return True - - @kernel - def run(self): - f = 9*MHz - dds_ftw = self.urukul_meas[0].frequency_to_ftw(f) - sawg_ftw = self.sawgs[0].frequency0.to_mu(f) - if dds_ftw != sawg_ftw: - print("DDS and SAWG FTWs do not match:", dds_ftw, sawg_ftw) - return - - self.core.reset() - self.urukul0_cpld.init() - - delay(1*ms) - self.urukul_hmc_ref.init() - self.urukul_hmc_ref.set_mu(0x40000000, asf=self.urukul_hmc_ref.amplitude_to_asf(0.6)) - self.urukul_hmc_ref.set_att(6.) - self.urukul_hmc_ref.sw.on() - - for urukul_ch in self.urukul_meas: - delay(1*ms) - urukul_ch.init() - urukul_ch.set_mu(dds_ftw, asf=urukul_ch.amplitude_to_asf(0.5)) - urukul_ch.set_att(6.) - urukul_ch.sw.on() - - while True: - print("waiting for DRTIO ready...") - while not self.drtio_is_up(): - pass - print("OK") - - self.core.reset() - - delay(10*ms) - self.basemod.reset() - delay(10*ms) - self.basemod.set(3.0, 3.0, 3.0, 3.0) - delay(10*ms) - for rfsw in self.rfsws: - delay(1*ms) - rfsw.on() - - for sawg in self.sawgs: - delay(1*ms) - sawg.reset() - - for sawg in self.sawgs: - delay(1*ms) - sawg.amplitude1.set(.4) - sawg.frequency0.set_mu(sawg_ftw) - sawg.phase0.set_mu(sawg_ftw*now_mu() >> 17) - - while self.drtio_is_up(): - pass diff --git a/artiq/examples/metlino_sayma_ttl/device_db.py b/artiq/examples/metlino_sayma_ttl/device_db.py deleted file mode 100644 index 317173cd3..000000000 --- a/artiq/examples/metlino_sayma_ttl/device_db.py +++ /dev/null @@ -1,102 +0,0 @@ -core_addr = "192.168.1.65" - -device_db = { - "core": { - "type": "local", - "module": "artiq.coredevice.core", - "class": "Core", - "arguments": {"host": core_addr, "ref_period": 1/(8*150e6)} - }, - "core_log": { - "type": "controller", - "host": "::1", - "port": 1068, - "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr - }, - "core_moninj": { - "type": "controller", - "host": "::1", - "port_proxy": 1383, - "port": 1384, - "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr - }, - "core_cache": { - "type": "local", - "module": "artiq.coredevice.cache", - "class": "CoreCache" - }, - "core_dma": { - "type": "local", - "module": "artiq.coredevice.dma", - "class": "CoreDMA" - } -} - -# master peripherals -for i in range(4): - device_db["led" + str(i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": i}, -} - -# DEST#1 peripherals -amc_base = 0x070000 -rtm_base = 0x020000 - -for i in range(4): - device_db["led" + str(4+i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": amc_base + i}, - } - -#DIO (EEM0) starting at RTIO channel 0x000056 -for i in range(8): - device_db["ttl" + str(i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": amc_base + 0x000056 + i}, - } - -#DIO (EEM1) starting at RTIO channel 0x00005e -for i in range(8): - device_db["ttl" + str(8+i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": amc_base + 0x00005e + i}, - } - -device_db["fmcdio_dirctl_clk"] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": amc_base + 0x000066} -} - -device_db["fmcdio_dirctl_ser"] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": amc_base + 0x000067} -} - -device_db["fmcdio_dirctl_latch"] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": amc_base + 0x000068} -} - -device_db["fmcdio_dirctl"] = { - "type": "local", - "module": "artiq.coredevice.shiftreg", - "class": "ShiftReg", - "arguments": {"clk": "fmcdio_dirctl_clk", - "ser": "fmcdio_dirctl_ser", - "latch": "fmcdio_dirctl_latch"} -} diff --git a/artiq/examples/metlino_sayma_ttl/repository/demo.py b/artiq/examples/metlino_sayma_ttl/repository/demo.py deleted file mode 100644 index bb273ce2c..000000000 --- a/artiq/examples/metlino_sayma_ttl/repository/demo.py +++ /dev/null @@ -1,129 +0,0 @@ -import sys -import os -import select - -from artiq.experiment import * -from artiq.coredevice.fmcdio_vhdci_eem import * - - -def chunker(seq, size): - res = [] - for el in seq: - res.append(el) - if len(res) == size: - yield res - res = [] - if res: - yield res - - -def is_enter_pressed() -> TBool: - if os.name == "nt": - if msvcrt.kbhit() and msvcrt.getch() == b"\r": - return True - else: - return False - else: - if select.select([sys.stdin, ], [], [], 0.0)[0]: - sys.stdin.read(1) - return True - else: - return False - - -class Demo(EnvExperiment): - def build(self): - self.setattr_device("core") - self.setattr_device("fmcdio_dirctl") - - self.leds = dict() - self.ttl_outs = dict() - - ddb = self.get_device_db() - for name, desc in ddb.items(): - if isinstance(desc, dict) and desc["type"] == "local": - module, cls = desc["module"], desc["class"] - if (module, cls) == ("artiq.coredevice.ttl", "TTLOut"): - dev = self.get_device(name) - if "led" in name: # guess - self.leds[name] = dev - elif "ttl" in name: # to exclude fmcdio_dirctl - self.ttl_outs[name] = dev - - self.leds = sorted(self.leds.items(), key=lambda x: x[1].channel) - self.ttl_outs = sorted(self.ttl_outs.items(), key=lambda x: x[1].channel) - - self.dirctl_word = ( - shiftreg_bits(0, dio_bank0_out_pins | dio_bank1_out_pins) | - shiftreg_bits(1, dio_bank0_out_pins | dio_bank1_out_pins) - ) - - @kernel - def init(self): - self.core.break_realtime() - print("*** Waiting for DRTIO ready...") - drtio_indices = [7] - for i in drtio_indices: - while not self.drtio_is_up(i): - pass - - self.fmcdio_dirctl.set(self.dirctl_word) - - @kernel - def drtio_is_up(self, drtio_index): - if not self.core.get_rtio_destination_status(drtio_index): - return False - print("DRTIO #", drtio_index, "is ready\n") - return True - - @kernel - def test_led(self, led): - while not is_enter_pressed(): - self.core.break_realtime() - # do not fill the FIFOs too much to avoid long response times - t = now_mu() - self.core.seconds_to_mu(0.2) - while self.core.get_rtio_counter_mu() < t: - pass - for i in range(3): - led.pulse(100*ms) - delay(100*ms) - - def test_leds(self): - print("*** Testing LEDs.") - print("Check for blinking. Press ENTER when done.") - - for led_name, led_dev in self.leds: - print("Testing LED: {}".format(led_name)) - self.test_led(led_dev) - - @kernel - def test_ttl_out_chunk(self, ttl_chunk): - while not is_enter_pressed(): - self.core.break_realtime() - for _ in range(50000): - i = 0 - for ttl in ttl_chunk: - i += 1 - for _ in range(i): - ttl.pulse(1*us) - delay(1*us) - delay(10*us) - - def test_ttl_outs(self): - print("*** Testing TTL outputs.") - print("Outputs are tested in groups of 4. Touch each TTL connector") - print("with the oscilloscope probe tip, and check that the number of") - print("pulses corresponds to its number in the group.") - print("Press ENTER when done.") - - for ttl_chunk in chunker(self.ttl_outs, 4): - print("Testing TTL outputs: {}.".format(", ".join(name for name, dev in ttl_chunk))) - self.test_ttl_out_chunk([dev for name, dev in ttl_chunk]) - - def run(self): - self.core.reset() - - if self.leds: - self.test_leds() - if self.ttl_outs: - self.test_ttl_outs() diff --git a/artiq/examples/sayma_master/device_db.py b/artiq/examples/sayma_master/device_db.py deleted file mode 100644 index 4ce3f1be0..000000000 --- a/artiq/examples/sayma_master/device_db.py +++ /dev/null @@ -1,173 +0,0 @@ -core_addr = "192.168.1.60" - -device_db = { - "core": { - "type": "local", - "module": "artiq.coredevice.core", - "class": "Core", - "arguments": {"host": core_addr, "ref_period": 1/(8*150e6)} - }, - "core_log": { - "type": "controller", - "host": "::1", - "port": 1068, - "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr - }, - "core_moninj": { - "type": "controller", - "host": "::1", - "port_proxy": 1383, - "port": 1384, - "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr - }, - "core_cache": { - "type": "local", - "module": "artiq.coredevice.cache", - "class": "CoreCache" - }, - "core_dma": { - "type": "local", - "module": "artiq.coredevice.dma", - "class": "CoreDMA" - }, -} - -for i in range(4): - device_db["led" + str(i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": i}, - } - - -for i in range(2): - device_db["ttl" + str(i)] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLInOut", - "arguments": {"channel": 4 + i}, - } - - -device_db.update( - fmcdio_dirctl_clk={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 6} - }, - fmcdio_dirctl_ser={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 7} - }, - fmcdio_dirctl_latch={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 8} - }, - fmcdio_dirctl={ - "type": "local", - "module": "artiq.coredevice.shiftreg", - "class": "ShiftReg", - "arguments": {"clk": "fmcdio_dirctl_clk", - "ser": "fmcdio_dirctl_ser", - "latch": "fmcdio_dirctl_latch"} - } -) - -device_db.update( - spi_urukul0={ - "type": "local", - "module": "artiq.coredevice.spi2", - "class": "SPIMaster", - "arguments": {"channel": 17} - }, - ttl_urukul0_io_update={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 18} - }, - ttl_urukul0_sw0={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 19} - }, - ttl_urukul0_sw1={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 20} - }, - ttl_urukul0_sw2={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 21} - }, - ttl_urukul0_sw3={ - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 22} - }, - urukul0_cpld={ - "type": "local", - "module": "artiq.coredevice.urukul", - "class": "CPLD", - "arguments": { - "spi_device": "spi_urukul0", - "io_update_device": "ttl_urukul0_io_update", - "refclk": 125e6, - "clk_sel": 0 - } - } -) - -for i in range(4): - device_db["urukul0_ch" + str(i)] = { - "type": "local", - "module": "artiq.coredevice.ad9910", - "class": "AD9910", - "arguments": { - "pll_n": 32, - "chip_select": 4 + i, - "cpld_device": "urukul0_cpld", - "sw_device": "ttl_urukul0_sw" + str(i) - } - } - - -device_db["spi_zotino0"] = { - "type": "local", - "module": "artiq.coredevice.spi2", - "class": "SPIMaster", - "arguments": {"channel": 23} -} -device_db["ttl_zotino0_ldac"] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 24} -} -device_db["ttl_zotino0_clr"] = { - "type": "local", - "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 25} -} -device_db["zotino0"] = { - "type": "local", - "module": "artiq.coredevice.zotino", - "class": "Zotino", - "arguments": { - "spi_device": "spi_zotino0", - "ldac_device": "ttl_zotino0_ldac", - "clr_device": "ttl_zotino0_clr" - } -} diff --git a/artiq/examples/sayma_master/repository/demo.py b/artiq/examples/sayma_master/repository/demo.py deleted file mode 100644 index 9b40f4b42..000000000 --- a/artiq/examples/sayma_master/repository/demo.py +++ /dev/null @@ -1,41 +0,0 @@ -from artiq.experiment import * -from artiq.coredevice.fmcdio_vhdci_eem import * - - -class Demo(EnvExperiment): - def build(self): - self.setattr_device("core") - self.setattr_device("fmcdio_dirctl") - - self.ttls = [self.get_device("ttl" + str(i)) for i in range(8)] - self.setattr_device("urukul0_cpld") - self.urukul_chs = [self.get_device("urukul0_ch" + str(i)) for i in range(4)] - self.setattr_device("zotino0") - - self.dirctl_word = ( - shiftreg_bits(1, urukul_out_pins) | - shiftreg_bits(0, urukul_aux_out_pins) | - shiftreg_bits(2, dio_bank0_out_pins | dio_bank1_out_pins) | - shiftreg_bits(3, zotino_out_pins)) - - @kernel - def run(self): - self.core.reset() - delay(10*ms) - self.fmcdio_dirctl.set(self.dirctl_word) - delay(10*ms) - - self.urukul0_cpld.init() - delay(10*ms) - - self.zotino0.init() - delay(1*ms) - for i in range(32): - self.zotino0.write_dac(i, i/4) - delay(1*ms) - - while True: - for ttl in self.ttls: - ttl.pulse(100*ms) - for urukul_ch in self.urukul_chs: - urukul_ch.sw.pulse(100*ms) diff --git a/artiq/firmware/libboard_artiq/ad9154.rs b/artiq/firmware/libboard_artiq/ad9154.rs deleted file mode 100644 index de32ff2e2..000000000 --- a/artiq/firmware/libboard_artiq/ad9154.rs +++ /dev/null @@ -1,549 +0,0 @@ -use board_misoc::{csr, clock}; -use ad9154_reg; - -fn spi_setup(dacno: u8) { - unsafe { - while csr::converter_spi::idle_read() == 0 {} - csr::converter_spi::offline_write(0); - csr::converter_spi::end_write(1); - csr::converter_spi::cs_polarity_write(0b0001); - csr::converter_spi::clk_polarity_write(0); - csr::converter_spi::clk_phase_write(0); - csr::converter_spi::lsb_first_write(0); - csr::converter_spi::half_duplex_write(0); - csr::converter_spi::length_write(24 - 1); - csr::converter_spi::div_write(16 - 2); - csr::converter_spi::cs_write(1 << (csr::CONFIG_CONVERTER_SPI_FIRST_AD9154_CS + dacno as u32)); - } -} - -fn write(addr: u16, data: u8) { - unsafe { - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::data_write( - ((addr as u32) << 16) | ((data as u32) << 8)); - } -} - -fn read(addr: u16) -> u8 { - unsafe { - write((1 << 15) | addr, 0); - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::data_read() as u8 - } -} - -// ad9154 mode 1 -// linerate 5Gbps or 6Gbps -// deviceclock_fpga 125MHz or 150MHz -// deviceclock_dac 500MHz or 600MHz - -struct JESDSettings { - did: u8, - bid: u8, - - l: u8, // lanes - m: u8, // converters - n: u8, // bits/converter - np: u8, // bits/sample - - f: u8, // octets/(lane and frame) - s: u8, // samples/(converter and frame) - k: u8, // frames/multiframe - cs: u8, // control bits/sample - - subclassv: u8, - jesdv: u8 -} - -fn jesd_checksum(settings: &JESDSettings) -> u8 { - let mut r: u8 = 0; - for field in [ - settings.did, - settings.bid, - settings.l - 1, - settings.f - 1, - settings.k - 1, - settings.m - 1, - settings.n - 1, - settings.cs, - settings.np - 1, - settings.subclassv, - settings.s - 1, - settings.jesdv, - ].iter() { - r = r.overflowing_add(*field).0; - } - r -} - -const JESD_SETTINGS: JESDSettings = JESDSettings { - did: 0x5a, - bid: 0x5, - - l: 8, - m: 4, - n: 16, - np: 16, - f: 2, - s: 2, - k: 16, - cs: 0, - - subclassv: 1, - jesdv: 1 -}; - -pub fn reset_and_detect(dacno: u8) -> Result<(), &'static str> { - spi_setup(dacno); - // reset - write(ad9154_reg::SPI_INTFCONFA, - 1*ad9154_reg::SOFTRESET_M | 1*ad9154_reg::SOFTRESET | - 0*ad9154_reg::LSBFIRST_M | 0*ad9154_reg::LSBFIRST | - 0*ad9154_reg::ADDRINC_M | 0*ad9154_reg::ADDRINC | - 1*ad9154_reg::SDOACTIVE_M | 1*ad9154_reg::SDOACTIVE); - clock::spin_us(100); - write(ad9154_reg::SPI_INTFCONFA, - 0*ad9154_reg::SOFTRESET_M | 0*ad9154_reg::SOFTRESET | - 0*ad9154_reg::LSBFIRST_M | 0*ad9154_reg::LSBFIRST | - 0*ad9154_reg::ADDRINC_M | 0*ad9154_reg::ADDRINC | - 1*ad9154_reg::SDOACTIVE_M | 1*ad9154_reg::SDOACTIVE); - clock::spin_us(100); - if (read(ad9154_reg::PRODIDH) as u16) << 8 | (read(ad9154_reg::PRODIDL) as u16) != 0x9154 { - return Err("invalid AD9154 identification"); - } else { - info!("AD9154-{} found", dacno); - } - Ok(()) -} - -pub fn setup(dacno: u8, linerate: u64) -> Result<(), &'static str> { - spi_setup(dacno); - info!("AD9154-{} initializing...", dacno); - write(ad9154_reg::PWRCNTRL0, - 0*ad9154_reg::PD_DAC0 | 0*ad9154_reg::PD_DAC1 | - 0*ad9154_reg::PD_DAC2 | 0*ad9154_reg::PD_DAC3 | - 0*ad9154_reg::PD_BG); - clock::spin_us(100); - write(ad9154_reg::TXENMASK1, 0*ad9154_reg::DACA_MASK | - 0*ad9154_reg::DACB_MASK); // DAC PD not controlled by TXEN pins - write(ad9154_reg::PWRCNTRL3, 1*ad9154_reg::ENA_SPI_TXEN | - 1*ad9154_reg::SPI_TXEN); - write(ad9154_reg::CLKCFG0, - 0*ad9154_reg::REF_CLKDIV_EN | 1*ad9154_reg::RF_SYNC_EN | - 1*ad9154_reg::DUTY_EN | 0*ad9154_reg::PD_CLK_REC | - 0*ad9154_reg::PD_SERDES_PCLK | 0*ad9154_reg::PD_CLK_DIG | - 0*ad9154_reg::PD_CLK23 | 0*ad9154_reg::PD_CLK01); - write(ad9154_reg::DACPLLCNTRL, - 0*ad9154_reg::ENABLE_DACPLL | 0*ad9154_reg::RECAL_DACPLL); - write(ad9154_reg::SYSREF_ACTRL0, // jesd204b subclass 1 - 0*ad9154_reg::HYS_CNTRL1 | 0*ad9154_reg::SYSREF_RISE | - 0*ad9154_reg::HYS_ON | 0*ad9154_reg::PD_SYSREF_BUFFER); - - write(ad9154_reg::DEVICE_CONFIG_REG_0, 0x8b); // magic - write(ad9154_reg::DEVICE_CONFIG_REG_1, 0x01); // magic - write(ad9154_reg::DEVICE_CONFIG_REG_2, 0x01); // magic - - write(ad9154_reg::SPI_PAGEINDX, 0x3); // A and B dual - - write(ad9154_reg::INTERP_MODE, 0x03); // 4x - write(ad9154_reg::MIX_MODE, 0); - write(ad9154_reg::DATA_FORMAT, 0*ad9154_reg::BINARY_FORMAT); // s16 - write(ad9154_reg::DATAPATH_CTRL, - 0*ad9154_reg::I_TO_Q | 0*ad9154_reg::SEL_SIDEBAND | - 0*ad9154_reg::MODULATION_TYPE | 0*ad9154_reg::PHASE_ADJ_ENABLE | - 1*ad9154_reg::DIG_GAIN_ENABLE | 0*ad9154_reg::INVSINC_ENABLE); - write(ad9154_reg::IDAC_DIG_GAIN0, 0x00); - write(ad9154_reg::IDAC_DIG_GAIN1, 0x8); - write(ad9154_reg::QDAC_DIG_GAIN0, 0x00); - write(ad9154_reg::QDAC_DIG_GAIN1, 0x8); - write(ad9154_reg::DC_OFFSET_CTRL, 0); - write(ad9154_reg::IPATH_DC_OFFSET_1PART0, 0x00); - write(ad9154_reg::IPATH_DC_OFFSET_1PART1, 0x00); - write(ad9154_reg::IPATH_DC_OFFSET_2PART, 0x00); - write(ad9154_reg::QPATH_DC_OFFSET_1PART0, 0x00); - write(ad9154_reg::QPATH_DC_OFFSET_1PART1, 0x00); - write(ad9154_reg::QPATH_DC_OFFSET_2PART, 0x00); - write(ad9154_reg::PHASE_ADJ0, 0); - write(ad9154_reg::PHASE_ADJ1, 0); - write(ad9154_reg::GROUP_DLY, 0x8*ad9154_reg::COARSE_GROUP_DELAY | - 0x8*ad9154_reg::GROUP_DELAY_RESERVED); - write(ad9154_reg::GROUPDELAY_COMP_BYP, - 1*ad9154_reg::GROUPCOMP_BYPQ | - 1*ad9154_reg::GROUPCOMP_BYPI); - write(ad9154_reg::GROUPDELAY_COMP_I, 0); - write(ad9154_reg::GROUPDELAY_COMP_Q, 0); - write(ad9154_reg::PDP_AVG_TIME, 0*ad9154_reg::PDP_ENABLE); - - write(ad9154_reg::MASTER_PD, 0); - write(ad9154_reg::PHY_PD, 0x00); // lanes 0-7 enabled - write(ad9154_reg::GENERIC_PD, - 0*ad9154_reg::PD_SYNCOUT0B | - 1*ad9154_reg::PD_SYNCOUT1B); - write(ad9154_reg::GENERAL_JRX_CTRL_0, - 0x0*ad9154_reg::LINK_EN | 0*ad9154_reg::LINK_PAGE | - 0*ad9154_reg::LINK_MODE | 0*ad9154_reg::CHECKSUM_MODE); - write(ad9154_reg::ILS_DID, JESD_SETTINGS.did); - write(ad9154_reg::ILS_BID, JESD_SETTINGS.bid); - write(ad9154_reg::ILS_LID0, 0x00); // lane id - write(ad9154_reg::ILS_SCR_L, - (JESD_SETTINGS.l - 1)*ad9154_reg::L_1 | - 1*ad9154_reg::SCR); - write(ad9154_reg::ILS_F, JESD_SETTINGS.f - 1); - write(ad9154_reg::ILS_K, JESD_SETTINGS.k - 1); - write(ad9154_reg::ILS_M, JESD_SETTINGS.m - 1); - write(ad9154_reg::ILS_CS_N, - (JESD_SETTINGS.n - 1)*ad9154_reg::N_1 | - 0*ad9154_reg::CS); - write(ad9154_reg::ILS_NP, - (JESD_SETTINGS.np - 1)*ad9154_reg::NP_1 | - JESD_SETTINGS.subclassv*ad9154_reg::SUBCLASSV); - write(ad9154_reg::ILS_S, - (JESD_SETTINGS.s - 1)*ad9154_reg::S_1 | - JESD_SETTINGS.jesdv*ad9154_reg::JESDV); - write(ad9154_reg::ILS_HD_CF, - 0*ad9154_reg::HD | 0*ad9154_reg::CF); - write(ad9154_reg::ILS_CHECKSUM, jesd_checksum(&JESD_SETTINGS)); - write(ad9154_reg::LANEDESKEW, 0xff); - for i in 0..8 { - write(ad9154_reg::BADDISPARITY, 0*ad9154_reg::RST_IRQ_DIS | - 0*ad9154_reg::DISABLE_ERR_CNTR_DIS | - 1*ad9154_reg::RST_ERR_CNTR_DIS | i*ad9154_reg::LANE_ADDR_DIS); - write(ad9154_reg::BADDISPARITY, 0*ad9154_reg::RST_IRQ_DIS | - 0*ad9154_reg::DISABLE_ERR_CNTR_DIS | - 0*ad9154_reg::RST_ERR_CNTR_DIS | i*ad9154_reg::LANE_ADDR_DIS); - write(ad9154_reg::NIT_W, 0*ad9154_reg::RST_IRQ_NIT | - 0*ad9154_reg::DISABLE_ERR_CNTR_NIT | - 1*ad9154_reg::RST_ERR_CNTR_NIT | i*ad9154_reg::LANE_ADDR_NIT); - write(ad9154_reg::NIT_W, 0*ad9154_reg::RST_IRQ_NIT | - 0*ad9154_reg::DISABLE_ERR_CNTR_NIT | - 0*ad9154_reg::RST_ERR_CNTR_NIT | i*ad9154_reg::LANE_ADDR_NIT); - write(ad9154_reg::UNEXPECTEDCONTROL_W, 0*ad9154_reg::RST_IRQ_UCC | - 0*ad9154_reg::DISABLE_ERR_CNTR_UCC | - 1*ad9154_reg::RST_ERR_CNTR_UCC | i*ad9154_reg::LANE_ADDR_UCC); - write(ad9154_reg::BADDISPARITY, 0*ad9154_reg::RST_IRQ_UCC | - 0*ad9154_reg::DISABLE_ERR_CNTR_UCC | - 0*ad9154_reg::RST_ERR_CNTR_UCC | i*ad9154_reg::LANE_ADDR_UCC); - } - write(ad9154_reg::CTRLREG1, JESD_SETTINGS.f); - write(ad9154_reg::CTRLREG2, 0*ad9154_reg::ILAS_MODE | - 0*ad9154_reg::THRESHOLD_MASK_EN); - write(ad9154_reg::KVAL, 1); // *4*K multiframes during ILAS - write(ad9154_reg::LANEENABLE, 0xff); // CGS _after_ this - - write(ad9154_reg::TERM_BLK1_CTRLREG0, 1); - write(ad9154_reg::TERM_BLK2_CTRLREG0, 1); - write(ad9154_reg::SERDES_SPI_REG, 1); - if linerate > 5_650_000_000 { - write(ad9154_reg::CDR_OPERATING_MODE_REG_0, - 0*ad9154_reg::CDR_OVERSAMP | 0x2*ad9154_reg::CDR_RESERVED | - 1*ad9154_reg::ENHALFRATE); - } else { - write(ad9154_reg::CDR_OPERATING_MODE_REG_0, - 0*ad9154_reg::CDR_OVERSAMP | 0x2*ad9154_reg::CDR_RESERVED | - 0*ad9154_reg::ENHALFRATE); - } - write(ad9154_reg::CDR_RESET, 0); - write(ad9154_reg::CDR_RESET, 1); - if linerate > 5_650_000_000 { - write(ad9154_reg::REF_CLK_DIVIDER_LDO, - 0*ad9154_reg::SPI_CDR_OVERSAMP | - 1*ad9154_reg::SPI_LDO_BYPASS_FILT | - 0*ad9154_reg::SPI_LDO_REF_SEL); - } else { - write(ad9154_reg::REF_CLK_DIVIDER_LDO, - 1*ad9154_reg::SPI_CDR_OVERSAMP | - 1*ad9154_reg::SPI_LDO_BYPASS_FILT | - 0*ad9154_reg::SPI_LDO_REF_SEL); - } - write(ad9154_reg::LDO_FILTER_1, 0x62); // magic - write(ad9154_reg::LDO_FILTER_2, 0xc9); // magic - write(ad9154_reg::LDO_FILTER_3, 0x0e); // magic - write(ad9154_reg::CP_CURRENT_SPI, - 0x12*ad9154_reg::SPI_CP_CURRENT | - 0*ad9154_reg::SPI_SERDES_LOGEN_POWER_MODE); - write(ad9154_reg::VCO_LDO, 0x7b); // magic - write(ad9154_reg::PLL_RD_REG, - 0*ad9154_reg::SPI_SERDES_LOGEN_PD_CORE | - 0*ad9154_reg::SPI_SERDES_LDO_PD | 0*ad9154_reg::SPI_SYN_PD | - 0*ad9154_reg::SPI_VCO_PD_ALC | 0*ad9154_reg::SPI_VCO_PD_PTAT | - 0*ad9154_reg::SPI_VCO_PD); - write(ad9154_reg::ALC_VARACTOR, - 0x9*ad9154_reg::SPI_VCO_VARACTOR | - 0x8*ad9154_reg::SPI_INIT_ALC_VALUE); - write(ad9154_reg::VCO_OUTPUT, - 0xc*ad9154_reg::SPI_VCO_OUTPUT_LEVEL | - 0x4*ad9154_reg::SPI_VCO_OUTPUT_RESERVED); - write(ad9154_reg::CP_CONFIG, - 0*ad9154_reg::SPI_CP_TEST | - 1*ad9154_reg::SPI_CP_CAL_EN | - 0*ad9154_reg::SPI_CP_FORCE_CALBITS | - 0*ad9154_reg::SPI_CP_OFFSET_OFF | - 1*ad9154_reg::SPI_CP_ENABLE_MACHINE | - 0*ad9154_reg::SPI_CP_DITHER_MODE | - 0*ad9154_reg::SPI_CP_HALF_VCO_CAL_CLK); - write(ad9154_reg::VCO_BIAS_1, - 0x3*ad9154_reg::SPI_VCO_BIAS_REF | - 0x3*ad9154_reg::SPI_VCO_BIAS_TCF); - write(ad9154_reg::VCO_BIAS_2, - 0x1*ad9154_reg::SPI_PRESCALE_BIAS | - 1*ad9154_reg::SPI_LAST_ALC_EN | - 0x1*ad9154_reg::SPI_PRESCALE_BYPASS_R | - 0*ad9154_reg::SPI_VCO_COMP_BYPASS_BIASR | - 0*ad9154_reg::SPI_VCO_BYPASS_DAC_R); - write(ad9154_reg::VCO_PD_OVERRIDES, - 0*ad9154_reg::SPI_VCO_PD_OVERRIDE_VCO_BUF | - 1*ad9154_reg::SPI_VCO_PD_OVERRIDE_CAL_TCF | - 0*ad9154_reg::SPI_VCO_PD_OVERRIDE_VAR_REF_TCF | - 0*ad9154_reg::SPI_VCO_PD_OVERRIDE_VAR_REF); - write(ad9154_reg::VCO_CAL, - 0x2*ad9154_reg::SPI_FB_CLOCK_ADV | - 0x3*ad9154_reg::SPI_VCO_CAL_COUNT | - 0*ad9154_reg::SPI_VCO_CAL_ALC_WAIT | - 1*ad9154_reg::SPI_VCO_CAL_EN); - write(ad9154_reg::CP_LEVEL_DETECT, - 0x2*ad9154_reg::SPI_CP_LEVEL_THRESHOLD_HIGH | - 0x5*ad9154_reg::SPI_CP_LEVEL_THRESHOLD_LOW | - 0*ad9154_reg::SPI_CP_LEVEL_DET_PD); - write(ad9154_reg::VCO_VARACTOR_CTRL_0, - 0xe*ad9154_reg::SPI_VCO_VARACTOR_OFFSET | - 0x7*ad9154_reg::SPI_VCO_VARACTOR_REF_TCF); - write(ad9154_reg::VCO_VARACTOR_CTRL_1, - 0x6*ad9154_reg::SPI_VCO_VARACTOR_REF); - // ensure link is txing - //write(ad9154_reg::SERDESPLL_ENABLE_CNTRL, - // 1*ad9154_reg::ENABLE_SERDESPLL | 1*ad9154_reg::RECAL_SERDESPLL) - write(ad9154_reg::SERDESPLL_ENABLE_CNTRL, - 1*ad9154_reg::ENABLE_SERDESPLL | 0*ad9154_reg::RECAL_SERDESPLL); - let t = clock::get_ms(); - while read(ad9154_reg::PLL_STATUS) & ad9154_reg::SERDES_PLL_LOCK_RB == 0 { - if clock::get_ms() > t + 200 { - return Err("SERDES PLL lock timeout"); - } - } - - write(ad9154_reg::EQ_BIAS_REG, 0x22*ad9154_reg::EQ_BIAS_RESERVED | - 1*ad9154_reg::EQ_POWER_MODE); - - write(ad9154_reg::GENERAL_JRX_CTRL_1, 1); // subclass 1 - write(ad9154_reg::LMFC_DELAY_0, 0); - write(ad9154_reg::LMFC_DELAY_1, 0); - write(ad9154_reg::LMFC_VAR_0, 0x0a); // receive buffer delay - write(ad9154_reg::LMFC_VAR_1, 0x0a); - write(ad9154_reg::SYNC_ERRWINDOW, 0); // +- 1/2 DAC clock - // datasheet seems to say ENABLE and ARM should be separate steps, - // so enable now so it can be armed in sync(). - write(ad9154_reg::SYNC_CONTROL, - 0x1*ad9154_reg::SYNCMODE | 1*ad9154_reg::SYNCENABLE | - 0*ad9154_reg::SYNCARM | 0*ad9154_reg::SYNCCLRSTKY); - - write(ad9154_reg::XBAR_LN_0_1, - 0*ad9154_reg::LOGICAL_LANE0_SRC | 1*ad9154_reg::LOGICAL_LANE1_SRC); - write(ad9154_reg::XBAR_LN_2_3, - 2*ad9154_reg::LOGICAL_LANE2_SRC | 3*ad9154_reg::LOGICAL_LANE3_SRC); - write(ad9154_reg::XBAR_LN_4_5, - 4*ad9154_reg::LOGICAL_LANE4_SRC | 5*ad9154_reg::LOGICAL_LANE5_SRC); - write(ad9154_reg::XBAR_LN_6_7, - 6*ad9154_reg::LOGICAL_LANE6_SRC | 7*ad9154_reg::LOGICAL_LANE7_SRC); - write(ad9154_reg::JESD_BIT_INVERSE_CTRL, 0x00); - write(ad9154_reg::GENERAL_JRX_CTRL_0, - 0x1*ad9154_reg::LINK_EN | 0*ad9154_reg::LINK_PAGE | - 0*ad9154_reg::LINK_MODE | 0*ad9154_reg::CHECKSUM_MODE); - info!(" ...done"); - Ok(()) -} - -pub fn status(dacno: u8) { - spi_setup(dacno); - info!("Printing status of AD9154-{}", dacno); - info!("PRODID: 0x{:04x}", (read(ad9154_reg::PRODIDH) as u16) << 8 | (read(ad9154_reg::PRODIDL) as u16)); - info!("SERDES_PLL_LOCK: {}", - (read(ad9154_reg::PLL_STATUS) & ad9154_reg::SERDES_PLL_LOCK_RB)); - info!(""); - info!("CODEGRPSYNC: 0x{:02x}", read(ad9154_reg::CODEGRPSYNCFLG)); - info!("FRAMESYNC: 0x{:02x}", read(ad9154_reg::FRAMESYNCFLG)); - info!("GOODCHECKSUM: 0x{:02x}", read(ad9154_reg::GOODCHKSUMFLG)); - info!("INITLANESYNC: 0x{:02x}", read(ad9154_reg::INITLANESYNCFLG)); - info!(""); - info!("DID_REG: 0x{:02x}", read(ad9154_reg::DID_REG)); - info!("BID_REG: 0x{:02x}", read(ad9154_reg::BID_REG)); - info!("SCR_L_REG: 0x{:02x}", read(ad9154_reg::SCR_L_REG)); - info!("F_REG: 0x{:02x}", read(ad9154_reg::F_REG)); - info!("K_REG: 0x{:02x}", read(ad9154_reg::K_REG)); - info!("M_REG: 0x{:02x}", read(ad9154_reg::M_REG)); - info!("CS_N_REG: 0x{:02x}", read(ad9154_reg::CS_N_REG)); - info!("NP_REG: 0x{:02x}", read(ad9154_reg::NP_REG)); - info!("S_REG: 0x{:02x}", read(ad9154_reg::S_REG)); - info!("HD_CF_REG: 0x{:02x}", read(ad9154_reg::HD_CF_REG)); - info!("RES1_REG: 0x{:02x}", read(ad9154_reg::RES1_REG)); - info!("RES2_REG: 0x{:02x}", read(ad9154_reg::RES2_REG)); - info!("LIDx_REG: 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x}", - read(ad9154_reg::LID0_REG), - read(ad9154_reg::LID1_REG), - read(ad9154_reg::LID2_REG), - read(ad9154_reg::LID3_REG), - read(ad9154_reg::LID4_REG), - read(ad9154_reg::LID5_REG), - read(ad9154_reg::LID6_REG), - read(ad9154_reg::LID7_REG)); - info!("CHECKSUMx_REG: 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x}", - read(ad9154_reg::CHECKSUM0_REG), - read(ad9154_reg::CHECKSUM1_REG), - read(ad9154_reg::CHECKSUM2_REG), - read(ad9154_reg::CHECKSUM3_REG), - read(ad9154_reg::CHECKSUM4_REG), - read(ad9154_reg::CHECKSUM5_REG), - read(ad9154_reg::CHECKSUM6_REG), - read(ad9154_reg::CHECKSUM7_REG)); - info!("COMPSUMx_REG: 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x} 0x{:02x}", - read(ad9154_reg::COMPSUM0_REG), - read(ad9154_reg::COMPSUM1_REG), - read(ad9154_reg::COMPSUM2_REG), - read(ad9154_reg::COMPSUM3_REG), - read(ad9154_reg::COMPSUM4_REG), - read(ad9154_reg::COMPSUM5_REG), - read(ad9154_reg::COMPSUM6_REG), - read(ad9154_reg::COMPSUM7_REG)); - info!("BADDISPARITY: 0x{:02x}", read(ad9154_reg::BADDISPARITY)); - info!("NITDISPARITY: 0x{:02x}", read(ad9154_reg::NIT_W)); -} - -pub fn prbs(dacno: u8) -> Result<(), &'static str> { - let mut prbs_errors: u32 = 0; - spi_setup(dacno); - - /* follow phy prbs testing (p58 of ad9154 datasheet) */ - info!("AD9154-{} running PRBS test...", dacno); - - /* step 2: select prbs mode */ - write(ad9154_reg::PHY_PRBS_TEST_CTRL, - 0b00*ad9154_reg::PHY_PRBS_PAT_SEL); - - /* step 3: enable test for all lanes */ - write(ad9154_reg::PHY_PRBS_TEST_EN, 0xff); - - /* step 4: reset */ - write(ad9154_reg::PHY_PRBS_TEST_CTRL, - 0b00*ad9154_reg::PHY_PRBS_PAT_SEL | - 1*ad9154_reg::PHY_TEST_RESET); - write(ad9154_reg::PHY_PRBS_TEST_CTRL, - 0b00*ad9154_reg::PHY_PRBS_PAT_SEL); - - /* step 5: prbs threshold */ - write(ad9154_reg::PHY_PRBS_TEST_THRESHOLD_LOBITS, 0); - write(ad9154_reg::PHY_PRBS_TEST_THRESHOLD_MIDBITS, 0); - write(ad9154_reg::PHY_PRBS_TEST_THRESHOLD_HIBITS, 0); - - /* step 6: start */ - write(ad9154_reg::PHY_PRBS_TEST_CTRL, - 0b00*ad9154_reg::PHY_PRBS_PAT_SEL); - write(ad9154_reg::PHY_PRBS_TEST_CTRL, - 0b00*ad9154_reg::PHY_PRBS_PAT_SEL | - 1*ad9154_reg::PHY_TEST_START); - - /* step 7: wait 500 ms */ - clock::spin_us(500000); - - /* step 8 : stop */ - write(ad9154_reg::PHY_PRBS_TEST_CTRL, - 0b00*ad9154_reg::PHY_PRBS_PAT_SEL); - - for i in 0..8 { - /* step 9.a: select src err */ - write(ad9154_reg::PHY_PRBS_TEST_CTRL, - i*ad9154_reg::PHY_SRC_ERR_CNT); - /* step 9.b: retrieve number of errors */ - let lane_errors = (read(ad9154_reg::PHY_PRBS_TEST_ERRCNT_LOBITS) as u32) | - ((read(ad9154_reg::PHY_PRBS_TEST_ERRCNT_MIDBITS) as u32) << 8) | - ((read(ad9154_reg::PHY_PRBS_TEST_ERRCNT_HIBITS) as u32) << 16); - if lane_errors > 0 { - warn!(" PRBS errors on lane{}: {:06x}", i, lane_errors); - } - prbs_errors += lane_errors - } - - if prbs_errors > 0 { - return Err("PRBS failed") - } - info!(" ...passed"); - Ok(()) -} - -pub fn stpl(dacno: u8, m: u8, s: u8) -> Result<(), &'static str> { - spi_setup(dacno); - - info!("AD9154-{} running STPL test...", dacno); - - fn prng(seed: u32) -> u32 { - return ((seed + 1)*0x31415979 + 1) & 0xffff; - } - - for i in 0..m { - let mut data: u32; - let mut errors: u8 = 0; - for j in 0..s { - /* select converter */ - write(ad9154_reg::SHORT_TPL_TEST_0, - 0b0*ad9154_reg::SHORT_TPL_TEST_EN | - 0b0*ad9154_reg::SHORT_TPL_TEST_RESET | - i*ad9154_reg::SHORT_TPL_DAC_SEL | - j*ad9154_reg::SHORT_TPL_SP_SEL); - - /* set expected value */ - data = prng(((i as u32) << 8) | (j as u32)); - write(ad9154_reg::SHORT_TPL_TEST_1, (data & 0x00ff) as u8); - write(ad9154_reg::SHORT_TPL_TEST_2, ((data & 0xff00) >> 8) as u8); - - /* enable stpl */ - write(ad9154_reg::SHORT_TPL_TEST_0, - 0b1*ad9154_reg::SHORT_TPL_TEST_EN | - 0b0*ad9154_reg::SHORT_TPL_TEST_RESET | - i*ad9154_reg::SHORT_TPL_DAC_SEL | - j*ad9154_reg::SHORT_TPL_SP_SEL); - - /* reset stpl */ - write(ad9154_reg::SHORT_TPL_TEST_0, - 0b1*ad9154_reg::SHORT_TPL_TEST_EN | - 0b1*ad9154_reg::SHORT_TPL_TEST_RESET | - i*ad9154_reg::SHORT_TPL_DAC_SEL | - j*ad9154_reg::SHORT_TPL_SP_SEL); - - /* release reset stpl */ - write(ad9154_reg::SHORT_TPL_TEST_0, - 0b1*ad9154_reg::SHORT_TPL_TEST_EN | - 0b0*ad9154_reg::SHORT_TPL_TEST_RESET | - i*ad9154_reg::SHORT_TPL_DAC_SEL | - j*ad9154_reg::SHORT_TPL_SP_SEL); - errors += read(ad9154_reg::SHORT_TPL_TEST_3); - } - info!(" c{} errors: {}", i, errors); - if errors > 0 { - return Err("STPL failed") - } - } - - info!(" ...passed"); - Ok(()) -} - -pub fn sync(dacno: u8) -> Result { - spi_setup(dacno); - - write(ad9154_reg::SYNC_CONTROL, - 0x1*ad9154_reg::SYNCMODE | 1*ad9154_reg::SYNCENABLE | - 1*ad9154_reg::SYNCARM | 1*ad9154_reg::SYNCCLRSTKY); - clock::spin_us(1000); // ensure at least one sysref edge - let sync_status = read(ad9154_reg::SYNC_STATUS); - - if sync_status & ad9154_reg::SYNC_BUSY != 0 { - return Err("sync logic busy"); - } - if sync_status & ad9154_reg::SYNC_LOCK == 0 { - return Err("no sync lock"); - } - if sync_status & ad9154_reg::SYNC_TRIP == 0 { - return Err("no sysref edge"); - } - let realign_occured = sync_status & ad9154_reg::SYNC_ROTATE != 0; - Ok(realign_occured) -} diff --git a/artiq/firmware/libboard_artiq/ad9154_reg.rs b/artiq/firmware/libboard_artiq/ad9154_reg.rs deleted file mode 100644 index 3af180496..000000000 --- a/artiq/firmware/libboard_artiq/ad9154_reg.rs +++ /dev/null @@ -1,826 +0,0 @@ -#![allow(dead_code)] - -pub const SPI_INTFCONFA : u16 = 0x000; -pub const SOFTRESET : u8 = 1 << 0; -pub const LSBFIRST : u8 = 1 << 1; -pub const ADDRINC : u8 = 1 << 2; -pub const SDOACTIVE : u8 = 1 << 3; -pub const SDOACTIVE_M : u8 = 1 << 4; -pub const ADDRINC_M : u8 = 1 << 5; -pub const LSBFIRST_M : u8 = 1 << 6; -pub const SOFTRESET_M : u8 = 1 << 7; - -pub const CHIPTYPE : u16 = 0x003; - -pub const PRODIDL : u16 = 0x004; - -pub const PRODIDH : u16 = 0x005; - -pub const CHIPGRADE : u16 = 0x006; -pub const DEV_REVISION : u8 = 1 << 0; -pub const PROD_GRADE : u8 = 1 << 4; - -pub const SPI_PAGEINDX : u16 = 0x008; - -pub const PWRCNTRL0 : u16 = 0x011; -pub const PD_DAC3 : u8 = 1 << 3; -pub const PD_DAC2 : u8 = 1 << 4; -pub const PD_DAC1 : u8 = 1 << 5; -pub const PD_DAC0 : u8 = 1 << 6; -pub const PD_BG : u8 = 1 << 7; - -pub const TXENMASK1 : u16 = 0x012; -pub const DACA_MASK : u8 = 1 << 6; -pub const DACB_MASK : u8 = 1 << 7; - -pub const PWRCNTRL3 : u16 = 0x013; -pub const SPI_TXEN : u8 = 1 << 0; -pub const ENA_SPI_TXEN : u8 = 1 << 1; -pub const SPI_PA_CTRL : u8 = 1 << 2; -pub const ENA_PA_CTRL_FROM_SPI : u8 = 1 << 3; -pub const ENA_PA_CTRL_FROM_BLSM : u8 = 1 << 4; -pub const ENA_PA_CTRL_FROM_TXENSM : u8 = 1 << 5; -pub const ENA_PA_CTRL_FROM_PARROT_ERR : u8 = 1 << 6; - -pub const GROUP_DLY : u16 = 0x014; -pub const COARSE_GROUP_DELAY : u8 = 1 << 0; -pub const GROUP_DELAY_RESERVED : u8 = 1 << 4; - -pub const IRQEN_STATUSMODE0 : u16 = 0x01f; -pub const IRQEN_SMODE_LANEFIFOERR : u8 = 1 << 1; -pub const IRQEN_SMODE_SERPLLLOCK : u8 = 1 << 2; -pub const IRQEN_SMODE_SERPLLLOST : u8 = 1 << 3; -pub const IRQEN_SMODE_DACPLLLOCK : u8 = 1 << 4; -pub const IRQEN_SMODE_DACPLLLOST : u8 = 1 << 5; - -pub const IRQEN_STATUSMODE1 : u16 = 0x020; -pub const IRQEN_SMODE_PRBS0 : u8 = 1 << 0; -pub const IRQEN_SMODE_PRBS1 : u8 = 1 << 1; -pub const IRQEN_SMODE_PRBS2 : u8 = 1 << 2; -pub const IRQEN_SMODE_PRBS3 : u8 = 1 << 3; - -pub const IRQEN_STATUSMODE2 : u16 = 0x021; -pub const IRQEN_SMODE_SYNC_TRIP0 : u8 = 1 << 0; -pub const IRQEN_SMODE_SYNC_WLIM0 : u8 = 1 << 1; -pub const IRQEN_SMODE_SYNC_ROTATE0 : u8 = 1 << 2; -pub const IRQEN_SMODE_SYNC_LOCK0 : u8 = 1 << 3; -pub const IRQEN_SMODE_NCO_ALIGN0 : u8 = 1 << 4; -pub const IRQEN_SMODE_BLNKDONE0 : u8 = 1 << 5; -pub const IRQEN_SMODE_PDPERR0 : u8 = 1 << 7; - -pub const IRQEN_STATUSMODE3 : u16 = 0x022; -pub const IRQEN_SMODE_SYNC_TRIP1 : u8 = 1 << 0; -pub const IRQEN_SMODE_SYNC_WLIM1 : u8 = 1 << 1; -pub const IRQEN_SMODE_SYNC_ROTATE1 : u8 = 1 << 2; -pub const IRQEN_SMODE_SYNC_LOCK1 : u8 = 1 << 3; -pub const IRQEN_SMODE_NCO_ALIGN1 : u8 = 1 << 4; -pub const IRQEN_SMODE_BLNKDONE1 : u8 = 1 << 5; -pub const IRQEN_SMODE_PDPERR1 : u8 = 1 << 7; - -pub const IRQ_STATUS0 : u16 = 0x023; -pub const LANEFIFOERR : u8 = 1 << 1; -pub const SERPLLLOCK : u8 = 1 << 2; -pub const SERPLLLOST : u8 = 1 << 3; -pub const DACPLLLOCK : u8 = 1 << 4; -pub const DACPLLLOST : u8 = 1 << 5; - -pub const IRQ_STATUS1 : u16 = 0x024; -pub const PRBS0 : u8 = 1 << 0; -pub const PRBS1 : u8 = 1 << 1; -pub const PRBS2 : u8 = 1 << 2; -pub const PRBS3 : u8 = 1 << 3; - -pub const IRQ_STATUS2 : u16 = 0x025; -pub const SYNC_TRIP0 : u8 = 1 << 0; -pub const SYNC_WLIM0 : u8 = 1 << 1; -pub const SYNC_ROTATE0 : u8 = 1 << 2; -pub const SYNC_LOCK0 : u8 = 1 << 3; -pub const NCO_ALIGN0 : u8 = 1 << 4; -pub const BLNKDONE0 : u8 = 1 << 5; -pub const PDPERR0 : u8 = 1 << 7; - -pub const IRQ_STATUS3 : u16 = 0x026; -pub const SYNC_TRIP1 : u8 = 1 << 0; -pub const SYNC_WLIM1 : u8 = 1 << 1; -pub const SYNC_ROTATE1 : u8 = 1 << 2; -pub const SYNC_LOCK1 : u8 = 1 << 3; -pub const NCO_ALIGN1 : u8 = 1 << 4; -pub const BLNKDONE1 : u8 = 1 << 5; -pub const PDPERR1 : u8 = 1 << 7; - -pub const JESD_CHECKS : u16 = 0x030; -pub const ERR_INTSUPP : u8 = 1 << 0; -pub const ERR_SUBCLASS : u8 = 1 << 1; -pub const ERR_KUNSUPP : u8 = 1 << 2; -pub const ERR_JESDBAD : u8 = 1 << 3; -pub const ERR_WINLIMIT : u8 = 1 << 4; -pub const ERR_DLYOVER : u8 = 1 << 5; - -pub const SYNC_ERRWINDOW : u16 = 0x034; - -pub const SYNC_LASTERR_L : u16 = 0x038; - -pub const SYNC_LASTERR_H : u16 = 0x039; -pub const LASTERROR_H : u8 = 1 << 0; -pub const LASTOVER : u8 = 1 << 6; -pub const LASTUNDER : u8 = 1 << 7; - -pub const SYNC_CONTROL : u16 = 0x03a; -pub const SYNCMODE : u8 = 1 << 0; -pub const SYNCCLRLAST : u8 = 1 << 4; -pub const SYNCCLRSTKY : u8 = 1 << 5; -pub const SYNCARM : u8 = 1 << 6; -pub const SYNCENABLE : u8 = 1 << 7; - -pub const SYNC_STATUS : u16 = 0x03b; -pub const SYNC_TRIP : u8 = 1 << 0; -pub const SYNC_WLIM : u8 = 1 << 1; -pub const SYNC_ROTATE : u8 = 1 << 2; -pub const SYNC_LOCK : u8 = 1 << 3; -pub const SYNC_BUSY : u8 = 1 << 7; - -pub const SYNC_CURRERR_L : u16 = 0x03c; - -pub const SYNC_CURRERR_H : u16 = 0x03d; -pub const CURRERROR_H : u8 = 1 << 0; -pub const CURROVER : u8 = 1 << 6; -pub const CURRUNDER : u8 = 1 << 7; - -pub const DACGAIN0_I : u16 = 0x040; - -pub const DACGAIN1_I : u16 = 0x041; - -pub const DACGAIN0_Q : u16 = 0x042; - -pub const DACGAIN1_Q : u16 = 0x043; - -pub const GROUPDELAY_COMP_I : u16 = 0x044; - -pub const GROUPDELAY_COMP_Q : u16 = 0x045; - -pub const GROUPDELAY_COMP_BYP : u16 = 0x046; -pub const GROUPCOMP_BYPQ : u8 = 1 << 0; -pub const GROUPCOMP_BYPI : u8 = 1 << 1; - -pub const MIX_MODE : u16 = 0x04a; - -pub const NCOALIGN_MODE : u16 = 0x050; -pub const NCO_ALIGN_MODE : u8 = 1 << 0; -pub const NCO_ALIGN_FAIL : u8 = 1 << 3; -pub const NCO_ALIGN_PASS : u8 = 1 << 4; -pub const NCO_ALIGN_MTCH : u8 = 1 << 5; -pub const NCO_ALIGN_ARM : u8 = 1 << 7; - -pub const NCOKEY_ILSB : u16 = 0x051; - -pub const NCOKEY_IMSB : u16 = 0x052; - -pub const NCOKEY_QLSB : u16 = 0x053; - -pub const NCOKEY_QMSB : u16 = 0x054; - -pub const PDP_THRES0 : u16 = 0x060; - -pub const PDP_THRES1 : u16 = 0x061; - -pub const PDP_AVG_TIME : u16 = 0x062; -pub const PDP_AVG_TIME_ : u8 = 1 << 0; -pub const PA_BUS_SWAP : u8 = 1 << 6; -pub const PDP_ENABLE : u8 = 1 << 7; - -pub const PDP_POWER0 : u16 = 0x063; - -pub const PDP_POWER1 : u16 = 0x064; - -pub const CLKCFG0 : u16 = 0x080; -pub const REF_CLKDIV_EN : u8 = 1 << 0; -pub const RF_SYNC_EN : u8 = 1 << 1; -pub const DUTY_EN : u8 = 1 << 2; -pub const PD_CLK_REC : u8 = 1 << 3; -pub const PD_SERDES_PCLK : u8 = 1 << 4; -pub const PD_CLK_DIG : u8 = 1 << 5; -pub const PD_CLK23 : u8 = 1 << 6; -pub const PD_CLK01 : u8 = 1 << 7; - -pub const SYSREF_ACTRL0 : u16 = 0x081; -pub const HYS_CNTRL1 : u8 = 1 << 0; -pub const SYSREF_RISE : u8 = 1 << 2; -pub const HYS_ON : u8 = 1 << 3; -pub const PD_SYSREF_BUFFER : u8 = 1 << 4; - -pub const SYSREF_ACTRL1 : u16 = 0x082; - -pub const DACPLLCNTRL : u16 = 0x083; -pub const ENABLE_DACPLL : u8 = 1 << 4; -pub const RECAL_DACPLL : u8 = 1 << 7; - -pub const DACPLLSTATUS : u16 = 0x084; -pub const DACPLL_LOCK : u8 = 1 << 1; -pub const VCO_CAL_PROGRESS : u8 = 1 << 3; -pub const CP_CAL_VALID : u8 = 1 << 4; -pub const CP_OVERRANGE_L : u8 = 1 << 5; -pub const CP_OVERRANGE_H : u8 = 1 << 6; - -pub const DACINTEGERWORD0 : u16 = 0x085; - -pub const DACLOOPFILT1 : u16 = 0x087; -pub const LF_C1_WORD : u8 = 1 << 0; -pub const LF_C2_WORD : u8 = 1 << 4; - -pub const DACLOOPFILT2 : u16 = 0x088; -pub const LF_C3_WORD : u8 = 1 << 0; -pub const LF_R1_WORD : u8 = 1 << 4; - -pub const DACLOOPFILT3 : u16 = 0x089; -pub const LF_R3_WORD : u8 = 1 << 0; -pub const LF_BYPASS_C1 : u8 = 1 << 4; -pub const LF_BYPASS_C2 : u8 = 1 << 5; -pub const LF_BYPASS_R1 : u8 = 1 << 6; -pub const LF_BYPASS_R3 : u8 = 1 << 7; - -pub const DACCPCNTRL : u16 = 0x08a; -pub const CP_CURRENT : u8 = 1 << 0; -pub const VT_FORCE : u8 = 1 << 6; - -pub const DACLOGENCNTRL : u16 = 0x08b; -pub const LODIVMODE : u8 = 1 << 0; -pub const LO_POWER_MODE : u8 = 1 << 4; - -pub const DACLDOCNTRL1 : u16 = 0x08c; -pub const REFDIVMODE : u8 = 1 << 0; -pub const LDO_BYPASS_FLT : u8 = 1 << 6; -pub const LDO_REF_SEL : u8 = 1 << 7; - -pub const DACLDOCNTRL2 : u16 = 0x08d; -pub const LDO_VDROP : u8 = 1 << 0; -pub const LDO_SEL : u8 = 1 << 2; -pub const LDO_INRUSH : u8 = 1 << 5; -pub const LDO_BYPASS : u8 = 1 << 7; - -pub const DATA_FORMAT : u16 = 0x110; -pub const BINARY_FORMAT : u8 = 1 << 7; - -pub const DATAPATH_CTRL : u16 = 0x111; -pub const I_TO_Q : u8 = 1 << 0; -pub const SEL_SIDEBAND : u8 = 1 << 1; -pub const MODULATION_TYPE : u8 = 1 << 2; -pub const PHASE_ADJ_ENABLE : u8 = 1 << 4; -pub const DIG_GAIN_ENABLE : u8 = 1 << 5; -pub const INVSINC_ENABLE : u8 = 1 << 7; - -pub const INTERP_MODE : u16 = 0x112; - -pub const NCO_FTW_UPDATE : u16 = 0x113; -pub const FTW_UPDATE_REQ : u8 = 1 << 0; -pub const FTW_UPDATE_ACK : u8 = 1 << 1; - -pub const FTW0 : u16 = 0x114; - -pub const FTW1 : u16 = 0x115; - -pub const FTW2 : u16 = 0x116; - -pub const FTW3 : u16 = 0x117; - -pub const FTW4 : u16 = 0x118; - -pub const FTW5 : u16 = 0x119; - -pub const NCO_PHASE_OFFSET0 : u16 = 0x11a; - -pub const NCO_PHASE_OFFSET1 : u16 = 0x11b; - -pub const PHASE_ADJ0 : u16 = 0x11c; - -pub const PHASE_ADJ1 : u16 = 0x11d; - -pub const TXEN_SM_0 : u16 = 0x11f; -pub const TXEN_SM_EN : u8 = 1 << 0; -pub const GP_PA_CTRL : u8 = 1 << 1; -pub const GP_PA_ON_INVERT : u8 = 1 << 2; -pub const RISE_COUNTERS : u8 = 1 << 4; -pub const FALL_COUNTERS : u8 = 1 << 6; - -pub const TXEN_RISE_COUNT_0 : u16 = 0x121; - -pub const TXEN_RISE_COUNT_1 : u16 = 0x122; - -pub const TXEN_FALL_COUNT_0 : u16 = 0x123; - -pub const TXEN_FALL_COUNT_1 : u16 = 0x124; - -pub const DEVICE_CONFIG_REG_0 : u16 = 0x12d; - -pub const DIE_TEMP_CTRL0 : u16 = 0x12f; -pub const AUXADC_ENABLE : u8 = 1 << 0; -pub const AUXADC_RESERVED : u8 = 1 << 1; - -pub const DIE_TEMP0 : u16 = 0x132; - -pub const DIE_TEMP1 : u16 = 0x133; - -pub const DIE_TEMP_UPDATE : u16 = 0x134; - -pub const DC_OFFSET_CTRL : u16 = 0x135; - -pub const IPATH_DC_OFFSET_1PART0 : u16 = 0x136; - -pub const IPATH_DC_OFFSET_1PART1 : u16 = 0x137; - -pub const QPATH_DC_OFFSET_1PART0 : u16 = 0x138; - -pub const QPATH_DC_OFFSET_1PART1 : u16 = 0x139; - -pub const IPATH_DC_OFFSET_2PART : u16 = 0x13a; - -pub const QPATH_DC_OFFSET_2PART : u16 = 0x13b; - -pub const IDAC_DIG_GAIN0 : u16 = 0x13c; - -pub const IDAC_DIG_GAIN1 : u16 = 0x13d; - -pub const QDAC_DIG_GAIN0 : u16 = 0x13e; - -pub const QDAC_DIG_GAIN1 : u16 = 0x13f; - -pub const GAIN_RAMP_UP_STEP0 : u16 = 0x140; - -pub const GAIN_RAMP_UP_STEP1 : u16 = 0x141; - -pub const GAIN_RAMP_DOWN_STEP0 : u16 = 0x142; - -pub const GAIN_RAMP_DOWN_STEP1 : u16 = 0x143; - -pub const DEVICE_CONFIG_REG_1 : u16 = 0x146; - -pub const BSM_STAT : u16 = 0x147; -pub const SOFTBLANKRB : u8 = 1 << 6; - -pub const PRBS : u16 = 0x14b; -pub const PRBS_EN : u8 = 1 << 0; -pub const PRBS_RESET : u8 = 1 << 1; -pub const PRBS_MODE : u8 = 1 << 2; -pub const PRBS_GOOD_I : u8 = 1 << 6; -pub const PRBS_GOOD_Q : u8 = 1 << 7; - -pub const PRBS_ERROR_I : u16 = 0x14c; - -pub const PRBS_ERROR_Q : u16 = 0x14d; - -pub const DACPLLT0 : u16 = 0x1b0; -pub const LOGEN_PD : u8 = 1 << 1; -pub const LDO_PD : u8 = 1 << 3; -pub const SYNTH_PD : u8 = 1 << 4; -pub const VCO_PD_ALC : u8 = 1 << 5; -pub const VCO_PD_PTAT : u8 = 1 << 6; -pub const VCO_PD_IN : u8 = 1 << 7; - -pub const DACPLLT1 : u16 = 0x1b1; -pub const PFD_EDGE : u8 = 1 << 1; -pub const PFD_DELAY : u8 = 1 << 2; - -pub const DACPLLT2 : u16 = 0x1b2; -pub const EXT_ALC_WORD : u8 = 1 << 0; -pub const EXT_ALC_WORD_EN : u8 = 1 << 7; - -pub const DACPLLT3 : u16 = 0x1b3; -pub const EXT_BAND1 : u8 = 1 << 0; - -pub const DACPLLT4 : u16 = 0x1b4; -pub const EXT_BAND2 : u8 = 1 << 0; -pub const EXT_BAND_EN : u8 = 1 << 1; -pub const VCO_CAL_OFFSET : u8 = 1 << 3; -pub const BYP_LOAD_DELAY : u8 = 1 << 7; - -pub const DACPLLT5 : u16 = 0x1b5; - -pub const DACPLLT6 : u16 = 0x1b6; - -pub const DACPLLT7 : u16 = 0x1b7; - -pub const DACPLLT8 : u16 = 0x1b8; - -pub const DACPLLT9 : u16 = 0x1b9; - -pub const DACPLLTA : u16 = 0x1ba; - -pub const DACPLLTB : u16 = 0x1bb; -pub const VCO_BIAS_REF : u8 = 1 << 0; -pub const VCO_BIAS_TCF : u8 = 1 << 3; - -pub const DACPLLTC : u16 = 0x1bc; - -pub const DACPLLTD : u16 = 0x1bd; - -pub const DACPLLTE : u16 = 0x1be; - -pub const DACPLLTF : u16 = 0x1bf; - -pub const DACPLLT10 : u16 = 0x1c0; - -pub const DACPLLT11 : u16 = 0x1c1; - -pub const DACPLLT15 : u16 = 0x1c2; - -pub const DACPLLT16 : u16 = 0x1c3; - -pub const DACPLLT17 : u16 = 0x1c4; - -pub const DACPLLT18 : u16 = 0x1c5; - -pub const MASTER_PD : u16 = 0x200; - -pub const PHY_PD : u16 = 0x201; - -pub const GENERIC_PD : u16 = 0x203; -pub const PD_SYNCOUT1B : u8 = 1 << 0; -pub const PD_SYNCOUT0B : u8 = 1 << 1; - -pub const CDR_RESET : u16 = 0x206; - -pub const CDR_OPERATING_MODE_REG_0 : u16 = 0x230; -pub const CDR_OVERSAMP : u8 = 1 << 1; -pub const CDR_RESERVED : u8 = 1 << 2; -pub const ENHALFRATE : u8 = 1 << 5; - -pub const EQ_BIAS_REG : u16 = 0x268; -pub const EQ_BIAS_RESERVED : u8 = 1 << 0; -pub const EQ_POWER_MODE : u8 = 1 << 6; - -pub const SERDESPLL_ENABLE_CNTRL : u16 = 0x280; -pub const ENABLE_SERDESPLL : u8 = 1 << 0; -pub const RECAL_SERDESPLL : u8 = 1 << 2; - -pub const PLL_STATUS : u16 = 0x281; -pub const SERDES_PLL_LOCK_RB : u8 = 1 << 0; -pub const SERDES_CURRENTS_READY_RB : u8 = 1 << 1; -pub const SERDES_VCO_CAL_IN_PROGRESS_RB : u8 = 1 << 2; -pub const SERDES_PLL_CAL_VALID_RB : u8 = 1 << 3; -pub const SERDES_PLL_OVERRANGE_L_RB : u8 = 1 << 4; -pub const SERDES_PLL_OVERRANGE_H_RB : u8 = 1 << 5; - -pub const LDO_FILTER_1 : u16 = 0x284; - -pub const LDO_FILTER_2 : u16 = 0x285; - -pub const LDO_FILTER_3 : u16 = 0x286; - -pub const CP_CURRENT_SPI : u16 = 0x287; -pub const SPI_CP_CURRENT : u8 = 1 << 0; -pub const SPI_SERDES_LOGEN_POWER_MODE : u8 = 1 << 6; - -pub const REF_CLK_DIVIDER_LDO : u16 = 0x289; -pub const SPI_CDR_OVERSAMP : u8 = 1 << 0; -pub const SPI_LDO_BYPASS_FILT : u8 = 1 << 2; -pub const SPI_LDO_REF_SEL : u8 = 1 << 3; - -pub const VCO_LDO : u16 = 0x28a; - -pub const PLL_RD_REG : u16 = 0x28b; -pub const SPI_SERDES_LOGEN_PD_CORE : u8 = 1 << 0; -pub const SPI_SERDES_LDO_PD : u8 = 1 << 2; -pub const SPI_SYN_PD : u8 = 1 << 3; -pub const SPI_VCO_PD_ALC : u8 = 1 << 4; -pub const SPI_VCO_PD_PTAT : u8 = 1 << 5; -pub const SPI_VCO_PD : u8 = 1 << 6; - -pub const ALC_VARACTOR : u16 = 0x290; -pub const SPI_VCO_VARACTOR : u8 = 1 << 0; -pub const SPI_INIT_ALC_VALUE : u8 = 1 << 4; - -pub const VCO_OUTPUT : u16 = 0x291; -pub const SPI_VCO_OUTPUT_LEVEL : u8 = 1 << 0; -pub const SPI_VCO_OUTPUT_RESERVED : u8 = 1 << 4; - -pub const CP_CONFIG : u16 = 0x294; -pub const SPI_CP_TEST : u8 = 1 << 0; -pub const SPI_CP_CAL_EN : u8 = 1 << 2; -pub const SPI_CP_FORCE_CALBITS : u8 = 1 << 3; -pub const SPI_CP_OFFSET_OFF : u8 = 1 << 4; -pub const SPI_CP_ENABLE_MACHINE : u8 = 1 << 5; -pub const SPI_CP_DITHER_MODE : u8 = 1 << 6; -pub const SPI_CP_HALF_VCO_CAL_CLK : u8 = 1 << 7; - -pub const VCO_BIAS_1 : u16 = 0x296; -pub const SPI_VCO_BIAS_REF : u8 = 1 << 0; -pub const SPI_VCO_BIAS_TCF : u8 = 1 << 3; - -pub const VCO_BIAS_2 : u16 = 0x297; -pub const SPI_PRESCALE_BIAS : u8 = 1 << 0; -pub const SPI_LAST_ALC_EN : u8 = 1 << 2; -pub const SPI_PRESCALE_BYPASS_R : u8 = 1 << 3; -pub const SPI_VCO_COMP_BYPASS_BIASR : u8 = 1 << 4; -pub const SPI_VCO_BYPASS_DAC_R : u8 = 1 << 5; - -pub const VCO_PD_OVERRIDES : u16 = 0x299; -pub const SPI_VCO_PD_OVERRIDE_VCO_BUF : u8 = 1 << 0; -pub const SPI_VCO_PD_OVERRIDE_CAL_TCF : u8 = 1 << 1; -pub const SPI_VCO_PD_OVERRIDE_VAR_REF_TCF : u8 = 1 << 2; -pub const SPI_VCO_PD_OVERRIDE_VAR_REF : u8 = 1 << 3; - -pub const VCO_CAL : u16 = 0x29a; -pub const SPI_FB_CLOCK_ADV : u8 = 1 << 0; -pub const SPI_VCO_CAL_COUNT : u8 = 1 << 2; -pub const SPI_VCO_CAL_ALC_WAIT : u8 = 1 << 4; -pub const SPI_VCO_CAL_EN : u8 = 1 << 7; - -pub const CP_LEVEL_DETECT : u16 = 0x29c; -pub const SPI_CP_LEVEL_THRESHOLD_HIGH : u8 = 1 << 0; -pub const SPI_CP_LEVEL_THRESHOLD_LOW : u8 = 1 << 3; -pub const SPI_CP_LEVEL_DET_PD : u8 = 1 << 6; - -pub const VCO_VARACTOR_CTRL_0 : u16 = 0x29f; -pub const SPI_VCO_VARACTOR_OFFSET : u8 = 1 << 0; -pub const SPI_VCO_VARACTOR_REF_TCF : u8 = 1 << 4; - -pub const VCO_VARACTOR_CTRL_1 : u16 = 0x2a0; -pub const SPI_VCO_VARACTOR_REF : u8 = 1 << 0; - -pub const TERM_BLK1_CTRLREG0 : u16 = 0x2a7; - -pub const TERM_BLK2_CTRLREG0 : u16 = 0x2ae; - -pub const GENERAL_JRX_CTRL_0 : u16 = 0x300; -pub const LINK_EN : u8 = 1 << 0; -pub const LINK_PAGE : u8 = 1 << 2; -pub const LINK_MODE : u8 = 1 << 3; -pub const CHECKSUM_MODE : u8 = 1 << 6; - -pub const GENERAL_JRX_CTRL_1 : u16 = 0x301; - -pub const DYN_LINK_LATENCY_0 : u16 = 0x302; - -pub const DYN_LINK_LATENCY_1 : u16 = 0x303; - -pub const LMFC_DELAY_0 : u16 = 0x304; - -pub const LMFC_DELAY_1 : u16 = 0x305; - -pub const LMFC_VAR_0 : u16 = 0x306; - -pub const LMFC_VAR_1 : u16 = 0x307; - -pub const XBAR_LN_0_1 : u16 = 0x308; -pub const LOGICAL_LANE0_SRC : u8 = 1 << 0; -pub const LOGICAL_LANE1_SRC : u8 = 1 << 3; - -pub const XBAR_LN_2_3 : u16 = 0x309; -pub const LOGICAL_LANE2_SRC : u8 = 1 << 0; -pub const LOGICAL_LANE3_SRC : u8 = 1 << 3; - -pub const XBAR_LN_4_5 : u16 = 0x30a; -pub const LOGICAL_LANE4_SRC : u8 = 1 << 0; -pub const LOGICAL_LANE5_SRC : u8 = 1 << 3; - -pub const XBAR_LN_6_7 : u16 = 0x30b; -pub const LOGICAL_LANE6_SRC : u8 = 1 << 0; -pub const LOGICAL_LANE7_SRC : u8 = 1 << 3; - -pub const FIFO_STATUS_REG_0 : u16 = 0x30c; - -pub const FIFO_STATUS_REG_1 : u16 = 0x30d; - -pub const SYNCB_GEN_1 : u16 = 0x312; -pub const SYNCB_ERR_DUR : u8 = 1 << 4; - -pub const SERDES_SPI_REG : u16 = 0x314; - -pub const PHY_PRBS_TEST_EN : u16 = 0x315; - -pub const PHY_PRBS_TEST_CTRL : u16 = 0x316; -pub const PHY_TEST_RESET : u8 = 1 << 0; -pub const PHY_TEST_START : u8 = 1 << 1; -pub const PHY_PRBS_PAT_SEL : u8 = 1 << 2; -pub const PHY_SRC_ERR_CNT : u8 = 1 << 4; - -pub const PHY_PRBS_TEST_THRESHOLD_LOBITS : u16 = 0x317; - -pub const PHY_PRBS_TEST_THRESHOLD_MIDBITS : u16 = 0x318; - -pub const PHY_PRBS_TEST_THRESHOLD_HIBITS : u16 = 0x319; - -pub const PHY_PRBS_TEST_ERRCNT_LOBITS : u16 = 0x31a; - -pub const PHY_PRBS_TEST_ERRCNT_MIDBITS : u16 = 0x31b; - -pub const PHY_PRBS_TEST_ERRCNT_HIBITS : u16 = 0x31c; - -pub const PHY_PRBS_TEST_STATUS : u16 = 0x31d; - -pub const SHORT_TPL_TEST_0 : u16 = 0x32c; -pub const SHORT_TPL_TEST_EN : u8 = 1 << 0; -pub const SHORT_TPL_TEST_RESET : u8 = 1 << 1; -pub const SHORT_TPL_DAC_SEL : u8 = 1 << 2; -pub const SHORT_TPL_SP_SEL : u8 = 1 << 4; - -pub const SHORT_TPL_TEST_1 : u16 = 0x32d; - -pub const SHORT_TPL_TEST_2 : u16 = 0x32e; - -pub const SHORT_TPL_TEST_3 : u16 = 0x32f; - -pub const DEVICE_CONFIG_REG_2 : u16 = 0x333; - -pub const JESD_BIT_INVERSE_CTRL : u16 = 0x334; - -pub const DID_REG : u16 = 0x400; - -pub const BID_REG : u16 = 0x401; -pub const BID_RD : u8 = 1 << 0; -pub const ADJCNT_RD : u8 = 1 << 4; - -pub const LID0_REG : u16 = 0x402; -pub const LID0_RD : u8 = 1 << 0; -pub const PHADJ_RD : u8 = 1 << 5; -pub const ADJDIR_RD : u8 = 1 << 6; - -pub const SCR_L_REG : u16 = 0x403; -pub const L_1_RD : u8 = 1 << 0; -pub const SCR_RD : u8 = 1 << 7; - -pub const F_REG : u16 = 0x404; - -pub const K_REG : u16 = 0x405; - -pub const M_REG : u16 = 0x406; - -pub const CS_N_REG : u16 = 0x407; -pub const N_1_RD : u8 = 1 << 0; -pub const CS_RD : u8 = 1 << 6; - -pub const NP_REG : u16 = 0x408; -pub const NP_1_RD : u8 = 1 << 0; -pub const SUBCLASSV_RD : u8 = 1 << 5; - -pub const S_REG : u16 = 0x409; -pub const S_1_RD : u8 = 1 << 0; -pub const JESDV_RD : u8 = 1 << 5; - -pub const HD_CF_REG : u16 = 0x40a; -pub const CF_RD : u8 = 1 << 0; -pub const HD_RD : u8 = 1 << 7; - -pub const RES1_REG : u16 = 0x40b; - -pub const RES2_REG : u16 = 0x40c; - -pub const CHECKSUM0_REG : u16 = 0x40d; - -pub const COMPSUM0_REG : u16 = 0x40e; - -pub const LID1_REG : u16 = 0x412; - -pub const CHECKSUM1_REG : u16 = 0x415; - -pub const COMPSUM1_REG : u16 = 0x416; - -pub const LID2_REG : u16 = 0x41a; - -pub const CHECKSUM2_REG : u16 = 0x41d; - -pub const COMPSUM2_REG : u16 = 0x41e; - -pub const LID3_REG : u16 = 0x422; - -pub const CHECKSUM3_REG : u16 = 0x425; - -pub const COMPSUM3_REG : u16 = 0x426; - -pub const LID4_REG : u16 = 0x42a; - -pub const CHECKSUM4_REG : u16 = 0x42d; - -pub const COMPSUM4_REG : u16 = 0x42e; - -pub const LID5_REG : u16 = 0x432; - -pub const CHECKSUM5_REG : u16 = 0x435; - -pub const COMPSUM5_REG : u16 = 0x436; - -pub const LID6_REG : u16 = 0x43a; - -pub const CHECKSUM6_REG : u16 = 0x43d; - -pub const COMPSUM6_REG : u16 = 0x43e; - -pub const LID7_REG : u16 = 0x442; - -pub const CHECKSUM7_REG : u16 = 0x445; - -pub const COMPSUM7_REG : u16 = 0x446; - -pub const ILS_DID : u16 = 0x450; - -pub const ILS_BID : u16 = 0x451; -pub const BID : u8 = 1 << 0; -pub const ADJCNT : u8 = 1 << 4; - -pub const ILS_LID0 : u16 = 0x452; -pub const LID0 : u8 = 1 << 0; -pub const PHADJ : u8 = 1 << 5; -pub const ADJDIR : u8 = 1 << 6; - -pub const ILS_SCR_L : u16 = 0x453; -pub const L_1 : u8 = 1 << 0; -pub const SCR : u8 = 1 << 7; - -pub const ILS_F : u16 = 0x454; - -pub const ILS_K : u16 = 0x455; - -pub const ILS_M : u16 = 0x456; - -pub const ILS_CS_N : u16 = 0x457; -pub const N_1 : u8 = 1 << 0; -pub const CS : u8 = 1 << 6; - -pub const ILS_NP : u16 = 0x458; -pub const NP_1 : u8 = 1 << 0; -pub const SUBCLASSV : u8 = 1 << 5; - -pub const ILS_S : u16 = 0x459; -pub const S_1 : u8 = 1 << 0; -pub const JESDV : u8 = 1 << 5; - -pub const ILS_HD_CF : u16 = 0x45a; -pub const CF : u8 = 1 << 0; -pub const HD : u8 = 1 << 7; - -pub const ILS_RES1 : u16 = 0x45b; - -pub const ILS_RES2 : u16 = 0x45c; - -pub const ILS_CHECKSUM : u16 = 0x45d; - -pub const ERRCNTRMON : u16 = 0x46b; -pub const CNTRSEL : u8 = 1 << 0; -pub const LANESEL : u8 = 1 << 4; - -pub const LANEDESKEW : u16 = 0x46c; - -pub const BADDISPARITY : u16 = 0x46d; -pub const LANE_ADDR_DIS : u8 = 1 << 0; -pub const RST_ERR_CNTR_DIS : u8 = 1 << 5; -pub const DISABLE_ERR_CNTR_DIS : u8 = 1 << 6; -pub const RST_IRQ_DIS : u8 = 1 << 7; - -pub const NIT_W : u16 = 0x46e; -pub const LANE_ADDR_NIT : u8 = 1 << 0; -pub const RST_ERR_CNTR_NIT : u8 = 1 << 5; -pub const DISABLE_ERR_CNTR_NIT : u8 = 1 << 6; -pub const RST_IRQ_NIT : u8 = 1 << 7; - -pub const UNEXPECTEDCONTROL_W : u16 = 0x46f; -pub const LANE_ADDR_UCC : u8 = 1 << 0; -pub const RST_ERR_CNTR_UCC : u8 = 1 << 5; -pub const DISABLE_ERR_CNTR_UCC : u8 = 1 << 6; -pub const RST_IRQ_UCC : u8 = 1 << 7; - -pub const CODEGRPSYNCFLG : u16 = 0x470; - -pub const FRAMESYNCFLG : u16 = 0x471; - -pub const GOODCHKSUMFLG : u16 = 0x472; - -pub const INITLANESYNCFLG : u16 = 0x473; - -pub const CTRLREG1 : u16 = 0x476; - -pub const CTRLREG2 : u16 = 0x477; -pub const THRESHOLD_MASK_EN : u8 = 1 << 3; -pub const ILAS_MODE : u8 = 1 << 7; - -pub const KVAL : u16 = 0x478; - -pub const IRQVECTOR_MASK : u16 = 0x47a; -pub const CODEGRPSYNC_MASK : u8 = 1 << 0; -pub const BADCHECKSUM_MASK : u8 = 1 << 2; -pub const INITIALLANESYNC_MASK : u8 = 1 << 3; -pub const UCC_MASK : u8 = 1 << 5; -pub const NIT_MASK : u8 = 1 << 6; -pub const BADDIS_MASK : u8 = 1 << 7; - -pub const SYNCASSERTIONMASK : u16 = 0x47b; -pub const CMM_ENABLE : u8 = 1 << 3; -pub const CMM : u8 = 1 << 4; -pub const UCC_S : u8 = 1 << 5; -pub const NIT_S : u8 = 1 << 6; -pub const BADDIS_S : u8 = 1 << 7; - -pub const ERRORTHRES : u16 = 0x47c; - -pub const LANEENABLE : u16 = 0x47d; - -pub const RAMP_ENA : u16 = 0x47e; - -pub const DIG_TEST0 : u16 = 0x520; -pub const DC_TEST_MODE : u8 = 1 << 1; - -pub const DC_TEST_VALUEI0 : u16 = 0x521; - -pub const DC_TEST_VALUEI1 : u16 = 0x522; - -pub const DC_TEST_VALUEQ0 : u16 = 0x523; - -pub const DC_TEST_VALUEQ1 : u16 = 0x524; diff --git a/artiq/firmware/libboard_artiq/hmc830_7043.rs b/artiq/firmware/libboard_artiq/hmc830_7043.rs deleted file mode 100644 index adf753141..000000000 --- a/artiq/firmware/libboard_artiq/hmc830_7043.rs +++ /dev/null @@ -1,419 +0,0 @@ -mod hmc830 { - use board_misoc::{csr, clock}; - - fn spi_setup() { - unsafe { - while csr::converter_spi::idle_read() == 0 {} - csr::converter_spi::offline_write(0); - csr::converter_spi::end_write(1); - csr::converter_spi::cs_polarity_write(0b0001); - csr::converter_spi::clk_polarity_write(0); - csr::converter_spi::clk_phase_write(0); - csr::converter_spi::lsb_first_write(0); - csr::converter_spi::half_duplex_write(0); - csr::converter_spi::length_write(32 - 1); - csr::converter_spi::div_write(16 - 2); - csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_HMC830_CS); - } - } - - pub fn select_spi_mode() { - spi_setup(); - unsafe { - // rising egde on CS since cs_polarity still 0 - // selects "HMC Mode" - // do a dummy cycle with cs still high to clear CS - csr::converter_spi::length_write(0); - csr::converter_spi::data_write(0); - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::length_write(32 - 1); - } - } - - fn write(addr: u8, data: u32) { - let val = ((addr as u32) << 24) | data; - unsafe { - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::data_write(val << 1); // last clk cycle loads data - } - } - - fn read(addr: u8) -> u32 { - // SDO (miso/read bits) is technically CPHA=1, while SDI is CPHA=0 - // trust that the 8.2ns+0.2ns/pF provide enough hold time on top of - // the SPI round trip delay and stick with CPHA=0 - write((1 << 6) | addr, 0); - unsafe { - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::data_read() & 0xffffff - } - } - - pub fn detect() -> Result<(), &'static str> { - spi_setup(); - let id = read(0x00); - if id != 0xa7975 { - error!("invalid HMC830 ID: 0x{:08x}", id); - return Err("invalid HMC830 identification"); - } - - Ok(()) - } - - pub fn init() { - // Configure HMC830 for integer-N operation - // See "PLLs with integrated VCO- RF Applications Product & Operating - // Guide" - spi_setup(); - info!("loading HMC830 configuration..."); - - write(0x0, 0x20); // software reset - write(0x0, 0x00); // normal operation - write(0x6, 0x307ca); // integer-N mode (NB data sheet table 5.8 not self-consistent) - write(0x7, 0x4d); // digital lock detect, 1/2 cycle window (6.5ns window) - write(0x9, 0x2850); // charge pump: 1.6mA, no offset - write(0xa, 0x2045); // for wideband devices like the HMC830 - write(0xb, 0x7c061); // for HMC830 - - // VCO subsystem registers - // NB software reset does not seem to reset these registers, so always - // program them all! - write(0x5, 0xf88); // 1: defaults - write(0x5, 0x6010); // 2: mute output until output divider set - write(0x5, 0x2818); // 3: wideband PLL defaults - write(0x5, 0x60a0); // 4: HMC830 magic value - write(0x5, 0x1628); // 5: HMC830 magic value - write(0x5, 0x7fb0); // 6: HMC830 magic value - write(0x5, 0x0); // ready for VCO auto-cal - - info!(" ...done"); - } - - pub fn set_dividers(r_div: u32, n_div: u32, m_div: u32, out_div: u32) { - // VCO frequency: f_vco = (f_ref/r_div)*(n_int + n_frac/2**24) - // VCO frequency range [1.5GHz, 3GHz] - // Output frequency: f_out = f_vco/out_div - // Max PFD frequency: 125MHz for integer-N, 100MHz for fractional - // (mode B) - // Max reference frequency: 350MHz, however f_ref >= 200MHz requires - // setting 0x08[21]=1 - // - // Warning: Output divider is not synchronized! Set to 1 for deterministic - // phase at the output. - // - // :param r_div: reference divider [1, 16383] - // :param n_div: VCO divider, integer part. Integer-N mode: [16, 2**19-1] - // fractional mode: [20, 2**19-4] - // :param m_div: VCO divider, fractional part [0, 2**24-1] - // :param out_div: output divider [1, 62] (0 mutes output) - info!("setting HMC830 dividers..."); - write(0x5, 0x6010 + (out_div << 7) + (((out_div <= 2) as u32) << 15)); - write(0x5, 0x0); // ready for VCO auto-cal - write(0x2, r_div); - write(0x4, m_div); - write(0x3, n_div); - - info!(" ...done"); - } - - pub fn check_locked() -> Result<(), &'static str> { - info!("waiting for HMC830 lock..."); - let t = clock::get_ms(); - while read(0x12) & 0x02 == 0 { - if clock::get_ms() > t + 2000 { - error!("lock timeout. Register dump:"); - for addr in 0x00..0x14 { - // These registers don't exist (in the data sheet at least) - if addr == 0x0d || addr == 0x0e { continue; } - error!(" [0x{:02x}] = 0x{:04x}", addr, read(addr)); - } - return Err("lock timeout"); - } - } - info!(" ...locked"); - - Ok(()) - } -} - -pub mod hmc7043 { - use board_misoc::{csr, clock}; - - // Warning: dividers are not synchronized with HMC830 clock input! - // Set DAC_CLK_DIV to 1 or 0 for deterministic phase. - // (0 bypasses the divider and reduces noise) - const DAC_CLK_DIV: u16 = 0; - const FPGA_CLK_DIV: u16 = 16; // Keep in sync with jdcg.rs - const SYSREF_DIV: u16 = 256; // Keep in sync with jdcg.rs - const HMC_SYSREF_DIV: u16 = SYSREF_DIV*8; // must be <= 4MHz - - // enabled, divider, output config, is sysref - const OUTPUT_CONFIG: [(bool, u16, u8, bool); 14] = [ - (true, DAC_CLK_DIV, 0x08, false), // 0: DAC1_CLK - (true, SYSREF_DIV, 0x01, true), // 1: DAC1_SYSREF - (true, DAC_CLK_DIV, 0x08, false), // 2: DAC0_CLK - (true, SYSREF_DIV, 0x01, true), // 3: DAC0_SYSREF - (true, SYSREF_DIV, 0x10, true), // 4: AMC_FPGA_SYSREF0 - (false, FPGA_CLK_DIV, 0x10, true), // 5: AMC_FPGA_SYSREF1 - (false, 0, 0x10, false), // 6: unused - (true, FPGA_CLK_DIV, 0x10, true), // 7: RTM_FPGA_SYSREF0 - (true, FPGA_CLK_DIV, 0x08, false), // 8: GTP_CLK0_IN - (false, 0, 0x10, false), // 9: unused - (false, 0, 0x10, false), // 10: unused - (false, 0, 0x08, false), // 11: unused / uFL - (false, 0, 0x10, false), // 12: unused - (false, FPGA_CLK_DIV, 0x10, true), // 13: RTM_FPGA_SYSREF1 - ]; - - fn spi_setup() { - unsafe { - while csr::converter_spi::idle_read() == 0 {} - csr::converter_spi::offline_write(0); - csr::converter_spi::end_write(1); - csr::converter_spi::cs_polarity_write(0b0001); - csr::converter_spi::clk_polarity_write(0); - csr::converter_spi::clk_phase_write(0); - csr::converter_spi::lsb_first_write(0); - csr::converter_spi::half_duplex_write(0); // change mid-transaction for reads - csr::converter_spi::length_write(24 - 1); - csr::converter_spi::div_write(16 - 2); - csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_HMC7043_CS); - } - } - - fn spi_wait_idle() { - unsafe { - while csr::converter_spi::idle_read() == 0 {} - } - } - - fn write(addr: u16, data: u8) { - let cmd = (0 << 15) | addr; - let val = ((cmd as u32) << 8) | data as u32; - unsafe { - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::data_write(val << 8); - } - } - - fn read(addr: u16) -> u8 { - let cmd = (1 << 15) | addr; - let val = cmd as u32; - unsafe { - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::end_write(0); - csr::converter_spi::length_write(16 - 1); - csr::converter_spi::data_write(val << 16); - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::end_write(1); - csr::converter_spi::half_duplex_write(1); - csr::converter_spi::length_write(8 - 1); - csr::converter_spi::data_write(0); - while csr::converter_spi::writable_read() == 0 {} - csr::converter_spi::half_duplex_write(0); - csr::converter_spi::length_write(24 - 1); - csr::converter_spi::data_read() as u8 - } - } - - pub const CHIP_ID: u32 = 0xf17904; - - pub fn get_id() -> u32 { - spi_setup(); - (read(0x78) as u32) << 16 | (read(0x79) as u32) << 8 | read(0x7a) as u32 - } - - pub fn detect() -> Result<(), &'static str> { - let id = get_id(); - if id != CHIP_ID { - error!("invalid HMC7043 ID: 0x{:08x}", id); - return Err("invalid HMC7043 identification"); - } - - Ok(()) - } - - pub fn enable() { - info!("enabling HMC7043"); - - unsafe { - csr::hmc7043_reset::out_write(0); - } - clock::spin_us(10_000); - - spi_setup(); - write(0x0, 0x1); // Software reset - write(0x0, 0x0); // Normal operation - write(0x1, 0x48); // mute all outputs - } - - const GPO_MUX_CLK_OUT_PHASE: u8 = 3; - const GPO_MUX_FORCE1: u8 = 10; - const GPO_MUX_FORCE0: u8 = 11; - - /* Read an HMC7043 internal status bit through the GPO interface. - * This method is required to work around bugs in the register interface. - */ - fn gpo_indirect_read(mux_setting: u8) -> bool { - write(0x50, (mux_setting << 2) | 0x3); - spi_wait_idle(); - unsafe { - csr::hmc7043_gpo::in_read() == 1 - } - } - - pub fn init() { - spi_setup(); - info!("loading configuration..."); - - write(0x3, 0x14); // Disable the RFSYNCIN reseeder - write(0xA, 0x06); // Disable the RFSYNCIN input buffer - write(0xB, 0x07); // Enable the CLKIN input as LVPECL - write(0x9F, 0x4d); // Unexplained high-performance mode - write(0xA0, 0xdf); // Unexplained high-performance mode - - // Enable required output groups - let mut output_group_en = 0; - for channel in 0..OUTPUT_CONFIG.len() { - let enabled = OUTPUT_CONFIG[channel].0; - if enabled { - let group = channel/2; - output_group_en |= 1 << group; - } - } - write(0x4, output_group_en); - - // Set SYSREF timer divider. - // We don't need this "feature", but the HMC7043 won't work without. - write(0x5c, (HMC_SYSREF_DIV & 0xff) as u8); - write(0x5d, ((HMC_SYSREF_DIV & 0xf00) >> 8) as u8); - - for channel in 0..OUTPUT_CONFIG.len() { - let channel_base = 0xc8 + 0x0a*(channel as u16); - let (enabled, divider, outcfg, is_sysref) = OUTPUT_CONFIG[channel]; - - if enabled { - if !is_sysref { - // DCLK channel: enable high-performance mode - write(channel_base, 0xd1); - } else { - // SYSREF channel: disable hi-perf mode, enable slip - write(channel_base, 0x71); - } - } else { - write(channel_base, 0x10); - } - write(channel_base + 0x1, (divider & 0xff) as u8); - write(channel_base + 0x2, ((divider & 0xf00) >> 8) as u8); - - // bypass analog phase shift on DCLK channels to reduce noise - if !is_sysref { - if divider != 0 { - write(channel_base + 0x7, 0x00); // enable divider - } else { - write(channel_base + 0x7, 0x03); // bypass divider for lowest noise - } - } else { - write(channel_base + 0x7, 0x01); - } - - write(channel_base + 0x8, outcfg) - } - - write(0x1, 0x4a); // Reset dividers and FSMs - write(0x1, 0x48); - write(0x1, 0xc8); // Synchronize dividers - write(0x1, 0x40); // Unmute, high-performance/low-noise mode - - clock::spin_us(10_000); - - info!(" ...done"); - } - - pub fn test_gpo() -> Result<(), &'static str> { - info!("testing GPO..."); - for trial in 0..10 { - if !gpo_indirect_read(GPO_MUX_FORCE1) { - info!(" ...failed. GPO I/O did not go high (#{})", trial + 1); - return Err("GPO is not functioning"); - } - if gpo_indirect_read(GPO_MUX_FORCE0) { - info!(" ...failed. GPO I/O did not return low (#{})", trial + 1); - return Err("GPO is not functioning"); - } - } - info!(" ...passed"); - Ok(()) - } - - pub fn check_phased() -> Result<(), &'static str> { - if !gpo_indirect_read(GPO_MUX_CLK_OUT_PHASE) { - return Err("GPO reported phases did not align"); - } - // Should be the same as the GPO read - let sysref_fsm_status = read(0x91); - if sysref_fsm_status != 0x2 { - error!("Bad SYSREF FSM status: {:02x}", sysref_fsm_status); - return Err("Bad SYSREF FSM status"); - } - Ok(()) - } - - pub fn unmute() { - /* - * Never missing an opportunity to be awful, the HMC7043 produces broadband noise - * prior to intialization, which can upset the AMC FPGA. - * External circuitry mutes it. - */ - unsafe { - csr::hmc7043_out_en::out_write(1); - } - } - - pub fn sysref_delay_dac(dacno: u8, phase_offset: u8) { - spi_setup(); - if dacno == 0 { - write(0x00e9, phase_offset); - } else if dacno == 1 { - write(0x00d5, phase_offset); - } else { - unimplemented!(); - } - clock::spin_us(100); - } - - pub fn sysref_slip() { - spi_setup(); - write(0x0002, 0x02); - write(0x0002, 0x00); - clock::spin_us(100); - } -} - -pub fn init() -> Result<(), &'static str> { - #[cfg(all(hmc830_ref = "125", rtio_frequency = "125.0"))] - const DIV: (u32, u32, u32, u32) = (2, 32, 0, 1); // 125MHz -> 2.0GHz - #[cfg(all(hmc830_ref = "150", rtio_frequency = "150.0"))] - const DIV: (u32, u32, u32, u32) = (2, 32, 0, 1); // 150MHz -> 2.4GHz - - /* do not use other SPI devices before HMC830 SPI mode selection */ - hmc830::select_spi_mode(); - hmc830::detect()?; - hmc830::init(); - - hmc830::set_dividers(DIV.0, DIV.1, DIV.2, DIV.3); - - hmc830::check_locked()?; - - if hmc7043::get_id() == hmc7043::CHIP_ID { - error!("HMC7043 detected while in reset (board rework missing?)"); - } - hmc7043::enable(); - hmc7043::detect()?; - hmc7043::init(); - hmc7043::test_gpo()?; - hmc7043::check_phased()?; - hmc7043::unmute(); - - Ok(()) -} diff --git a/artiq/firmware/libboard_artiq/lib.rs b/artiq/firmware/libboard_artiq/lib.rs index 694805cfa..7436fc8c5 100644 --- a/artiq/firmware/libboard_artiq/lib.rs +++ b/artiq/firmware/libboard_artiq/lib.rs @@ -25,13 +25,6 @@ pub mod si5324; #[cfg(has_wrpll)] pub mod wrpll; -#[cfg(has_hmc830_7043)] -pub mod hmc830_7043; -#[cfg(has_ad9154)] -mod ad9154_reg; -#[cfg(has_ad9154)] -pub mod ad9154; - #[cfg(has_grabber)] pub mod grabber; diff --git a/artiq/firmware/libboard_artiq/si5324.rs b/artiq/firmware/libboard_artiq/si5324.rs index 3b1103d99..63e49bd5e 100644 --- a/artiq/firmware/libboard_artiq/si5324.rs +++ b/artiq/firmware/libboard_artiq/si5324.rs @@ -182,12 +182,6 @@ fn init() -> Result<()> { i2c::switch_select(BUSNO, 0x70, 0)?; i2c::switch_select(BUSNO, 0x71, 1 << 3)?; } - #[cfg(soc_platform = "sayma_amc")] - i2c::switch_select(BUSNO, 0x70, 1 << 4)?; - #[cfg(soc_platform = "sayma_rtm")] - i2c::switch_select(BUSNO, 0x77, 1 << 5)?; - #[cfg(soc_platform = "metlino")] - i2c::switch_select(BUSNO, 0x70, 1 << 4)?; #[cfg(soc_platform = "kc705")] i2c::switch_select(BUSNO, 0x74, 1 << 7)?; diff --git a/artiq/firmware/libboard_artiq/wrpll.rs b/artiq/firmware/libboard_artiq/wrpll.rs index 4b0fa9754..a9c9a702f 100644 --- a/artiq/firmware/libboard_artiq/wrpll.rs +++ b/artiq/firmware/libboard_artiq/wrpll.rs @@ -175,8 +175,6 @@ mod si549 { use board_misoc::clock; use super::i2c; - #[cfg(any(soc_platform = "metlino", soc_platform = "sayma_amc", soc_platform = "sayma_rtm"))] - pub const ADDRESS: u8 = 0x55; #[cfg(soc_platform = "kasli")] pub const ADDRESS: u8 = 0x67; diff --git a/artiq/firmware/libboard_misoc/net_settings.rs b/artiq/firmware/libboard_misoc/net_settings.rs index 2b69d9262..36c85319f 100644 --- a/artiq/firmware/libboard_misoc/net_settings.rs +++ b/artiq/firmware/libboard_misoc/net_settings.rs @@ -67,10 +67,6 @@ pub fn get_adresses() -> NetAddresses { .map(|addr_buf| EthernetAddress(addr_buf)) .unwrap_or_else(|_e| EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x21])); } - #[cfg(soc_platform = "sayma_amc")] - { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x11]); } - #[cfg(soc_platform = "metlino")] - { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x19]); } #[cfg(soc_platform = "kc705")] { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]); } } diff --git a/artiq/firmware/libboard_misoc/spiflash.rs b/artiq/firmware/libboard_misoc/spiflash.rs index 9b5ca31f5..598d96633 100644 --- a/artiq/firmware/libboard_misoc/spiflash.rs +++ b/artiq/firmware/libboard_misoc/spiflash.rs @@ -114,7 +114,7 @@ pub unsafe fn write(mut addr: usize, mut data: &[u8]) { } } -#[cfg(any(soc_platform = "kasli", soc_platform = "metlino", soc_platform = "kc705"))] +#[cfg(any(soc_platform = "kasli", soc_platform = "kc705"))] pub unsafe fn reload () -> ! { csr::icap::iprog_write(1); loop {} diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index b36fd9251..f91f4d391 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -341,7 +341,7 @@ pub fn panic_impl(info: &core::panic::PanicInfo) -> ! { }); if config::read_str("panic_reset", |r| r == Ok("1")) && - cfg!(any(soc_platform = "kasli", soc_platform = "metlino", soc_platform = "kc705")) { + cfg!(any(soc_platform = "kasli", soc_platform = "kc705")) { println!("restarting..."); unsafe { kernel::stop(); diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index 52ab35915..e23934e33 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -126,7 +126,7 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { crystal_ref: false } }, - RtioClock::Int_100 => { // 100MHz output, from crystal. Also used as reference for Sayma HMC830. + RtioClock::Int_100 => { // 100MHz output, from crystal info!("using internal 100MHz RTIO clock"); si5324::FrequencySettings { n1_hs : 9, @@ -172,8 +172,6 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { let si5324_ref_input = si5324::Input::Ckin1; #[cfg(all(soc_platform = "kasli", not(hw_rev = "v2.0")))] let si5324_ref_input = si5324::Input::Ckin2; - #[cfg(soc_platform = "metlino")] - let si5324_ref_input = si5324::Input::Ckin2; #[cfg(soc_platform = "kc705")] let si5324_ref_input = si5324::Input::Ckin2; si5324::setup(&si5324_settings, si5324_ref_input).expect("cannot initialize Si5324"); @@ -192,8 +190,6 @@ fn setup_si5324(clock_cfg: RtioClock) { let si5324_ext_input = si5324::Input::Ckin1; #[cfg(all(soc_platform = "kasli", not(hw_rev = "v2.0")))] let si5324_ext_input = si5324::Input::Ckin2; - #[cfg(soc_platform = "metlino")] - let si5324_ext_input = si5324::Input::Ckin2; #[cfg(soc_platform = "kc705")] let si5324_ext_input = si5324::Input::Ckin1; match clock_cfg { diff --git a/artiq/firmware/satman/jdac_common.rs b/artiq/firmware/satman/jdac_common.rs deleted file mode 100644 index 3c185516f..000000000 --- a/artiq/firmware/satman/jdac_common.rs +++ /dev/null @@ -1,74 +0,0 @@ -pub const INIT: u8 = 0x00; -pub const PRINT_STATUS: u8 = 0x01; -pub const PRBS: u8 = 0x02; -pub const STPL: u8 = 0x03; - -pub const SYSREF_DELAY_DAC: u8 = 0x10; -pub const SYSREF_SLIP: u8 = 0x11; -pub const SYNC: u8 = 0x12; - -pub const DDMTD_SYSREF_RAW: u8 = 0x20; -pub const DDMTD_SYSREF: u8 = 0x21; - - -fn average_2phases(a: i32, b: i32, modulo: i32) -> i32 { - let diff = ((a - b + modulo/2 + modulo) % modulo) - modulo/2; - return (modulo + b + diff/2) % modulo; -} - -pub fn average_phases(phases: &[i32], modulo: i32) -> i32 { - if phases.len() == 1 { - panic!("input array length must be a power of 2"); - } else if phases.len() == 2 { - average_2phases(phases[0], phases[1], modulo) - } else { - let cut = phases.len()/2; - average_2phases( - average_phases(&phases[..cut], modulo), - average_phases(&phases[cut..], modulo), - modulo) - } -} - -pub const RAW_DDMTD_N_SHIFT: i32 = 6; -pub const RAW_DDMTD_N: i32 = 1 << RAW_DDMTD_N_SHIFT; -pub const DDMTD_DITHER_BITS: i32 = 1; -pub const DDMTD_N_SHIFT: i32 = RAW_DDMTD_N_SHIFT + DDMTD_DITHER_BITS; -pub const DDMTD_N: i32 = 1 << DDMTD_N_SHIFT; - -#[cfg(has_ad9154)] -use board_misoc::{clock, csr}; - -#[cfg(has_ad9154)] -pub fn init_ddmtd() -> Result<(), &'static str> { - unsafe { - csr::sysref_ddmtd::reset_write(1); - clock::spin_us(1); - csr::sysref_ddmtd::reset_write(0); - clock::spin_us(100); - if csr::sysref_ddmtd::locked_read() != 0 { - Ok(()) - } else { - Err("DDMTD helper PLL failed to lock") - } - } -} - -#[cfg(has_ad9154)] -pub fn measure_ddmdt_phase_raw() -> i32 { - unsafe { csr::sysref_ddmtd::dt_read() as i32 } -} - -#[cfg(has_ad9154)] -pub fn measure_ddmdt_phase() -> i32 { - const AVG_PRECISION_SHIFT: i32 = 6; - const AVG_PRECISION: i32 = 1 << AVG_PRECISION_SHIFT; - const AVG_MOD: i32 = 1 << (RAW_DDMTD_N_SHIFT + AVG_PRECISION_SHIFT + DDMTD_DITHER_BITS); - - let mut measurements = [0; AVG_PRECISION as usize]; - for i in 0..AVG_PRECISION { - measurements[i as usize] = measure_ddmdt_phase_raw() << (AVG_PRECISION_SHIFT + DDMTD_DITHER_BITS); - clock::spin_us(10); - } - average_phases(&measurements, AVG_MOD) >> AVG_PRECISION_SHIFT -} diff --git a/artiq/firmware/satman/jdcg.rs b/artiq/firmware/satman/jdcg.rs deleted file mode 100644 index c8a34827b..000000000 --- a/artiq/firmware/satman/jdcg.rs +++ /dev/null @@ -1,589 +0,0 @@ -pub mod jesd { - use board_misoc::{csr, clock}; - - pub fn reset(reset: bool) { - unsafe { - csr::jesd_crg::jreset_write(if reset {1} else {0}); - } - } - - pub fn enable(dacno: u8, en: bool) { - unsafe { - (csr::JDCG[dacno as usize].jesd_control_enable_write)(if en {1} else {0}) - } - } - - pub fn phy_done(dacno: u8) -> bool { - unsafe { - (csr::JDCG[dacno as usize].jesd_control_phy_done_read)() != 0 - } - } - - pub fn ready(dacno: u8) -> bool { - unsafe { - (csr::JDCG[dacno as usize].jesd_control_ready_read)() != 0 - } - } - - pub fn prbs(dacno: u8, en: bool) { - unsafe { - (csr::JDCG[dacno as usize].jesd_control_prbs_config_write)(if en {0b01} else {0b00}) - } - clock::spin_us(5000); - } - - pub fn stpl(dacno: u8, en: bool) { - unsafe { - (csr::JDCG[dacno as usize].jesd_control_stpl_enable_write)(if en {1} else {0}) - } - clock::spin_us(5000); - } - - pub fn jsync(dacno: u8) -> bool { - unsafe { - (csr::JDCG[dacno as usize].jesd_control_jsync_read)() != 0 - } - } -} - -pub mod jdac { - use board_misoc::{csr, clock}; - use board_artiq::drtioaux; - - use super::jesd; - use super::super::jdac_common; - - pub fn basic_request(dacno: u8, reqno: u8, param: u8) -> Result { - if let Err(e) = drtioaux::send(1, &drtioaux::Packet::JdacBasicRequest { - destination: 0, - dacno: dacno, - reqno: reqno, - param: param - }) { - error!("aux packet error ({})", e); - return Err("aux packet error while sending for JESD DAC basic request"); - } - match drtioaux::recv_timeout(1, Some(1000)) { - Ok(drtioaux::Packet::JdacBasicReply { succeeded, retval }) => { - if succeeded { - Ok(retval) - } else { - error!("JESD DAC basic request failed (dacno={}, reqno={})", dacno, reqno); - Err("remote error status to JESD DAC basic request") - } - }, - Ok(packet) => { - error!("received unexpected aux packet: {:?}", packet); - Err("unexpected aux packet in reply to JESD DAC basic request") - }, - Err(e) => { - error!("aux packet error ({})", e); - Err("aux packet error while waiting for JESD DAC basic reply") - } - } - } - - pub fn init() -> Result<(), &'static str> { - for dacno in 0..csr::JDCG.len() { - let dacno = dacno as u8; - info!("DAC-{} initializing...", dacno); - - jesd::enable(dacno, true); - clock::spin_us(10_000); - if !jesd::phy_done(dacno) { - error!("JESD core PHY not done"); - return Err("JESD core PHY not done"); - } - - basic_request(dacno, jdac_common::INIT, 0)?; - - // JESD ready depends on JSYNC being valid, so DAC init needs to happen first - if !jesd::ready(dacno) { - error!("JESD core reported not ready, sending DAC status print request"); - basic_request(dacno, jdac_common::PRINT_STATUS, 0)?; - return Err("JESD core reported not ready"); - } - - jesd::prbs(dacno, true); - basic_request(dacno, jdac_common::PRBS, 0)?; - jesd::prbs(dacno, false); - - basic_request(dacno, jdac_common::INIT, 0)?; - clock::spin_us(5000); - - if !jesd::jsync(dacno) { - error!("JESD core reported bad SYNC"); - return Err("JESD core reported bad SYNC"); - } - - info!(" ...done initializing"); - } - Ok(()) - } - - pub fn stpl() -> Result<(), &'static str> { - for dacno in 0..csr::JDCG.len() { - let dacno = dacno as u8; - - info!("Running STPL test on DAC-{}...", dacno); - - jesd::stpl(dacno, true); - basic_request(dacno, jdac_common::STPL, 0)?; - jesd::stpl(dacno, false); - - info!(" ...done STPL test"); - } - Ok(()) - } -} - -pub mod jesd204sync { - use board_misoc::{csr, clock, config}; - - use super::jdac; - use super::super::jdac_common; - - const HMC7043_ANALOG_DELAY_RANGE: u8 = 24; - - const FPGA_CLK_DIV: u16 = 16; // Keep in sync with hmc830_7043.rs - const SYSREF_DIV: u16 = 256; // Keep in sync with hmc830_7043.rs - - fn hmc7043_sysref_delay_dac(dacno: u8, phase_offset: u8) -> Result<(), &'static str> { - match jdac::basic_request(dacno, jdac_common::SYSREF_DELAY_DAC, phase_offset) { - Ok(_) => Ok(()), - Err(e) => Err(e) - } - } - - - fn hmc7043_sysref_slip() -> Result<(), &'static str> { - match jdac::basic_request(0, jdac_common::SYSREF_SLIP, 0) { - Ok(_) => Ok(()), - Err(e) => Err(e) - } - } - - fn ad9154_sync(dacno: u8) -> Result { - match jdac::basic_request(dacno, jdac_common::SYNC, 0) { - Ok(0) => Ok(false), - Ok(_) => Ok(true), - Err(e) => Err(e) - } - } - - fn measure_ddmdt_phase_raw() -> Result { - Ok(jdac::basic_request(0, jdac_common::DDMTD_SYSREF_RAW, 0)? as i32) - } - - fn measure_ddmdt_phase() -> Result { - Ok(jdac::basic_request(0, jdac_common::DDMTD_SYSREF, 0)? as i32) - } - - fn test_ddmtd_stability(raw: bool, tolerance: i32) -> Result<(), &'static str> { - info!("testing DDMTD stability (raw={}, tolerance={})...", raw, tolerance); - - let modulo = if raw { jdac_common::RAW_DDMTD_N } else { jdac_common::DDMTD_N }; - let measurement = if raw { measure_ddmdt_phase_raw } else { measure_ddmdt_phase }; - let ntests = if raw { 150 } else { 15 }; - - let mut max_pkpk = 0; - for _ in 0..32 { - // If we are near the edges, wraparound can throw off the simple min/max computation. - // In this case, add an offset to get near the center. - let quadrant = measure_ddmdt_phase()?; - let center_offset = - if quadrant < jdac_common::DDMTD_N/4 || quadrant > 3*jdac_common::DDMTD_N/4 { - modulo/2 - } else { - 0 - }; - - let mut min = modulo; - let mut max = 0; - for _ in 0..ntests { - let m = (measurement()? + center_offset) % modulo; - if m < min { - min = m; - } - if m > max { - max = m; - } - } - let pkpk = max - min; - if pkpk > max_pkpk { - max_pkpk = pkpk; - } - if pkpk > tolerance { - error!(" ...excessive peak-peak jitter: {} (min={} max={} center_offset={})", pkpk, - min, max, center_offset); - return Err("excessive DDMTD peak-peak jitter"); - } - hmc7043_sysref_slip(); - } - - info!(" ...passed, peak-peak jitter: {}", max_pkpk); - Ok(()) - } - - fn test_slip_ddmtd() -> Result<(), &'static str> { - // expected_step = (RTIO clock frequency)*(DDMTD N)/(HMC7043 CLKIN frequency) - let expected_step = 8; - let tolerance = 1; - - info!("testing HMC7043 SYSREF slip against DDMTD..."); - let mut old_phase = measure_ddmdt_phase()?; - for _ in 0..1024 { - hmc7043_sysref_slip(); - let phase = measure_ddmdt_phase()?; - let step = (jdac_common::DDMTD_N + old_phase - phase) % jdac_common::DDMTD_N; - if (step - expected_step).abs() > tolerance { - error!(" ...got unexpected step: {} ({} -> {})", step, old_phase, phase); - return Err("HMC7043 SYSREF slip produced unexpected DDMTD step"); - } - old_phase = phase; - } - info!(" ...passed"); - Ok(()) - } - - fn sysref_sh_error() -> bool { - unsafe { - csr::sysref_sampler::sh_error_reset_write(1); - clock::spin_us(1); - csr::sysref_sampler::sh_error_reset_write(0); - clock::spin_us(10); - csr::sysref_sampler::sh_error_read() != 0 - } - } - - const SYSREF_SH_PRECISION_SHIFT: i32 = 5; - const SYSREF_SH_PRECISION: i32 = 1 << SYSREF_SH_PRECISION_SHIFT; - const SYSREF_SH_MOD: i32 = 1 << (jdac_common::DDMTD_N_SHIFT + SYSREF_SH_PRECISION_SHIFT); - - #[derive(Default)] - struct SysrefShLimits { - rising_phases: [i32; SYSREF_SH_PRECISION as usize], - falling_phases: [i32; SYSREF_SH_PRECISION as usize], - } - - fn measure_sysref_sh_limits() -> Result { - let mut ret = SysrefShLimits::default(); - let mut nslips = 0; - let mut rising_n = 0; - let mut falling_n = 0; - - let mut previous = sysref_sh_error(); - while rising_n < SYSREF_SH_PRECISION || falling_n < SYSREF_SH_PRECISION { - hmc7043_sysref_slip(); - nslips += 1; - if nslips > 1024 { - return Err("too many slips and not enough SYSREF S/H error transitions"); - } - - let current = sysref_sh_error(); - let phase = measure_ddmdt_phase()?; - if current && !previous && rising_n < SYSREF_SH_PRECISION { - ret.rising_phases[rising_n as usize] = phase << SYSREF_SH_PRECISION_SHIFT; - rising_n += 1; - } - if !current && previous && falling_n < SYSREF_SH_PRECISION { - ret.falling_phases[falling_n as usize] = phase << SYSREF_SH_PRECISION_SHIFT; - falling_n += 1; - } - previous = current; - } - Ok(ret) - } - - fn max_phase_deviation(average: i32, phases: &[i32]) -> i32 { - let mut ret = 0; - for phase in phases.iter() { - let deviation = (phase - average + jdac_common::DDMTD_N) % jdac_common::DDMTD_N; - if deviation > ret { - ret = deviation; - } - } - return ret; - } - - fn reach_sysref_ddmtd_target(target: i32, tolerance: i32) -> Result { - for _ in 0..1024 { - let delta = (measure_ddmdt_phase()? - target + jdac_common::DDMTD_N) % jdac_common::DDMTD_N; - if delta <= tolerance { - return Ok(delta) - } - hmc7043_sysref_slip(); - } - Err("failed to reach SYSREF DDMTD phase target") - } - - fn calibrate_sysref_target(rising_average: i32, falling_average: i32) -> Result { - info!("calibrating SYSREF DDMTD target phase..."); - let coarse_target = - if rising_average < falling_average { - (rising_average + falling_average)/2 - } else { - ((falling_average - (jdac_common::DDMTD_N - rising_average))/2 + jdac_common::DDMTD_N) % jdac_common::DDMTD_N - }; - info!(" SYSREF calibration coarse target: {}", coarse_target); - reach_sysref_ddmtd_target(coarse_target, 8)?; - let target = measure_ddmdt_phase()?; - info!(" ...done, target={}", target); - Ok(target) - } - - fn sysref_get_tsc_phase_raw() -> Result { - if sysref_sh_error() { - return Err("SYSREF failed S/H timing"); - } - let ret = unsafe { csr::sysref_sampler::sysref_phase_read() }; - Ok(ret) - } - - // Note: the code below assumes RTIO/SYSREF frequency ratio is a power of 2 - - fn sysref_get_tsc_phase() -> Result { - let mask = (SYSREF_DIV/FPGA_CLK_DIV - 1) as u8; - Ok((sysref_get_tsc_phase_raw()? & mask) as i32) - } - - pub fn test_sysref_frequency() -> Result<(), &'static str> { - info!("testing SYSREF frequency against raw TSC phase bit toggles..."); - - let mut all_toggles = 0; - let initial_phase = sysref_get_tsc_phase_raw()?; - for _ in 0..20000 { - clock::spin_us(1); - all_toggles |= sysref_get_tsc_phase_raw()? ^ initial_phase; - } - - let ratio = (SYSREF_DIV/FPGA_CLK_DIV) as u8; - let expected_toggles = 0xff ^ (ratio - 1); - if all_toggles == expected_toggles { - info!(" ...done (0x{:02x})", all_toggles); - Ok(()) - } else { - error!(" ...unexpected toggles: got 0x{:02x}, expected 0x{:02x}", - all_toggles, expected_toggles); - Err("unexpected toggles") - } - } - - fn sysref_slip_rtio_cycle() { - for _ in 0..FPGA_CLK_DIV { - hmc7043_sysref_slip(); - } - } - - pub fn test_slip_tsc() -> Result<(), &'static str> { - info!("testing HMC7043 SYSREF slip against TSC phase..."); - let initial_phase = sysref_get_tsc_phase()?; - let modulo = (SYSREF_DIV/FPGA_CLK_DIV) as i32; - for i in 0..128 { - sysref_slip_rtio_cycle(); - let expected_phase = (initial_phase + i + 1) % modulo; - let phase = sysref_get_tsc_phase()?; - if phase != expected_phase { - error!(" ...unexpected TSC phase: got {}, expected {} ", phase, expected_phase); - return Err("HMC7043 SYSREF slip produced unexpected TSC phase"); - } - } - info!(" ...done"); - Ok(()) - } - - pub fn sysref_rtio_align() -> Result<(), &'static str> { - info!("aligning SYSREF with RTIO TSC..."); - let mut nslips = 0; - loop { - sysref_slip_rtio_cycle(); - if sysref_get_tsc_phase()? == 0 { - info!(" ...done"); - return Ok(()) - } - - nslips += 1; - if nslips > SYSREF_DIV/FPGA_CLK_DIV { - return Err("failed to find SYSREF transition aligned with RTIO TSC"); - } - } - } - - pub fn sysref_auto_rtio_align() -> Result<(), &'static str> { - test_ddmtd_stability(true, 4)?; - test_ddmtd_stability(false, 1)?; - test_slip_ddmtd()?; - - info!("determining SYSREF S/H limits..."); - let sysref_sh_limits = measure_sysref_sh_limits()?; - let rising_average = jdac_common::average_phases(&sysref_sh_limits.rising_phases, SYSREF_SH_MOD); - let falling_average = jdac_common::average_phases(&sysref_sh_limits.falling_phases, SYSREF_SH_MOD); - let rising_max_deviation = max_phase_deviation(rising_average, &sysref_sh_limits.rising_phases); - let falling_max_deviation = max_phase_deviation(falling_average, &sysref_sh_limits.falling_phases); - - let rising_average = rising_average >> SYSREF_SH_PRECISION_SHIFT; - let falling_average = falling_average >> SYSREF_SH_PRECISION_SHIFT; - let rising_max_deviation = rising_max_deviation >> SYSREF_SH_PRECISION_SHIFT; - let falling_max_deviation = falling_max_deviation >> SYSREF_SH_PRECISION_SHIFT; - - info!(" SYSREF S/H average limits (DDMTD phases): {} {}", rising_average, falling_average); - info!(" SYSREF S/H maximum limit deviation: {} {}", rising_max_deviation, falling_max_deviation); - if rising_max_deviation > 8 || falling_max_deviation > 8 { - return Err("excessive SYSREF S/H limit deviation"); - } - info!(" ...done"); - - let entry = config::read_str("sysref_ddmtd_phase_fpga", |r| r.map(|s| s.parse())); - let target_phase = match entry { - Ok(Ok(phase)) => { - info!("using FPGA SYSREF DDMTD phase target from config: {}", phase); - phase - } - _ => { - let phase = calibrate_sysref_target(rising_average, falling_average)?; - if let Err(e) = config::write_int("sysref_ddmtd_phase_fpga", phase as u32) { - error!("failed to update FPGA SYSREF DDMTD phase target in config: {}", e); - } - phase - } - }; - - info!("aligning SYSREF with RTIO clock..."); - let delta = reach_sysref_ddmtd_target(target_phase, 3)?; - if sysref_sh_error() { - return Err("SYSREF does not meet S/H timing at DDMTD phase target"); - } - info!(" ...done, delta={}", delta); - - test_sysref_frequency()?; - test_slip_tsc()?; - sysref_rtio_align()?; - - Ok(()) - } - - fn sysref_cal_dac(dacno: u8) -> Result { - info!("calibrating SYSREF delay at DAC-{}...", dacno); - - // Allocate for more than expected as jitter may create spurious entries. - let mut limits_buf = [0; 8]; - let mut n_limits = 0; - - limits_buf[n_limits] = -1; - n_limits += 1; - - // avoid spurious rotation at delay=0 - hmc7043_sysref_delay_dac(dacno, 0); - ad9154_sync(dacno)?; - - for scan_delay in 0..HMC7043_ANALOG_DELAY_RANGE { - hmc7043_sysref_delay_dac(dacno, scan_delay); - if ad9154_sync(dacno)? { - limits_buf[n_limits] = scan_delay as i16; - n_limits += 1; - if n_limits >= limits_buf.len() - 1 { - break; - } - } - } - - limits_buf[n_limits] = HMC7043_ANALOG_DELAY_RANGE as i16; - n_limits += 1; - - info!(" using limits: {:?}", &limits_buf[..n_limits]); - - let mut delay = 0; - let mut best_margin = 0; - - for i in 0..(n_limits-1) { - let margin = limits_buf[i+1] - limits_buf[i]; - if margin > best_margin { - best_margin = margin; - delay = ((limits_buf[i+1] + limits_buf[i])/2) as u8; - } - } - - info!(" ...done, delay={}", delay); - Ok(delay) - } - - fn sysref_dac_align(dacno: u8, delay: u8) -> Result<(), &'static str> { - let tolerance = 5; - - info!("verifying SYSREF margins at DAC-{}...", dacno); - - // avoid spurious rotation at delay=0 - hmc7043_sysref_delay_dac(dacno, 0); - ad9154_sync(dacno)?; - - let mut rotation_seen = false; - for scan_delay in 0..HMC7043_ANALOG_DELAY_RANGE { - hmc7043_sysref_delay_dac(dacno, scan_delay); - if ad9154_sync(dacno)? { - rotation_seen = true; - let distance = (scan_delay as i16 - delay as i16).abs(); - if distance < tolerance { - error!(" rotation at delay={} is {} delay steps from target (FAIL)", scan_delay, distance); - return Err("insufficient SYSREF margin at DAC"); - } else { - info!(" rotation at delay={} is {} delay steps from target (PASS)", scan_delay, distance); - } - } - } - - if !rotation_seen { - return Err("no rotation seen when scanning DAC SYSREF delay"); - } - - info!(" ...done"); - - // We tested that the value is correct - now use it - info!("synchronizing DAC-{}", dacno); - hmc7043_sysref_delay_dac(dacno, delay); - ad9154_sync(dacno)?; - - Ok(()) - } - - pub fn sysref_auto_dac_align() -> Result<(), &'static str> { - // We assume that DAC SYSREF traces are length-matched so only one delay - // value is needed, and we use DAC-0 as calibration reference. - - let entry = config::read_str("sysref_7043_delay_dac", |r| r.map(|s| s.parse())); - let delay = match entry { - Ok(Ok(delay)) => { - info!("using DAC SYSREF delay from config: {}", delay); - delay - }, - _ => { - let delay = sysref_cal_dac(0)?; - if let Err(e) = config::write_int("sysref_7043_delay_dac", delay as u32) { - error!("failed to update DAC SYSREF delay in config: {}", e); - } - delay - } - }; - - for dacno in 0..csr::JDCG.len() { - sysref_dac_align(dacno as u8, delay)?; - } - Ok(()) - } - - pub fn sysref_auto_align() { - if let Err(e) = sysref_auto_rtio_align() { - error!("failed to align SYSREF at FPGA: {}", e); - } - if let Err(e) = sysref_auto_dac_align() { - error!("failed to align SYSREF at DAC: {}", e); - } - } - - pub fn resync_dacs() -> Result<(), &'static str> { - for dacno in 0..csr::JDCG.len() { - info!("resynchronizing DAC-{}", dacno); - ad9154_sync(dacno as u8)?; - } - Ok(()) - } -} diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 366aa1d5b..7d69f7d0d 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -16,15 +16,9 @@ use board_artiq::si5324; use board_artiq::wrpll; use board_artiq::{spi, drtioaux}; use board_artiq::drtio_routing; -#[cfg(has_hmc830_7043)] -use board_artiq::hmc830_7043; use riscv::register::{mcause, mepc, mtval}; mod repeater; -#[cfg(has_jdcg)] -mod jdcg; -#[cfg(any(has_ad9154, has_jdcg))] -pub mod jdac_common; fn drtiosat_reset(reset: bool) { unsafe { @@ -303,43 +297,6 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater], } } - drtioaux::Packet::JdacBasicRequest { destination: _destination, dacno: _dacno, - reqno: _reqno, param: _param } => { - forward!(_routing_table, _destination, *_rank, _repeaters, &packet); - #[cfg(has_ad9154)] - let (succeeded, retval) = { - #[cfg(rtio_frequency = "125.0")] - const LINERATE: u64 = 5_000_000_000; - #[cfg(rtio_frequency = "150.0")] - const LINERATE: u64 = 6_000_000_000; - match _reqno { - jdac_common::INIT => (board_artiq::ad9154::setup(_dacno, LINERATE).is_ok(), 0), - jdac_common::PRINT_STATUS => { board_artiq::ad9154::status(_dacno); (true, 0) }, - jdac_common::PRBS => (board_artiq::ad9154::prbs(_dacno).is_ok(), 0), - jdac_common::STPL => (board_artiq::ad9154::stpl(_dacno, 4, 2).is_ok(), 0), - jdac_common::SYSREF_DELAY_DAC => { board_artiq::hmc830_7043::hmc7043::sysref_delay_dac(_dacno, _param); (true, 0) }, - jdac_common::SYSREF_SLIP => { board_artiq::hmc830_7043::hmc7043::sysref_slip(); (true, 0) }, - jdac_common::SYNC => { - match board_artiq::ad9154::sync(_dacno) { - Ok(false) => (true, 0), - Ok(true) => (true, 1), - Err(e) => { - error!("DAC sync failed: {}", e); - (false, 0) - } - } - }, - jdac_common::DDMTD_SYSREF_RAW => (true, jdac_common::measure_ddmdt_phase_raw() as u8), - jdac_common::DDMTD_SYSREF => (true, jdac_common::measure_ddmdt_phase() as u8), - _ => (false, 0) - } - }; - #[cfg(not(has_ad9154))] - let (succeeded, retval) = (false, 0); - drtioaux::send(0, - &drtioaux::Packet::JdacBasicReply { succeeded: succeeded, retval: retval }) - } - _ => { warn!("received unexpected aux packet"); Ok(()) @@ -530,7 +487,6 @@ pub extern fn main() -> i32 { sysclk_setup(); - #[cfg(not(has_jdcg))] unsafe { csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); } @@ -539,17 +495,6 @@ pub extern fn main() -> i32 { init_rtio_crg(); - #[cfg(has_hmc830_7043)] - /* must be the first SPI init because of HMC830 SPI mode selection */ - hmc830_7043::init().expect("cannot initialize HMC830/7043"); - #[cfg(has_ad9154)] - { - jdac_common::init_ddmtd().expect("failed to initialize SYSREF DDMTD core"); - for dacno in 0..csr::CONFIG_AD9154_COUNT { - board_artiq::ad9154::reset_and_detect(dacno as u8).expect("AD9154 DAC not detected"); - } - } - #[cfg(has_drtio_routing)] let mut repeaters = [repeater::Repeater::default(); csr::DRTIOREP.len()]; #[cfg(not(has_drtio_routing))] @@ -563,11 +508,6 @@ pub extern fn main() -> i32 { let mut hardware_tick_ts = 0; loop { - #[cfg(has_jdcg)] - unsafe { - // Hide from uplink until RTM is ready - csr::drtio_transceiver::txenable_write(0xfffffffeu32 as _); - } while !drtiosat_link_rx_up() { drtiosat_process_errors(); for rep in repeaters.iter_mut() { @@ -594,8 +534,6 @@ pub extern fn main() -> i32 { drtiosat_reset(false); drtiosat_reset_phy(false); - #[cfg(has_jdcg)] - let mut was_up = false; while drtiosat_link_rx_up() { drtiosat_process_errors(); process_aux_packets(&mut repeaters, &mut routing_table, &mut rank); @@ -610,18 +548,6 @@ pub extern fn main() -> i32 { hardware_tick(&mut hardware_tick_ts); if drtiosat_tsc_loaded() { info!("TSC loaded from uplink"); - #[cfg(has_jdcg)] - { - // We assume that the RTM on repeater0 is up. - // Uplink should not send a TSC load command unless the link is - // up, and we are hiding when the RTM is down. - if let Err(e) = jdcg::jesd204sync::sysref_rtio_align() { - error!("failed to align SYSREF with TSC ({})", e); - } - if let Err(e) = jdcg::jesd204sync::resync_dacs() { - error!("DAC resync failed after SYSREF/TSC realignment ({})", e); - } - } for rep in repeaters.iter() { if let Err(e) = rep.sync_tsc() { error!("failed to sync TSC ({})", e); @@ -631,38 +557,8 @@ pub extern fn main() -> i32 { error!("aux packet error: {}", e); } } - #[cfg(has_jdcg)] - { - let is_up = repeaters[0].is_up(); - if is_up && !was_up { - /* - * One side of the JESD204 elastic buffer is clocked by the jitter filter - * (Si5324 or WRPLL), the other by the RTM. - * The elastic buffer can operate only when those two clocks are derived from - * the same oscillator. - * This is the case when either of those conditions is true: - * (1) The DRTIO master and the RTM are clocked directly from a common external - * source, *and* the jitter filter has locked to the recovered clock. - * This clocking scheme may provide less noise and phase drift at the DACs. - * (2) The RTM clock is connected to the jitter filter output. - * To handle those cases, we simply keep the JESD204 core in reset unless the - * jitter filter is locked to the recovered clock. - */ - jdcg::jesd::reset(false); - let _ = jdcg::jdac::init(); - jdcg::jesd204sync::sysref_auto_align(); - jdcg::jdac::stpl(); - unsafe { - csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); // unhide - } - } - was_up = is_up; - } } - #[cfg(has_jdcg)] - jdcg::jesd::reset(true); - drtiosat_reset_phy(true); drtiosat_reset(true); drtiosat_tsc_loaded(); diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index 1462ec83e..96203fa83 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -25,12 +25,10 @@ def get_argparser(): Valid actions: * gateware: write main gateware bitstream to flash - * rtm_gateware: write RTM gateware bitstream to flash * bootloader: write bootloader to flash * storage: write storage image to flash * firmware: write firmware to flash * load: load main gateware bitstream into device (volatile but fast) - * rtm_load: load RTM gateware bitstream into device * erase: erase flash memory * start: trigger the target to (re)load its gateware bitstream from flash @@ -61,7 +59,7 @@ Prerequisites: help="SSH host to jump through") parser.add_argument("-t", "--target", default="kasli", help="target board, default: %(default)s, one of: " - "kasli sayma metlino kc705") + "kasli kc705") parser.add_argument("-I", "--preinit-command", default=[], action="append", help="add a pre-initialization OpenOCD command. " "Useful for selecting a board when several are connected.") @@ -69,8 +67,6 @@ Prerequisites: parser.add_argument("-d", "--dir", default=None, help="look for board binaries in this directory") parser.add_argument("--srcbuild", help="board binaries directory is laid out as a source build tree", default=False, action="store_true") - parser.add_argument("--no-rtm-jtag", help="do not attempt JTAG to the RTM", - default=False, action="store_true") parser.add_argument("action", metavar="ACTION", nargs="*", default=[], help="actions to perform, default: flash everything") @@ -234,76 +230,6 @@ class ProgrammerXC7(Programmer): "xc7_program xc7.tap") -class ProgrammerAMCRTM(Programmer): - _sector_size = 0x10000 - - def __init__(self, client, preinit_script): - Programmer.__init__(self, client, preinit_script) - - add_commands(self._board_script, - "source {}".format(self._transfer_script("fpga/xilinx-xadc.cfg")), - - "interface ftdi", - "ftdi_device_desc \"Quad RS232-HS\"", - "ftdi_vid_pid 0x0403 0x6011", - "ftdi_channel 0", - # EN_USB_JTAG on ADBUS7: out, high - # nTRST on ADBUS4: out, high, but R46 is DNP - "ftdi_layout_init 0x0098 0x008b", - "reset_config none", - "adapter_khz 5000", - "transport select jtag", - # tap 0, pld 0 - "source {}".format(self._transfer_script("cpld/xilinx-xc7.cfg")), - # tap 1, pld 1 - "set CHIP XCKU040", - "source {}".format(self._transfer_script("cpld/xilinx-xcu.cfg"))) - self.add_flash_bank("spi0", "xcu", index=0) - self.add_flash_bank("spi1", "xcu", index=1) - - add_commands(self._script, "echo \"RTM FPGA XADC:\"", "xadc_report xc7.tap") - add_commands(self._script, "echo \"AMC FPGA XADC:\"", "xadc_report xcu.tap") - - def load_proxy(self): - self.load(find_proxy_bitfile("bscan_spi_xcku040.bit"), pld=1) - - def start(self): - add_commands(self._script, "xcu_program xcu.tap") - - -class ProgrammerAMC(Programmer): - _sector_size = 0x10000 - - def __init__(self, client, preinit_script): - Programmer.__init__(self, client, preinit_script) - - add_commands(self._board_script, - "source {}".format(self._transfer_script("fpga/xilinx-xadc.cfg")), - - "interface ftdi", - "ftdi_device_desc \"Quad RS232-HS\"", - "ftdi_vid_pid 0x0403 0x6011", - "ftdi_channel 0", - # EN_USB_JTAG on ADBUS7: out, high - # nTRST on ADBUS4: out, high, but R46 is DNP - "ftdi_layout_init 0x0098 0x008b", - "reset_config none", - "adapter_khz 5000", - "transport select jtag", - "set CHIP XCKU040", - "source {}".format(self._transfer_script("cpld/xilinx-xcu.cfg"))) - self.add_flash_bank("spi0", "xcu", index=0) - self.add_flash_bank("spi1", "xcu", index=1) - - add_commands(self._script, "echo \"AMC FPGA XADC:\"", "xadc_report xcu.tap") - - def load_proxy(self): - self.load(find_proxy_bitfile("bscan_spi_xcku040.bit"), pld=0) - - def start(self): - add_commands(self._script, "xcu_program xcu.tap") - - def main(): args = get_argparser().parse_args() common_args.init_logger_from_args(args) @@ -316,21 +242,6 @@ def main(): "storage": ("spi0", 0x440000), "firmware": ("spi0", 0x450000), }, - "sayma": { - "programmer": ProgrammerAMCRTM, - "gateware": ("spi0", 0x000000), - "bootloader": ("spi1", 0x000000), - "storage": ("spi1", 0x040000), - "firmware": ("spi1", 0x050000), - "rtm_gateware": ("spi1", 0x200000), - }, - "metlino": { - "programmer": ProgrammerAMC, - "gateware": ("spi0", 0x000000), - "bootloader": ("spi1", 0x000000), - "storage": ("spi1", 0x040000), - "firmware": ("spi1", 0x050000), - }, "kc705": { "programmer": partial(ProgrammerXC7, board="kc705", proxy="bscan_spi_xc7k325t.bit"), "gateware": ("spi0", 0x000000), @@ -341,32 +252,21 @@ def main(): }[args.target] if not args.action: - if args.target == "sayma": - args.action = "gateware rtm_gateware bootloader firmware start".split() - else: - args.action = "gateware bootloader firmware start".split() + args.action = "gateware bootloader firmware start".split() needs_artifacts = any( action in args.action - for action in ["gateware", "rtm_gateware", "bootloader", "firmware", "load", "rtm_load"]) + for action in ["gateware", "bootloader", "firmware", "load"]) if needs_artifacts and args.dir is None: raise ValueError("the directory containing the binaries need to be specified using -d.") binary_dir = args.dir - if binary_dir is not None: - rtm_binary_dir = os.path.join(binary_dir, "rtm") - else: - rtm_binary_dir = None if args.host is None: client = LocalClient() else: client = SSHClient(args.host, args.jump) - if args.target == "sayma" and args.no_rtm_jtag: - programmer_cls = ProgrammerAMC - else: - programmer_cls = config["programmer"] - programmer = programmer_cls(client, preinit_script=args.preinit_command) + programmer = config["programmer"](client, preinit_script=args.preinit_command) def artifact_path(this_binary_dir, *path_filename): if args.srcbuild: @@ -377,7 +277,7 @@ def main(): *_, filename = path_filename return os.path.join(this_binary_dir, filename) - def convert_gateware(bit_filename, header=False): + def convert_gateware(bit_filename): bin_handle, bin_filename = tempfile.mkstemp( prefix="artiq_", suffix="_" + os.path.basename(bit_filename)) with open(bit_filename, "rb") as bit_file, \ @@ -385,12 +285,6 @@ def main(): if header: bin_file.write(b"\x00"*8) bit2bin(bit_file, bin_file) - if header: - magic = 0x5352544d # "SRTM", see sayma_rtm target - length = bin_file.tell() - 8 - bin_file.seek(0) - bin_file.write(magic.to_bytes(4, byteorder="little")) - bin_file.write(length.to_bytes(4, byteorder="little")) atexit.register(lambda: os.unlink(bin_filename)) return bin_filename @@ -399,11 +293,6 @@ def main(): gateware_bin = convert_gateware( artifact_path(binary_dir, "gateware", "top.bit")) programmer.write_binary(*config["gateware"], gateware_bin) - elif action == "rtm_gateware": - rtm_gateware_bin = convert_gateware( - artifact_path(rtm_binary_dir, "gateware", "top.bit"), header=True) - programmer.write_binary(*config["rtm_gateware"], - rtm_gateware_bin) elif action == "bootloader": bootloader_bin = artifact_path(binary_dir, "software", "bootloader", "bootloader.bin") programmer.write_binary(*config["bootloader"], bootloader_bin) @@ -423,23 +312,12 @@ def main(): "Found firmware files: {}".format(" ".join(firmware_fbis))) programmer.write_binary(*config["firmware"], firmware_fbis[0]) elif action == "load": - if args.target == "sayma": - gateware_bit = artifact_path(binary_dir, "gateware", "top.bit") - programmer.load(gateware_bit, 1) - else: - gateware_bit = artifact_path(binary_dir, "gateware", "top.bit") - programmer.load(gateware_bit, 0) - elif action == "rtm_load": - rtm_gateware_bit = artifact_path(rtm_binary_dir, "gateware", "top.bit") - programmer.load(rtm_gateware_bit, 0) + gateware_bit = artifact_path(binary_dir, "gateware", "top.bit") + programmer.load(gateware_bit, 0) elif action == "start": programmer.start() elif action == "erase": - if args.target == "sayma" or args.target == "metlino": - programmer.erase_flash("spi0") - programmer.erase_flash("spi1") - else: - programmer.erase_flash("spi0") + programmer.erase_flash("spi0") else: raise ValueError("invalid action", action) diff --git a/artiq/gateware/drtio/transceiver/gth_ultrascale.py b/artiq/gateware/drtio/transceiver/gth_ultrascale.py deleted file mode 100644 index ddc88037a..000000000 --- a/artiq/gateware/drtio/transceiver/gth_ultrascale.py +++ /dev/null @@ -1,704 +0,0 @@ -from functools import reduce -from operator import or_, and_ - -from migen import * -from migen.genlib.resetsync import AsyncResetSynchronizer - -from misoc.cores.code_8b10b import Encoder, Decoder - -from microscope import * - -from artiq.gateware.drtio.core import TransceiverInterface, ChannelInterface -from artiq.gateware.drtio.transceiver.clock_aligner import BruteforceClockAligner -from artiq.gateware.drtio.transceiver.gth_ultrascale_init import * - - -class GTHSingle(Module): - def __init__(self, refclk, pads, sys_clk_freq, rtio_clk_freq, rtiox_mul, dw, mode): - assert (dw == 20) or (dw == 40) - assert mode in ["single", "master", "slave"] - self.mode = mode - - # phase alignment - self.txsyncallin = Signal() - self.txphaligndone = Signal() - self.txsyncallin = Signal() - self.txsyncin = Signal() - self.txsyncout = Signal() - self.txdlysreset = Signal() - - # # # - - self.txenable = Signal() - nwords = dw//10 - self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")( - Encoder(nwords, True)) - self.submodules.decoders = decoders = [ClockDomainsRenamer("rtio_rx")( - (Decoder(True))) for _ in range(nwords)] - self.rx_ready = Signal() - - # transceiver direct clock outputs - # for OBUFDS_GTE3 - self.rxrecclkout = Signal() - # useful to specify clock constraints in a way palatable to Vivado - self.txoutclk = Signal() - self.rxoutclk = Signal() - - # # # - - # TX generates RTIO clock, init must be in system domain - self.submodules.tx_init = tx_init = GTHInit(sys_clk_freq, False, mode) - # RX receives restart commands from RTIO domain - rx_init = ClockDomainsRenamer("rtio_tx")(GTHInit(rtio_clk_freq, True)) - self.submodules += rx_init - - cpll_reset = Signal() - cpll_lock = Signal() - self.comb += [ - cpll_reset.eq(tx_init.pllreset), - tx_init.plllock.eq(cpll_lock), - rx_init.plllock.eq(cpll_lock) - ] - - txdata = Signal(dw) - rxdata = Signal(dw) - rxphaligndone = Signal() - gth_params = dict( - p_ACJTAG_DEBUG_MODE =0b0, - p_ACJTAG_MODE =0b0, - p_ACJTAG_RESET =0b0, - p_ADAPT_CFG0 =0b1111100000000000, - p_ADAPT_CFG1 =0b0000000000000000, - p_ALIGN_COMMA_DOUBLE ="FALSE", - p_ALIGN_COMMA_ENABLE =0b0000000000, - p_ALIGN_COMMA_WORD =1, - p_ALIGN_MCOMMA_DET ="FALSE", - p_ALIGN_MCOMMA_VALUE =0b1010000011, - p_ALIGN_PCOMMA_DET ="FALSE", - p_ALIGN_PCOMMA_VALUE =0b0101111100, - p_A_RXOSCALRESET =0b0, - p_A_RXPROGDIVRESET =0b0, - p_A_TXPROGDIVRESET =0b0, - p_CBCC_DATA_SOURCE_SEL ="ENCODED", - p_CDR_SWAP_MODE_EN =0b0, - p_CHAN_BOND_KEEP_ALIGN ="FALSE", - p_CHAN_BOND_MAX_SKEW =1, - p_CHAN_BOND_SEQ_1_1 =0b0000000000, - p_CHAN_BOND_SEQ_1_2 =0b0000000000, - p_CHAN_BOND_SEQ_1_3 =0b0000000000, - p_CHAN_BOND_SEQ_1_4 =0b0000000000, - p_CHAN_BOND_SEQ_1_ENABLE =0b1111, - p_CHAN_BOND_SEQ_2_1 =0b0000000000, - p_CHAN_BOND_SEQ_2_2 =0b0000000000, - p_CHAN_BOND_SEQ_2_3 =0b0000000000, - p_CHAN_BOND_SEQ_2_4 =0b0000000000, - p_CHAN_BOND_SEQ_2_ENABLE =0b1111, - p_CHAN_BOND_SEQ_2_USE ="FALSE", - p_CHAN_BOND_SEQ_LEN =1, - p_CLK_CORRECT_USE ="FALSE", - p_CLK_COR_KEEP_IDLE ="FALSE", - p_CLK_COR_MAX_LAT =20, - p_CLK_COR_MIN_LAT =18, - p_CLK_COR_PRECEDENCE ="TRUE", - p_CLK_COR_REPEAT_WAIT =0, - p_CLK_COR_SEQ_1_1 =0b0000000000, - p_CLK_COR_SEQ_1_2 =0b0000000000, - p_CLK_COR_SEQ_1_3 =0b0000000000, - p_CLK_COR_SEQ_1_4 =0b0000000000, - p_CLK_COR_SEQ_1_ENABLE =0b1111, - p_CLK_COR_SEQ_2_1 =0b0000000000, - p_CLK_COR_SEQ_2_2 =0b0000000000, - p_CLK_COR_SEQ_2_3 =0b0000000000, - p_CLK_COR_SEQ_2_4 =0b0000000000, - p_CLK_COR_SEQ_2_ENABLE =0b1111, - p_CLK_COR_SEQ_2_USE ="FALSE", - p_CLK_COR_SEQ_LEN =1, - p_CPLL_CFG0 =0b0110011111111000, - p_CPLL_CFG1 =0b1010010010101100, - p_CPLL_CFG2 =0b0000000000000111, - p_CPLL_CFG3 =0b000000, - p_CPLL_FBDIV =5, - p_CPLL_FBDIV_45 =4, - p_CPLL_INIT_CFG0 =0b0000001010110010, - p_CPLL_INIT_CFG1 =0b00000000, - p_CPLL_LOCK_CFG =0b0000000111101000, - p_CPLL_REFCLK_DIV =1, - p_DDI_CTRL =0b00, - p_DDI_REALIGN_WAIT =15, - p_DEC_MCOMMA_DETECT ="FALSE", - p_DEC_PCOMMA_DETECT ="FALSE", - p_DEC_VALID_COMMA_ONLY ="FALSE", - p_DFE_D_X_REL_POS =0b0, - p_DFE_VCM_COMP_EN =0b0, - p_DMONITOR_CFG0 =0b0000000000, - p_DMONITOR_CFG1 =0b00000000, - p_ES_CLK_PHASE_SEL =0b0, - p_ES_CONTROL =0b000000, - p_ES_ERRDET_EN ="FALSE", - p_ES_EYE_SCAN_EN ="FALSE", - p_ES_HORZ_OFFSET =0b000000000000, - p_ES_PMA_CFG =0b0000000000, - p_ES_PRESCALE =0b00000, - p_ES_QUALIFIER0 =0b0000000000000000, - p_ES_QUALIFIER1 =0b0000000000000000, - p_ES_QUALIFIER2 =0b0000000000000000, - p_ES_QUALIFIER3 =0b0000000000000000, - p_ES_QUALIFIER4 =0b0000000000000000, - p_ES_QUAL_MASK0 =0b0000000000000000, - p_ES_QUAL_MASK1 =0b0000000000000000, - p_ES_QUAL_MASK2 =0b0000000000000000, - p_ES_QUAL_MASK3 =0b0000000000000000, - p_ES_QUAL_MASK4 =0b0000000000000000, - p_ES_SDATA_MASK0 =0b0000000000000000, - p_ES_SDATA_MASK1 =0b0000000000000000, - p_ES_SDATA_MASK2 =0b0000000000000000, - p_ES_SDATA_MASK3 =0b0000000000000000, - p_ES_SDATA_MASK4 =0b0000000000000000, - p_EVODD_PHI_CFG =0b00000000000, - p_EYE_SCAN_SWAP_EN =0b0, - p_FTS_DESKEW_SEQ_ENABLE =0b1111, - p_FTS_LANE_DESKEW_CFG =0b1111, - p_FTS_LANE_DESKEW_EN ="FALSE", - p_GEARBOX_MODE =0b00000, - p_GM_BIAS_SELECT =0b0, - p_LOCAL_MASTER =0b1, - p_OOBDIVCTL =0b00, - p_OOB_PWRUP =0b0, - p_PCI3_AUTO_REALIGN ="OVR_1K_BLK", - p_PCI3_PIPE_RX_ELECIDLE =0b0, - p_PCI3_RX_ASYNC_EBUF_BYPASS =0b00, - p_PCI3_RX_ELECIDLE_EI2_ENABLE =0b0, - p_PCI3_RX_ELECIDLE_H2L_COUNT =0b000000, - p_PCI3_RX_ELECIDLE_H2L_DISABLE =0b000, - p_PCI3_RX_ELECIDLE_HI_COUNT =0b000000, - p_PCI3_RX_ELECIDLE_LP4_DISABLE =0b0, - p_PCI3_RX_FIFO_DISABLE =0b0, - p_PCIE_BUFG_DIV_CTRL =0b0001000000000000, - p_PCIE_RXPCS_CFG_GEN3 =0b0000001010100100, - p_PCIE_RXPMA_CFG =0b0000000000001010, - p_PCIE_TXPCS_CFG_GEN3 =0b0010010010100100, - p_PCIE_TXPMA_CFG =0b0000000000001010, - p_PCS_PCIE_EN ="FALSE", - p_PCS_RSVD0 =0b0000000000000000, - p_PCS_RSVD1 =0b000, - p_PD_TRANS_TIME_FROM_P2 =0b000000111100, - p_PD_TRANS_TIME_NONE_P2 =0b00011001, - p_PD_TRANS_TIME_TO_P2 =0b01100100, - p_PLL_SEL_MODE_GEN12 =0b00, - p_PLL_SEL_MODE_GEN3 =0b11, - p_PMA_RSV1 =0b1111000000000000, - p_PROCESS_PAR =0b010, - p_RATE_SW_USE_DRP =0b1, - p_RESET_POWERSAVE_DISABLE =0b0, - ) - gth_params.update( - p_RXBUFRESET_TIME =0b00011, - p_RXBUF_ADDR_MODE ="FAST", - p_RXBUF_EIDLE_HI_CNT =0b1000, - p_RXBUF_EIDLE_LO_CNT =0b0000, - p_RXBUF_EN ="FALSE", - p_RXBUF_RESET_ON_CB_CHANGE ="TRUE", - p_RXBUF_RESET_ON_COMMAALIGN ="FALSE", - p_RXBUF_RESET_ON_EIDLE ="FALSE", - p_RXBUF_RESET_ON_RATE_CHANGE ="TRUE", - p_RXBUF_THRESH_OVFLW =0, - p_RXBUF_THRESH_OVRD ="FALSE", - p_RXBUF_THRESH_UNDFLW =0, - p_RXCDRFREQRESET_TIME =0b00001, - p_RXCDRPHRESET_TIME =0b00001, - p_RXCDR_CFG0 =0b0000000000000000, - p_RXCDR_CFG0_GEN3 =0b0000000000000000, - p_RXCDR_CFG1 =0b0000000000000000, - p_RXCDR_CFG1_GEN3 =0b0000000000000000, - p_RXCDR_CFG2 =0b0000011111010110, - p_RXCDR_CFG2_GEN3 =0b0000011111100110, - p_RXCDR_CFG3 =0b0000000000000000, - p_RXCDR_CFG3_GEN3 =0b0000000000000000, - p_RXCDR_CFG4 =0b0000000000000000, - p_RXCDR_CFG4_GEN3 =0b0000000000000000, - p_RXCDR_CFG5 =0b0000000000000000, - p_RXCDR_CFG5_GEN3 =0b0000000000000000, - p_RXCDR_FR_RESET_ON_EIDLE =0b0, - p_RXCDR_HOLD_DURING_EIDLE =0b0, - p_RXCDR_LOCK_CFG0 =0b0100010010000000, - p_RXCDR_LOCK_CFG1 =0b0101111111111111, - p_RXCDR_LOCK_CFG2 =0b0111011111000011, - p_RXCDR_PH_RESET_ON_EIDLE =0b0, - p_RXCFOK_CFG0 =0b0100000000000000, - p_RXCFOK_CFG1 =0b0000000001100101, - p_RXCFOK_CFG2 =0b0000000000101110, - p_RXDFELPMRESET_TIME =0b0001111, - p_RXDFELPM_KL_CFG0 =0b0000000000000000, - p_RXDFELPM_KL_CFG1 =0b0000000000000010, - p_RXDFELPM_KL_CFG2 =0b0000000000000000, - p_RXDFE_CFG0 =0b0000101000000000, - p_RXDFE_CFG1 =0b0000000000000000, - p_RXDFE_GC_CFG0 =0b0000000000000000, - p_RXDFE_GC_CFG1 =0b0111100001110000, - p_RXDFE_GC_CFG2 =0b0000000000000000, - p_RXDFE_H2_CFG0 =0b0000000000000000, - p_RXDFE_H2_CFG1 =0b0000000000000000, - p_RXDFE_H3_CFG0 =0b0100000000000000, - p_RXDFE_H3_CFG1 =0b0000000000000000, - p_RXDFE_H4_CFG0 =0b0010000000000000, - p_RXDFE_H4_CFG1 =0b0000000000000011, - p_RXDFE_H5_CFG0 =0b0010000000000000, - p_RXDFE_H5_CFG1 =0b0000000000000011, - p_RXDFE_H6_CFG0 =0b0010000000000000, - p_RXDFE_H6_CFG1 =0b0000000000000000, - p_RXDFE_H7_CFG0 =0b0010000000000000, - p_RXDFE_H7_CFG1 =0b0000000000000000, - p_RXDFE_H8_CFG0 =0b0010000000000000, - p_RXDFE_H8_CFG1 =0b0000000000000000, - p_RXDFE_H9_CFG0 =0b0010000000000000, - p_RXDFE_H9_CFG1 =0b0000000000000000, - p_RXDFE_HA_CFG0 =0b0010000000000000, - p_RXDFE_HA_CFG1 =0b0000000000000000, - p_RXDFE_HB_CFG0 =0b0010000000000000, - p_RXDFE_HB_CFG1 =0b0000000000000000, - p_RXDFE_HC_CFG0 =0b0000000000000000, - p_RXDFE_HC_CFG1 =0b0000000000000000, - p_RXDFE_HD_CFG0 =0b0000000000000000, - p_RXDFE_HD_CFG1 =0b0000000000000000, - p_RXDFE_HE_CFG0 =0b0000000000000000, - p_RXDFE_HE_CFG1 =0b0000000000000000, - p_RXDFE_HF_CFG0 =0b0000000000000000, - p_RXDFE_HF_CFG1 =0b0000000000000000, - p_RXDFE_OS_CFG0 =0b1000000000000000, - p_RXDFE_OS_CFG1 =0b0000000000000000, - p_RXDFE_UT_CFG0 =0b1000000000000000, - p_RXDFE_UT_CFG1 =0b0000000000000011, - p_RXDFE_VP_CFG0 =0b1010101000000000, - p_RXDFE_VP_CFG1 =0b0000000000110011, - p_RXDLY_CFG =0b0000000000011111, - p_RXDLY_LCFG =0b0000000000110000, - p_RXELECIDLE_CFG ="SIGCFG_4", - p_RXGBOX_FIFO_INIT_RD_ADDR =4, - p_RXGEARBOX_EN ="FALSE", - p_RXISCANRESET_TIME =0b00001, - p_RXLPM_CFG =0b0000000000000000, - p_RXLPM_GC_CFG =0b0001000000000000, - p_RXLPM_KH_CFG0 =0b0000000000000000, - p_RXLPM_KH_CFG1 =0b0000000000000010, - p_RXLPM_OS_CFG0 =0b1000000000000000, - p_RXLPM_OS_CFG1 =0b0000000000000010, - p_RXOOB_CFG =0b000000110, - p_RXOOB_CLK_CFG ="PMA", - p_RXOSCALRESET_TIME =0b00011, - p_RXOUT_DIV =2, - p_RXPCSRESET_TIME =0b00011, - p_RXPHBEACON_CFG =0b0000000000000000, - p_RXPHDLY_CFG =0b0010000000100000, - p_RXPHSAMP_CFG =0b0010000100000000, - p_RXPHSLIP_CFG =0b0110011000100010, - p_RXPH_MONITOR_SEL =0b00000, - p_RXPI_CFG0 =0b00, - p_RXPI_CFG1 =0b00, - p_RXPI_CFG2 =0b00, - p_RXPI_CFG3 =0b00, - p_RXPI_CFG4 =0b1, - p_RXPI_CFG5 =0b1, - p_RXPI_CFG6 =0b000, - p_RXPI_LPM =0b0, - p_RXPI_VREFSEL =0b0, - p_RXPMACLK_SEL ="DATA", - p_RXPMARESET_TIME =0b00011, - p_RXPRBS_ERR_LOOPBACK =0b0, - p_RXPRBS_LINKACQ_CNT =15, - p_RXSLIDE_AUTO_WAIT =7, - p_RXSLIDE_MODE ="OFF", - p_RXSYNC_MULTILANE =0b0, - p_RXSYNC_OVRD =0b0, - p_RXSYNC_SKIP_DA =0b0, - p_RX_AFE_CM_EN =0b0, - p_RX_BIAS_CFG0 =0b0000101010110100, - p_RX_BUFFER_CFG =0b000000, - p_RX_CAPFF_SARC_ENB =0b0, - p_RX_CLK25_DIV =6, - p_RX_CLKMUX_EN =0b1, - p_RX_CLK_SLIP_OVRD =0b00000, - p_RX_CM_BUF_CFG =0b1010, - p_RX_CM_BUF_PD =0b0, - p_RX_CM_SEL =0b11, - p_RX_CM_TRIM =0b1010, - p_RX_CTLE3_LPF =0b00000001, - p_RX_DATA_WIDTH =dw, - p_RX_DDI_SEL =0b000000, - p_RX_DEFER_RESET_BUF_EN ="TRUE", - p_RX_DFELPM_CFG0 =0b0110, - p_RX_DFELPM_CFG1 =0b1, - p_RX_DFELPM_KLKH_AGC_STUP_EN =0b1, - p_RX_DFE_AGC_CFG0 =0b10, - p_RX_DFE_AGC_CFG1 =0b100, - p_RX_DFE_KL_LPM_KH_CFG0 =0b01, - p_RX_DFE_KL_LPM_KH_CFG1 =0b100, - p_RX_DFE_KL_LPM_KL_CFG0 =0b01, - p_RX_DFE_KL_LPM_KL_CFG1 =0b100, - p_RX_DFE_LPM_HOLD_DURING_EIDLE =0b0, - p_RX_DISPERR_SEQ_MATCH ="TRUE", - p_RX_DIVRESET_TIME =0b00001, - p_RX_EN_HI_LR =0b0, - p_RX_EYESCAN_VS_CODE =0b0000000, - p_RX_EYESCAN_VS_NEG_DIR =0b0, - p_RX_EYESCAN_VS_RANGE =0b00, - p_RX_EYESCAN_VS_UT_SIGN =0b0, - p_RX_FABINT_USRCLK_FLOP =0b0, - p_RX_INT_DATAWIDTH =dw==40, - p_RX_PMA_POWER_SAVE =0b0, - p_RX_PROGDIV_CFG =0.0, - p_RX_SAMPLE_PERIOD =0b111, - p_RX_SIG_VALID_DLY =11, - p_RX_SUM_DFETAPREP_EN =0b0, - p_RX_SUM_IREF_TUNE =0b0000, - p_RX_SUM_RES_CTRL =0b00, - p_RX_SUM_VCMTUNE =0b0000, - p_RX_SUM_VCM_OVWR =0b0, - p_RX_SUM_VREF_TUNE =0b000, - p_RX_TUNE_AFE_OS =0b10, - p_RX_WIDEMODE_CDR =0b0, - p_RX_XCLK_SEL ="RXUSR", - p_SAS_MAX_COM =64, - p_SAS_MIN_COM =36, - p_SATA_BURST_SEQ_LEN =0b1110, - p_SATA_CPLL_CFG ="VCO_3000MHZ", - p_SATA_MAX_BURST =8, - p_SATA_MAX_INIT =21, - p_SATA_MAX_WAKE =7, - p_SATA_MIN_BURST =4, - p_SATA_MIN_INIT =12, - p_SATA_MIN_WAKE =4, - p_SHOW_REALIGN_COMMA ="TRUE", - p_SIM_RECEIVER_DETECT_PASS ="TRUE", - p_SIM_RESET_SPEEDUP ="TRUE", - p_SIM_TX_EIDLE_DRIVE_LEVEL =0b0, - p_SIM_VERSION =2, - p_TAPDLY_SET_TX =0b00, - p_TEMPERATUR_PAR =0b0010, - p_TERM_RCAL_CFG =0b100001000010000, - p_TERM_RCAL_OVRD =0b000, - p_TRANS_TIME_RATE =0b00001110, - p_TST_RSV0 =0b00000000, - p_TST_RSV1 =0b00000000, - ) - gth_params.update( - p_TXBUF_EN ="FALSE", - p_TXBUF_RESET_ON_RATE_CHANGE ="TRUE", - p_TXDLY_CFG =0b0000000000001001, - p_TXDLY_LCFG =0b0000000001010000, - p_TXDRVBIAS_N =0b1010, - p_TXDRVBIAS_P =0b1010, - p_TXFIFO_ADDR_CFG ="LOW", - p_TXGBOX_FIFO_INIT_RD_ADDR =4, - p_TXGEARBOX_EN ="FALSE", - p_TXOUT_DIV =2, - p_TXPCSRESET_TIME =0b00011, - p_TXPHDLY_CFG0 =0b0010000000100000, - p_TXPHDLY_CFG1 =0b0000000001110101, - p_TXPH_CFG =0b0000100110000000, - p_TXPH_MONITOR_SEL =0b00000, - p_TXPI_CFG0 =0b00, - p_TXPI_CFG1 =0b00, - p_TXPI_CFG2 =0b00, - p_TXPI_CFG3 =0b1, - p_TXPI_CFG4 =0b1, - p_TXPI_CFG5 =0b000, - p_TXPI_GRAY_SEL =0b0, - p_TXPI_INVSTROBE_SEL =0b0, - p_TXPI_LPM =0b0, - p_TXPI_PPMCLK_SEL ="TXUSRCLK2", - p_TXPI_PPM_CFG =0b00000000, - p_TXPI_SYNFREQ_PPM =0b001, - p_TXPI_VREFSEL =0b0, - p_TXPMARESET_TIME =0b00011, - p_TXSYNC_MULTILANE =0 if mode == "single" else 1, - p_TXSYNC_OVRD =0b0, - p_TXSYNC_SKIP_DA =0b0, - p_TX_CLK25_DIV =6, - p_TX_CLKMUX_EN =0b1, - p_TX_DATA_WIDTH =dw, - p_TX_DCD_CFG =0b000010, - p_TX_DCD_EN =0b0, - p_TX_DEEMPH0 =0b000000, - p_TX_DEEMPH1 =0b000000, - p_TX_DIVRESET_TIME =0b00001, - p_TX_DRIVE_MODE ="DIRECT", - p_TX_EIDLE_ASSERT_DELAY =0b100, - p_TX_EIDLE_DEASSERT_DELAY =0b011, - p_TX_EML_PHI_TUNE =0b0, - p_TX_FABINT_USRCLK_FLOP =0b0, - p_TX_IDLE_DATA_ZERO =0b0, - p_TX_INT_DATAWIDTH =dw==40, - p_TX_LOOPBACK_DRIVE_HIZ ="FALSE", - p_TX_MAINCURSOR_SEL =0b0, - p_TX_MARGIN_FULL_0 =0b1001111, - p_TX_MARGIN_FULL_1 =0b1001110, - p_TX_MARGIN_FULL_2 =0b1001100, - p_TX_MARGIN_FULL_3 =0b1001010, - p_TX_MARGIN_FULL_4 =0b1001000, - p_TX_MARGIN_LOW_0 =0b1000110, - p_TX_MARGIN_LOW_1 =0b1000101, - p_TX_MARGIN_LOW_2 =0b1000011, - p_TX_MARGIN_LOW_3 =0b1000010, - p_TX_MARGIN_LOW_4 =0b1000000, - p_TX_MODE_SEL =0b000, - p_TX_PMADATA_OPT =0b0, - p_TX_PMA_POWER_SAVE =0b0, - p_TX_PROGCLK_SEL ="PREPI", - p_TX_PROGDIV_CFG =dw/rtiox_mul, - p_TX_QPI_STATUS_EN =0b0, - p_TX_RXDETECT_CFG =0b00000000110010, - p_TX_RXDETECT_REF =0b100, - p_TX_SAMPLE_PERIOD =0b111, - p_TX_SARC_LPBK_ENB =0b0, - p_TX_XCLK_SEL ="TXUSR", - p_USE_PCS_CLK_PHASE_SEL =0b0, - p_WB_MODE =0b00, - ) - gth_params.update( - # Reset modes - i_GTRESETSEL=0, - i_RESETOVRD=0, - - i_CPLLRESET=0, - i_CPLLPD=cpll_reset, - o_CPLLLOCK=cpll_lock, - i_CPLLLOCKEN=1, - i_CPLLREFCLKSEL=0b001, - i_TSTIN=2**20-1, - i_GTREFCLK0=refclk, - - # TX clock - o_TXOUTCLK=self.txoutclk, - i_TXSYSCLKSEL=0b00, - i_TXPLLCLKSEL=0b00, - i_TXOUTCLKSEL=0b101, - - # TX Startup/Reset - i_GTTXRESET=tx_init.gtXxreset, - o_TXRESETDONE=tx_init.Xxresetdone, - i_TXDLYSRESET=tx_init.Xxdlysreset if mode != "slave" else self.txdlysreset, - o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone, - o_TXPHALIGNDONE=tx_init.Xxphaligndone, - i_TXUSERRDY=tx_init.Xxuserrdy, - i_TXSYNCMODE=mode != "slave", - - i_TXSYNCALLIN=self.txsyncallin, - i_TXSYNCIN=self.txsyncin, - o_TXSYNCOUT=self.txsyncout, - - # TX data - i_TXINHIBIT=~self.txenable, - i_TXCTRL0=Cat(*[txdata[10*i+8] for i in range(nwords)]), - i_TXCTRL1=Cat(*[txdata[10*i+9] for i in range(nwords)]), - i_TXDATA=Cat(*[txdata[10*i:10*i+8] for i in range(nwords)]), - i_TXUSRCLK=ClockSignal("rtio_tx"), - i_TXUSRCLK2=ClockSignal("rtio_tx"), - - # TX electrical - i_TXPD=0b00, - i_TXBUFDIFFCTRL=0b000, - i_TXDIFFCTRL=0b1100, - - # RX Startup/Reset - i_GTRXRESET=rx_init.gtXxreset, - o_RXRESETDONE=rx_init.Xxresetdone, - i_RXDLYSRESET=rx_init.Xxdlysreset, - o_RXPHALIGNDONE=rxphaligndone, - i_RXSYNCALLIN=rxphaligndone, - i_RXUSERRDY=rx_init.Xxuserrdy, - i_RXSYNCIN=0, - i_RXSYNCMODE=1, - o_RXSYNCDONE=rx_init.Xxsyncdone, - - # RX AFE - i_RXDFEAGCCTRL=1, - i_RXDFEXYDEN=1, - i_RXLPMEN=1, - i_RXOSINTCFG=0xd, - i_RXOSINTEN=1, - - # RX clock - i_RXRATE=0, - i_RXDLYBYPASS=0, - i_RXSYSCLKSEL=0b00, - i_RXOUTCLKSEL=0b010, - i_RXPLLCLKSEL=0b00, - o_RXRECCLKOUT=self.rxrecclkout, - o_RXOUTCLK=self.rxoutclk, - i_RXUSRCLK=ClockSignal("rtio_rx"), - i_RXUSRCLK2=ClockSignal("rtio_rx"), - - # RX data - o_RXCTRL0=Cat(*[rxdata[10*i+8] for i in range(nwords)]), - o_RXCTRL1=Cat(*[rxdata[10*i+9] for i in range(nwords)]), - o_RXDATA=Cat(*[rxdata[10*i:10*i+8] for i in range(nwords)]), - - # RX electrical - i_RXPD=Replicate(rx_init.restart, 2), - i_RXELECIDLEMODE=0b11, - - # Pads - i_GTHRXP=pads.rxp, - i_GTHRXN=pads.rxn, - o_GTHTXP=pads.txp, - o_GTHTXN=pads.txn - ) - self.specials += Instance("GTHE3_CHANNEL", **gth_params) - self.comb += self.txphaligndone.eq(tx_init.Xxphaligndone) - - self.submodules += [ - add_probe_async("drtio_gth", "cpll_lock", cpll_lock), - add_probe_async("drtio_gth", "txuserrdy", tx_init.Xxuserrdy), - add_probe_async("drtio_gth", "tx_init_done", tx_init.done), - add_probe_async("drtio_gth", "rxuserrdy", rx_init.Xxuserrdy), - add_probe_async("drtio_gth", "rx_init_done", rx_init.done), - add_probe_buffer("drtio_gth", "txdata", txdata, clock_domain="rtio_tx"), - add_probe_buffer("drtio_gth", "rxdata", rxdata, clock_domain="rtio_rx") - ] - - # tx clocking - tx_reset_deglitched = Signal() - tx_reset_deglitched.attr.add("no_retiming") - self.sync += tx_reset_deglitched.eq(~tx_init.done) - self.clock_domains.cd_rtio_tx = ClockDomain() - self.clock_domains.cd_rtiox_tx = ClockDomain() - if mode == "master" or mode == "single": - self.specials += [ - Instance("BUFG_GT", i_I=self.txoutclk, o_O=self.cd_rtiox_tx.clk, i_DIV=0), - Instance("BUFG_GT", i_I=self.txoutclk, o_O=self.cd_rtio_tx.clk, i_DIV=rtiox_mul-1) - ] - self.specials += AsyncResetSynchronizer(self.cd_rtio_tx, tx_reset_deglitched) - - # rx clocking - rx_reset_deglitched = Signal() - rx_reset_deglitched.attr.add("no_retiming") - self.sync.rtio_tx += rx_reset_deglitched.eq(~rx_init.done) - self.clock_domains.cd_rtio_rx = ClockDomain() - self.specials += [ - Instance("BUFG_GT", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk), - AsyncResetSynchronizer(self.cd_rtio_rx, rx_reset_deglitched) - ] - - # tx data - self.comb += txdata.eq(Cat(*[encoder.output[i] for i in range(nwords)])) - - # rx data - for i in range(nwords): - self.comb += decoders[i].input.eq(rxdata[10*i:10*(i+1)]) - - # clock alignment - clock_aligner = BruteforceClockAligner(0b0101111100, rtio_clk_freq) - self.submodules += clock_aligner - self.comb += [ - clock_aligner.rxdata.eq(rxdata), - rx_init.restart.eq(clock_aligner.restart), - self.rx_ready.eq(clock_aligner.ready) - ] - self.submodules += add_probe_async("drtio_gth", "clock_aligner_ready", clock_aligner.ready) - - -class GTHTXPhaseAlignement(Module): - # TX Buffer Bypass in Single-Lane/Multi-Lane Auto Mode (ug576) - def __init__(self, gths): - txsyncallin = Signal() - txsync = Signal() - txphaligndone = Signal(len(gths)) - txdlysreset = Signal() - ready_for_align = Signal(len(gths)) - all_ready_for_align = Signal() - - for i, gth in enumerate(gths): - # Common to all transceivers - self.comb += [ - ready_for_align[i].eq(1), - gth.txsyncin.eq(txsync), - gth.txsyncallin.eq(txsyncallin), - txphaligndone[i].eq(gth.txphaligndone) - ] - # Specific to Master or Single transceivers - if gth.mode == "master" or gth.mode == "single": - self.comb += [ - gth.tx_init.all_ready_for_align.eq(all_ready_for_align), - txsync.eq(gth.txsyncout), - txdlysreset.eq(gth.tx_init.Xxdlysreset) - ] - # Specific to Slave transceivers - else: - self.comb += [ - ready_for_align[i].eq(gth.tx_init.ready_for_align), - gth.txdlysreset.eq(txdlysreset), - ] - - self.comb += [ - txsyncallin.eq(reduce(and_, [txphaligndone[i] for i in range(len(gths))])), - all_ready_for_align.eq(reduce(and_, [ready_for_align[i] for i in range(len(gths))])) - ] - - -class GTH(Module, TransceiverInterface): - def __init__(self, clock_pads, data_pads, sys_clk_freq, rtio_clk_freq, rtiox_mul=2, dw=20, master=0, clock_recout_pads=None): - self.nchannels = nchannels = len(data_pads) - self.gths = [] - - # # # - - create_buf = hasattr(clock_pads, "p") - if create_buf: - refclk = Signal() - ibufds_ceb = Signal() - self.specials += Instance("IBUFDS_GTE3", - i_CEB=ibufds_ceb, - i_I=clock_pads.p, - i_IB=clock_pads.n, - o_O=refclk) - else: - refclk = clock_pads - - rtio_tx_clk = Signal() - channel_interfaces = [] - for i in range(nchannels): - if nchannels == 1: - mode = "single" - else: - mode = "master" if i == master else "slave" - gth = GTHSingle(refclk, data_pads[i], sys_clk_freq, rtio_clk_freq, rtiox_mul, dw, mode) - if mode == "master": - self.comb += rtio_tx_clk.eq(gth.cd_rtio_tx.clk) - elif mode == "slave": - self.comb += gth.cd_rtio_tx.clk.eq(rtio_tx_clk) - self.gths.append(gth) - setattr(self.submodules, "gth"+str(i), gth) - channel_interface = ChannelInterface(gth.encoder, gth.decoders) - self.comb += channel_interface.rx_ready.eq(gth.rx_ready) - channel_interfaces.append(channel_interface) - - self.submodules.tx_phase_alignment = GTHTXPhaseAlignement(self.gths) - - TransceiverInterface.__init__(self, channel_interfaces) - for n, gth in enumerate(self.gths): - self.comb += gth.txenable.eq(self.txenable.storage[n]) - self.clock_domains.cd_rtiox = ClockDomain(reset_less=True) - if create_buf: - # GTH PLLs recover on their own from an interrupted clock input, - # but be paranoid about HMC7043 noise. - self.stable_clkin.storage.attr.add("no_retiming") - self.comb += ibufds_ceb.eq(~self.stable_clkin.storage) - - self.comb += [ - self.cd_rtio.clk.eq(self.gths[master].cd_rtio_tx.clk), - self.cd_rtiox.clk.eq(self.gths[master].cd_rtiox_tx.clk), - self.cd_rtio.rst.eq(reduce(or_, [gth.cd_rtio_tx.rst for gth in self.gths])) - ] - for i in range(nchannels): - self.comb += [ - getattr(self, "cd_rtio_rx" + str(i)).clk.eq(self.gths[i].cd_rtio_rx.clk), - getattr(self, "cd_rtio_rx" + str(i)).rst.eq(self.gths[i].cd_rtio_rx.rst) - ] - - if clock_recout_pads is not None: - self.specials += Instance("OBUFDS_GTE3", - p_REFCLK_EN_TX_PATH=0b1, - p_REFCLK_ICNTL_TX=0b00111, - i_I=self.gths[0].rxrecclkout, - i_CEB=0, - o_O=clock_recout_pads.p, o_OB=clock_recout_pads.n) diff --git a/artiq/gateware/drtio/transceiver/gth_ultrascale_init.py b/artiq/gateware/drtio/transceiver/gth_ultrascale_init.py deleted file mode 100644 index 30645b876..000000000 --- a/artiq/gateware/drtio/transceiver/gth_ultrascale_init.py +++ /dev/null @@ -1,157 +0,0 @@ -from math import ceil - -from migen import * -from migen.genlib.cdc import MultiReg -from migen.genlib.misc import WaitTimer - - -__all__ = ["GTHInit"] - - -class GTHInit(Module): - def __init__(self, sys_clk_freq, rx, mode="master"): - assert not (rx and mode != "master") - self.done = Signal() - self.restart = Signal() - - # GTH signals - self.plllock = Signal() - self.pllreset = Signal() - self.gtXxreset = Signal() - self.Xxresetdone = Signal() - self.Xxdlysreset = Signal() - self.Xxdlysresetdone = Signal() - self.Xxphaligndone = Signal() - self.Xxsyncdone = Signal() - self.Xxuserrdy = Signal() - - self.all_ready_for_align = Signal(reset=1) - self.ready_for_align = Signal() - - # # # - - # Double-latch transceiver asynch outputs - plllock = Signal() - Xxresetdone = Signal() - Xxdlysresetdone = Signal() - Xxphaligndone = Signal() - Xxsyncdone = Signal() - self.specials += [ - MultiReg(self.plllock, plllock), - MultiReg(self.Xxresetdone, Xxresetdone), - MultiReg(self.Xxdlysresetdone, Xxdlysresetdone), - MultiReg(self.Xxphaligndone, Xxphaligndone), - MultiReg(self.Xxsyncdone, Xxsyncdone) - ] - - # Deglitch FSM outputs driving transceiver asynch inputs - gtXxreset = Signal() - Xxdlysreset = Signal() - Xxuserrdy = Signal() - self.sync += [ - self.gtXxreset.eq(gtXxreset), - self.Xxdlysreset.eq(Xxdlysreset), - self.Xxuserrdy.eq(Xxuserrdy) - ] - - # PLL reset must be at least 2us - pll_reset_cycles = ceil(2000*sys_clk_freq/1000000000) - pll_reset_timer = WaitTimer(pll_reset_cycles) - self.submodules += pll_reset_timer - - startup_fsm = ResetInserter()(FSM(reset_state="RESET_ALL")) - self.submodules += startup_fsm - - ready_timer = WaitTimer(int(sys_clk_freq/1000)) - self.submodules += ready_timer - self.comb += [ - ready_timer.wait.eq(~self.done & ~startup_fsm.reset), - startup_fsm.reset.eq(self.restart | ready_timer.done) - ] - - if rx: - cdr_stable_timer = WaitTimer(1024) - self.submodules += cdr_stable_timer - - Xxphaligndone_r = Signal(reset=1) - Xxphaligndone_rising = Signal() - self.sync += Xxphaligndone_r.eq(Xxphaligndone) - self.comb += Xxphaligndone_rising.eq(Xxphaligndone & ~Xxphaligndone_r) - - startup_fsm.act("RESET_ALL", - gtXxreset.eq(1), - self.pllreset.eq(1), - pll_reset_timer.wait.eq(1), - If(pll_reset_timer.done, - NextState("RELEASE_PLL_RESET") - ) - ) - startup_fsm.act("RELEASE_PLL_RESET", - gtXxreset.eq(1), - If(plllock, NextState("RELEASE_GTH_RESET")) - ) - # Release GTH reset and wait for GTH resetdone - # (from UG476, GTH is reset on falling edge - # of gtXxreset) - if rx: - startup_fsm.act("RELEASE_GTH_RESET", - Xxuserrdy.eq(1), - cdr_stable_timer.wait.eq(1), - If(Xxresetdone & cdr_stable_timer.done, NextState("ALIGN")) - ) - else: - startup_fsm.act("RELEASE_GTH_RESET", - Xxuserrdy.eq(1), - If(Xxresetdone, - If(mode == "slave", - NextState("WAIT_ALIGN") - ).Else( - NextState("ALIGN") - ) - ) - ) - # Start delay alignment (pulse) - startup_fsm.act("ALIGN", - Xxuserrdy.eq(1), - If(self.all_ready_for_align, - Xxdlysreset.eq(1), - NextState("WAIT_ALIGN") - ) - ) - if rx: - # Wait for delay alignment - startup_fsm.act("WAIT_ALIGN", - Xxuserrdy.eq(1), - If(Xxsyncdone, - NextState("READY") - ) - ) - else: - # Wait for delay alignment - startup_fsm.act("WAIT_ALIGN", - Xxuserrdy.eq(1), - self.ready_for_align.eq(1), - If(Xxdlysresetdone, - If(mode == "slave", - NextState("WAIT_LAST_ALIGN_DONE") - ).Else( - NextState("WAIT_FIRST_ALIGN_DONE") - ) - ) - ) - - # Wait 2 rising edges of Xxphaligndone - # (from UG576 in TX Buffer Bypass in Single-Lane Auto Mode) - startup_fsm.act("WAIT_FIRST_ALIGN_DONE", - Xxuserrdy.eq(1), - If(Xxphaligndone_rising, NextState("WAIT_LAST_ALIGN_DONE")) - ) - startup_fsm.act("WAIT_LAST_ALIGN_DONE", - Xxuserrdy.eq(1), - If(Xxphaligndone_rising, NextState("READY")) - ) - startup_fsm.act("READY", - Xxuserrdy.eq(1), - self.done.eq(1), - If(self.restart, NextState("RESET_ALL")) - ) diff --git a/artiq/gateware/dsp/__init__.py b/artiq/gateware/dsp/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/artiq/gateware/dsp/accu.py b/artiq/gateware/dsp/accu.py deleted file mode 100644 index 79e297883..000000000 --- a/artiq/gateware/dsp/accu.py +++ /dev/null @@ -1,112 +0,0 @@ -from migen import * -from misoc.interconnect.stream import Endpoint - - -class Accu(Module): - def __init__(self, width, meta=[]): - self.i = Endpoint([("p", width), ("f", width), ("clr", 1)]) - self.o = Endpoint([("z", width)]) - self.latency = 1 - - ### - - f = Signal.like(self.i.f) - p = Signal.like(self.i.p) - self.comb += self.i.ack.eq(~self.o.stb | self.o.ack) - self.sync += [ - If(self.o.ack, - self.o.stb.eq(0), - ), - If(self.i.ack, - self.o.stb.eq(1), - If(self.i.stb, - self.o.z.eq(self.i.p + Mux(self.i.clr, 0, self.o.z + p)), - f.eq(self.i.f), - p.eq(self.i.f - self.i.p), - ).Else( - self.o.z.eq(self.o.z + f), - ) - ) - ] - - -class MCM(Module): - def __init__(self, width, constants): - n = len(constants) - self.i = i = Signal(width) - self.o = o = [Signal.like(self.i) for i in range(n)] - - ### - - # TODO: improve MCM - assert range(n) == constants - assert n <= 9 - - if n > 0: - self.comb += o[0].eq(0) - if n > 1: - self.comb += o[1].eq(i) - if n > 2: - self.comb += o[2].eq(i << 1) - if n > 3: - self.comb += o[3].eq(i + (i << 1)) - if n > 4: - self.comb += o[4].eq(i << 2) - if n > 5: - self.comb += o[5].eq(i + (i << 2)) - if n > 6: - self.comb += o[6].eq(o[3] << 1) - if n > 7: - self.comb += o[7].eq((i << 3) - i) - if n > 8: - self.comb += o[8].eq(i << 3) - - -class PhasedAccu(Module): - def __init__(self, width, parallelism=8): - self.i = Endpoint([("p", width), ("f", width), ("clr", 1)]) - self.o = Endpoint([("z{}".format(i), width) for i in - range(parallelism)]) - self.parallelism = parallelism - self.latency = 2 - - ### - - a = MCM(width, range(parallelism + 1)) - self.submodules += a - z = [Signal(width, reset_less=True) for i in range(parallelism)] - o = self.o.payload.flatten() - load = Signal(reset_less=True) - clr = Signal(reset_less=True) - p = Signal.like(self.i.p) - f = Signal.like(self.i.f, reset_less=True) - fp = Signal.like(self.i.f) - self.comb += [ - self.i.ack.eq(self.o.ack), - a.i.eq(self.i.f), - ] - - self.sync += [ - If(self.o.ack, - self.o.stb.eq(0), - ), - If(~self.o.stb | self.o.ack, - self.o.stb.eq(1), - If(load, - load.eq(0), - [oi.eq(Mux(clr, 0, o[0] + fp) + zi) - for oi, zi in zip(o, z)], - fp.eq(f), - ).Else( - [oi.eq(oi + fp) for oi in o], - ), - ), - If(self.i.stb & self.i.ack, - [zi.eq(self.i.p - Mux(self.i.clr, 0, p) + aoi) - for zi, aoi in zip(z, a.o)], - clr.eq(self.i.clr), - p.eq(self.i.p), - f.eq(a.o[parallelism]), - load.eq(1), - ), - ] diff --git a/artiq/gateware/dsp/fir.py b/artiq/gateware/dsp/fir.py deleted file mode 100644 index 002487e32..000000000 --- a/artiq/gateware/dsp/fir.py +++ /dev/null @@ -1,172 +0,0 @@ -from math import floor -from operator import add -from functools import reduce -from collections import namedtuple - -import numpy as np - -from migen import * - - -def halfgen4(width, n, df=1e-3): - """ - http://recycle.lbl.gov/~ldoolitt/halfband - - params: - * `up` is the passband/stopband width, as a fraction of - input sampling rate - * `n is the order of half-band filter to generate - returns: - * `a` is the full set of FIR coefficients, `4*n-1` long. - implement wisely. - """ - - npt = n*40 - wmax = 2*np.pi*width - wfit = (1 - np.linspace(0, 1, npt)[:, None]**2)*wmax - - target = .5*np.ones_like(wfit) - basis = np.cos(wfit*np.arange(1, 2*n, 2)) - weight = np.ones_like(wfit) - - f0 = None - - for i in range(40): - l = np.linalg.pinv(basis*weight)@(target*weight) - err = np.fabs(basis@l - .5) - f = np.max(err)/np.mean(err) - if f0 and (f0 - f)/(f0 + f) < df/2: - break - f0 = f - weight[err > (1 - df)*np.max(err)] *= 1 + 1.5/(i + 11) - a = np.c_[l, np.zeros_like(l)].ravel()[:-1] - a = np.r_[a[::-1], 1, a]/2 - return a - - -_Widths = namedtuple("_Widths", "A B P") - -_widths = { - "DSP48E1": _Widths(25, 18, 48), -} - - -class ParallelFIR(Module): - """Full-rate parallelized finite impulse response filter. - - Tries to use transposed form as much as possible. - - :param coefficients: tap coefficients (normalized to 1.), - increasing delay. - :param parallelism: number of samples per cycle. - :param width: bit width of input and output. - :param arch: architecture (default: "DSP48E1"). - """ - def __init__(self, coefficients, parallelism, width=16, - arch="DSP48E1", cull_delays=()): - self.width = width - self.parallelism = p = parallelism - n = len(coefficients) - # input and output: old to new, decreasing delay - self.i = [Signal((width, True)) for i in range(p)] - self.o = [Signal((width, True), reset_less=True) for i in range(p)] - self.latency = (n + 1)//2//p + 2 - w = _widths[arch] - - c_max = max(abs(c) for c in coefficients) - c_shift = bits_for(floor((1 << w.B - 2) / c_max)) - self.coefficients = cs = [int(round(c*(1 << c_shift))) - for c in coefficients] - assert max(bits_for(c) for c in cs) <= w.B - max_out = sum(abs(c)*(1 << w.A - 1) for c in cs) - assert max_out <= (1 << w.P - 1) - 1, (bits_for(max_out), w) - - ### - - # Delay line: increasing delay - x = [Signal((w.A, True), reset_less=True) for _ in range(n + p - 1)] - - for xi, xj in zip(x, self.i[::-1]): - self.comb += xi.eq(xj) - for xi, xj in zip(x[len(self.i):], x): - self.sync += xi.eq(xj) - - for delay in range(p): - o = Signal((w.P, True), reset_less=True) - self.sync += self.o[delay].eq(o >> c_shift) - # Make products - tap = delay - for i, c in enumerate(cs): - # simplify for halfband and symmetric filters - if not c or c in cs[:i]: - continue - js = [j + p - 1 for j, cj in enumerate(cs) if cj == c] - m = Signal.like(o) - o0, o = o, Signal.like(o) - q = Signal.like(x[0]) - if tap + p <= js[0]: - self.sync += o0.eq(o + m) - tap += p - else: - self.comb += o0.eq(o + m) - assert min(js) - tap >= 0 - js = [j for j in js - if (p - 1 - j - tap) % p not in cull_delays] - if not js: - continue - self.comb += q.eq(reduce(add, [x[j - tap] for j in js])) - self.sync += m.eq(c*q) - # symmetric rounding - if c_shift > 1 and delay not in cull_delays: - self.comb += o.eq((1 << c_shift - 1) - 1) - - -class FIR(ParallelFIR): - def __init__(self, *args, **kwargs): - super().__init__(self, *args, parallelism=1, **kwargs) - self.i = self.i[0] - self.o = self.o[0] - - -def halfgen4_cascade(rate, width, order=None): - """Generate coefficients for cascaded half-band filters. - - Coefficients are normalized to a gain of two per stage to compensate for - the zero stuffing. - - :param rate: upsampling rate. power of two - :param width: passband/stopband width in units of input sampling rate. - :param order: highest order, defaults to :param:`rate`""" - if order is None: - order = rate - coeff = [] - p = 1 - while p < rate: - p *= 2 - coeff.append(2*halfgen4(width*p/rate/2, order*p//rate)) - return coeff - - -class ParallelHBFUpsampler(Module): - """Parallel, power-of-two, half-band, cascading upsampler. - - Coefficients should be normalized to overall gain of 2 - (highest/center coefficient being 1).""" - def __init__(self, coefficients, width=16, **kwargs): - self.parallelism = 1 # accumulate - self.latency = 0 # accumulate - self.width = width - self.i = Signal((width, True)) - - ### - - i = [self.i] - for coeff in coefficients: - self.parallelism *= 2 - hbf = ParallelFIR(coeff, self.parallelism, width=width, - cull_delays={0}, **kwargs) - self.submodules += hbf - self.comb += [a.eq(b) for a, b in zip(hbf.i[1::2], i)] - i = hbf.o - self.latency += hbf.latency - self.o = i diff --git a/artiq/gateware/dsp/sawg.py b/artiq/gateware/dsp/sawg.py deleted file mode 100644 index e0e9d1db4..000000000 --- a/artiq/gateware/dsp/sawg.py +++ /dev/null @@ -1,220 +0,0 @@ -from collections import namedtuple - -from migen import * -from misoc.interconnect.stream import Endpoint -from misoc.cores.cordic import Cordic - -from .accu import PhasedAccu -from .tools import eqh, SatAddMixin -from .spline import Spline -from .fir import ParallelHBFUpsampler, halfgen4_cascade - - -_Widths = namedtuple("_Widths", "t a p f") -_Orders = namedtuple("_Orders", "a p f") - - -class SplineParallelDUC(Module): - def __init__(self, widths, orders, parallelism=1, **kwargs): - self.parallelism = parallelism - self.widths = widths - p = Spline(order=orders.p, width=widths.p) - f = Spline(order=orders.f, width=widths.f) - self.f = f.tri(widths.t) - self.p = p.tri(widths.t) - self.submodules += p, f - self.ce = Signal(reset=1) - self.clr = Signal() - - ### - accu = PhasedAccu(len(self.f.a0), parallelism) - cordic = [Cordic(width=widths.a, widthz=len(self.p.a0), guard=None, - eval_mode="pipelined") for i in range(parallelism)] - self.submodules += accu, cordic - - self.xi = [c.xi for c in cordic] - self.yi = [c.yi for c in cordic] - self.xo = [c.xo for c in cordic] - self.yo = [c.yo for c in cordic] - self.latency = cordic[0].latency - self.gain = cordic[0].gain - self.f.latency += accu.latency + self.latency - self.p.latency += accu.latency + self.latency - - ### - - assert p.latency == f.latency - self.comb += [ - p.o.ack.eq(self.ce), - f.o.ack.eq(self.ce), - eqh(accu.i.f, f.o.a0), - eqh(accu.i.p, p.o.a0), - accu.i.stb.eq(p.o.stb | f.o.stb), - accu.o.ack.eq(1), - [eqh(c.zi, zi) for c, zi in - zip(cordic, accu.o.payload.flatten())] - ] - - assert p.latency == 1 - accu.i.clr.reset_less = True - self.sync += [ - accu.i.clr.eq(0), - If(p.i.stb, - accu.i.clr.eq(self.clr), - ), - ] - - -class SplineParallelDDS(SplineParallelDUC): - def __init__(self, widths, orders, **kwargs): - a = Spline(order=orders.a, width=widths.a) - self.a = a.tri(widths.t) - self.submodules += a - super().__init__(widths._replace(a=len(self.a.a0)), orders, **kwargs) - - self.a.latency += self.latency - - ### - - self.comb += [ - a.o.ack.eq(self.ce), - [eqh(x, a.o.a0) for x in self.xi], - [y.eq(0) for y in self.yi], - ] - del self.xi - del self.yi - - -class Config(Module): - def __init__(self, width, cordic_gain): - self.clr = Signal(3, reset=0b111) - self.iq_en = Signal(2, reset=0b01) - self.limits = [[Signal((width, True)), Signal((width, True))] - for i in range(2)] - limit = (1 << width - 1) - 1 - limit_cordic = int(limit/cordic_gain) - self.limits[0][0].reset = Constant(-limit, (width, True)) - self.limits[0][1].reset = Constant(limit, (width, True)) - self.limits[1][0].reset = Constant(-limit_cordic, (width, True)) - self.limits[1][1].reset = Constant(limit_cordic, (width, True)) - # TODO make persistent, add read-out/notification/clear - self.clipped = [Signal(2) for i in range(2)] - self.i = Endpoint([("addr", bits_for(4 + 2*len(self.limits) - 1)), - ("data", width)]) - assert len(self.i.addr) == 3 - self.ce = Signal() - - ### - - div = Signal(16, reset=0) - n = Signal.like(div) - - self.comb += self.ce.eq(n == 0) - self.sync += [ - n.eq(n - 1), - If(self.ce, - n.eq(div), - ) - ] - - pad = Signal() - - reg = Array(sum(self.limits, - [Cat(div, n), self.clr, self.iq_en, pad])) - - self.comb += self.i.ack.eq(1) - self.sync += [ - If(self.i.stb, - reg[self.i.addr].eq(self.i.data), - ), - ] - - -class Channel(Module, SatAddMixin): - def __init__(self, width=16, parallelism=4, widths=None, orders=None): - if orders is None: - orders = _Orders(a=4, f=2, p=1) - if widths is None: - widths = _Widths(t=width, a=orders.a*width, p=orders.p*width, - f=(orders.f + 2)*width) - - self.submodules.a1 = a1 = SplineParallelDDS(widths, orders) - self.submodules.a2 = a2 = SplineParallelDDS(widths, orders) - coeff = halfgen4_cascade(parallelism, width=.4, order=8) - hbf = [ParallelHBFUpsampler(coeff, width=width + 1) for i in range(2)] - self.submodules.b = b = SplineParallelDUC( - widths._replace(a=len(hbf[0].o[0]), f=widths.f - width), orders, - parallelism=parallelism) - cfg = Config(width, b.gain) - u = Spline(width=widths.a, order=orders.a) - self.submodules += cfg, u, hbf - self.u = u.tri(widths.t) - self.i = [cfg.i, self.u, a1.a, a1.f, a1.p, a2.a, a2.f, a2.p, b.f, b.p] - self.i_names = "cfg u a1 f1 p1 a2 f2 p2 f0 p0".split() - self.i_named = dict(zip(self.i_names, self.i)) - self.y_in = [Signal.like(b.yo[0]) for i in range(parallelism)] - self.o = [Signal((width, True), reset_less=True) - for i in range(parallelism)] - self.widths = widths - self.orders = orders - self.parallelism = parallelism - self.cordic_gain = a2.gain*b.gain - - self.u.latency += 1 # self.o - b.p.latency += 1 # self.o - b.f.latency += 1 # self.o - a_latency_delta = hbf[0].latency + b.latency + 2 # hbf.i, self.o - for a in a1, a2: - a.a.latency += a_latency_delta - a.p.latency += a_latency_delta - a.f.latency += a_latency_delta - - self.latency = max(_.latency for _ in self.i[1:]) - for i in self.i[1:]: - i.latency -= self.latency - assert i.latency <= 0 - cfg.i.latency = 0 - - ### - - self.comb += [ - a1.ce.eq(cfg.ce), - a2.ce.eq(cfg.ce), - b.ce.eq(cfg.ce), - u.o.ack.eq(cfg.ce), - Cat(b.clr, a1.clr, a2.clr).eq(cfg.clr), - [i.eq(j) for i, j in zip(b.xi, hbf[0].o)], - [i.eq(j) for i, j in zip(b.yi, hbf[1].o)], - ] - hbf[0].i.reset_less = True - hbf[1].i.reset_less = True - self.sync += [ - hbf[0].i.eq(self.sat_add((a1.xo[0], a2.xo[0]), - width=len(hbf[0].i), - limits=cfg.limits[1], clipped=cfg.clipped[1])), - hbf[1].i.eq(self.sat_add((a1.yo[0], a2.yo[0]), - width=len(hbf[1].i), - limits=cfg.limits[1])), - ] - # wire up outputs and q_{i,o} exchange - for o, x, y in zip(self.o, b.xo, self.y_in): - o_offset = Signal.like(o) - o_x = Signal.like(x) - o_y = Signal.like(y) - self.comb += [ - o_offset.eq(u.o.a0[-len(o):]), - If(cfg.iq_en[0], - o_x.eq(x) - ), - If(cfg.iq_en[1], - o_y.eq(y) - ), - ] - self.sync += [ - o.eq(self.sat_add((o_offset, o_x, o_y), - width=len(o), - limits=cfg.limits[0], clipped=cfg.clipped[0])), - ] - - def connect_y(self, buddy): - self.comb += [i.eq(j) for i, j in zip(buddy.y_in, self.b.yo)] diff --git a/artiq/gateware/dsp/spline.py b/artiq/gateware/dsp/spline.py deleted file mode 100644 index 8185ae856..000000000 --- a/artiq/gateware/dsp/spline.py +++ /dev/null @@ -1,47 +0,0 @@ -from migen import * -from misoc.interconnect.stream import Endpoint - - -class Spline(Module): - def __init__(self, order, width, step=1, time_width=None): - if not (step == 1 or order <= 2): - raise ValueError("For non-linear splines, " - "`step` needs to be one.") - layout = [("a{}".format(i), (width, True)) for i in range(order)] - self.i = Endpoint(layout) - self.o = Endpoint(layout) - self.latency = 1 - - ### - - o = self.o.payload.flatten() - - self.comb += self.i.ack.eq(~self.o.stb | self.o.ack) - self.sync += [ - If(self.o.ack, - self.o.stb.eq(0), - ), - If(self.i.ack, - self.o.stb.eq(1), - [o[i].eq(o[i] + (o[i + 1] << log2_int(step))) - for i in range(order - 1)], - If(self.i.stb, - self.o.payload.eq(self.i.payload), - ), - ), - ] - - def tri(self, time_width): - layout = [(name, (length - i*time_width, signed)) - for i, (name, (length, signed), dir) in - enumerate(self.i.payload.layout[::-1])] - layout.reverse() - i = Endpoint(layout) - i.latency = self.latency - self.comb += [ - self.i.stb.eq(i.stb), - i.ack.eq(self.i.ack), - [i0[-len(i1):].eq(i1) for i0, i1 in - zip(self.i.payload.flatten(), i.payload.flatten())] - ] - return i diff --git a/artiq/gateware/dsp/tools.py b/artiq/gateware/dsp/tools.py deleted file mode 100644 index c198d1706..000000000 --- a/artiq/gateware/dsp/tools.py +++ /dev/null @@ -1,69 +0,0 @@ -from operator import add -from functools import reduce - -from migen import * - - -class Delay(Module): - def __init__(self, i, delay, o=None): - if isinstance(i, (int, tuple)): - z = [Signal(i) for j in range(delay + 1)] - elif isinstance(i, list): - z = [Record(i) for j in range(delay + 1)] - elif isinstance(i, Record): - z = [Record(i.layout) for j in range(delay + 1)] - else: - z = [Signal.like(i) for j in range(delay + 1)] - self.i = z[0] - self.o = z[-1] - if not isinstance(i, (int, list, tuple)): - self.comb += self.i.eq(i) - if o is not None: - self.comb += o.eq(self.o) - self.latency = delay - self.sync += [z[j + 1].eq(z[j]) for j in range(delay)] - - -def eqh(a, b): - return a[-len(b):].eq(b[-len(a):]) - - -class SatAddMixin: - """Signed saturating addition mixin""" - def sat_add(self, a, width, limits=None, clipped=None): - a = list(a) - # assert all(value_bits_sign(ai)[1] for ai in a) - max_width = max(value_bits_sign(ai)[0] for ai in a) - carry = log2_int(len(a), need_pow2=False) - full = Signal((max_width + carry, True)) - limited = Signal((width, True)) - carry = len(full) - width - assert carry >= 0 - clip = Signal(2) - sign = Signal() - if clipped is not None: - self.comb += clipped.eq(clip) - self.comb += [ - full.eq(reduce(add, a)), - sign.eq(full[-1]), - limited.eq(full) - ] - if limits is None: - self.comb += [ - If(full[-1-carry:] != Replicate(sign, carry + 1), - clip.eq(Cat(sign, ~sign)), - limited.eq(Cat(Replicate(~sign, width - 1), sign)), - ) - ] - else: - self.comb += [ - If(full < limits[0], - clip.eq(0b01), - limited.eq(limits[0]) - ), - If(full > limits[1], - clip.eq(0b10), - limited.eq(limits[1]), - ) - ] - return limited diff --git a/artiq/gateware/fmcdio_vhdci_eem.py b/artiq/gateware/fmcdio_vhdci_eem.py deleted file mode 100644 index 0296efe8e..000000000 --- a/artiq/gateware/fmcdio_vhdci_eem.py +++ /dev/null @@ -1,29 +0,0 @@ -from migen.build.generic_platform import * - -from artiq.coredevice.fmcdio_vhdci_eem import * - - -io = [ - ("fmcdio_dirctl", 0, - Subsignal("clk", Pins("LPC:LA32_N")), - Subsignal("ser", Pins("LPC:LA33_P")), - Subsignal("latch", Pins("LPC:LA32_P")), - IOStandard("LVCMOS18") - ), -] - -def _get_connectors(): - connectors = [] - for i in range(4): - connections = dict() - for j, pair in enumerate(eem_fmc_connections[i]): - for pn in "n", "p": - cc = "cc_" if j == 0 else "" - lpc_cc = "CC_" if eem_fmc_connections[i][j] in (0, 1, 17, 18) else "" - connections["d{}_{}{}".format(j, cc, pn)] = \ - "LPC:LA{:02d}_{}{}".format(pair, lpc_cc, pn.upper()) - connectors.append(("eem{}".format(i), connections)) - return connectors - - -connectors = _get_connectors() diff --git a/artiq/gateware/jesd204_tools.py b/artiq/gateware/jesd204_tools.py deleted file mode 100644 index d05d6432f..000000000 --- a/artiq/gateware/jesd204_tools.py +++ /dev/null @@ -1,290 +0,0 @@ -from collections import namedtuple - -from migen import * -from migen.genlib.cdc import MultiReg, BusSynchronizer -from migen.genlib.resetsync import AsyncResetSynchronizer -from misoc.interconnect.csr import * - -from jesd204b.common import (JESD204BTransportSettings, - JESD204BPhysicalSettings, - JESD204BSettings) -from jesd204b.phy.gth import (GTHChannelPLL as JESD204BGTHChannelPLL, - GTHQuadPLL as JESD204BGTHQuadPLL, - GTHTransmitter as JESD204BGTHTransmitter, - GTHInit as JESD204BGTHInit, - GTHTransmitterInterconnect as JESD204BGTHTransmitterInterconnect) -from jesd204b.phy import JESD204BPhyTX -from jesd204b.core import JESD204BCoreTX -from jesd204b.core import JESD204BCoreTXControl - - -class UltrascaleCRG(Module, AutoCSR): - linerate = int(6e9) # linerate = 20*data_rate*4/8 = data_rate*10 - # data_rate = dac_rate/interp_factor - refclk_freq = int(150e6) - fabric_freq = int(125e6) - - def __init__(self, platform, use_rtio_clock=False): - self.jreset = CSRStorage(reset=1) - self.refclk = Signal() - self.clock_domains.cd_jesd = ClockDomain() - - refclk2 = Signal() - refclk_pads = platform.request("dac_refclk", 0) - platform.add_period_constraint(refclk_pads.p, 1e9/self.refclk_freq) - self.specials += [ - Instance("IBUFDS_GTE3", i_CEB=0, p_REFCLK_HROW_CK_SEL=0b00, - i_I=refclk_pads.p, i_IB=refclk_pads.n, - o_O=self.refclk, o_ODIV2=refclk2), - AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage), - ] - - if use_rtio_clock: - self.cd_jesd.clk.attr.add("keep") - self.comb += self.cd_jesd.clk.eq(ClockSignal("rtio")) - else: - self.specials += Instance("BUFG_GT", i_I=refclk2, o_O=self.cd_jesd.clk) - - -PhyPads = namedtuple("PhyPads", "txp txn") - - -class UltrascaleTX(Module, AutoCSR): - def __init__(self, platform, sys_crg, jesd_crg, dac, pll_type="cpll", tx_half=False): - # Note: In general, the choice between channel and quad PLLs can be made based on the "nominal operating ranges", which are (see UG576, Ch.2): - # CPLL: 2.0 - 6.25 GHz - # QPLL0: 9.8 - 16.375 GHz - # QPLL1: 8.0 - 13.0 GHz - # However, the exact frequency and/or linerate range should be checked according to the model and speed grade from their corresponding datasheets. - pll_cls = { - "cpll": JESD204BGTHChannelPLL, - "qpll": JESD204BGTHQuadPLL - }[pll_type] - ps = JESD204BPhysicalSettings(l=8, m=4, n=16, np=16) - ts = JESD204BTransportSettings(f=2, s=2, k=16, cs=0) - settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5) - - jesd_pads = platform.request("dac_jesd", dac) - plls = [] - phys = [] - for i in range(len(jesd_pads.txp)): - pll = pll_cls( - jesd_crg.refclk, jesd_crg.refclk_freq, jesd_crg.linerate) - self.submodules += pll - plls.append(pll) - # QPLL quads - if pll_type == "qpll": - gthe3_common_cfgs = [] - for i in range(0, len(plls), 4): - # GTHE3_COMMON common signals - qpll_clk = Signal() - qpll_refclk = Signal() - qpll_reset = Signal() - qpll_lock = Signal() - # GTHE3_COMMON - self.specials += pll_cls.get_gthe3_common( - jesd_crg.refclk, jesd_crg.refclk_freq, jesd_crg.linerate, - qpll_clk, qpll_refclk, qpll_reset, qpll_lock) - gthe3_common_cfgs.append({ - "clk": qpll_clk, - "refclk": qpll_refclk, - "reset": qpll_reset, - "lock": qpll_lock - }) - # Per-channel PLL phys - for i, pll in enumerate(plls): - # PhyTX - phy = JESD204BPhyTX( - pll, jesd_crg.refclk, PhyPads(jesd_pads.txp[i], jesd_pads.txn[i]), - jesd_crg.fabric_freq, transceiver="gth", tx_half=tx_half) - phys.append(phy) - if tx_half: - platform.add_period_constraint(phy.transmitter.cd_tx_half.clk, - 80*1e9/jesd_crg.linerate) - platform.add_false_path_constraints( - sys_crg.cd_sys.clk, - jesd_crg.cd_jesd.clk, - phy.transmitter.cd_tx_half.clk) - else: - platform.add_period_constraint(phy.transmitter.cd_tx.clk, - 40*1e9/jesd_crg.linerate) - platform.add_false_path_constraints( - sys_crg.cd_sys.clk, - jesd_crg.cd_jesd.clk, - phy.transmitter.cd_tx.clk) - # CHANNEL & init interconnects - for i, (pll, phy) in enumerate(zip(plls, phys)): - # CPLLs: 1 init per channel - if pll_type == "cpll": - phy_channel_cfg = {} - # Connect reset/lock to init - pll_reset = pll.reset - pll_lock = pll.lock - self.submodules += JESD204BGTHTransmitterInterconnect( - pll_reset, pll_lock, phy.transmitter, phy.transmitter.init) - # QPLL: 4 inits and 4 channels per quad - elif pll_type == "qpll": - # Connect clk/refclk to CHANNEL - phy_cfg = gthe3_common_cfgs[int(i//4)] - phy_channel_cfg = { - "qpll_clk": phy_cfg["clk"], - "qpll_refclk": phy_cfg["refclk"] - } - # Connect reset/lock to init - pll_reset = phy_cfg["reset"] - pll_lock = phy_cfg["lock"] - if i % 4 == 0: - self.submodules += JESD204BGTHTransmitterInterconnect( - pll_reset, pll_lock, phy.transmitter, - [phys[j].transmitter.init for j in range(i, min(len(phys), i+4))]) - # GTHE3_CHANNEL - self.specials += JESD204BGTHTransmitter.get_gthe3_channel( - pll, phy.transmitter, **phy_channel_cfg) - - self.submodules.core = JESD204BCoreTX( - phys, settings, converter_data_width=64) - self.submodules.control = JESD204BCoreTXControl(self.core) - self.core.register_jsync(platform.request("dac_sync", dac)) - - -class DDMTDEdgeDetector(Module): - def __init__(self, i): - self.rising = Signal() - - history = Signal(4) - deglitched = Signal() - self.sync.helper += history.eq(Cat(history[1:], i)) - self.comb += deglitched.eq(i | history[0] | history[1] | history[2] | history[3]) - - deglitched_r = Signal() - self.sync.helper += [ - deglitched_r.eq(deglitched), - self.rising.eq(deglitched & ~deglitched_r) - ] - - -# See "Digital femtosecond time difference circuit for CERN's timing system" -# by P. Moreira and I. Darwazeh -class DDMTD(Module, AutoCSR): - def __init__(self, input_pads, rtio_clk_freq=150e6): - N = 64 - self.reset = CSRStorage(reset=1) - self.locked = CSRStatus() - self.dt = CSRStatus(N.bit_length()) - - # # # - - self.clock_domains.cd_helper = ClockDomain(reset_less=True) - helper_locked = Signal() - helper_fb = Signal() - helper_output = Signal() - - input_se = Signal() - beat1 = Signal() - beat2 = Signal() - self.specials += [ - Instance("MMCME2_BASE", - p_CLKIN1_PERIOD=1e9/rtio_clk_freq, - i_CLKIN1=ClockSignal("rtio"), - i_RST=self.reset.storage, - o_LOCKED=helper_locked, - - # VCO at 1200MHz with 150MHz RTIO frequency - p_CLKFBOUT_MULT_F=8.0, - p_DIVCLK_DIVIDE=1, - - o_CLKFBOUT=helper_fb, i_CLKFBIN=helper_fb, - - # helper PLL ratio: 64/65 (N=64) - p_CLKOUT0_DIVIDE_F=8.125, - o_CLKOUT0=helper_output, - ), - MultiReg(helper_locked, self.locked.status), - Instance("BUFG", i_I=helper_output, o_O=self.cd_helper.clk), - Instance("IBUFDS", i_I=input_pads.p, i_IB=input_pads.n, o_O=input_se), - Instance("FD", i_C=self.cd_helper.clk, i_D=input_se, o_Q=beat1, attr={("IOB", "TRUE")}), - Instance("FD", i_C=self.cd_helper.clk, i_D=ClockSignal("rtio"), o_Q=beat2), - ] - - ed1 = DDMTDEdgeDetector(beat1) - ed2 = DDMTDEdgeDetector(beat2) - self.submodules += ed1, ed2 - - counting = Signal() - counter = Signal(N.bit_length()) - result = Signal.like(counter) - self.sync.helper += [ - If(counting, - counter.eq(counter + 1) - ).Else( - result.eq(counter) - ), - - If(ed1.rising, counting.eq(1), counter.eq(0)), - If(ed2.rising, counting.eq(0)) - ] - - bsync = BusSynchronizer(len(result), "helper", "sys") - self.submodules += bsync - self.comb += [ - bsync.i.eq(result), - self.dt.status.eq(bsync.o) - ] - - -# This assumes: -# * fine RTIO frequency (rtiox) = 2*RTIO frequency -# * JESD and coarse RTIO clocks are the same -# (only reset may differ). -class SysrefSampler(Module, AutoCSR): - def __init__(self, sysref_pads, coarse_ts, sysref_phase_bits=8): - self.sh_error = CSRStatus() - self.sh_error_reset = CSRStorage() - # Note: only the lower log2(RTIO frequency / SYSREF frequency) bits are stable - self.sysref_phase = CSRStatus(8) - - self.jref = Signal() - - # # # - - sysref_se = Signal() - sysref_oversample = Signal(4) - self.specials += [ - Instance("IBUFDS", i_I=sysref_pads.p, i_IB=sysref_pads.n, o_O=sysref_se), - Instance("ISERDESE3", - p_IS_CLK_INVERTED=0, - p_IS_CLK_B_INVERTED=1, - p_DATA_WIDTH=4, - - i_D=sysref_se, - i_RST=ResetSignal("rtio"), - i_FIFO_RD_EN=0, - i_CLK=ClockSignal("rtiox"), - i_CLK_B=ClockSignal("rtiox"), # locally inverted - i_CLKDIV=ClockSignal("rtio"), - o_Q=sysref_oversample) - ] - - self.comb += self.jref.eq(sysref_oversample[1]) - sh_error = Signal() - sh_error_reset = Signal() - self.sync.rtio += [ - If(~( (sysref_oversample[0] == sysref_oversample[1]) - & (sysref_oversample[1] == sysref_oversample[2])), - sh_error.eq(1) - ), - If(sh_error_reset, sh_error.eq(0)) - ] - self.specials += [ - MultiReg(self.sh_error_reset.storage, sh_error_reset, "rtio"), - MultiReg(sh_error, self.sh_error.status) - ] - - jref_r = Signal() - sysref_phase_rtio = Signal(sysref_phase_bits) - self.sync.rtio += [ - jref_r.eq(self.jref), - If(self.jref & ~jref_r, sysref_phase_rtio.eq(coarse_ts)) - ] - sysref_phase_rtio.attr.add("no_retiming") - self.specials += MultiReg(sysref_phase_rtio, self.sysref_phase.status) diff --git a/artiq/gateware/rtio/phy/sawg.py b/artiq/gateware/rtio/phy/sawg.py deleted file mode 100644 index 7968eb2b6..000000000 --- a/artiq/gateware/rtio/phy/sawg.py +++ /dev/null @@ -1,39 +0,0 @@ -from collections import namedtuple - -from migen import * -from artiq.gateware.rtio import rtlink - -from artiq.gateware.dsp.sawg import Channel as _Channel - - -_Phy = namedtuple("Phy", "rtlink probes overrides") - -_ChannelPHY = ClockDomainsRenamer("rio_phy")(_Channel) - - -class Channel(_ChannelPHY): - def __init__(self, *args, **kwargs): - _ChannelPHY.__init__(self, *args, **kwargs) - self.phys = [] - cfg = self.i[0] - rl = rtlink.Interface(rtlink.OInterface( - data_width=len(cfg.data), address_width=len(cfg.addr), - enable_replace=False)) - self.comb += [ - cfg.stb.eq(rl.o.stb), - rl.o.busy.eq(~cfg.ack), - cfg.data.eq(rl.o.data), - cfg.addr.eq(rl.o.address), - ] - self.phys.append(_Phy(rl, [], [])) - for i in self.i[1:]: - rl = rtlink.Interface(rtlink.OInterface(len(i.payload), - delay=-i.latency)) - self.comb += [ - i.stb.eq(rl.o.stb), - rl.o.busy.eq(~i.ack), - i.payload.raw_bits().eq(rl.o.data), - ] - # TODO probes, overrides - self.phys.append(_Phy(rl, [], [])) - self.phys_named = dict(zip(self.i_names, self.phys)) diff --git a/artiq/gateware/targets/metlino.py b/artiq/gateware/targets/metlino.py deleted file mode 100755 index ffb2b38b9..000000000 --- a/artiq/gateware/targets/metlino.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -from functools import partial - -from migen import * -from migen.build.generic_platform import IOStandard - -from misoc.cores import gpio -from misoc.integration.builder import builder_args, builder_argdict -from misoc.interconnect.csr import * -from misoc.targets.metlino import * - -from artiq.gateware.amp import AMPSoC -from artiq.gateware import eem -from artiq.gateware import rtio -from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_ultrascale -from artiq.gateware.drtio.transceiver import gth_ultrascale -from artiq.gateware.drtio import * -from artiq.build_soc import * - - -def workaround_us_lvds_tristate(platform): - # Those shoddy Kintex Ultrascale FPGAs take almost a microsecond to change the direction of a - # LVDS I/O buffer. The application has to cope with it and this cannot be handled at static - # timing analysis. Disable the latter for IOBUFDS. - # See: - # https://forums.xilinx.com/t5/Timing-Analysis/Delay-890-ns-in-OBUFTDS-in-Kintex-UltraScale/td-p/868364 - platform.add_platform_command( - "set_false_path -through [get_pins -filter {{REF_PIN_NAME == T}} -of [get_cells -filter {{REF_NAME == IOBUFDS}}]]") - - -class Master(MiniSoC, AMPSoC): - mem_map = { - "cri_con": 0x10000000, - "rtio": 0x11000000, - "rtio_dma": 0x12000000, - "drtioaux": 0x14000000, - "mailbox": 0x70000000 - } - mem_map.update(MiniSoC.mem_map) - - def __init__(self, gateware_identifier_str=None, **kwargs): - MiniSoC.__init__(self, - cpu_type="vexriscv", - cpu_bus_width=64, - sdram_controller_type="minicon", - l2_size=128*1024, - integrated_sram_size=8192, - ethmac_nrxslots=4, - ethmac_ntxslots=4, - csr_address_width=15, - **kwargs) - AMPSoC.__init__(self) - add_identifier(self, gateware_identifier_str=gateware_identifier_str) - - platform = self.platform - rtio_clk_freq = 150e6 - - self.comb += platform.request("input_clk_sel").eq(1) - self.comb += platform.request("filtered_clk_sel").eq(1) - self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) - self.csr_devices.append("si5324_rst_n") - i2c = self.platform.request("i2c") - self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) - self.csr_devices.append("i2c") - self.config["I2C_BUS_COUNT"] = 1 - self.config["HAS_SI5324"] = None - self.config["SI5324_AS_SYNTHESIZER"] = None - self.config["RTIO_FREQUENCY"] = str(rtio_clk_freq/1e6) - - self.submodules.drtio_transceiver = gth_ultrascale.GTH( - clock_pads=platform.request("cdr_clk_clean", 0), - data_pads=[platform.request("mch_fabric_d", i) for i in range(11)], - sys_clk_freq=self.clk_freq, - rtio_clk_freq=rtio_clk_freq) - self.csr_devices.append("drtio_transceiver") - - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) - - drtio_csr_group = [] - drtioaux_csr_group = [] - drtioaux_memory_group = [] - drtio_cri = [] - for i in range(len(self.drtio_transceiver.channels)): - core_name = "drtio" + str(i) - coreaux_name = "drtioaux" + str(i) - memory_name = "drtioaux" + str(i) + "_mem" - drtio_csr_group.append(core_name) - drtioaux_csr_group.append(coreaux_name) - drtioaux_memory_group.append(memory_name) - - cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)}) - - core = cdr(DRTIOMaster(self.rtio_tsc, self.drtio_transceiver.channels[i])) - setattr(self.submodules, core_name, core) - drtio_cri.append(core.cri) - self.csr_devices.append(core_name) - - coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) - setattr(self.submodules, coreaux_name, coreaux) - self.csr_devices.append(coreaux_name) - - memory_address = self.mem_map["drtioaux"] + 0x800*i - self.add_wb_slave(memory_address, 0x800, - coreaux.bus) - self.add_memory_region(memory_name, memory_address | self.shadow_base, 0x800) - self.config["HAS_DRTIO"] = None - self.config["HAS_DRTIO_ROUTING"] = None - self.add_csr_group("drtio", drtio_csr_group) - self.add_csr_group("drtioaux", drtioaux_csr_group) - self.add_memory_group("drtioaux_mem", drtioaux_memory_group) - - rtio_clk_period = 1e9/rtio_clk_freq - gth0 = self.drtio_transceiver.gths[0] - platform.add_period_constraint(gth0.txoutclk, rtio_clk_period/2) - platform.add_period_constraint(gth0.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, - gth0.txoutclk, gth0.rxoutclk) - for gth in self.drtio_transceiver.gths[1:]: - platform.add_period_constraint(gth.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, gth0.txoutclk, gth.rxoutclk) - - self.rtio_channels = rtio_channels = [] - for i in range(4): - phy = ttl_simple.Output(platform.request("user_led", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - output_4x = partial(ttl_serdes_ultrascale.Output, 4) - eem.DIO.add_std(self, 2, output_4x, output_4x, - iostandard=lambda eem: IOStandard("LVDS")) - eem.Urukul.add_std(self, 0, 1, output_4x, - iostandard=lambda eem: IOStandard("LVDS")) - eem.Zotino.add_std(self, 3, output_4x, - iostandard=lambda eem: IOStandard("LVDS")) - workaround_us_lvds_tristate(platform) - - self.config["HAS_RTIO_LOG"] = None - self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) - rtio_channels.append(rtio.LogChannel()) - - self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) - self.csr_devices.append("rtio_moninj") - - self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) - self.csr_devices.append("rtio_core") - - self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) - self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if(), self.cpu_dw)) - self.register_kernel_cpu_csrdevice("rtio") - self.register_kernel_cpu_csrdevice("rtio_dma") - self.submodules.cri_con = rtio.CRIInterconnectShared( - [self.rtio.cri, self.rtio_dma.cri], - [self.rtio_core.cri] + drtio_cri, - enable_routing=True) - self.register_kernel_cpu_csrdevice("cri_con") - self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) - self.csr_devices.append("routing_table") - - -def main(): - parser = argparse.ArgumentParser( - description="Metlino gateware and firmware builder") - builder_args(parser) - soc_sdram_args(parser) - parser.set_defaults(output_dir="artiq_metlino") - parser.add_argument("--gateware-identifier-str", default=None, - help="Override ROM identifier") - args = parser.parse_args() - args.variant = "master" - soc = Master(gateware_identifier_str=args.gateware_identifier_str, **soc_sdram_argdict(args)) - build_artiq_soc(soc, builder_argdict(args)) - - -if __name__ == "__main__": - main() diff --git a/artiq/gateware/targets/sayma_amc.py b/artiq/gateware/targets/sayma_amc.py deleted file mode 100755 index 527d37b5c..000000000 --- a/artiq/gateware/targets/sayma_amc.py +++ /dev/null @@ -1,462 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import warnings -from functools import partial - -from migen import * -from migen.build.generic_platform import IOStandard - -from misoc.cores import gpio -from misoc.integration.builder import builder_args, builder_argdict -from misoc.interconnect.csr import * -from misoc.targets.sayma_amc import * - -from artiq.gateware.amp import AMPSoC -from artiq.gateware import eem -from artiq.gateware import rtio -from artiq.gateware import jesd204_tools -from artiq.gateware import fmcdio_vhdci_eem -from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_ultrascale, sawg -from artiq.gateware.drtio.transceiver import gth_ultrascale -from artiq.gateware.drtio.siphaser import SiPhaser7Series -from artiq.gateware.drtio.wrpll import WRPLL, DDMTDSamplerExtFF -from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer -from artiq.gateware.drtio import * -from artiq.build_soc import * - - -def workaround_us_lvds_tristate(platform): - # Those shoddy Kintex Ultrascale FPGAs take almost a microsecond to change the direction of a - # LVDS I/O buffer. The application has to cope with it and this cannot be handled at static - # timing analysis. Disable the latter for IOBUFDS. - # See: - # https://forums.xilinx.com/t5/Timing-Analysis/Delay-890-ns-in-OBUFTDS-in-Kintex-UltraScale/td-p/868364 - platform.add_platform_command( - "set_false_path -through [get_pins -filter {{REF_PIN_NAME == T}} -of [get_cells -filter {{REF_NAME == IOBUFDS}}]]") - - -class RTMUARTForward(Module): - def __init__(self, platform): - # forward RTM UART to second FTDI UART channel - serial_1 = platform.request("serial", 1) - serial_rtm = platform.request("serial_rtm") - self.comb += [ - serial_1.tx.eq(serial_rtm.rx), - serial_rtm.tx.eq(serial_1.rx) - ] - - -class SatelliteBase(MiniSoC): - mem_map = { - "drtioaux": 0x14000000, - } - mem_map.update(MiniSoC.mem_map) - - def __init__(self, rtio_clk_freq=125e6, identifier_suffix="", gateware_identifier_str=None, with_sfp=False, *, with_wrpll, **kwargs): - MiniSoC.__init__(self, - cpu_type="vexriscv", - cpu_bus_width=64, - sdram_controller_type="minicon", - l2_size=128*1024, - integrated_sram_size=8192, - ethmac_nrxslots=4, - ethmac_ntxslots=4, - **kwargs) - add_identifier(self, suffix=identifier_suffix, gateware_identifier_str=gateware_identifier_str) - self.rtio_clk_freq = rtio_clk_freq - - platform = self.platform - - if with_wrpll: - clock_recout_pads = platform.request("ddmtd_rec_clk") - else: - clock_recout_pads = None - if with_sfp: - # Use SFP0 to connect to master (Kasli) - self.comb += platform.request("sfp_tx_disable", 0).eq(0) - drtio_uplink = platform.request("sfp", 0) - else: - drtio_uplink = platform.request("fat_pipe", 0) - self.submodules.drtio_transceiver = gth_ultrascale.GTH( - clock_pads=platform.request("cdr_clk_clean"), - data_pads=[drtio_uplink, platform.request("rtm_amc_link")], - sys_clk_freq=self.clk_freq, - rtio_clk_freq=rtio_clk_freq, - clock_recout_pads=clock_recout_pads) - self.csr_devices.append("drtio_transceiver") - - self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) - - drtioaux_csr_group = [] - drtioaux_memory_group = [] - drtiorep_csr_group = [] - self.drtio_cri = [] - for i in range(len(self.drtio_transceiver.channels)): - coreaux_name = "drtioaux" + str(i) - memory_name = "drtioaux" + str(i) + "_mem" - drtioaux_csr_group.append(coreaux_name) - drtioaux_memory_group.append(memory_name) - - cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)}) - - if i == 0: - self.submodules.rx_synchronizer = cdr(XilinxRXSynchronizer()) - core = cdr(DRTIOSatellite( - self.rtio_tsc, self.drtio_transceiver.channels[i], - self.rx_synchronizer)) - self.submodules.drtiosat = core - self.csr_devices.append("drtiosat") - else: - corerep_name = "drtiorep" + str(i-1) - drtiorep_csr_group.append(corerep_name) - - core = cdr(DRTIORepeater( - self.rtio_tsc, self.drtio_transceiver.channels[i])) - setattr(self.submodules, corerep_name, core) - self.drtio_cri.append(core.cri) - self.csr_devices.append(corerep_name) - - coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) - setattr(self.submodules, coreaux_name, coreaux) - self.csr_devices.append(coreaux_name) - - memory_address = self.mem_map["drtioaux"] + 0x800*i - self.add_wb_slave(memory_address, 0x800, - coreaux.bus) - self.add_memory_region(memory_name, memory_address | self.shadow_base, 0x800) - self.config["HAS_DRTIO"] = None - self.config["HAS_DRTIO_ROUTING"] = None - self.add_csr_group("drtioaux", drtioaux_csr_group) - self.add_memory_group("drtioaux_mem", drtioaux_memory_group) - self.add_csr_group("drtiorep", drtiorep_csr_group) - - rtio_clk_period = 1e9/rtio_clk_freq - self.config["RTIO_FREQUENCY"] = str(rtio_clk_freq/1e6) - if with_wrpll: - self.comb += [ - platform.request("filtered_clk_sel").eq(0), - platform.request("ddmtd_main_dcxo_oe").eq(1), - platform.request("ddmtd_helper_dcxo_oe").eq(1) - ] - self.submodules.wrpll_sampler = DDMTDSamplerExtFF( - platform.request("ddmtd_inputs")) - self.submodules.wrpll = WRPLL( - helper_clk_pads=platform.request("ddmtd_helper_clk"), - main_dcxo_i2c=platform.request("ddmtd_main_dcxo_i2c"), - helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c"), - ddmtd_inputs=self.wrpll_sampler) - self.csr_devices.append("wrpll") - platform.add_period_constraint(self.wrpll.cd_helper.clk, rtio_clk_period*0.99) - platform.add_false_path_constraints(self.crg.cd_sys.clk, self.wrpll.cd_helper.clk) - else: - self.comb += platform.request("filtered_clk_sel").eq(1) - self.submodules.siphaser = SiPhaser7Series( - si5324_clkin=platform.request("si5324_clkin"), - rx_synchronizer=self.rx_synchronizer, - ultrascale=True, - rtio_clk_freq=rtio_clk_freq) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) - self.csr_devices.append("siphaser") - self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) - self.csr_devices.append("si5324_rst_n") - i2c = self.platform.request("i2c") - self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) - self.csr_devices.append("i2c") - self.config["I2C_BUS_COUNT"] = 1 - self.config["HAS_SI5324"] = None - - gth = self.drtio_transceiver.gths[0] - platform.add_period_constraint(gth.txoutclk, rtio_clk_period/2) - platform.add_period_constraint(gth.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, - gth.txoutclk, gth.rxoutclk) - - def add_rtio(self, rtio_channels): - # Only add MonInj core if there is anything to monitor - if any([len(c.probes) for c in rtio_channels]): - self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) - self.csr_devices.append("rtio_moninj") - - self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels) - self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) - self.submodules.cri_con = rtio.CRIInterconnectShared( - [self.drtiosat.cri], - [self.local_io.cri] + self.drtio_cri, - mode="sync", enable_routing=True) - self.csr_devices.append("cri_con") - self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) - self.csr_devices.append("routing_table") - - -# JESD204 DAC Channel Group -class JDCGSAWG(Module, AutoCSR): - def __init__(self, platform, sys_crg, jesd_crg, dac): - # Kintex Ultrascale GTH, speed grade -1C: - # CPLL linerate (D=1): 4.0 - 8.5 Gb/s - self.submodules.jesd = jesd204_tools.UltrascaleTX( - platform, sys_crg, jesd_crg, dac) - - self.submodules.sawgs = [sawg.Channel(width=16, parallelism=4) for i in range(4)] - - for conv, ch in zip(self.jesd.core.sink.flatten(), self.sawgs): - assert len(Cat(ch.o)) == len(conv) - self.sync.jesd += conv.eq(Cat(ch.o)) - - -class JDCGPattern(Module, AutoCSR): - def __init__(self, platform, sys_crg, jesd_crg, dac): - self.submodules.jesd = jesd204_tools.UltrascaleTX( - platform, sys_crg, jesd_crg, dac) - - self.sawgs = [] - - ramp = Signal(4) - self.sync.rtio += ramp.eq(ramp + 1) - - samples = [[Signal(16) for i in range(4)] for j in range(4)] - self.comb += [ - a.eq(Cat(b)) for a, b in zip( - self.jesd.core.sink.flatten(), samples) - ] - # ch0: 16-step ramp with big carry toggles - for i in range(4): - self.comb += [ - samples[0][i][-4:].eq(ramp), - samples[0][i][:-4].eq(0x7ff if i % 2 else 0x800) - ] - # ch1: 50 MHz - from math import pi, cos - data = [int(round(cos(i/12*2*pi)*((1 << 15) - 1))) - for i in range(12)] - k = Signal(2) - self.sync.rtio += If(k == 2, k.eq(0)).Else(k.eq(k + 1)) - self.comb += [ - Case(k, { - i: [samples[1][j].eq(data[i*4 + j]) for j in range(4)] - for i in range(3) - }) - ] - # ch2: ch0, ch3: ch1 - self.comb += [ - Cat(samples[2]).eq(Cat(samples[0])), - Cat(samples[3]).eq(Cat(samples[1])) - ] - - -class JDCGSyncDDS(Module, AutoCSR): - def __init__(self, platform, sys_crg, jesd_crg, dac): - self.submodules.jesd = jesd204_tools.UltrascaleTX( - platform, sys_crg, jesd_crg, dac) - self.coarse_ts = Signal(32) - - self.sawgs = [] - - ftw = round(2**len(self.coarse_ts)*9e6/600e6) - parallelism = 4 - - mul_1 = Signal.like(self.coarse_ts) - mul_2 = Signal.like(self.coarse_ts) - mul_3 = Signal.like(self.coarse_ts) - self.sync.rtio += [ - mul_1.eq(self.coarse_ts*ftw*parallelism), - mul_2.eq(mul_1), - mul_3.eq(mul_2) - ] - - phases = [Signal.like(self.coarse_ts) for i in range(parallelism)] - self.sync.rtio += [phases[i].eq(mul_3 + i*ftw) for i in range(parallelism)] - - resolution = 10 - steps = 2**resolution - from math import pi, cos - data = [(2**16 + round(cos(i/steps*2*pi)*((1 << 15) - 1))) & 0xffff - for i in range(steps)] - samples = [Signal(16) for i in range(4)] - for phase, sample in zip(phases, samples): - table = Memory(16, steps, init=data) - table_port = table.get_port(clock_domain="rtio") - self.specials += table, table_port - self.comb += [ - table_port.adr.eq(phase >> (len(self.coarse_ts) - resolution)), - sample.eq(table_port.dat_r) - ] - - self.sync.rtio += [sink.eq(Cat(samples)) - for sink in self.jesd.core.sink.flatten()] - - -class Satellite(SatelliteBase): - """ - DRTIO satellite with local DAC/SAWG channels, as well as TTL channels via FMC and VHDCI carrier. - """ - def __init__(self, jdcg_type, **kwargs): - SatelliteBase.__init__(self, 150e6, - identifier_suffix="." + jdcg_type, - **kwargs) - - platform = self.platform - - self.submodules += RTMUARTForward(platform) - - # RTM bitstream upload - slave_fpga_cfg = self.platform.request("rtm_fpga_cfg") - self.submodules.slave_fpga_cfg = gpio.GPIOTristate([ - slave_fpga_cfg.cclk, - slave_fpga_cfg.din, - slave_fpga_cfg.done, - slave_fpga_cfg.init_b, - slave_fpga_cfg.program_b, - ]) - self.csr_devices.append("slave_fpga_cfg") - self.config["SLAVE_FPGA_GATEWARE"] = 0x200000 - - self.rtio_channels = rtio_channels = [] - for i in range(4): - phy = ttl_simple.Output(platform.request("user_led", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - mcx_io = platform.request("mcx_io", 0) - phy = ttl_serdes_ultrascale.InOut(4, mcx_io.level) - self.comb += mcx_io.direction.eq(phy.oe) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - mcx_io = platform.request("mcx_io", 1) - phy = ttl_serdes_ultrascale.InOut(4, mcx_io.level) - self.comb += mcx_io.direction.eq(phy.oe) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - self.submodules.jesd_crg = jesd204_tools.UltrascaleCRG( - platform, use_rtio_clock=True) - cls = { - "sawg": JDCGSAWG, - "pattern": JDCGPattern, - "syncdds": JDCGSyncDDS - }[jdcg_type] - self.submodules.jdcg_0 = cls(platform, self.crg, self.jesd_crg, 0) - self.submodules.jdcg_1 = cls(platform, self.crg, self.jesd_crg, 1) - self.csr_devices.append("jesd_crg") - self.csr_devices.append("jdcg_0") - self.csr_devices.append("jdcg_1") - self.config["HAS_JDCG"] = None - self.add_csr_group("jdcg", ["jdcg_0", "jdcg_1"]) - self.config["RTIO_FIRST_SAWG_CHANNEL"] = len(rtio_channels) - rtio_channels.extend(rtio.Channel.from_phy(phy) - for sawg in self.jdcg_0.sawgs + - self.jdcg_1.sawgs - for phy in sawg.phys) - - # FMC-VHDCI-EEM DIOs x 2 (all OUTPUTs) - platform.add_connectors(fmcdio_vhdci_eem.connectors) - output_4x = partial(ttl_serdes_ultrascale.Output, 4) - eem.DIO.add_std(self, 0, - output_4x, output_4x, - iostandard=lambda eem: IOStandard("LVDS")) - eem.DIO.add_std(self, 1, - output_4x, output_4x, - iostandard=lambda eem: IOStandard("LVDS")) - # FMC-DIO-32ch-LVDS-a Direction Control Pins (via shift register) as TTLs x 3 - platform.add_extension(fmcdio_vhdci_eem.io) - print("fmcdio_vhdci_eem.[CLK, SER, LATCH] starting at RTIO channel 0x{:06x}" - .format(len(rtio_channels))) - fmcdio_dirctl = platform.request("fmcdio_dirctl", 0) - fmcdio_dirctl_phys = [ - ttl_simple.Output(fmcdio_dirctl.clk), - ttl_simple.Output(fmcdio_dirctl.ser), - ttl_simple.Output(fmcdio_dirctl.latch) - ] - for phy in fmcdio_dirctl_phys: - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - workaround_us_lvds_tristate(platform) - - self.add_rtio(rtio_channels) - - self.submodules.sysref_sampler = jesd204_tools.SysrefSampler( - platform.request("amc_fpga_sysref", 0), self.rtio_tsc.coarse_ts) - self.csr_devices.append("sysref_sampler") - self.jdcg_0.jesd.core.register_jref(self.sysref_sampler.jref) - self.jdcg_1.jesd.core.register_jref(self.sysref_sampler.jref) - if jdcg_type == "syncdds": - self.comb += [ - self.jdcg_0.coarse_ts.eq(self.rtio_tsc.coarse_ts), - self.jdcg_1.coarse_ts.eq(self.rtio_tsc.coarse_ts), - ] - - -class SimpleSatellite(SatelliteBase): - def __init__(self, **kwargs): - SatelliteBase.__init__(self, **kwargs) - - platform = self.platform - - self.submodules += RTMUARTForward(platform) - - rtio_channels = [] - for i in range(4): - phy = ttl_simple.Output(platform.request("user_led", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - mcx_io = platform.request("mcx_io", 0) - phy = ttl_serdes_ultrascale.InOut(4, mcx_io.level) - self.comb += mcx_io.direction.eq(phy.oe) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - mcx_io = platform.request("mcx_io", 1) - phy = ttl_serdes_ultrascale.InOut(4, mcx_io.level) - self.comb += mcx_io.direction.eq(phy.oe) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - self.add_rtio(rtio_channels) - - -def main(): - parser = argparse.ArgumentParser( - description="Sayma AMC gateware and firmware builder") - builder_args(parser) - soc_sayma_amc_args(parser) - parser.set_defaults(output_dir="artiq_sayma") - parser.add_argument("-V", "--variant", default="satellite", - help="variant: satellite/simplesatellite " - "(default: %(default)s)") - parser.add_argument("--sfp", default=False, action="store_true", - help="use SFP port for DRTIO instead of uTCA backplane") - parser.add_argument("--rtm-csr-csv", - default=os.path.join("artiq_sayma", "rtm_gateware", "rtm_csr.csv"), - help="CSV file listing remote CSRs on RTM (default: %(default)s)") - parser.add_argument("--jdcg-type", - default="sawg", - help="Change type of signal generator. This is used exclusively for " - "development and debugging.") - parser.add_argument("--with-wrpll", default=False, action="store_true") - parser.add_argument("--gateware-identifier-str", default=None, - help="Override ROM identifier") - args = parser.parse_args() - - variant = args.variant.lower() - if variant == "satellite": - soc = Satellite( - with_sfp=args.sfp, - jdcg_type=args.jdcg_type, - with_wrpll=args.with_wrpll, - gateware_identifier_str=args.gateware_identifier_str, - **soc_sayma_amc_argdict(args)) - elif variant == "simplesatellite": - soc = SimpleSatellite( - with_sfp=args.sfp, - with_wrpll=args.with_wrpll, - gateware_identifier_str=args.gateware_identifier_str, - **soc_sayma_amc_argdict(args)) - else: - raise SystemExit("Invalid variant (-V/--variant)") - - build_artiq_soc(soc, builder_argdict(args)) - - -if __name__ == "__main__": - main() diff --git a/artiq/gateware/targets/sayma_rtm.py b/artiq/gateware/targets/sayma_rtm.py deleted file mode 100755 index 9d8a818b4..000000000 --- a/artiq/gateware/targets/sayma_rtm.py +++ /dev/null @@ -1,280 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import subprocess -import struct - -from migen import * -from migen.genlib.cdc import MultiReg - -from misoc.interconnect.csr import * -from misoc.cores import gpio -from misoc.cores import spi2 -from misoc.cores.a7_gtp import * -from misoc.targets.sayma_rtm import BaseSoC, soc_sayma_rtm_args, soc_sayma_rtm_argdict -from misoc.integration.builder import Builder, builder_args, builder_argdict - -from artiq.gateware import rtio -from artiq.gateware import jesd204_tools -from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series -from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier, fix_serdes_timing_path -from artiq.gateware.drtio.transceiver import gtp_7series -from artiq.gateware.drtio.siphaser import SiPhaser7Series -from artiq.gateware.drtio.wrpll import WRPLL, DDMTDSamplerGTP -from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer -from artiq.gateware.drtio import * -from artiq.build_soc import add_identifier -from artiq import __artiq_dir__ as artiq_dir - - -class _SatelliteBase(BaseSoC): - mem_map = { - "drtioaux": 0x50000000, - } - mem_map.update(BaseSoC.mem_map) - - def __init__(self, rtio_clk_freq, *, with_wrpll, gateware_identifier_str, **kwargs): - BaseSoC.__init__(self, - cpu_type="vexriscv", - cpu_bus_width=64, - **kwargs) - add_identifier(self, gateware_identifier_str=gateware_identifier_str) - self.rtio_clk_freq = rtio_clk_freq - - platform = self.platform - - disable_cdrclkc_ibuf = Signal(reset=1) - disable_cdrclkc_ibuf.attr.add("no_retiming") - cdrclkc_clkout = platform.request("cdr_clk_clean") - cdrclkc_clkout_buf = Signal() - self.specials += Instance("IBUFDS_GTE2", - i_CEB=disable_cdrclkc_ibuf, - i_I=cdrclkc_clkout.p, i_IB=cdrclkc_clkout.n, - o_O=cdrclkc_clkout_buf) - qpll_drtio_settings = QPLLSettings( - refclksel=0b001, - fbdiv=4, - fbdiv_45=5, - refclk_div=1) - qpll = QPLL(cdrclkc_clkout_buf, qpll_drtio_settings) - self.submodules += qpll - - self.submodules.drtio_transceiver = gtp_7series.GTP( - qpll_channel=qpll.channels[0], - data_pads=[platform.request("rtm_amc_link", 0)], - sys_clk_freq=self.clk_freq, - rtio_clk_freq=rtio_clk_freq) - self.csr_devices.append("drtio_transceiver") - self.sync += disable_cdrclkc_ibuf.eq( - ~self.drtio_transceiver.stable_clkin.storage) - - self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) - - cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx0"}) - - self.submodules.rx_synchronizer = cdr(XilinxRXSynchronizer()) - core = cdr(DRTIOSatellite( - self.rtio_tsc, self.drtio_transceiver.channels[0], - self.rx_synchronizer)) - self.submodules.drtiosat = core - self.csr_devices.append("drtiosat") - - coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) - self.submodules.drtioaux0 = coreaux - self.csr_devices.append("drtioaux0") - - memory_address = self.mem_map["drtioaux"] - self.add_wb_slave(memory_address, 0x800, - coreaux.bus) - self.add_memory_region("drtioaux0_mem", memory_address | self.shadow_base, 0x800) - - self.config["HAS_DRTIO"] = None - self.add_csr_group("drtioaux", ["drtioaux0"]) - self.add_memory_group("drtioaux_mem", ["drtioaux0_mem"]) - - gtp = self.drtio_transceiver.gtps[0] - rtio_clk_period = 1e9/rtio_clk_freq - self.config["RTIO_FREQUENCY"] = str(rtio_clk_freq/1e6) - if with_wrpll: - self.comb += [ - platform.request("filtered_clk_sel").eq(0), - platform.request("ddmtd_main_dcxo_oe").eq(1), - platform.request("ddmtd_helper_dcxo_oe").eq(1) - ] - self.submodules.wrpll_sampler = DDMTDSamplerGTP( - self.drtio_transceiver, - platform.request("cdr_clk_clean_fabric")) - self.submodules.wrpll = WRPLL( - helper_clk_pads=platform.request("ddmtd_helper_clk"), - main_dcxo_i2c=platform.request("ddmtd_main_dcxo_i2c"), - helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c"), - ddmtd_inputs=self.wrpll_sampler) - self.csr_devices.append("wrpll") - platform.add_period_constraint(self.wrpll.cd_helper.clk, rtio_clk_period*0.99) - platform.add_false_path_constraints(self.crg.cd_sys.clk, self.wrpll.cd_helper.clk) - platform.add_false_path_constraints(self.wrpll.cd_helper.clk, gtp.rxoutclk) - else: - self.comb += platform.request("filtered_clk_sel").eq(1) - self.submodules.siphaser = SiPhaser7Series( - si5324_clkin=platform.request("si5324_clkin"), - rx_synchronizer=self.rx_synchronizer, - ref_clk=self.crg.cd_sys.clk, ref_div2=True, - rtio_clk_freq=rtio_clk_freq) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) - self.csr_devices.append("siphaser") - self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) - self.csr_devices.append("si5324_rst_n") - i2c = self.platform.request("i2c") - self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) - self.csr_devices.append("i2c") - self.config["I2C_BUS_COUNT"] = 1 - self.config["HAS_SI5324"] = None - - platform.add_period_constraint(gtp.txoutclk, rtio_clk_period) - platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, - gtp.txoutclk, gtp.rxoutclk) - - self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) - self.csr_devices.append("rtio_crg") - fix_serdes_timing_path(platform) - - def add_rtio(self, rtio_channels): - self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) - self.csr_devices.append("rtio_moninj") - - self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels) - self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) - self.comb += self.drtiosat.cri.connect(self.local_io.cri) - - -class Satellite(_SatelliteBase): - def __init__(self, **kwargs): - _SatelliteBase.__init__(self, **kwargs) - - platform = self.platform - - rtio_channels = [] - for bm in range(2): - print("BaseMod{} RF switches starting at RTIO channel 0x{:06x}" - .format(bm, len(rtio_channels))) - for i in range(4): - phy = ttl_serdes_7series.Output_8X(platform.request("basemod{}_rfsw".format(bm), i), - invert=True) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - print("BaseMod{} attenuator starting at RTIO channel 0x{:06x}" - .format(bm, len(rtio_channels))) - basemod_att = platform.request("basemod{}_att".format(bm)) - for name in "rst_n clk le".split(): - signal = getattr(basemod_att, name) - for i in range(len(signal)): - phy = ttl_simple.Output(signal[i]) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - phy = ttl_simple.Output(basemod_att.mosi[0]) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - for i in range(3): - self.comb += basemod_att.mosi[i+1].eq(basemod_att.miso[i]) - phy = ttl_simple.InOut(basemod_att.miso[3]) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - self.add_rtio(rtio_channels) - - self.comb += platform.request("clk_src_ext_sel").eq(0) - - # HMC clock chip and DAC control - self.comb += [ - platform.request("ad9154_rst_n", 0).eq(1), - platform.request("ad9154_rst_n", 1).eq(1) - ] - self.submodules.converter_spi = spi2.SPIMaster(spi2.SPIInterface( - platform.request("hmc_spi"), - platform.request("ad9154_spi", 0), - platform.request("ad9154_spi", 1))) - self.csr_devices.append("converter_spi") - self.submodules.hmc7043_reset = gpio.GPIOOut( - platform.request("hmc7043_reset"), reset_out=1) - self.csr_devices.append("hmc7043_reset") - self.submodules.hmc7043_gpo = gpio.GPIOIn( - platform.request("hmc7043_gpo")) - self.csr_devices.append("hmc7043_gpo") - self.config["HAS_HMC830_7043"] = None - self.config["HAS_AD9154"] = None - self.config["AD9154_COUNT"] = 2 - self.config["CONVERTER_SPI_HMC830_CS"] = 0 - self.config["CONVERTER_SPI_HMC7043_CS"] = 1 - self.config["CONVERTER_SPI_FIRST_AD9154_CS"] = 2 - self.config["HMC830_REF"] = str(int(self.rtio_clk_freq/1e6)) - - # HMC workarounds - self.comb += platform.request("hmc830_pwr_en").eq(1) - self.submodules.hmc7043_out_en = gpio.GPIOOut( - platform.request("hmc7043_out_en")) - self.csr_devices.append("hmc7043_out_en") - - # DDMTD - sysref_pads = platform.request("rtm_fpga_sysref", 0) - self.submodules.sysref_ddmtd = jesd204_tools.DDMTD(sysref_pads, self.rtio_clk_freq) - self.csr_devices.append("sysref_ddmtd") - platform.add_false_path_constraints( - self.sysref_ddmtd.cd_helper.clk, self.drtio_transceiver.gtps[0].txoutclk) - platform.add_false_path_constraints( - self.sysref_ddmtd.cd_helper.clk, self.crg.cd_sys.clk) - - -class SatmanSoCBuilder(Builder): - def __init__(self, *args, **kwargs): - Builder.__init__(self, *args, **kwargs) - firmware_dir = os.path.join(artiq_dir, "firmware") - self.software_packages = [] - self.add_software_package("satman", os.path.join(firmware_dir, "satman")) - - def initialize_memory(self): - satman = os.path.join(self.output_dir, "software", "satman", - "satman.bin") - with open(satman, "rb") as boot_file: - boot_data = [] - unpack_endian = " l1: - lim = l1 - clip = 2 - with self.subTest(i0=i0, i1=i1): - self.assertEqual(lim, o) - self.assertEqual(clip, c) - yield - - mg.run_simulation(self.dut, (gen(), rec())) - - def test_inst(self): - pass - - def test_run(self): - self._sweep() - - def test_limits(self): - for l0 in -8, 0, 1, 7: - for l1 in -8, 0, 1, 7: - self.setUp() - self.dut.l0.reset = l0 - self.dut.l1.reset = l1 - with self.subTest(l0=l0, l1=l1): - self._sweep() diff --git a/artiq/gateware/test/dsp/test_sawg.py b/artiq/gateware/test/dsp/test_sawg.py deleted file mode 100644 index fd392607d..000000000 --- a/artiq/gateware/test/dsp/test_sawg.py +++ /dev/null @@ -1,36 +0,0 @@ -import numpy as np - -from migen import * -from migen.fhdl.verilog import convert - -from artiq.gateware.dsp import sawg -from artiq.gateware.test.dsp.tools import xfer - - -def _test_gen_dds(dut, o): - yield from xfer(dut, - a=dict(a0=10), - p=dict(a0=0), - f=dict(a0=1), - ) - for i in range(256//dut.parallelism): - yield - o.append((yield from [(yield _) for _ in dut.xo])) - - -def _test_channel(): - widths = sawg._Widths(t=8, a=4*8, p=8, f=16) - orders = sawg._Orders(a=4, p=1, f=2) - dut = sawg.SplineParallelDDS(widths, orders, parallelism=2) - - if False: - print(convert(dut)) - else: - o = [] - run_simulation(dut, _test_gen_dds(dut, o), vcd_name="dds.vcd") - o = np.array(o) - print(o[:, :]) - - -if __name__ == "__main__": - _test_channel() diff --git a/artiq/gateware/test/dsp/test_sawg_fe.py b/artiq/gateware/test/dsp/test_sawg_fe.py deleted file mode 100644 index 1f7cdc08c..000000000 --- a/artiq/gateware/test/dsp/test_sawg_fe.py +++ /dev/null @@ -1,255 +0,0 @@ -import unittest - -import migen as mg -from numpy import int32 - -from artiq.coredevice import sawg, spline -from artiq.language import (at_mu, now_mu, delay, - core as core_language) -from artiq.gateware.rtio.phy.sawg import Channel -from artiq.sim import devices as sim_devices, time as sim_time - - -class RTIOManager: - def __init__(self): - self.outputs = [] - - def rtio_output(self, target, data): - channel = target >> 8 - addr = target & 0xff - self.outputs.append((now_mu(), channel, addr, data)) - - def rtio_output_wide(self, *args, **kwargs): - self.rtio_output(*args, **kwargs) - - def delay_mu(self, t): - delay(t) - - def patch(self, mod): - assert not hasattr(mod, "_saved") - mod._saved = {} - for name in "rtio_output rtio_output_wide delay_mu".split(): - mod._saved[name] = getattr(mod, name, None) - setattr(mod, name, getattr(self, name)) - - def unpatch(self, mod): - mod.__dict__.update(mod._saved) - del mod._saved - - -class SAWGTest(unittest.TestCase): - def setUp(self): - core_language.set_time_manager(sim_time.Manager()) - self.rtio_manager = RTIOManager() - self.rtio_manager.patch(spline) - self.rtio_manager.patch(sawg) - self.core = sim_devices.Core({}) - self.core.coarse_ref_period = 20/3 - self.core.ref_multiplier = 1 - self.t = self.core.coarse_ref_period - self.channel = mg.ClockDomainsRenamer({"rio_phy": "sys"})( - Channel(width=16, parallelism=2)) - self.driver = sawg.SAWG({"core": self.core}, channel_base=0, - parallelism=self.channel.parallelism) - - def tearDown(self): - self.rtio_manager.unpatch(spline) - self.rtio_manager.unpatch(sawg) - - def test_instantiate(self): - pass - - def test_make_events(self): - d = self.driver - d.offset.set(.9) - delay(2*self.t) - d.frequency0.set(.1) - d.frequency1.set(.1) - delay(2*self.t) - d.offset.set(0) - v = int(round((1 << 48) * .1 * self.t)) - self.assertEqual( - self.rtio_manager.outputs, [ - (0., 1, 0, int(round(self.driver.offset.scale*.9))), - (2.*self.t, 8, 0, int(round( - (1 << self.driver.frequency0.width) * - self.t/self.channel.parallelism*.1))), - (2.*self.t, 3, 0, [int32(v), int32(v >> 32)]), - (4.*self.t, 1, 0, 0), - ]) - - def run_channel(self, events): - def gen(dut, events): - c = 0 - for time, channel, address, data in events: - time //= self.t - assert c <= time - while c < time: - yield - c += 1 - for phy in dut.phys: - yield phy.rtlink.o.stb.eq(0) - rt = dut.phys[channel].rtlink.o - if isinstance(data, list): - data = sum(int(d) << (i*32) for i, d in enumerate(data)) - yield rt.data.eq(int(data)) - if hasattr(rt, "address"): - yield rt.address.eq(address) - yield rt.stb.eq(1) - assert not (yield rt.busy) - # print("{}: set ch {} to {}".format(time, channel, hex(data))) - - def log(dut, data, n): - for i in range(n + dut.latency): - yield - data.append((yield from [(yield _) for _ in dut.o])) - - data = [] - # print(int(events[-1][0]) + 1) - mg.run_simulation(self.channel, [ - gen(self.channel, events), - log(self.channel, data, int(events[-1][0]//self.t) + 1)], - vcd_name="dds.vcd") - return data - - def test_run_channel(self): - self.test_make_events() - self.run_channel(self.rtio_manager.outputs) - - def test_coeff(self): - import struct - # these get discrete_compensate - # [.1, .01, -.00001], [.1, .01, .00001, -.000000001] - for v in [-.1], [.1, -.01]: - ch = self.driver.offset - p = ch.coeff_as_packed(v) - t = ch.time_width - w = ch.width - p = [_ & 0xffffffff for _ in p] - p0 = [int(round(vi*ch.scale*ch.time_scale**i)) - for i, vi in enumerate(v)] - p0 = [struct.pack("<" + "_bhiiqqqq"[(w + i*t)//8], vi - )[:(w + i*t)//8] - for i, vi in enumerate(p0)] - p0 = b"".join(p0) - if len(p0) % 4: - p0 += b"\x00"*(4 - len(p0) % 4) - p0 = list(struct.unpack("<" + "I"*((len(p0) + 3)//4), p0)) - with self.subTest(v): - self.assertEqual(p, p0) - - def test_linear(self): - d = self.driver - d.offset.set_coeff_mu([100, 10]) - delay(10*self.t) - d.offset.set_coeff([0]) - delay(1*self.t) - out = self.run_channel(self.rtio_manager.outputs) - out = out[self.channel.latency + self.channel.u.latency:][:11] - for i in range(len(out) - 1): - with self.subTest(i): - v = 100 + i*10 - self.assertEqual(out[i], [v, v]) - self.assertEqual(out[-1], [0, 0]) - - def test_pack(self): - ch = self.driver.offset - self.assertEqual(ch.coeff_as_packed_mu([1]), [1]) - self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 16]), [1, 1]) - self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 32]), [1, 0]) - self.assertEqual(ch.coeff_as_packed_mu([0x1234, 0xa5a5a5a5]), - [0xa5a51234, 0xa5a5]) - self.assertEqual(ch.coeff_as_packed_mu([1, 2, 3, 4]), - [0x20001, 0x30000, 0, 4, 0]) - self.assertEqual(ch.coeff_as_packed_mu([-1, -2, -3, -4]), - [0xfffeffff, 0xfffdffff, -1, -4, -1]) - self.assertEqual(ch.coeff_as_packed_mu([0, -1, 0, -1]), - [0xffff0000, 0x0000ffff, 0, -1, -1]) - - def test_smooth_linear(self): - ch = self.driver.offset - ch.smooth(.1, .2, 13*self.t, 1) - ch.set(.2) - delay(1*self.t) - out = self.run_channel(self.rtio_manager.outputs) - out = out[self.channel.latency + self.channel.u.latency:][:14] - a = int(round(.1*ch.scale)) - da = int(round(.1*ch.scale*(1 << ch.width)//13)) - for i in range(len(out) - 1): - with self.subTest(i): - v = a + (i*da >> ch.width) - self.assertEqual(out[i], [v, v]) - a = int(round(.2*ch.scale)) - self.assertEqual(out[-1], [a, a]) - - def test_smooth_cubic(self): - ch = self.driver.offset - ch.smooth(.1, .2, 13*self.t, 3) - ch.set(.2) - delay(1*self.t) - out = self.run_channel(self.rtio_manager.outputs) - out = out[self.channel.latency + self.channel.u.latency:][:14] - if False: - import matplotlib.pyplot as plt - plt.plot(sum(out, [])) - plt.show() - - @unittest.skip("needs artiq.sim.time.TimeManager tweak for " - "reverse timeline jumps") - def test_demo_2tone(self): - MHz = 1e-3 - ns = 1. - self.sawg0 = self.driver - - t_up = t_hold = t_down = 400*ns - a1 = .3 - a2 = .4 - order = 3 - - self.sawg0.frequency0.set(10*MHz) - self.sawg0.phase0.set(0.) - self.sawg0.frequency1.set(1*MHz) - self.sawg0.phase1.set(0.) - self.sawg0.frequency2.set(13*MHz) - self.sawg0.phase2.set(0.) - t = now_mu() - self.sawg0.amplitude1.smooth(.0, a1, t_up, order) - at_mu(t) - self.sawg0.amplitude2.smooth(.0, a2, t_up, order) - self.sawg0.amplitude1.set(a1) - self.sawg0.amplitude2.set(a2) - delay(t_hold) - t = now_mu() - self.sawg0.amplitude1.smooth(a1, .0, t_down, order) - at_mu(t) - self.sawg0.amplitude2.smooth(a2, .0, t_down, order) - self.sawg0.amplitude1.set(.0) - self.sawg0.amplitude2.set(.0) - - out = self.run_channel(self.rtio_manager.outputs) - out = sum(out, []) - if True: - import matplotlib.pyplot as plt - plt.plot(out) - plt.show() - - def test_fir_overflow(self): - MHz = 1e-3 - ns = 1. - f1 = self.driver.frequency1 - a1 = self.driver.amplitude1 - p1 = self.driver.phase1 - cfg = self.driver.config - f1.set(1*MHz) - a1.set(.99) - delay(100*ns) - p1.set(.5) - delay(100*ns) - a1.set(0) - - out = self.run_channel(self.rtio_manager.outputs) - out = sum(out, []) - if False: - import matplotlib.pyplot as plt - plt.plot(out) - plt.show() diff --git a/artiq/gateware/test/dsp/test_sawg_phy.py b/artiq/gateware/test/dsp/test_sawg_phy.py deleted file mode 100644 index 35666a5f6..000000000 --- a/artiq/gateware/test/dsp/test_sawg_phy.py +++ /dev/null @@ -1,70 +0,0 @@ -import numpy as np -from operator import or_ - -from migen import * -from migen.fhdl.verilog import convert - -from artiq.gateware.rtio.phy.sawg import Channel -from .tools import rtio_xfer - - -def pack_tri(port, *v): - r = 0 - w = 0 - for vi, p in zip(v, port.payload.flatten()): - w += len(p) - r |= int(vi*(1 << w)) - return r - - -def gen_rtio(dut): - yield - yield from rtio_xfer( - dut, - a1=pack_tri(dut.a1.a, .1), - f0=pack_tri(dut.b.f, .01234567), - f1=pack_tri(dut.a1.f, .01234567), - a2=pack_tri(dut.a1.a, .05), - f2=pack_tri(dut.a1.f, .00534567), - ) - - -def gen_log(dut, o, n): - for i in range(3 + dut.latency): - yield - for i in range(n): - yield - o.append((yield from [(yield _) for _ in dut.o])) - #o.append([(yield dut.a1.xo[0])]) - - -def _test_channel(): - width = 16 - - dut = ClockDomainsRenamer({"rio_phy": "sys"})( - Channel(width=width, parallelism=4) - ) - - if False: - print(convert(dut)) - return - - o = [] - run_simulation( - dut, - [gen_rtio(dut), gen_log(dut, o, 128)], - vcd_name="dds.vcd") - o = np.array(o)/(1 << (width - 1)) - o = o.ravel() - np.savez_compressed("dds.npz", o=o) - - import matplotlib.pyplot as plt - fig, ax = plt.subplots(2) - ax[0].step(np.arange(o.size), o) - ax[1].psd(o, 1 << 10, Fs=1, noverlap=1 << 9, scale_by_freq=False) - fig.savefig("dds.pdf") - plt.show() - - -if __name__ == "__main__": - _test_channel() diff --git a/artiq/gateware/test/dsp/test_spline.py b/artiq/gateware/test/dsp/test_spline.py deleted file mode 100644 index fe2d82c28..000000000 --- a/artiq/gateware/test/dsp/test_spline.py +++ /dev/null @@ -1,31 +0,0 @@ -import numpy as np - -from migen import * -from migen.fhdl.verilog import convert - -from artiq.gateware.dsp.spline import Spline -from .tools import xfer - - -def _test_gen_spline(dut, o): - yield dut.o.ack.eq(1) - yield from xfer(dut, i=dict(a0=0, a1=1, a2=2)) - for i in range(20): - yield - o.append((yield dut.o.a0)) - - -def _test_spline(): - dut = Spline(order=3, width=16, step=1) - - if False: - print(convert(dut)) - else: - o = [] - run_simulation(dut, _test_gen_spline(dut, o), vcd_name="spline.vcd") - o = np.array(o) - print(o) - - -if __name__ == "__main__": - _test_spline() diff --git a/artiq/gateware/test/dsp/tools.py b/artiq/gateware/test/dsp/tools.py deleted file mode 100644 index 8d22ad475..000000000 --- a/artiq/gateware/test/dsp/tools.py +++ /dev/null @@ -1,49 +0,0 @@ -def set_dict(e, **k): - for k, v in k.items(): - if isinstance(v, dict): - yield from set_dict(getattr(e, k), **v) - else: - yield getattr(e, k).eq(v) - - -def xfer(dut, **kw): - ep = [] - for e, v in kw.items(): - e = getattr(dut, e) - yield from set_dict(e, **v) - ep.append(e) - for e in ep: - yield e.stb.eq(1) - while ep: - yield - for e in ep[:]: - if hasattr(e, "busy") and (yield e.busy): - raise ValueError(e, "busy") - if not hasattr(e, "ack") or (yield e.ack): - yield e.stb.eq(0) - ep.remove(e) - - -def szip(*iters): - active = {it: None for it in iters} - while active: - for it in list(active): - while True: - try: - val = it.send(active[it]) - except StopIteration: - del active[it] - break - if val is None: - break - else: - active[it] = (yield val) - val = (yield None) - for it in active: - active[it] = val - - -def rtio_xfer(dut, **kwargs): - yield from szip(*( - xfer(dut.phys_named[k].rtlink, o={"data": v}) - for k, v in kwargs.items())) diff --git a/artiq/test/test_coefficients.py b/artiq/test/test_coefficients.py deleted file mode 100644 index 138e0a86a..000000000 --- a/artiq/test/test_coefficients.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2014, 2015 Robert Jordens - -import unittest - -import numpy as np - -from artiq.wavesynth import coefficients, compute_samples - - -class TestSplineCoef(unittest.TestCase): - def setUp(self): - self.x = np.arange(5.) - self.y = np.sin(2*np.pi*self.x/5) + np.arange(2)[:, None] - self.s = coefficients.SplineSource(self.x, self.y, order=4) - - def test_get_segment(self): - return list(self.s.get_segment(start=1.5, stop=3.2, scale=.01)) - - def test_synth(self): - d = self.test_get_segment() - d[0]["trigger"] = True - return compute_samples.Synthesizer(self.y.shape[0], [d, d + d]) - - def drive(self, s): - y = [] - for f in 0, 1, None, 0: - if f is not None: - s.select(f) - y += s.trigger()[0] - return y - - def test_run(self): - return self.drive(self.test_synth()) - - def test_compare(self): - scale = 100 - d = list(self.s.get_segment(start=0, stop=4, scale=1/scale)) - d[0]["trigger"] = True - s = compute_samples.Synthesizer(self.y.shape[0], [d]) - s.select(0) - y = s.trigger()[0] - np.testing.assert_almost_equal(y[::scale], self.y[0, :-1]) - - @unittest.skip("manual/visual test") - def test_plot(self): - import matplotlib.pyplot as plt - y = self.test_run() - plt.step(np.arange(len(y)), y) - plt.show() diff --git a/doc/manual/core_drivers_reference.rst b/doc/manual/core_drivers_reference.rst index 175039862..38cf25e45 100644 --- a/doc/manual/core_drivers_reference.rst +++ b/doc/manual/core_drivers_reference.rst @@ -47,12 +47,6 @@ Digital I/O drivers .. automodule:: artiq.coredevice.edge_counter :members: -:mod:`artiq.coredevice.shiftreg` module -+++++++++++++++++++++++++++++++++++++++ - -.. automodule:: artiq.coredevice.shiftreg - :members: - :mod:`artiq.coredevice.spi2` module +++++++++++++++++++++++++++++++++++ @@ -104,25 +98,6 @@ RF generation drivers .. automodule:: artiq.coredevice.adf5356 :members: -:mod:`artiq.coredevice.spline` module -+++++++++++++++++++++++++++++++++++++ - -.. automodule:: artiq.coredevice.spline - :members: - -:mod:`artiq.coredevice.sawg` module -+++++++++++++++++++++++++++++++++++ - -.. automodule:: artiq.coredevice.sawg - :members: - - -:mod:`artiq.coredevice.basemod_att` module -++++++++++++++++++++++++++++++++++++++++++ - -.. automodule:: artiq.coredevice.basemod_att - :members: - :mod:`artiq.coredevice.phaser` module +++++++++++++++++++++++++++++++++++++ diff --git a/doc/manual/utilities.rst b/doc/manual/utilities.rst index d66d91342..11745dc34 100644 --- a/doc/manual/utilities.rst +++ b/doc/manual/utilities.rst @@ -128,9 +128,6 @@ Core device RTIO analyzer tool :ref: artiq.frontend.artiq_coreanalyzer.get_argparser :prog: artiq_coreanalyzer -.. note:: - The RTIO analyzer does not support SAWG. - .. _routing-table-tool: DRTIO routing table manipulation tool diff --git a/flake.nix b/flake.nix index 4c5178a83..e10d005b3 100644 --- a/flake.nix +++ b/flake.nix @@ -182,18 +182,6 @@ propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; }; - jesd204b = pkgs.python3Packages.buildPythonPackage rec { - pname = "jesd204b"; - version = "unstable-2021-05-05"; - src = pkgs.fetchFromGitHub { - owner = "m-labs"; - repo = "jesd204b"; - rev = "bf1cd9014c8b7a9db67609f653634daaf3bcd39b"; - sha256 = "sha256-wyYOCRIPANReeCl+KaIpiAStsn2mzfMlK+cSrUzVrAw="; - }; - propagatedBuildInputs = with pkgs.python3Packages; [ migen misoc ]; - }; - microscope = pkgs.python3Packages.buildPythonPackage rec { pname = "microscope"; version = "unstable-2020-12-28"; @@ -404,7 +392,7 @@ devShell.x86_64-linux = pkgs.mkShell { name = "artiq-dev-shell"; buildInputs = [ - (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc jesd204b artiq ps.paramiko ps.jsonschema microscope ])) + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ps.jsonschema microscope ])) rustPlatform.rust.rustc rustPlatform.rust.cargo cargo-xbuild From 668997a4510242f1f3a7b44762fd509dab06b65c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Jan 2023 17:49:13 +0800 Subject: [PATCH 11/16] flake: update dependencies --- flake.lock | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/flake.lock b/flake.lock index d138f372c..0c8bcd6d0 100644 --- a/flake.lock +++ b/flake.lock @@ -42,11 +42,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": { @@ -57,11 +57,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1666056570, - "narHash": "sha256-e7EkIY68Tp7NKyp9JSHh6CgPPdsKYYWxiL4wZQN8Cwg=", + "lastModified": 1672580127, + "narHash": "sha256-3lW3xZslREhJogoOkjeZtlBtvFMyxHku7I/9IVehhT8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "47edaa313fc3767ce3026037a5b62352f22f3602", + "rev": "0874168639713f547c05947c76124f78441ea46c", "type": "github" }, "original": { @@ -89,11 +89,11 @@ ] }, "locked": { - "lastModified": 1664319253, - "narHash": "sha256-hycJAgy+NFF9f5I6++7yo8KdhMSyKCPKJazRPxeedI4=", + "lastModified": 1669369686, + "narHash": "sha256-YHez+S3PTUgtuliUNB5WM+RXcj8RKLbHVRvOgELSkwU=", "owner": "m-labs", "repo": "sipyco", - "rev": "d58ded7280e0f020be2446d4fee70f4393e6045f", + "rev": "98db6eacb084c2c5280fb653bee3d313e3ca6df8", "type": "github" }, "original": { @@ -105,11 +105,11 @@ "src-migen": { "flake": false, "locked": { - "lastModified": 1662111470, - "narHash": "sha256-IPyhoFZLhY8d3jHB8jyvGdbey7V+X5eCzBZYSrJ18ec=", + "lastModified": 1671263827, + "narHash": "sha256-hqvzLivGwc/4qMoyiwzmIpHEfLmwX0AmkiS0kVQojg8=", "owner": "m-labs", "repo": "migen", - "rev": "639e66f4f453438e83d86dc13491b9403bbd8ec6", + "rev": "12eb563e89ffc4a5e046239171207c9476f8f665", "type": "github" }, "original": { @@ -121,11 +121,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1665395741, - "narHash": "sha256-7ULMGBPPn5NxZX6rdxU5GheoSNBiJklHQEVf04jU9tI=", - "ref": "master", - "rev": "4fb0730db4c5de7e86f82fa3bd204e6c4608af85", - "revCount": 2427, + "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" From cf2a4972f742c87d300305e1a75c08e97e6568a4 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Jan 2023 17:53:11 +0800 Subject: [PATCH 12/16] remove WRPLL --- artiq/firmware/libboard_artiq/lib.rs | 2 - artiq/firmware/libboard_artiq/wrpll.rs | 536 --------------------- artiq/firmware/satman/main.rs | 21 - artiq/gateware/drtio/wrpll/__init__.py | 2 - artiq/gateware/drtio/wrpll/core.py | 156 ------- artiq/gateware/drtio/wrpll/ddmtd.py | 221 --------- artiq/gateware/drtio/wrpll/filters.py | 61 --- artiq/gateware/drtio/wrpll/si549.py | 340 -------------- artiq/gateware/drtio/wrpll/thls.py | 618 ------------------------- artiq/gateware/targets/kasli.py | 50 +- artiq/gateware/test/wrpll/__init__.py | 0 artiq/gateware/test/wrpll/test_dsp.py | 158 ------- artiq/gateware/test/wrpll/test_thls.py | 55 --- doc/wrpll_diagram.png | Bin 58653 -> 0 bytes 14 files changed, 13 insertions(+), 2207 deletions(-) delete mode 100644 artiq/firmware/libboard_artiq/wrpll.rs delete mode 100644 artiq/gateware/drtio/wrpll/__init__.py delete mode 100644 artiq/gateware/drtio/wrpll/core.py delete mode 100644 artiq/gateware/drtio/wrpll/ddmtd.py delete mode 100644 artiq/gateware/drtio/wrpll/filters.py delete mode 100644 artiq/gateware/drtio/wrpll/si549.py delete mode 100644 artiq/gateware/drtio/wrpll/thls.py delete mode 100644 artiq/gateware/test/wrpll/__init__.py delete mode 100644 artiq/gateware/test/wrpll/test_dsp.py delete mode 100644 artiq/gateware/test/wrpll/test_thls.py delete mode 100644 doc/wrpll_diagram.png diff --git a/artiq/firmware/libboard_artiq/lib.rs b/artiq/firmware/libboard_artiq/lib.rs index 7436fc8c5..209da3048 100644 --- a/artiq/firmware/libboard_artiq/lib.rs +++ b/artiq/firmware/libboard_artiq/lib.rs @@ -22,8 +22,6 @@ pub mod rpc_queue; #[cfg(has_si5324)] pub mod si5324; -#[cfg(has_wrpll)] -pub mod wrpll; #[cfg(has_grabber)] pub mod grabber; diff --git a/artiq/firmware/libboard_artiq/wrpll.rs b/artiq/firmware/libboard_artiq/wrpll.rs deleted file mode 100644 index a9c9a702f..000000000 --- a/artiq/firmware/libboard_artiq/wrpll.rs +++ /dev/null @@ -1,536 +0,0 @@ -use board_misoc::{csr, clock}; - -mod i2c { - use board_misoc::{csr, clock}; - - #[derive(Debug, Clone, Copy)] - pub enum Dcxo { - Main, - Helper - } - - fn half_period() { clock::spin_us(1) } - const SDA_MASK: u8 = 2; - const SCL_MASK: u8 = 1; - - fn sda_i(dcxo: Dcxo) -> bool { - let reg = match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_in_read() }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_in_read() }, - }; - reg & SDA_MASK != 0 - } - - fn sda_oe(dcxo: Dcxo, oe: bool) { - let reg = match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_oe_read() }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_oe_read() }, - }; - let reg = if oe { reg | SDA_MASK } else { reg & !SDA_MASK }; - match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_oe_write(reg) }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_oe_write(reg) } - } - } - - fn sda_o(dcxo: Dcxo, o: bool) { - let reg = match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_out_read() }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_out_read() }, - }; - let reg = if o { reg | SDA_MASK } else { reg & !SDA_MASK }; - match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_out_write(reg) }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_out_write(reg) } - } - } - - fn scl_oe(dcxo: Dcxo, oe: bool) { - let reg = match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_oe_read() }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_oe_read() }, - }; - let reg = if oe { reg | SCL_MASK } else { reg & !SCL_MASK }; - match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_oe_write(reg) }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_oe_write(reg) } - } - } - - fn scl_o(dcxo: Dcxo, o: bool) { - let reg = match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_out_read() }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_out_read() }, - }; - let reg = if o { reg | SCL_MASK } else { reg & !SCL_MASK }; - match dcxo { - Dcxo::Main => unsafe { csr::wrpll::main_dcxo_gpio_out_write(reg) }, - Dcxo::Helper => unsafe { csr::wrpll::helper_dcxo_gpio_out_write(reg) } - } - } - - pub fn init(dcxo: Dcxo) -> Result<(), &'static str> { - // Set SCL as output, and high level - scl_o(dcxo, true); - scl_oe(dcxo, true); - // Prepare a zero level on SDA so that sda_oe pulls it down - sda_o(dcxo, false); - // Release SDA - sda_oe(dcxo, false); - - // Check the I2C bus is ready - half_period(); - half_period(); - if !sda_i(dcxo) { - // Try toggling SCL a few times - for _bit in 0..8 { - scl_o(dcxo, false); - half_period(); - scl_o(dcxo, true); - half_period(); - } - } - - if !sda_i(dcxo) { - return Err("SDA is stuck low and doesn't get unstuck"); - } - Ok(()) - } - - pub fn start(dcxo: Dcxo) { - // Set SCL high then SDA low - scl_o(dcxo, true); - half_period(); - sda_oe(dcxo, true); - half_period(); - } - - pub fn stop(dcxo: Dcxo) { - // First, make sure SCL is low, so that the target releases the SDA line - scl_o(dcxo, false); - half_period(); - // Set SCL high then SDA high - sda_oe(dcxo, true); - scl_o(dcxo, true); - half_period(); - sda_oe(dcxo, false); - half_period(); - } - - pub fn write(dcxo: Dcxo, data: u8) -> bool { - // MSB first - for bit in (0..8).rev() { - // Set SCL low and set our bit on SDA - scl_o(dcxo, false); - sda_oe(dcxo, data & (1 << bit) == 0); - half_period(); - // Set SCL high ; data is shifted on the rising edge of SCL - scl_o(dcxo, true); - half_period(); - } - // Check ack - // Set SCL low, then release SDA so that the I2C target can respond - scl_o(dcxo, false); - half_period(); - sda_oe(dcxo, false); - // Set SCL high and check for ack - scl_o(dcxo, true); - half_period(); - // returns true if acked (I2C target pulled SDA low) - !sda_i(dcxo) - } - - pub fn read(dcxo: Dcxo, ack: bool) -> u8 { - // Set SCL low first, otherwise setting SDA as input may cause a transition - // on SDA with SCL high which will be interpreted as START/STOP condition. - scl_o(dcxo, false); - half_period(); // make sure SCL has settled low - sda_oe(dcxo, false); - - let mut data: u8 = 0; - - // MSB first - for bit in (0..8).rev() { - scl_o(dcxo, false); - half_period(); - // Set SCL high and shift data - scl_o(dcxo, true); - half_period(); - if sda_i(dcxo) { data |= 1 << bit } - } - // Send ack - // Set SCL low and pull SDA low when acking - scl_o(dcxo, false); - if ack { sda_oe(dcxo, true) } - half_period(); - // then set SCL high - scl_o(dcxo, true); - half_period(); - - data - } -} - -mod si549 { - use board_misoc::clock; - use super::i2c; - - #[cfg(soc_platform = "kasli")] - pub const ADDRESS: u8 = 0x67; - - pub fn write(dcxo: i2c::Dcxo, reg: u8, val: u8) -> Result<(), &'static str> { - i2c::start(dcxo); - if !i2c::write(dcxo, ADDRESS << 1) { - return Err("Si549 failed to ack write address") - } - if !i2c::write(dcxo, reg) { - return Err("Si549 failed to ack register") - } - if !i2c::write(dcxo, val) { - return Err("Si549 failed to ack value") - } - i2c::stop(dcxo); - Ok(()) - } - - pub fn write_no_ack_value(dcxo: i2c::Dcxo, reg: u8, val: u8) -> Result<(), &'static str> { - i2c::start(dcxo); - if !i2c::write(dcxo, ADDRESS << 1) { - return Err("Si549 failed to ack write address") - } - if !i2c::write(dcxo, reg) { - return Err("Si549 failed to ack register") - } - i2c::write(dcxo, val); - i2c::stop(dcxo); - Ok(()) - } - - pub fn read(dcxo: i2c::Dcxo, reg: u8) -> Result { - i2c::start(dcxo); - if !i2c::write(dcxo, ADDRESS << 1) { - return Err("Si549 failed to ack write address") - } - if !i2c::write(dcxo, reg) { - return Err("Si549 failed to ack register") - } - i2c::stop(dcxo); - - i2c::start(dcxo); - if !i2c::write(dcxo, (ADDRESS << 1) | 1) { - return Err("Si549 failed to ack read address") - } - let val = i2c::read(dcxo, false); - i2c::stop(dcxo); - - Ok(val) - } - - pub fn program(dcxo: i2c::Dcxo, hsdiv: u16, lsdiv: u8, fbdiv: u64) -> Result<(), &'static str> { - i2c::init(dcxo)?; - - write(dcxo, 255, 0x00)?; // PAGE - write_no_ack_value(dcxo, 7, 0x80)?; // RESET - clock::spin_us(100_000); // required? not specified in datasheet. - - write(dcxo, 255, 0x00)?; // PAGE - write(dcxo, 69, 0x00)?; // Disable FCAL override. - // Note: Value 0x00 from Table 5.6 is inconsistent with Table 5.7, - // which shows bit 0 as reserved and =1. - write(dcxo, 17, 0x00)?; // Synchronously disable output - - // The Si549 has no ID register, so we check that it responds correctly - // by writing values to a RAM-like register and reading them back. - for test_value in 0..255 { - write(dcxo, 23, test_value)?; - let readback = read(dcxo, 23)?; - if readback != test_value { - return Err("Si549 detection failed"); - } - } - - write(dcxo, 23, hsdiv as u8)?; - write(dcxo, 24, (hsdiv >> 8) as u8 | (lsdiv << 4))?; - write(dcxo, 26, fbdiv as u8)?; - write(dcxo, 27, (fbdiv >> 8) as u8)?; - write(dcxo, 28, (fbdiv >> 16) as u8)?; - write(dcxo, 29, (fbdiv >> 24) as u8)?; - write(dcxo, 30, (fbdiv >> 32) as u8)?; - write(dcxo, 31, (fbdiv >> 40) as u8)?; - - write(dcxo, 7, 0x08)?; // Start FCAL - write(dcxo, 17, 0x01)?; // Synchronously enable output - - Ok(()) - } - - // Si549 digital frequency trim ("all-digital PLL" register) - // ∆ f_out = adpll * 0.0001164e-6 (0.1164 ppb/lsb) - // max trim range is +- 950 ppm - pub fn set_adpll(dcxo: i2c::Dcxo, adpll: i32) -> Result<(), &'static str> { - write(dcxo, 231, adpll as u8)?; - write(dcxo, 232, (adpll >> 8) as u8)?; - write(dcxo, 233, (adpll >> 16) as u8)?; - clock::spin_us(100); - Ok(()) - } - - pub fn get_adpll(dcxo: i2c::Dcxo) -> Result { - let b1 = read(dcxo, 231)? as i32; - let b2 = read(dcxo, 232)? as i32; - let b3 = read(dcxo, 233)? as i8 as i32; - Ok(b3 << 16 | b2 << 8 | b1) - } -} - -// to do: load from gateware config -const DDMTD_COUNTER_N: u32 = 15; -const DDMTD_COUNTER_M: u32 = (1 << DDMTD_COUNTER_N); -const F_SYS: f64 = csr::CONFIG_CLOCK_FREQUENCY as f64; - -const F_MAIN: f64 = 125.0e6; -const F_HELPER: f64 = F_MAIN * DDMTD_COUNTER_M as f64 / (DDMTD_COUNTER_M + 1) as f64; -const F_BEAT: f64 = F_MAIN - F_HELPER; -const TIME_STEP: f32 = 1./F_BEAT as f32; - -fn ddmtd_tag_to_s(mu: f32) -> f32 { - return (mu as f32)*TIME_STEP; -} - -fn get_frequencies() -> (u32, u32, u32) { - unsafe { - csr::wrpll::frequency_counter_update_en_write(1); - // wait for at least one full update cycle (> 2 timer periods) - clock::spin_us(200_000); - csr::wrpll::frequency_counter_update_en_write(0); - let helper = csr::wrpll::frequency_counter_counter_helper_read(); - let main = csr::wrpll::frequency_counter_counter_rtio_read(); - let cdr = csr::wrpll::frequency_counter_counter_rtio_rx0_read(); - (helper, main, cdr) - } -} - -fn log_frequencies() -> (u32, u32, u32) { - let (f_helper, f_main, f_cdr) = get_frequencies(); - let conv_khz = |f| 4*(f as u64)*(csr::CONFIG_CLOCK_FREQUENCY as u64)/(1000*(1 << 23)); - info!("helper clock frequency: {}kHz ({})", conv_khz(f_helper), f_helper); - info!("main clock frequency: {}kHz ({})", conv_khz(f_main), f_main); - info!("CDR clock frequency: {}kHz ({})", conv_khz(f_cdr), f_cdr); - (f_helper, f_main, f_cdr) -} - -fn get_tags() -> (i32, i32, u16, u16) { - unsafe { - csr::wrpll::tag_arm_write(1); - while csr::wrpll::tag_arm_read() != 0 {} - - let main_diff = csr::wrpll::main_diff_tag_read() as i32; - let helper_diff = csr::wrpll::helper_diff_tag_read() as i32; - let ref_tag = csr::wrpll::ref_tag_read(); - let main_tag = csr::wrpll::main_tag_read(); - (main_diff, helper_diff, ref_tag, main_tag) - } -} - -fn print_tags() { - const NUM_TAGS: usize = 30; - let mut main_diffs = [0; NUM_TAGS]; // input to main loop filter - let mut helper_diffs = [0; NUM_TAGS]; // input to helper loop filter - let mut ref_tags = [0; NUM_TAGS]; - let mut main_tags = [0; NUM_TAGS]; - let mut jitter = [0 as f32; NUM_TAGS]; - - for i in 0..NUM_TAGS { - let (main_diff, helper_diff, ref_tag, main_tag) = get_tags(); - main_diffs[i] = main_diff; - helper_diffs[i] = helper_diff; - ref_tags[i] = ref_tag; - main_tags[i] = main_tag; - } - info!("DDMTD ref tags: {:?}", ref_tags); - info!("DDMTD main tags: {:?}", main_tags); - info!("DDMTD main diffs: {:?}", main_diffs); - info!("DDMTD helper diffs: {:?}", helper_diffs); - - // look at the difference between the main DCXO and reference... - let t0 = main_diffs[0]; - main_diffs.iter_mut().for_each(|x| *x -= t0); - - // crude estimate of the max difference across our sample set (assumes no unwrapping issues...) - let delta = main_diffs[main_diffs.len()-1] as f32 / (main_diffs.len()-1) as f32; - info!("detla: {:?} tags", delta); - let delta_f: f32 = delta/DDMTD_COUNTER_M as f32 * F_BEAT as f32; - info!("MAIN <-> ref frequency difference: {:?} Hz ({:?} ppm)", delta_f, delta_f/F_HELPER as f32 * 1e6); - - jitter.iter_mut().enumerate().for_each(|(i, x)| *x = main_diffs[i] as f32 - delta*(i as f32)); - info!("jitter: {:?} tags", jitter); - - let var = jitter.iter().map(|x| x*x).fold(0 as f32, |acc, x| acc + x as f32) / NUM_TAGS as f32; - info!("variance: {:?} tags^2", var); -} - -pub fn init() { - info!("initializing WR PLL..."); - - unsafe { csr::wrpll::helper_reset_write(1); } - - unsafe { - csr::wrpll::helper_dcxo_i2c_address_write(si549::ADDRESS); - csr::wrpll::main_dcxo_i2c_address_write(si549::ADDRESS); - } - - #[cfg(rtio_frequency = "125.0")] - let (h_hsdiv, h_lsdiv, h_fbdiv) = (0x05c, 0, 0x04b5badb98a); - #[cfg(rtio_frequency = "125.0")] - let (m_hsdiv, m_lsdiv, m_fbdiv) = (0x05c, 0, 0x04b5c447213); - - si549::program(i2c::Dcxo::Main, m_hsdiv, m_lsdiv, m_fbdiv) - .expect("cannot initialize main Si549"); - si549::program(i2c::Dcxo::Helper, h_hsdiv, h_lsdiv, h_fbdiv) - .expect("cannot initialize helper Si549"); - // Si549 Settling Time for Large Frequency Change. - // Datasheet said 10ms but it lied. - clock::spin_us(50_000); - - unsafe { csr::wrpll::helper_reset_write(0); } - clock::spin_us(1); -} - -pub fn diagnostics() { - info!("WRPLL diagnostics..."); - info!("Untrimmed oscillator frequencies:"); - log_frequencies(); - - info!("Increase helper DCXO frequency by +10ppm (1.25kHz):"); - si549::set_adpll(i2c::Dcxo::Helper, 85911).expect("ADPLL write failed"); - // to do: add check on frequency? - log_frequencies(); -} - -fn trim_dcxos(f_helper: u32, f_main: u32, f_cdr: u32) -> Result<(i32, i32), &'static str> { - info!("Trimming oscillator frequencies..."); - const DCXO_STEP: i64 = (1.0e6/0.0001164) as i64; - const ADPLL_MAX: i64 = (950.0/0.0001164) as i64; - - const TIMER_WIDTH: u32 = 23; - const COUNTER_DIV: u32 = 2; - - // how many counts we expect to measure - const SYS_COUNTS: i64 = (1 << (TIMER_WIDTH - COUNTER_DIV)) as i64; - const EXP_MAIN_COUNTS: i64 = ((SYS_COUNTS as f64) * (F_MAIN/F_SYS)) as i64; - const EXP_HELPER_COUNTS: i64 = ((SYS_COUNTS as f64) * (F_HELPER/F_SYS)) as i64; - - // calibrate the SYS clock to the CDR clock and correct the measured counts - // assume frequency errors are small so we can make an additive correction - // positive error means sys clock is too fast - let sys_err: i64 = EXP_MAIN_COUNTS - (f_cdr as i64); - let main_err: i64 = EXP_MAIN_COUNTS - (f_main as i64) - sys_err; - let helper_err: i64 = EXP_HELPER_COUNTS - (f_helper as i64) - sys_err; - - info!("sys count err {}", sys_err); - info!("main counts err {}", main_err); - info!("helper counts err {}", helper_err); - - // calculate required adjustment to the ADPLL register see - // https://www.silabs.com/documents/public/data-sheets/si549-datasheet.pdf - // section 5.6 - let helper_adpll: i64 = helper_err*DCXO_STEP/EXP_HELPER_COUNTS; - let main_adpll: i64 = main_err*DCXO_STEP/EXP_MAIN_COUNTS; - if helper_adpll.abs() > ADPLL_MAX { - return Err("helper DCXO offset too large"); - } - if main_adpll.abs() > ADPLL_MAX { - return Err("main DCXO offset too large"); - } - - info!("ADPLL offsets: helper={} main={}", helper_adpll, main_adpll); - Ok((helper_adpll as i32, main_adpll as i32)) -} - -fn statistics(data: &[u16]) -> (f32, f32) { - let sum = data.iter().fold(0 as u32, |acc, x| acc + *x as u32); - let mean = sum as f32 / data.len() as f32; - - let squared_sum = data.iter().fold(0 as u32, |acc, x| acc + (*x as u32).pow(2)); - let variance = (squared_sum as f32 / data.len() as f32) - mean; - return (mean, variance) -} - -fn select_recovered_clock_int(rc: bool) -> Result<(), &'static str> { - info!("Untrimmed oscillator frequencies:"); - let (f_helper, f_main, f_cdr) = log_frequencies(); - if rc { - let (helper_adpll, main_adpll) = trim_dcxos(f_helper, f_main, f_cdr)?; - // to do: add assertion on max frequency shift here? - si549::set_adpll(i2c::Dcxo::Helper, helper_adpll).expect("ADPLL write failed"); - si549::set_adpll(i2c::Dcxo::Main, main_adpll).expect("ADPLL write failed"); - - log_frequencies(); - clock::spin_us(100_000); // TO DO: remove/reduce! - print_tags(); - - info!("increasing main DCXO by 1ppm (125Hz):"); - si549::set_adpll(i2c::Dcxo::Main, main_adpll + 8591).expect("ADPLL write failed"); - clock::spin_us(100_000); - print_tags(); - - si549::set_adpll(i2c::Dcxo::Main, main_adpll).expect("ADPLL write failed"); - - unsafe { - csr::wrpll::adpll_offset_helper_write(helper_adpll as u32); - csr::wrpll::adpll_offset_main_write(main_adpll as u32); - csr::wrpll::helper_dcxo_gpio_enable_write(0); - csr::wrpll::main_dcxo_gpio_enable_write(0); - csr::wrpll::helper_dcxo_errors_write(0xff); - csr::wrpll::main_dcxo_errors_write(0xff); - csr::wrpll::collector_reset_write(0); - } - clock::spin_us(1_000); // wait for the collector to produce meaningful output - unsafe { - csr::wrpll::filter_reset_write(0); - } - - clock::spin_us(100_000); - - print_tags(); -// let mut tags = [0; 10]; -// for i in 0..tags.len() { -// tags[i] = get_ddmtd_helper_tag(); -// } -// info!("DDMTD helper tags: {:?}", tags); - - unsafe { - csr::wrpll::filter_reset_write(1); - csr::wrpll::collector_reset_write(1); - } - clock::spin_us(50_000); - unsafe { - csr::wrpll::helper_dcxo_gpio_enable_write(1); - csr::wrpll::main_dcxo_gpio_enable_write(1); - } - unsafe { - info!("error {} {}", - csr::wrpll::helper_dcxo_errors_read(), - csr::wrpll::main_dcxo_errors_read()); - } - info!("new ADPLL: {} {}", - si549::get_adpll(i2c::Dcxo::Helper)?, - si549::get_adpll(i2c::Dcxo::Main)?); - } else { - si549::set_adpll(i2c::Dcxo::Helper, 0).expect("ADPLL write failed"); - si549::set_adpll(i2c::Dcxo::Main, 0).expect("ADPLL write failed"); - } - Ok(()) -} - -pub fn select_recovered_clock(rc: bool) { - if rc { - info!("switching to recovered clock"); - } else { - info!("switching to local XO clock"); - } - match select_recovered_clock_int(rc) { - Ok(()) => info!("clock transition completed"), - Err(e) => error!("clock transition failed: {}", e) - } -} diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 7d69f7d0d..365131b7a 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -12,8 +12,6 @@ use core::convert::TryFrom; use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp}; #[cfg(has_si5324)] use board_artiq::si5324; -#[cfg(has_wrpll)] -use board_artiq::wrpll; use board_artiq::{spi, drtioaux}; use board_artiq::drtio_routing; use riscv::register::{mcause, mepc, mtval}; @@ -420,8 +418,6 @@ fn sysclk_setup() { else { #[cfg(has_si5324)] si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324"); - #[cfg(has_wrpll)] - wrpll::init(); info!("Switching sys clock, rebooting..."); // delay for clean UART log, wait until UART FIFO is empty clock::spin_us(1300); @@ -460,17 +456,6 @@ pub extern fn main() -> i32 { io_expander1 = board_misoc::io_expander::IoExpander::new(1); io_expander0.init().expect("I2C I/O expander #0 initialization failed"); io_expander1.init().expect("I2C I/O expander #1 initialization failed"); - #[cfg(has_wrpll)] - { - io_expander0.set_oe(1, 1 << 7).unwrap(); - io_expander0.set(1, 7, true); - io_expander0.service().unwrap(); - io_expander1.set_oe(0, 1 << 7).unwrap(); - io_expander1.set_oe(1, 1 << 7).unwrap(); - io_expander1.set(0, 7, true); - io_expander1.set(1, 7, true); - io_expander1.service().unwrap(); - } // Actively drive TX_DISABLE to false on SFP0..3 io_expander0.set_oe(0, 1 << 1).unwrap(); @@ -490,8 +475,6 @@ pub extern fn main() -> i32 { unsafe { csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); } - #[cfg(has_wrpll)] - wrpll::diagnostics(); init_rtio_crg(); @@ -527,8 +510,6 @@ pub extern fn main() -> i32 { si5324::siphaser::select_recovered_clock(true).expect("failed to switch clocks"); si5324::siphaser::calibrate_skew().expect("failed to calibrate skew"); } - #[cfg(has_wrpll)] - wrpll::select_recovered_clock(true); drtioaux::reset(0); drtiosat_reset(false); @@ -565,8 +546,6 @@ pub extern fn main() -> i32 { info!("uplink is down, switching to local oscillator clock"); #[cfg(has_si5324)] si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks"); - #[cfg(has_wrpll)] - wrpll::select_recovered_clock(false); } } diff --git a/artiq/gateware/drtio/wrpll/__init__.py b/artiq/gateware/drtio/wrpll/__init__.py deleted file mode 100644 index 25e510f4c..000000000 --- a/artiq/gateware/drtio/wrpll/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from artiq.gateware.drtio.wrpll.core import WRPLL -from artiq.gateware.drtio.wrpll.ddmtd import DDMTDSamplerExtFF, DDMTDSamplerGTP diff --git a/artiq/gateware/drtio/wrpll/core.py b/artiq/gateware/drtio/wrpll/core.py deleted file mode 100644 index 3003d4848..000000000 --- a/artiq/gateware/drtio/wrpll/core.py +++ /dev/null @@ -1,156 +0,0 @@ -from migen import * -from migen.genlib.resetsync import AsyncResetSynchronizer -from migen.genlib.cdc import MultiReg, PulseSynchronizer -from misoc.interconnect.csr import * - -from artiq.gateware.drtio.wrpll.si549 import Si549 -from artiq.gateware.drtio.wrpll.ddmtd import DDMTD, Collector -from artiq.gateware.drtio.wrpll import thls, filters - - -class FrequencyCounter(Module, AutoCSR): - def __init__(self, timer_width=23, counter_width=23, domains=["helper", "sys", "rtio_rx0"]): - for domain in domains: - name = "counter_" + domain - counter = CSRStatus(counter_width, name=name) - setattr(self, name, counter) - self.update_en = CSRStorage() - - timer = Signal(timer_width) - timer_tick = Signal() - self.sync += Cat(timer, timer_tick).eq(timer + 1) - - for domain in domains: - sync_domain = getattr(self.sync, domain) - divider = Signal(2) - sync_domain += divider.eq(divider + 1) - - divided = Signal() - divided.attr.add("no_retiming") - sync_domain += divided.eq(divider[-1]) - divided_sys = Signal() - self.specials += MultiReg(divided, divided_sys) - - divided_sys_r = Signal() - divided_tick = Signal() - self.sync += divided_sys_r.eq(divided_sys) - self.comb += divided_tick.eq(divided_sys & ~divided_sys_r) - - counter = Signal(counter_width) - counter_csr = getattr(self, "counter_" + domain) - self.sync += [ - If(timer_tick, - If(self.update_en.storage, counter_csr.status.eq(counter)), - counter.eq(0), - ).Else( - If(divided_tick, counter.eq(counter + 1)) - ) - ] - - -class WRPLL(Module, AutoCSR): - def __init__(self, helper_clk_pads, main_dcxo_i2c, helper_dxco_i2c, ddmtd_inputs, N=15): - self.helper_reset = CSRStorage(reset=1) - self.collector_reset = CSRStorage(reset=1) - self.filter_reset = CSRStorage(reset=1) - self.adpll_offset_helper = CSRStorage(24) - self.adpll_offset_main = CSRStorage(24) - - self.tag_arm = CSR() - self.main_diff_tag = CSRStatus(32) - self.helper_diff_tag = CSRStatus(32) - self.ref_tag = CSRStatus(N) - self.main_tag = CSRStatus(N) - - main_diff_tag_32 = Signal((32, True)) - helper_diff_tag_32 = Signal((32, True)) - self.comb += [ - self.main_diff_tag.status.eq(main_diff_tag_32), - self.helper_diff_tag.status.eq(helper_diff_tag_32) - ] - - self.clock_domains.cd_helper = ClockDomain() - self.clock_domains.cd_collector = ClockDomain() - self.clock_domains.cd_filter = ClockDomain() - self.helper_reset.storage.attr.add("no_retiming") - self.filter_reset.storage.attr.add("no_retiming") - self.specials += Instance("IBUFGDS", - i_I=helper_clk_pads.p, i_IB=helper_clk_pads.n, - o_O=self.cd_helper.clk) - self.comb += [ - self.cd_collector.clk.eq(self.cd_collector.clk), - self.cd_filter.clk.eq(self.cd_helper.clk), - ] - self.specials += [ - AsyncResetSynchronizer(self.cd_helper, self.helper_reset.storage), - AsyncResetSynchronizer(self.cd_collector, self.collector_reset.storage), - AsyncResetSynchronizer(self.cd_filter, self.filter_reset.storage) - ] - - self.submodules.helper_dcxo = Si549(helper_dxco_i2c) - self.submodules.main_dcxo = Si549(main_dcxo_i2c) - - # for diagnostics and PLL initialization - self.submodules.frequency_counter = FrequencyCounter() - - ddmtd_counter = Signal(N) - self.sync.helper += ddmtd_counter.eq(ddmtd_counter + 1) - self.submodules.ddmtd_ref = DDMTD(ddmtd_counter, ddmtd_inputs.rec_clk) - self.submodules.ddmtd_main = DDMTD(ddmtd_counter, ddmtd_inputs.main_xo) - - collector_cd = ClockDomainsRenamer("collector") - filter_cd = ClockDomainsRenamer("filter") - self.submodules.collector = collector_cd(Collector(N)) - self.submodules.filter_helper = filter_cd( - thls.make(filters.helper, data_width=48)) - self.submodules.filter_main = filter_cd( - thls.make(filters.main, data_width=48)) - - self.comb += [ - self.collector.tag_ref.eq(self.ddmtd_ref.h_tag), - self.collector.ref_stb.eq(self.ddmtd_ref.h_tag_update), - self.collector.tag_main.eq(self.ddmtd_main.h_tag), - self.collector.main_stb.eq(self.ddmtd_main.h_tag_update) - ] - - collector_stb_ps = PulseSynchronizer("helper", "sys") - self.submodules += collector_stb_ps - self.sync.helper += collector_stb_ps.i.eq(self.collector.out_stb) - collector_stb_sys = Signal() - self.sync += collector_stb_sys.eq(collector_stb_ps.o) - - main_diff_tag_sys = Signal((N+2, True)) - helper_diff_tag_sys = Signal((N+2, True)) - ref_tag_sys = Signal(N) - main_tag_sys = Signal(N) - self.specials += MultiReg(self.collector.out_main, main_diff_tag_sys) - self.specials += MultiReg(self.collector.out_helper, helper_diff_tag_sys) - self.specials += MultiReg(self.collector.tag_ref, ref_tag_sys) - self.specials += MultiReg(self.collector.tag_main, main_tag_sys) - - self.sync += [ - If(self.tag_arm.re & self.tag_arm.r, self.tag_arm.w.eq(1)), - If(collector_stb_sys, - self.tag_arm.w.eq(0), - If(self.tag_arm.w, - main_diff_tag_32.eq(main_diff_tag_sys), - helper_diff_tag_32.eq(helper_diff_tag_sys), - self.ref_tag.status.eq(ref_tag_sys), - self.main_tag.status.eq(main_tag_sys) - ) - ) - ] - - self.comb += [ - self.filter_helper.input.eq(self.collector.out_helper << 22), - self.filter_helper.input_stb.eq(self.collector.out_stb), - self.filter_main.input.eq(self.collector.out_main), - self.filter_main.input_stb.eq(self.collector.out_stb) - ] - - self.sync.helper += [ - self.helper_dcxo.adpll_stb.eq(self.filter_helper.output_stb), - self.helper_dcxo.adpll.eq(self.filter_helper.output + self.adpll_offset_helper.storage), - self.main_dcxo.adpll_stb.eq(self.filter_main.output_stb), - self.main_dcxo.adpll.eq(self.filter_main.output + self.adpll_offset_main.storage) - ] diff --git a/artiq/gateware/drtio/wrpll/ddmtd.py b/artiq/gateware/drtio/wrpll/ddmtd.py deleted file mode 100644 index ddeeac54e..000000000 --- a/artiq/gateware/drtio/wrpll/ddmtd.py +++ /dev/null @@ -1,221 +0,0 @@ -from migen import * -from migen.genlib.cdc import PulseSynchronizer, MultiReg -from migen.genlib.fsm import FSM -from misoc.interconnect.csr import * - - -class DDMTDSamplerExtFF(Module): - def __init__(self, ddmtd_inputs): - self.rec_clk = Signal() - self.main_xo = Signal() - - # # # - - # TODO: s/h timing at FPGA pads - if hasattr(ddmtd_inputs, "rec_clk"): - rec_clk_1 = ddmtd_inputs.rec_clk - else: - rec_clk_1 = Signal() - self.specials += Instance("IBUFDS", - i_I=ddmtd_inputs.rec_clk_p, i_IB=ddmtd_inputs.rec_clk_n, - o_O=rec_clk_1) - if hasattr(ddmtd_inputs, "main_xo"): - main_xo_1 = ddmtd_inputs.main_xo - else: - main_xo_1 = Signal() - self.specials += Instance("IBUFDS", - i_I=ddmtd_inputs.main_xo_p, i_IB=ddmtd_inputs.main_xo_n, - o_O=main_xo_1) - self.specials += [ - Instance("FD", i_C=ClockSignal("helper"), - i_D=rec_clk_1, o_Q=self.rec_clk, - attr={("IOB", "TRUE")}), - Instance("FD", i_C=ClockSignal("helper"), - i_D=main_xo_1, o_Q=self.main_xo, - attr={("IOB", "TRUE")}), - ] - - -class DDMTDSamplerGTP(Module): - def __init__(self, gtp, main_xo_pads): - self.rec_clk = Signal() - self.main_xo = Signal() - - # # # - - # Getting the main XO signal from IBUFDS_GTE2 is problematic because - # the transceiver PLL craps out if an improper clock signal is applied, - # so we are disabling the buffer until the clock is stable. - main_xo_se = Signal() - rec_clk_1 = Signal() - main_xo_1 = Signal() - self.specials += [ - Instance("IBUFDS", - i_I=main_xo_pads.p, i_IB=main_xo_pads.n, - o_O=main_xo_se), - Instance("FD", i_C=ClockSignal("helper"), - i_D=gtp.cd_rtio_rx0.clk, o_Q=rec_clk_1, - attr={("DONT_TOUCH", "TRUE")}), - Instance("FD", i_C=ClockSignal("helper"), - i_D=rec_clk_1, o_Q=self.rec_clk, - attr={("DONT_TOUCH", "TRUE")}), - Instance("FD", i_C=ClockSignal("helper"), - i_D=main_xo_se, o_Q=main_xo_1, - attr={("IOB", "TRUE")}), - Instance("FD", i_C=ClockSignal("helper"), - i_D=main_xo_1, o_Q=self.main_xo, - attr={("DONT_TOUCH", "TRUE")}), - ] - - -class DDMTDDeglitcherFirstEdge(Module): - def __init__(self, input_signal, blind_period=128): - self.detect = Signal() - self.tag_correction = 0 - - rising = Signal() - input_signal_r = Signal() - self.sync.helper += [ - input_signal_r.eq(input_signal), - rising.eq(input_signal & ~input_signal_r) - ] - - blind_counter = Signal(max=blind_period) - self.sync.helper += [ - If(blind_counter != 0, blind_counter.eq(blind_counter - 1)), - If(input_signal_r, blind_counter.eq(blind_period - 1)), - self.detect.eq(rising & (blind_counter == 0)) - ] - - -class DDMTD(Module): - def __init__(self, counter, input_signal): - - # in helper clock domain - self.h_tag = Signal(len(counter)) - self.h_tag_update = Signal() - - # # # - - deglitcher = DDMTDDeglitcherFirstEdge(input_signal) - self.submodules += deglitcher - - self.sync.helper += [ - self.h_tag_update.eq(0), - If(deglitcher.detect, - self.h_tag_update.eq(1), - self.h_tag.eq(counter + deglitcher.tag_correction) - ) - ] - - -class Collector(Module): - """Generates loop filter inputs from DDMTD outputs. - - The input to the main DCXO lock loop filter is the difference between the - reference and main tags after unwrapping (see below). - - The input to the helper DCXO lock loop filter is the difference between the - current reference tag and the previous reference tag after unwrapping. - - When the WR PLL is locked, the following ideally (no noise/jitter) obtain: - - f_main = f_ref - - f_helper = f_ref * 2^N/(2^N+1) - - f_beat = f_ref - f_helper = f_ref / (2^N + 1) (cycle time is: dt=1/f_beat) - - the reference and main DCXO tags are equal to each other at every cycle - (the main DCXO lock drives this difference to 0) - - the reference and main DCXO tags both have the same value at each cycle - (the tag difference for each DDMTD is given by - f_helper*dt = f_helper/f_beat = 2^N, which causes the N-bit DDMTD counter - to wrap around and come back to its previous value) - - Note that we currently lock the frequency of the helper DCXO to the - reference clock, not it's phase. As a result, while the tag differences are - controlled, their absolute values are arbitrary. We could consider moving - the helper lock to a phase lock at some point in the future... - - Since the DDMTD counter is only N bits, it is possible for tag values to - wrap around. This will happen frequently if the locked tags happens to be - near the edges of the counter, so that jitter can easily cause a phase wrap. - But, it can also easily happen during lock acquisition or other transients. - To avoid glitches in the output, we unwrap the tag differences. Currently - we do this in hardware, but we should consider extending the processor to - allow us to do it inside the filters. Since the processor uses wider - signals, this would significantly extend the overall glitch-free - range of the PLL and may aid lock acquisition. - """ - def __init__(self, N): - self.ref_stb = Signal() - self.main_stb = Signal() - self.tag_ref = Signal(N) - self.tag_main = Signal(N) - - self.out_stb = Signal() - self.out_main = Signal((N+2, True)) - self.out_helper = Signal((N+2, True)) - self.out_tag_ref = Signal(N) - self.out_tag_main = Signal(N) - - tag_ref_r = Signal(N) - tag_main_r = Signal(N) - main_tag_diff = Signal((N+2, True)) - helper_tag_diff = Signal((N+2, True)) - - # # # - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - NextValue(self.out_stb, 0), - If(self.ref_stb & self.main_stb, - NextValue(tag_ref_r, self.tag_ref), - NextValue(tag_main_r, self.tag_main), - NextState("DIFF") - ).Elif(self.ref_stb, - NextValue(tag_ref_r, self.tag_ref), - NextState("WAITMAIN") - ).Elif(self.main_stb, - NextValue(tag_main_r, self.tag_main), - NextState("WAITREF") - ) - ) - fsm.act("WAITREF", - If(self.ref_stb, - NextValue(tag_ref_r, self.tag_ref), - NextState("DIFF") - ) - ) - fsm.act("WAITMAIN", - If(self.main_stb, - NextValue(tag_main_r, self.tag_main), - NextState("DIFF") - ) - ) - fsm.act("DIFF", - NextValue(main_tag_diff, tag_main_r - tag_ref_r), - NextValue(helper_tag_diff, tag_ref_r - self.out_tag_ref), - NextState("UNWRAP") - ) - fsm.act("UNWRAP", - If(main_tag_diff - self.out_main > 2**(N-1), - NextValue(main_tag_diff, main_tag_diff - 2**N) - ).Elif(self.out_main - main_tag_diff > 2**(N-1), - NextValue(main_tag_diff, main_tag_diff + 2**N) - ), - - If(helper_tag_diff - self.out_helper > 2**(N-1), - NextValue(helper_tag_diff, helper_tag_diff - 2**N) - ).Elif(self.out_helper - helper_tag_diff > 2**(N-1), - NextValue(helper_tag_diff, helper_tag_diff + 2**N) - ), - NextState("OUTPUT") - ) - fsm.act("OUTPUT", - NextValue(self.out_tag_ref, tag_ref_r), - NextValue(self.out_tag_main, tag_main_r), - NextValue(self.out_main, main_tag_diff), - NextValue(self.out_helper, helper_tag_diff), - NextValue(self.out_stb, 1), - NextState("IDLE") - ) diff --git a/artiq/gateware/drtio/wrpll/filters.py b/artiq/gateware/drtio/wrpll/filters.py deleted file mode 100644 index 470f17bf3..000000000 --- a/artiq/gateware/drtio/wrpll/filters.py +++ /dev/null @@ -1,61 +0,0 @@ -helper_xn1 = 0 -helper_xn2 = 0 -helper_yn0 = 0 -helper_yn1 = 0 -helper_yn2 = 0 -helper_out = 0 - -main_xn1 = 0 -main_xn2 = 0 -main_yn0 = 0 -main_yn1 = 0 -main_yn2 = 0 - - -def helper(tag_diff): - global helper_xn1, helper_xn2, helper_yn0, \ - helper_yn1, helper_yn2, helper_out - - helper_xn0 = 0 - tag_diff # *(2**22) - - helper_yr = 4294967296 - - helper_yn2 = helper_yn1 - helper_yn1 = helper_yn0 - - helper_yn0 = (284885690 * (helper_xn0 - + (217319150 * helper_xn1 >> 44) - - (17591968725108 * helper_xn2 >> 44) - ) >> 44 - ) + (35184372088832*helper_yn1 >> 44) - helper_yn2 - - helper_xn2 = helper_xn1 - helper_xn1 = helper_xn0 - - helper_out = 268435456*helper_yn0 >> 44 - helper_out = min(helper_out, helper_yr) - helper_out = max(helper_out, 0 - helper_yr) - - return helper_out - - -def main(main_xn0): - global main_xn1, main_xn2, main_yn0, main_yn1, main_yn2 - - main_yr = 4294967296 - - main_yn2 = main_yn1 - main_yn1 = main_yn0 - main_yn0 = ( - ((133450380908*(((35184372088832*main_xn0) >> 44) + - ((17592186044417*main_xn1) >> 44))) >> 44) + - ((29455872930889*main_yn1) >> 44) - - ((12673794781453*main_yn2) >> 44)) - - main_xn2 = main_xn1 - main_xn1 = main_xn0 - - main_yn0 = min(main_yn0, main_yr) - main_yn0 = max(main_yn0, 0 - main_yr) - - return main_yn0 diff --git a/artiq/gateware/drtio/wrpll/si549.py b/artiq/gateware/drtio/wrpll/si549.py deleted file mode 100644 index 46ce0c138..000000000 --- a/artiq/gateware/drtio/wrpll/si549.py +++ /dev/null @@ -1,340 +0,0 @@ -from migen import * -from migen.genlib.fsm import * -from migen.genlib.cdc import MultiReg, PulseSynchronizer, BlindTransfer - -from misoc.interconnect.csr import * - - -class I2CClockGen(Module): - def __init__(self, width): - self.load = Signal(width) - self.clk2x = Signal() - - cnt = Signal.like(self.load) - self.comb += [ - self.clk2x.eq(cnt == 0), - ] - self.sync += [ - If(self.clk2x, - cnt.eq(self.load), - ).Else( - cnt.eq(cnt - 1), - ) - ] - - -class I2CMasterMachine(Module): - def __init__(self, clock_width): - self.scl = Signal(reset=1) - self.sda_o = Signal(reset=1) - self.sda_i = Signal() - - self.submodules.cg = CEInserter()(I2CClockGen(clock_width)) - self.start = Signal() - self.stop = Signal() - self.write = Signal() - self.ack = Signal() - self.data = Signal(8) - self.ready = Signal() - - ### - - bits = Signal(4) - data = Signal(8) - - fsm = CEInserter()(FSM("IDLE")) - self.submodules += fsm - - fsm.act("IDLE", - self.ready.eq(1), - If(self.start, - NextState("START0"), - ).Elif(self.stop, - NextState("STOP0"), - ).Elif(self.write, - NextValue(bits, 8), - NextValue(data, self.data), - NextState("WRITE0") - ) - ) - - fsm.act("START0", - NextValue(self.scl, 1), - NextState("START1") - ) - fsm.act("START1", - NextValue(self.sda_o, 0), - NextState("IDLE") - ) - - fsm.act("STOP0", - NextValue(self.scl, 0), - NextState("STOP1") - ) - fsm.act("STOP1", - NextValue(self.sda_o, 0), - NextState("STOP2") - ) - fsm.act("STOP2", - NextValue(self.scl, 1), - NextState("STOP3") - ) - fsm.act("STOP3", - NextValue(self.sda_o, 1), - NextState("IDLE") - ) - - fsm.act("WRITE0", - NextValue(self.scl, 0), - NextState("WRITE1") - ) - fsm.act("WRITE1", - If(bits == 0, - NextValue(self.sda_o, 1), - NextState("READACK0"), - ).Else( - NextValue(self.sda_o, data[7]), - NextState("WRITE2"), - ) - ) - fsm.act("WRITE2", - NextValue(self.scl, 1), - NextValue(data[1:], data[:-1]), - NextValue(bits, bits - 1), - NextState("WRITE0"), - ) - fsm.act("READACK0", - NextValue(self.scl, 1), - NextState("READACK1"), - ) - fsm.act("READACK1", - NextValue(self.ack, ~self.sda_i), - NextState("IDLE") - ) - - run = Signal() - idle = Signal() - self.comb += [ - run.eq((self.start | self.stop | self.write) & self.ready), - idle.eq(~run & fsm.ongoing("IDLE")), - self.cg.ce.eq(~idle), - fsm.ce.eq(run | self.cg.clk2x), - ] - - -class ADPLLProgrammer(Module): - def __init__(self): - self.i2c_divider = Signal(16) - self.i2c_address = Signal(7) - - self.adpll = Signal(24) - self.stb = Signal() - self.busy = Signal() - self.nack = Signal() - - self.scl = Signal() - self.sda_i = Signal() - self.sda_o = Signal() - - self.scl.attr.add("no_retiming") - self.sda_o.attr.add("no_retiming") - - # # # - - master = I2CMasterMachine(16) - self.submodules += master - - self.comb += [ - master.cg.load.eq(self.i2c_divider), - self.scl.eq(master.scl), - master.sda_i.eq(self.sda_i), - self.sda_o.eq(master.sda_o) - ] - - fsm = FSM() - self.submodules += fsm - - adpll = Signal.like(self.adpll) - - fsm.act("IDLE", - If(self.stb, - NextValue(adpll, self.adpll), - NextState("START") - ) - ) - fsm.act("START", - master.start.eq(1), - If(master.ready, NextState("DEVADDRESS")) - ) - fsm.act("DEVADDRESS", - master.data.eq(self.i2c_address << 1), - master.write.eq(1), - If(master.ready, NextState("REGADRESS")) - ) - fsm.act("REGADRESS", - master.data.eq(231), - master.write.eq(1), - If(master.ready, - If(master.ack, - NextState("DATA0") - ).Else( - self.nack.eq(1), - NextState("STOP") - ) - ) - ) - fsm.act("DATA0", - master.data.eq(adpll[0:8]), - master.write.eq(1), - If(master.ready, - If(master.ack, - NextState("DATA1") - ).Else( - self.nack.eq(1), - NextState("STOP") - ) - ) - ) - fsm.act("DATA1", - master.data.eq(adpll[8:16]), - master.write.eq(1), - If(master.ready, - If(master.ack, - NextState("DATA2") - ).Else( - self.nack.eq(1), - NextState("STOP") - ) - ) - ) - fsm.act("DATA2", - master.data.eq(adpll[16:24]), - master.write.eq(1), - If(master.ready, - If(~master.ack, self.nack.eq(1)), - NextState("STOP") - ) - ) - fsm.act("STOP", - master.stop.eq(1), - If(master.ready, - If(~master.ack, self.nack.eq(1)), - NextState("IDLE") - ) - ) - - self.comb += self.busy.eq(~fsm.ongoing("IDLE")) - - -def simulate_programmer(): - from migen.sim.core import run_simulation - - dut = ADPLLProgrammer() - - def generator(): - yield dut.i2c_divider.eq(4) - yield dut.i2c_address.eq(0x55) - yield - yield dut.adpll.eq(0x123456) - yield dut.stb.eq(1) - yield - yield dut.stb.eq(0) - yield - while (yield dut.busy): - yield - for _ in range(20): - yield - - run_simulation(dut, generator(), vcd_name="tb.vcd") - - -class Si549(Module, AutoCSR): - def __init__(self, pads): - self.gpio_enable = CSRStorage(reset=1) - self.gpio_in = CSRStatus(2) - self.gpio_out = CSRStorage(2) - self.gpio_oe = CSRStorage(2) - - self.i2c_divider = CSRStorage(16, reset=75) - self.i2c_address = CSRStorage(7) - self.errors = CSR(2) - - # in helper clock domain - self.adpll = Signal(24) - self.adpll_stb = Signal() - - # # # - - programmer = ClockDomainsRenamer("helper")(ADPLLProgrammer()) - self.submodules += programmer - - self.i2c_divider.storage.attr.add("no_retiming") - self.i2c_address.storage.attr.add("no_retiming") - self.specials += [ - MultiReg(self.i2c_divider.storage, programmer.i2c_divider, "helper"), - MultiReg(self.i2c_address.storage, programmer.i2c_address, "helper") - ] - self.comb += [ - programmer.adpll.eq(self.adpll), - programmer.stb.eq(self.adpll_stb) - ] - - self.gpio_enable.storage.attr.add("no_retiming") - self.gpio_out.storage.attr.add("no_retiming") - self.gpio_oe.storage.attr.add("no_retiming") - - # SCL GPIO and mux - ts_scl = TSTriple(1) - self.specials += ts_scl.get_tristate(pads.scl) - - status = Signal() - self.comb += self.gpio_in.status[0].eq(status) - - self.specials += MultiReg(ts_scl.i, status) - self.comb += [ - If(self.gpio_enable.storage, - ts_scl.o.eq(self.gpio_out.storage[0]), - ts_scl.oe.eq(self.gpio_oe.storage[0]) - ).Else( - ts_scl.o.eq(0), - ts_scl.oe.eq(~programmer.scl) - ) - ] - - # SDA GPIO and mux - ts_sda = TSTriple(1) - self.specials += ts_sda.get_tristate(pads.sda) - - status = Signal() - self.comb += self.gpio_in.status[1].eq(status) - - self.specials += MultiReg(ts_sda.i, status) - self.comb += [ - If(self.gpio_enable.storage, - ts_sda.o.eq(self.gpio_out.storage[1]), - ts_sda.oe.eq(self.gpio_oe.storage[1]) - ).Else( - ts_sda.o.eq(0), - ts_sda.oe.eq(~programmer.sda_o) - ) - ] - self.specials += MultiReg(ts_sda.i, programmer.sda_i, "helper") - - # Error reporting - collision_cdc = BlindTransfer("helper", "sys") - self.submodules += collision_cdc - self.comb += collision_cdc.i.eq(programmer.stb & programmer.busy) - - nack_cdc = PulseSynchronizer("helper", "sys") - self.submodules += nack_cdc - self.comb += nack_cdc.i.eq(programmer.nack) - - for n, trig in enumerate([collision_cdc.o, nack_cdc.o]): - self.sync += [ - If(self.errors.re & self.errors.r[n], self.errors.w[n].eq(0)), - If(trig, self.errors.w[n].eq(1)) - ] - - -if __name__ == "__main__": - simulate_programmer() diff --git a/artiq/gateware/drtio/wrpll/thls.py b/artiq/gateware/drtio/wrpll/thls.py deleted file mode 100644 index b11459692..000000000 --- a/artiq/gateware/drtio/wrpll/thls.py +++ /dev/null @@ -1,618 +0,0 @@ -import inspect -import ast -from copy import copy -import operator -from functools import reduce -from collections import OrderedDict - -from migen import * -from migen.genlib.fsm import * - - -class Isn: - def __init__(self, immediate=None, inputs=None, outputs=None): - if inputs is None: - inputs = [] - if outputs is None: - outputs = [] - self.immediate = immediate - self.inputs = inputs - self.outputs = outputs - - def __repr__(self): - r = "<" - r += self.__class__.__name__ - if self.immediate is not None: - r += " (" + str(self.immediate) + ")" - for inp in self.inputs: - r += " r" + str(inp) - if self.outputs: - r += " ->" - for outp in self.outputs: - r += " r" + str(outp) - r += ">" - return r - - -class NopIsn(Isn): - opcode = 0 - -class AddIsn(Isn): - opcode = 1 - -class SubIsn(Isn): - opcode = 2 - -class MulShiftIsn(Isn): - opcode = 3 - -# opcode = 4: MulShift with alternate shift - -class MinIsn(Isn): - opcode = 5 - -class MaxIsn(Isn): - opcode = 6 - -class CopyIsn(Isn): - opcode = 7 - -class InputIsn(Isn): - opcode = 8 - -class OutputIsn(Isn): - opcode = 9 - -class EndIsn(Isn): - opcode = 10 - - -class ASTCompiler: - def __init__(self): - self.program = [] - self.data = [] - self.next_ssa_reg = -1 - self.constants = dict() - self.names = dict() - self.globals = OrderedDict() - - def get_ssa_reg(self): - r = self.next_ssa_reg - self.next_ssa_reg -= 1 - return r - - def add_global(self, name): - if name not in self.globals: - r = len(self.data) - self.data.append(0) - self.names[name] = r - self.globals[name] = r - - def input(self, name): - target = self.get_ssa_reg() - self.program.append(InputIsn(outputs=[target])) - self.names[name] = target - - def emit(self, node): - if isinstance(node, ast.BinOp): - if isinstance(node.op, ast.RShift): - if not isinstance(node.left, ast.BinOp) or not isinstance(node.left.op, ast.Mult): - raise NotImplementedError - if not isinstance(node.right, ast.Num): - raise NotImplementedError - left = self.emit(node.left.left) - right = self.emit(node.left.right) - cons = lambda **kwargs: MulShiftIsn(immediate=node.right.n, **kwargs) - else: - left = self.emit(node.left) - right = self.emit(node.right) - if isinstance(node.op, ast.Add): - cons = AddIsn - elif isinstance(node.op, ast.Sub): - cons = SubIsn - elif isinstance(node.op, ast.Mult): - cons = lambda **kwargs: MulShiftIsn(immediate=0, **kwargs) - else: - raise NotImplementedError - output = self.get_ssa_reg() - self.program.append(cons(inputs=[left, right], outputs=[output])) - return output - elif isinstance(node, ast.Call): - if not isinstance(node.func, ast.Name): - raise NotImplementedError - funcname = node.func.id - if node.keywords: - raise NotImplementedError - inputs = [self.emit(x) for x in node.args] - if funcname == "min": - cons = MinIsn - elif funcname == "max": - cons = MaxIsn - else: - raise NotImplementedError - output = self.get_ssa_reg() - self.program.append(cons(inputs=inputs, outputs=[output])) - return output - elif isinstance(node, (ast.Num, ast.UnaryOp)): - if isinstance(node, ast.UnaryOp): - if not isinstance(node.operand, ast.Num): - raise NotImplementedError - if isinstance(node.op, ast.UAdd): - transform = lambda x: x - elif isinstance(node.op, ast.USub): - transform = operator.neg - elif isinstance(node.op, ast.Invert): - transform = operator.invert - else: - raise NotImplementedError - node = node.operand - else: - transform = lambda x: x - n = transform(node.n) - if n in self.constants: - return self.constants[n] - else: - r = len(self.data) - self.data.append(n) - self.constants[n] = r - return r - elif isinstance(node, ast.Name): - return self.names[node.id] - elif isinstance(node, ast.Assign): - output = self.emit(node.value) - for target in node.targets: - assert isinstance(target, ast.Name) - self.names[target.id] = output - elif isinstance(node, ast.Return): - value = self.emit(node.value) - self.program.append(OutputIsn(inputs=[value])) - elif isinstance(node, ast.Global): - pass - else: - raise NotImplementedError - - -class Processor: - def __init__(self, data_width=32, multiplier_stages=2): - self.data_width = data_width - self.multiplier_stages = multiplier_stages - self.multiplier_shifts = [] - self.program_rom_size = None - self.data_ram_size = None - self.opcode_bits = 4 - self.reg_bits = None - - def get_instruction_latency(self, isn): - return { - AddIsn: 2, - SubIsn: 2, - MulShiftIsn: 1 + self.multiplier_stages, - MinIsn: 2, - MaxIsn: 2, - CopyIsn: 1, - InputIsn: 1 - }[isn.__class__] - - def encode_instruction(self, isn, exit): - opcode = isn.opcode - if isn.immediate is not None and not isinstance(isn, MulShiftIsn): - r0 = isn.immediate - if len(isn.inputs) >= 1: - r1 = isn.inputs[0] - else: - r1 = 0 - else: - if len(isn.inputs) >= 1: - r0 = isn.inputs[0] - else: - r0 = 0 - if len(isn.inputs) >= 2: - r1 = isn.inputs[1] - else: - r1 = 0 - r = 0 - for value, bits in ((exit, self.reg_bits), (r1, self.reg_bits), (r0, self.reg_bits), (opcode, self.opcode_bits)): - r <<= bits - r |= value - return r - - def instruction_bits(self): - return 3*self.reg_bits + self.opcode_bits - - def implement(self, program, data): - return ProcessorImpl(self, program, data) - - -class Scheduler: - def __init__(self, processor, reserved_data, program): - self.processor = processor - self.reserved_data = reserved_data - self.used_registers = set(range(self.reserved_data)) - self.exits = dict() - self.program = program - self.remaining = copy(program) - self.output = [] - - def allocate_register(self): - r = min(set(range(max(self.used_registers) + 2)) - self.used_registers) - self.used_registers.add(r) - return r - - def free_register(self, r): - assert r >= self.reserved_data - self.used_registers.discard(r) - - def find_inputs(self, cycle, isn): - mapped_inputs = [] - for inp in isn.inputs: - if inp >= 0: - mapped_inputs.append(inp) - else: - found = False - for i in range(cycle): - if i in self.exits: - r, rm = self.exits[i] - if r == inp: - mapped_inputs.append(rm) - found = True - break - if not found: - return None - return mapped_inputs - - def schedule_one(self, isn): - cycle = len(self.output) - mapped_inputs = self.find_inputs(cycle, isn) - if mapped_inputs is None: - return False - - if isn.outputs: - # check that exit slot is free - latency = self.processor.get_instruction_latency(isn) - exit = cycle + latency - if exit in self.exits: - return False - - # avoid RAW hazard with global writeback - for output in isn.outputs: - if output >= 0: - for risn in self.remaining: - for inp in risn.inputs: - if inp == output: - return False - - # Instruction can be scheduled - - self.remaining.remove(isn) - - for inp, minp in zip(isn.inputs, mapped_inputs): - can_free = inp < 0 and all(inp != rinp for risn in self.remaining for rinp in risn.inputs) - if can_free: - self.free_register(minp) - - if isn.outputs: - assert len(isn.outputs) == 1 - if isn.outputs[0] < 0: - output = self.allocate_register() - else: - output = isn.outputs[0] - self.exits[exit] = (isn.outputs[0], output) - self.output.append(isn.__class__(immediate=isn.immediate, inputs=mapped_inputs)) - - return True - - def schedule(self): - while self.remaining: - success = False - for isn in self.remaining: - if self.schedule_one(isn): - success = True - break - if not success: - self.output.append(NopIsn()) - self.output += [NopIsn()]*(max(self.exits.keys()) - len(self.output) + 1) - return self.output - - -class CompiledProgram: - def __init__(self, processor, program, exits, data, glbs): - self.processor = processor - self.program = program - self.exits = exits - self.data = data - self.globals = glbs - - def pretty_print(self): - for cycle, isn in enumerate(self.program): - l = "{:4d} {:15}".format(cycle, str(isn)) - if cycle in self.exits: - l += " -> r{}".format(self.exits[cycle]) - print(l) - - def dimension_processor(self): - self.processor.program_rom_size = len(self.program) - self.processor.data_ram_size = len(self.data) - self.processor.reg_bits = (self.processor.data_ram_size - 1).bit_length() - for isn in self.program: - if isinstance(isn, MulShiftIsn) and isn.immediate not in self.processor.multiplier_shifts: - self.processor.multiplier_shifts.append(isn.immediate) - - def encode(self): - r = [] - for i, isn in enumerate(self.program): - exit = self.exits.get(i, 0) - r.append(self.processor.encode_instruction(isn, exit)) - return r - - -def compile(processor, function): - node = ast.parse(inspect.getsource(function)) - assert isinstance(node, ast.Module) - assert len(node.body) == 1 - node = node.body[0] - assert isinstance(node, ast.FunctionDef) - assert len(node.args.args) == 1 - arg = node.args.args[0].arg - body = node.body - - astcompiler = ASTCompiler() - for node in body: - if isinstance(node, ast.Global): - for name in node.names: - astcompiler.add_global(name) - arg_r = astcompiler.input(arg) - for node in body: - astcompiler.emit(node) - if isinstance(node, ast.Return): - break - for glbl, location in astcompiler.globals.items(): - new_location = astcompiler.names[glbl] - if new_location != location: - astcompiler.program.append(CopyIsn(inputs=[new_location], outputs=[location])) - - scheduler = Scheduler(processor, len(astcompiler.data), astcompiler.program) - scheduler.schedule() - - program = copy(scheduler.output) - program.append(EndIsn()) - - max_reg = max(max(max(isn.inputs + [0]) for isn in program), max(v[1] for k, v in scheduler.exits.items())) - - return CompiledProgram( - processor=processor, - program=program, - exits={k: v[1] for k, v in scheduler.exits.items()}, - data=astcompiler.data + [0]*(max_reg - len(astcompiler.data) + 1), - glbs=astcompiler.globals) - - -class BaseUnit(Module): - def __init__(self, data_width): - self.stb_i = Signal() - self.i0 = Signal((data_width, True)) - self.i1 = Signal((data_width, True)) - self.stb_o = Signal() - self.o = Signal((data_width, True)) - - -class NopUnit(BaseUnit): - pass - - -class OpUnit(BaseUnit): - def __init__(self, op, data_width, stages, op_data_width=None): - BaseUnit.__init__(self, data_width) - # work around Migen's mishandling of Verilog's cretinous operator width rules - if op_data_width is None: - op_data_width = data_width - - if stages > 1: - # Vivado backward retiming for DSP does not work correctly if DSP inputs - # are not registered. - i0 = Signal.like(self.i0) - i1 = Signal.like(self.i1) - stb_i = Signal() - self.sync += [ - i0.eq(self.i0), - i1.eq(self.i1), - stb_i.eq(self.stb_i) - ] - output_stages = stages - 1 - else: - i0, i1, stb_i = self.i0, self.i1, self.stb_i - output_stages = stages - - o = Signal((op_data_width, True)) - self.comb += o.eq(op(i0, i1)) - stb_o = stb_i - for i in range(output_stages): - n_o = Signal((data_width, True)) - if stages > 1: - n_o.attr.add(("retiming_backward", 1)) - n_stb_o = Signal() - self.sync += [ - n_o.eq(o), - n_stb_o.eq(stb_o) - ] - o = n_o - stb_o = n_stb_o - self.comb += [ - self.o.eq(o), - self.stb_o.eq(stb_o) - ] - - -class SelectUnit(BaseUnit): - def __init__(self, op, data_width): - BaseUnit.__init__(self, data_width) - - self.sync += [ - self.stb_o.eq(self.stb_i), - If(op(self.i0, self.i1), - self.o.eq(self.i0) - ).Else( - self.o.eq(self.i1) - ) - ] - - -class CopyUnit(BaseUnit): - def __init__(self, data_width): - BaseUnit.__init__(self, data_width) - - self.comb += [ - self.stb_o.eq(self.stb_i), - self.o.eq(self.i0) - ] - - -class InputUnit(BaseUnit): - def __init__(self, data_width, input_stb, input): - BaseUnit.__init__(self, data_width) - self.buffer = Signal(data_width) - - self.comb += [ - self.stb_o.eq(self.stb_i), - self.o.eq(self.buffer) - ] - - -class OutputUnit(BaseUnit): - def __init__(self, data_width, output_stb, output): - BaseUnit.__init__(self, data_width) - - self.sync += [ - output_stb.eq(self.stb_i), - output.eq(self.i0) - ] - - -class ProcessorImpl(Module): - def __init__(self, pd, program, data): - self.input_stb = Signal() - self.input = Signal((pd.data_width, True)) - - self.output_stb = Signal() - self.output = Signal((pd.data_width, True)) - - self.busy = Signal() - - # # # - - program_mem = Memory(pd.instruction_bits(), pd.program_rom_size, init=program) - data_mem0 = Memory(pd.data_width, pd.data_ram_size, init=data) - data_mem1 = Memory(pd.data_width, pd.data_ram_size, init=data) - self.specials += program_mem, data_mem0, data_mem1 - - pc = Signal(pd.instruction_bits()) - pc_next = Signal.like(pc) - pc_en = Signal() - self.sync += pc.eq(pc_next) - self.comb += [ - If(pc_en, - pc_next.eq(pc + 1) - ).Else( - pc_next.eq(0) - ) - ] - program_mem_port = program_mem.get_port() - self.specials += program_mem_port - self.comb += program_mem_port.adr.eq(pc_next) - - s = 0 - opcode = Signal(pd.opcode_bits) - self.comb += opcode.eq(program_mem_port.dat_r[s:s+pd.opcode_bits]) - s += pd.opcode_bits - r0 = Signal(pd.reg_bits) - self.comb += r0.eq(program_mem_port.dat_r[s:s+pd.reg_bits]) - s += pd.reg_bits - r1 = Signal(pd.reg_bits) - self.comb += r1.eq(program_mem_port.dat_r[s:s+pd.reg_bits]) - s += pd.reg_bits - exit = Signal(pd.reg_bits) - self.comb += exit.eq(program_mem_port.dat_r[s:s+pd.reg_bits]) - - data_read_port0 = data_mem0.get_port() - data_read_port1 = data_mem1.get_port() - self.specials += data_read_port0, data_read_port1 - self.comb += [ - data_read_port0.adr.eq(r0), - data_read_port1.adr.eq(r1) - ] - - data_write_port = data_mem0.get_port(write_capable=True) - data_write_port_dup = data_mem1.get_port(write_capable=True) - self.specials += data_write_port, data_write_port_dup - self.comb += [ - data_write_port_dup.we.eq(data_write_port.we), - data_write_port_dup.adr.eq(data_write_port.adr), - data_write_port_dup.dat_w.eq(data_write_port.dat_w), - data_write_port.adr.eq(exit) - ] - - nop = NopUnit(pd.data_width) - adder = OpUnit(operator.add, pd.data_width, 1) - subtractor = OpUnit(operator.sub, pd.data_width, 1) - if pd.multiplier_shifts: - if len(pd.multiplier_shifts) != 1: - raise NotImplementedError - multiplier = OpUnit(lambda a, b: a * b >> pd.multiplier_shifts[0], - pd.data_width, pd.multiplier_stages, op_data_width=2*pd.data_width) - else: - multiplier = NopUnit(pd.data_width) - minu = SelectUnit(operator.lt, pd.data_width) - maxu = SelectUnit(operator.gt, pd.data_width) - copier = CopyUnit(pd.data_width) - inu = InputUnit(pd.data_width, self.input_stb, self.input) - outu = OutputUnit(pd.data_width, self.output_stb, self.output) - units = [nop, adder, subtractor, multiplier, minu, maxu, copier, inu, outu] - self.submodules += units - - for unit in units: - self.sync += unit.stb_i.eq(0) - self.comb += [ - unit.i0.eq(data_read_port0.dat_r), - unit.i1.eq(data_read_port1.dat_r), - If(unit.stb_o, - data_write_port.we.eq(1), - data_write_port.dat_w.eq(unit.o) - ) - ] - - decode_table = [ - (NopIsn.opcode, nop), - (AddIsn.opcode, adder), - (SubIsn.opcode, subtractor), - (MulShiftIsn.opcode, multiplier), - (MulShiftIsn.opcode + 1, multiplier), - (MinIsn.opcode, minu), - (MaxIsn.opcode, maxu), - (CopyIsn.opcode, copier), - (InputIsn.opcode, inu), - (OutputIsn.opcode, outu) - ] - for allocated_opcode, unit in decode_table: - self.sync += If(pc_en & (opcode == allocated_opcode), unit.stb_i.eq(1)) - - fsm = FSM() - self.submodules += fsm - fsm.act("IDLE", - pc_en.eq(0), - NextValue(inu.buffer, self.input), - If(self.input_stb, NextState("PROCESSING")) - ) - fsm.act("PROCESSING", - self.busy.eq(1), - pc_en.eq(1), - If(opcode == EndIsn.opcode, - pc_en.eq(0), - NextState("IDLE") - ) - ) - - -def make(function, **kwargs): - proc = Processor(**kwargs) - cp = compile(proc, function) - cp.dimension_processor() - return proc.implement(cp.encode(), cp.data) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 9adfac0a2..448faefd7 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -21,7 +21,6 @@ from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path from artiq.gateware import eem from artiq.gateware.drtio.transceiver import gtp_7series from artiq.gateware.drtio.siphaser import SiPhaser7Series -from artiq.gateware.drtio.wrpll import WRPLL, DDMTDSamplerGTP from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer from artiq.gateware.drtio import * from artiq.build_soc import * @@ -410,7 +409,7 @@ class SatelliteBase(BaseSoC): } mem_map.update(BaseSoC.mem_map) - def __init__(self, rtio_clk_freq=125e6, enable_sata=False, *, with_wrpll=False, gateware_identifier_str=None, hw_rev="v2.0", **kwargs): + def __init__(self, rtio_clk_freq=125e6, enable_sata=False, *, gateware_identifier_str=None, hw_rev="v2.0", **kwargs): if hw_rev in ("v1.0", "v1.1"): cpu_bus_width = 32 else: @@ -533,35 +532,18 @@ class SatelliteBase(BaseSoC): rtio_clk_period = 1e9/rtio_clk_freq self.config["RTIO_FREQUENCY"] = str(rtio_clk_freq/1e6) - if with_wrpll: - self.submodules.wrpll_sampler = DDMTDSamplerGTP( - self.drtio_transceiver, - platform.request("cdr_clk_clean_fabric")) - helper_clk_pads = platform.request("ddmtd_helper_clk") - self.submodules.wrpll = WRPLL( - helper_clk_pads=helper_clk_pads, - main_dcxo_i2c=platform.request("ddmtd_main_dcxo_i2c"), - helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c"), - ddmtd_inputs=self.wrpll_sampler) - self.csr_devices.append("wrpll") - # note: do not use self.wrpll.cd_helper.clk; otherwise, vivado craps out with: - # critical warning: create_clock attempting to set clock on an unknown port/pin - # command: "create_clock -period 7.920000 -waveform {0.000000 3.960000} -name - # helper_clk [get_xlnx_outside_genome_inst_pin 20 0] - platform.add_period_constraint(helper_clk_pads.p, rtio_clk_period*0.99) - platform.add_false_path_constraints(self.crg.cd_sys.clk, helper_clk_pads.p) - else: - self.submodules.siphaser = SiPhaser7Series( - si5324_clkin=platform.request("cdr_clk") if platform.hw_rev == "v2.0" - else platform.request("si5324_clkin"), - rx_synchronizer=self.rx_synchronizer, - ref_clk=self.crg.clk125_div2, ref_div2=True, - rtio_clk_freq=rtio_clk_freq) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) - self.csr_devices.append("siphaser") - self.config["HAS_SI5324"] = None - self.config["SI5324_SOFT_RESET"] = None + + self.submodules.siphaser = SiPhaser7Series( + si5324_clkin=platform.request("cdr_clk") if platform.hw_rev == "v2.0" + else platform.request("si5324_clkin"), + rx_synchronizer=self.rx_synchronizer, + ref_clk=self.crg.clk125_div2, ref_div2=True, + rtio_clk_freq=rtio_clk_freq) + platform.add_false_path_constraints( + self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) + self.csr_devices.append("siphaser") + self.config["HAS_SI5324"] = None + self.config["SI5324_SOFT_RESET"] = None gtp = self.drtio_transceiver.gtps[0] txout_buf = Signal() @@ -573,9 +555,6 @@ class SatelliteBase(BaseSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtp.txoutclk, gtp.rxoutclk) - if with_wrpll: - platform.add_false_path_constraints( - helper_clk_pads.p, gtp.rxoutclk) for gtp in self.drtio_transceiver.gtps[1:]: platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period) platform.add_false_path_constraints( @@ -652,7 +631,6 @@ def main(): parser.add_argument("-V", "--variant", default="tester", help="variant: {} (default: %(default)s)".format( "/".join(sorted(VARIANTS.keys())))) - parser.add_argument("--with-wrpll", default=False, action="store_true") parser.add_argument("--tester-dds", default=None, help="Tester variant DDS type: ad9910/ad9912 " "(default: ad9910)") @@ -661,8 +639,6 @@ def main(): args = parser.parse_args() argdict = dict() - if args.with_wrpll: - argdict["with_wrpll"] = True argdict["gateware_identifier_str"] = args.gateware_identifier_str argdict["dds"] = args.tester_dds diff --git a/artiq/gateware/test/wrpll/__init__.py b/artiq/gateware/test/wrpll/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/artiq/gateware/test/wrpll/test_dsp.py b/artiq/gateware/test/wrpll/test_dsp.py deleted file mode 100644 index 033e69853..000000000 --- a/artiq/gateware/test/wrpll/test_dsp.py +++ /dev/null @@ -1,158 +0,0 @@ -import unittest - -import numpy as np - -from migen import * - -from artiq.gateware.drtio.wrpll.ddmtd import Collector -from artiq.gateware.drtio.wrpll import thls, filters - - -class HelperChainTB(Module): - def __init__(self, N): - self.tag_ref = Signal(N) - self.input_stb = Signal() - self.adpll = Signal((24, True)) - self.out_stb = Signal() - - ### - - self.submodules.collector = Collector(N) - self.submodules.loop_filter = thls.make(filters.helper, data_width=48) - - self.comb += [ - self.collector.tag_ref.eq(self.tag_ref), - self.collector.ref_stb.eq(self.input_stb), - self.collector.main_stb.eq(self.input_stb), - self.loop_filter.input.eq(self.collector.out_helper << 22), - self.loop_filter.input_stb.eq(self.collector.out_stb), - self.adpll.eq(self.loop_filter.output), - self.out_stb.eq(self.loop_filter.output_stb), - ] - - -class TestDSP(unittest.TestCase): - def test_main_collector(self): - N = 2 - collector = Collector(N=N) - # check collector phase unwrapping - tags = [(0, 0, 0), - (0, 1, 1), - (2, 1, -1), - (3, 1, -2), - (0, 1, -3), - (1, 1, -4), - (2, 1, -5), - (3, 1, -6), - (3, 3, -4), - (0, 0, -4), - (0, 1, -3), - (0, 2, -2), - (0, 3, -1), - (0, 0, 0)] - for i in range(10): - tags.append((i % (2**N), (i+1) % (2**N), 1)) - - def generator(): - for tag_ref, tag_main, out in tags: - yield collector.tag_ref.eq(tag_ref) - yield collector.tag_main.eq(tag_main) - yield collector.main_stb.eq(1) - yield collector.ref_stb.eq(1) - - yield - - yield collector.main_stb.eq(0) - yield collector.ref_stb.eq(0) - - while not (yield collector.out_stb): - yield - - out_main = yield collector.out_main - self.assertEqual(out_main, out) - - run_simulation(collector, generator()) - - def test_helper_collector(self): - N = 3 - collector = Collector(N=N) - # check collector phase unwrapping - tags = [((2**N - 1 - tag) % (2**N), -1) for tag in range(20)] - tags += [((tags[-1][0] + 1 + tag) % (2**N), 1) for tag in range(20)] - tags += [((tags[-1][0] - 2 - 2*tag) % (2**N), -2) for tag in range(20)] - - def generator(): - for tag_ref, out in tags: - yield collector.tag_ref.eq(tag_ref) - yield collector.main_stb.eq(1) - yield collector.ref_stb.eq(1) - - yield - - yield collector.main_stb.eq(0) - yield collector.ref_stb.eq(0) - - while not (yield collector.out_stb): - yield - - out_helper = yield collector.out_helper - self.assertEqual(out_helper, out) - - run_simulation(collector, generator()) - - # test helper collector + filter against output from MATLAB model - def test_helper_chain(self): - pll = HelperChainTB(15) - - initial_helper_out = -8000 - ref_tags = np.array([ - 24778, 16789, 8801, 814, 25596, 17612, 9628, 1646, - 26433, 18453, 10474, 2496, 27287, 19311, 11337, 3364, 28160, - 20190, 12221, 4253, 29054, 21088, 13124, 5161, 29966, 22005, - 14045, 6087, 30897, 22940, 14985, 7031, 31847, 23895, 15944, - 7995, 47, 24869, 16923, 8978, 1035, 25861, 17920, 9981, - 2042, 26873, 18937, 11002, 3069, 27904, 19973, 12042, 4113, - 28953, 21026, 13100, 5175, 30020, 22098, 14177, 6257, 31106, - 23189, 15273, 7358, 32212, 24300, 16388, 8478, 569, 25429, - 17522, 9617, 1712, 26577, 18675, 10774, 2875, 27745, 19848, - 11951, 4056, 28930, 21038, 13147, 5256, 30135, 22247, 14361, - 6475, 31359, 23476, 15595, 7714, 32603, 24725, 16847, 8971, - 1096 - ]) - adpll_sim = np.array([ - 8, 24, 41, 57, 74, 91, 107, 124, 140, 157, 173, - 190, 206, 223, 239, 256, 273, 289, 306, 322, 339, 355, - 372, 388, 405, 421, 438, 454, 471, 487, 504, 520, 537, - 553, 570, 586, 603, 619, 636, 652, 668, 685, 701, 718, - 734, 751, 767, 784, 800, 817, 833, 850, 866, 882, 899, - 915, 932, 948, 965, 981, 998, 1014, 1030, 1047, 1063, 1080, - 1096, 1112, 1129, 1145, 1162, 1178, 1194, 1211, 1227, 1244, 1260, - 1276, 1293, 1309, 1326, 1342, 1358, 1375, 1391, 1407, 1424, 1440, - 1457, 1473, 1489, 1506, 1522, 1538, 1555, 1571, 1587, 1604, 1620, - 1636]) - - def sim(): - yield pll.collector.out_helper.eq(initial_helper_out) - for ref_tag, adpll_matlab in zip(ref_tags, adpll_sim): - # feed collector - yield pll.tag_ref.eq(int(ref_tag)) - yield pll.input_stb.eq(1) - - yield - - yield pll.input_stb.eq(0) - - while not (yield pll.collector.out_stb): - yield - - tag_diff = yield pll.collector.out_helper - - while not (yield pll.loop_filter.output_stb): - yield - - adpll_migen = yield pll.adpll - self.assertEqual(adpll_migen, adpll_matlab) - - yield - - run_simulation(pll, [sim()]) diff --git a/artiq/gateware/test/wrpll/test_thls.py b/artiq/gateware/test/wrpll/test_thls.py deleted file mode 100644 index c1013de30..000000000 --- a/artiq/gateware/test/wrpll/test_thls.py +++ /dev/null @@ -1,55 +0,0 @@ -import unittest - -from migen import * - -from artiq.gateware.drtio.wrpll import thls - - -a = 0 - -def simple_test(x): - global a - a = a + (x*4 >> 1) - return a - - -class TestTHLS(unittest.TestCase): - def test_thls(self): - global a - - proc = thls.Processor() - a = 0 - cp = thls.compile(proc, simple_test) - print("Program:") - cp.pretty_print() - cp.dimension_processor() - print("Encoded program:", cp.encode()) - proc_impl = proc.implement(cp.encode(), cp.data) - - def send_values(values): - for value in values: - yield proc_impl.input.eq(value) - yield proc_impl.input_stb.eq(1) - yield - yield proc_impl.input.eq(0) - yield proc_impl.input_stb.eq(0) - yield - while (yield proc_impl.busy): - yield - @passive - def receive_values(callback): - while True: - while not (yield proc_impl.output_stb): - yield - callback((yield proc_impl.output)) - yield - - send_list = [42, 40, 10, 10] - receive_list = [] - - run_simulation(proc_impl, [send_values(send_list), receive_values(receive_list.append)]) - print("Execution:", send_list, "->", receive_list) - - a = 0 - expected_list = [simple_test(x) for x in send_list] - self.assertEqual(receive_list, expected_list) diff --git a/doc/wrpll_diagram.png b/doc/wrpll_diagram.png deleted file mode 100644 index 1085e0b15335dc913758370250c819caa810a42a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58653 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

25xcf?lM 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 Date: Fri, 6 Jan 2023 17:59:18 +0800 Subject: [PATCH 13/16] remove RTIOClockMultiplier --- artiq/gateware/rtio/xilinx_clocking.py | 36 -------------------------- artiq/gateware/targets/kc705.py | 2 +- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/artiq/gateware/rtio/xilinx_clocking.py b/artiq/gateware/rtio/xilinx_clocking.py index 20e0c36c6..aff4786bf 100644 --- a/artiq/gateware/rtio/xilinx_clocking.py +++ b/artiq/gateware/rtio/xilinx_clocking.py @@ -1,39 +1,3 @@ -from migen import * -from migen.genlib.cdc import MultiReg -from misoc.interconnect.csr import * - - -class RTIOClockMultiplier(Module, AutoCSR): - def __init__(self, rtio_clk_freq): - self.pll_reset = CSRStorage(reset=1) - self.pll_locked = CSRStatus() - self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) - - # See "Global Clock Network Deskew Using Two BUFGs" in ug472. - clkfbout = Signal() - clkfbin = Signal() - rtiox4_clk = Signal() - pll_locked = Signal() - self.specials += [ - Instance("MMCME2_BASE", - p_CLKIN1_PERIOD=1e9/rtio_clk_freq, - i_CLKIN1=ClockSignal("sys"), - i_RST=self.pll_reset.storage, - o_LOCKED=pll_locked, - - p_CLKFBOUT_MULT_F=8.0, p_DIVCLK_DIVIDE=1, - - o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbin, - - p_CLKOUT0_DIVIDE_F=2.0, o_CLKOUT0=rtiox4_clk, - ), - Instance("BUFG", i_I=clkfbout, o_O=clkfbin), - Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), - - MultiReg(pll_locked, self.pll_locked.status) - ] - - def fix_serdes_timing_path(platform): # ignore timing of path from OSERDESE2 through the pad to ISERDESE2 platform.add_platform_command( diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 3ad5f5bdf..037b9f108 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -17,7 +17,7 @@ from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.amp import AMPSoC 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 From ec893222a444dee480d05e6d4e526d03cd4acafd Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Jan 2023 18:22:05 +0800 Subject: [PATCH 14/16] rtio: remove support for async mode --- artiq/gateware/drtio/core.py | 4 +- artiq/gateware/rtio/core.py | 4 +- artiq/gateware/rtio/cri.py | 22 +++------ artiq/gateware/rtio/input_collector.py | 36 ++++----------- artiq/gateware/rtio/sed/core.py | 46 ++++++------------- artiq/gateware/rtio/sed/fifos.py | 16 ++----- artiq/gateware/rtio/tsc.py | 2 +- artiq/gateware/targets/kasli.py | 8 ++-- artiq/gateware/targets/kc705.py | 8 ++-- artiq/gateware/test/drtio/test_full_stack.py | 2 +- artiq/gateware/test/drtio/test_switching.py | 4 +- artiq/gateware/test/rtio/test_dma.py | 2 +- .../test/rtio/test_input_collector.py | 4 +- artiq/gateware/test/rtio/test_sed_top.py | 2 +- 14 files changed, 53 insertions(+), 107 deletions(-) diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index e8ca07e3f..434751ccc 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -58,7 +58,7 @@ class SyncRTIO(Module): assert tsc.glbl_fine_ts_width >= chan_fine_ts_width self.submodules.outputs = ClockDomainsRenamer("rio")( - SED(channels, tsc.glbl_fine_ts_width, "sync", + SED(channels, tsc.glbl_fine_ts_width, lane_count=lane_count, fifo_depth=fifo_depth, enable_spread=False, report_buffer_space=True, interface=self.cri)) @@ -66,7 +66,7 @@ class SyncRTIO(Module): self.sync += self.outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16) self.submodules.inputs = ClockDomainsRenamer("rio")( - InputCollector(tsc, channels, "sync", interface=self.cri)) + InputCollector(tsc, channels, interface=self.cri)) for attr, _ in async_errors_layout: self.comb += getattr(self.async_errors, attr).eq(getattr(self.outputs, attr)) diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 66144ceca..c4dae4dc1 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -60,7 +60,7 @@ class Core(Module, AutoCSR): # Outputs/Inputs quash_channels = [n for n, c in enumerate(channels) if isinstance(c, LogChannel)] - outputs = SED(channels, tsc.glbl_fine_ts_width, "sync", + outputs = SED(channels, tsc.glbl_fine_ts_width, quash_channels=quash_channels, lane_count=lane_count, fifo_depth=fifo_depth, interface=self.cri) @@ -68,7 +68,7 @@ class Core(Module, AutoCSR): self.comb += outputs.coarse_timestamp.eq(tsc.coarse_ts) self.sync += outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16) - inputs = InputCollector(tsc, channels, "sync", + inputs = InputCollector(tsc, channels, quash_channels=quash_channels, interface=self.cri) self.submodules += inputs diff --git a/artiq/gateware/rtio/cri.py b/artiq/gateware/rtio/cri.py index 8b38f4529..41bd20eeb 100644 --- a/artiq/gateware/rtio/cri.py +++ b/artiq/gateware/rtio/cri.py @@ -127,7 +127,7 @@ class KernelInitiator(Module, AutoCSR): class CRIDecoder(Module): - def __init__(self, slaves=2, master=None, mode="async", enable_routing=False): + def __init__(self, slaves=2, master=None, enable_routing=False): if isinstance(slaves, int): slaves = [Interface() for _ in range(slaves)] if master is None: @@ -155,10 +155,7 @@ class CRIDecoder(Module): if enable_routing: self.specials.routing_table = Memory(slave_bits, 256) - if mode == "async" or mode == "sync": - rtp_decoder = self.routing_table.get_port() - else: - raise ValueError + rtp_decoder = self.routing_table.get_port() self.specials += rtp_decoder self.comb += [ rtp_decoder.adr.eq(self.master.chan_sel[16:]), @@ -185,7 +182,7 @@ class CRIDecoder(Module): class CRISwitch(Module, AutoCSR): - def __init__(self, masters=2, slave=None, mode="async"): + def __init__(self, masters=2, slave=None): if isinstance(masters, int): masters = [Interface() for _ in range(masters)] if slave is None: @@ -197,11 +194,6 @@ class CRISwitch(Module, AutoCSR): # # # - if mode == "async" or mode == "sync": - selected = self.selected.storage - else: - raise ValueError - if len(masters) == 1: self.comb += masters[0].connect(slave) else: @@ -209,7 +201,7 @@ class CRISwitch(Module, AutoCSR): for name, size, direction in layout: if direction == DIR_M_TO_S: choices = Array(getattr(m, name) for m in masters) - self.comb += getattr(slave, name).eq(choices[selected]) + self.comb += getattr(slave, name).eq(choices[self.selected.storage]) # connect slave->master signals for name, size, direction in layout: @@ -221,10 +213,10 @@ class CRISwitch(Module, AutoCSR): class CRIInterconnectShared(Module): - def __init__(self, masters=2, slaves=2, mode="async", enable_routing=False): + def __init__(self, masters=2, slaves=2, enable_routing=False): shared = Interface() - self.submodules.switch = CRISwitch(masters, shared, mode) - self.submodules.decoder = CRIDecoder(slaves, shared, mode, enable_routing) + self.submodules.switch = CRISwitch(masters, shared) + self.submodules.decoder = CRIDecoder(slaves, shared, enable_routing) def get_csrs(self): return self.switch.get_csrs() diff --git a/artiq/gateware/rtio/input_collector.py b/artiq/gateware/rtio/input_collector.py index a65fe6d9d..75c018c06 100644 --- a/artiq/gateware/rtio/input_collector.py +++ b/artiq/gateware/rtio/input_collector.py @@ -1,6 +1,6 @@ from migen import * from migen.genlib.record import Record -from migen.genlib.fifo import * +from migen.genlib.fifo import SyncFIFOBuffered from migen.genlib.cdc import BlindTransfer from artiq.gateware.rtio import cri @@ -24,24 +24,13 @@ def get_channel_layout(coarse_ts_width, interface): class InputCollector(Module): - def __init__(self, tsc, channels, mode, quash_channels=[], interface=None): + def __init__(self, tsc, channels, quash_channels=[], interface=None): if interface is None: interface = cri.Interface() self.cri = interface # # # - if mode == "sync": - fifo_factory = SyncFIFOBuffered - sync_io = self.sync - sync_cri = self.sync - elif mode == "async": - fifo_factory = lambda *args: ClockDomainsRenamer({"write": "rio", "read": "sys"})(AsyncFIFO(*args)) - sync_io = self.sync.rio - sync_cri = self.sync.sys - else: - raise ValueError - i_statuses, i_datas, i_timestamps = [], [], [] i_ack = Signal() sel = self.cri.chan_sel[:16] @@ -55,7 +44,7 @@ class InputCollector(Module): # FIFO layout = get_channel_layout(len(tsc.coarse_ts), iif) - fifo = fifo_factory(layout_len(layout), channel.ififo_depth) + fifo = SyncFIFOBuffered(layout_len(layout), channel.ififo_depth) self.submodules += fifo fifo_in = Record(layout) fifo_out = Record(layout) @@ -67,7 +56,7 @@ class InputCollector(Module): # FIFO write if iif.delay: counter_rtio = Signal.like(tsc.coarse_ts, reset_less=True) - sync_io += counter_rtio.eq(tsc.coarse_ts - (iif.delay + 1)) + self.sync += counter_rtio.eq(tsc.coarse_ts - (iif.delay + 1)) else: counter_rtio = tsc.coarse_ts if hasattr(fifo_in, "data"): @@ -80,17 +69,8 @@ class InputCollector(Module): self.comb += fifo_in.timestamp.eq(full_ts) self.comb += fifo.we.eq(iif.stb) - overflow_io = Signal() - self.comb += overflow_io.eq(fifo.we & ~fifo.writable) - if mode == "sync": - overflow_trigger = overflow_io - elif mode == "async": - overflow_transfer = BlindTransfer("rio", "sys") - self.submodules += overflow_transfer - self.comb += overflow_transfer.i.eq(overflow_io) - overflow_trigger = overflow_transfer.o - else: - raise ValueError + overflow_trigger = Signal() + self.comb += overflow_trigger.eq(fifo.we & ~fifo.writable) # FIFO read, CRI connection if hasattr(fifo_out, "data"): @@ -107,7 +87,7 @@ class InputCollector(Module): self.comb += selected.eq(sel == n) overflow = Signal() - sync_cri += [ + self.sync += [ If(selected & i_ack, overflow.eq(0)), If(overflow_trigger, @@ -122,7 +102,7 @@ class InputCollector(Module): input_pending = Signal() self.cri.i_data.reset_less = True self.cri.i_timestamp.reset_less = True - sync_cri += [ + self.sync += [ i_ack.eq(0), If(i_ack, self.cri.i_status.eq(Cat(~i_status_raw[0], i_status_raw[1], 0)), diff --git a/artiq/gateware/rtio/sed/core.py b/artiq/gateware/rtio/sed/core.py index 2b3611854..8953ff9d2 100644 --- a/artiq/gateware/rtio/sed/core.py +++ b/artiq/gateware/rtio/sed/core.py @@ -11,41 +11,25 @@ __all__ = ["SED"] class SED(Module): - def __init__(self, channels, glbl_fine_ts_width, mode, + def __init__(self, channels, glbl_fine_ts_width, lane_count=8, fifo_depth=128, enable_spread=True, quash_channels=[], report_buffer_space=False, interface=None): - if mode == "sync": - lane_dist_cdr = lambda x: x - fifos_cdr = lambda x: x - gates_cdr = lambda x: x - output_driver_cdr = lambda x: x - elif mode == "async": - lane_dist_cdr = ClockDomainsRenamer("sys") - fifos_cdr = ClockDomainsRenamer({"write": "sys", "read": "rio"}) - gates_cdr = ClockDomainsRenamer("rio") - output_driver_cdr = ClockDomainsRenamer("rio") - else: - raise ValueError - seqn_width = layouts.seqn_width(lane_count, fifo_depth) - self.submodules.lane_dist = lane_dist_cdr( - LaneDistributor(lane_count, seqn_width, - layouts.fifo_payload(channels), - [channel.interface.o.delay for channel in channels], - glbl_fine_ts_width, - enable_spread=enable_spread, - quash_channels=quash_channels, - interface=interface)) - self.submodules.fifos = fifos_cdr( - FIFOs(lane_count, fifo_depth, - layouts.fifo_payload(channels), mode, report_buffer_space)) - self.submodules.gates = gates_cdr( - Gates(lane_count, seqn_width, - layouts.fifo_payload(channels), - layouts.output_network_payload(channels, glbl_fine_ts_width))) - self.submodules.output_driver = output_driver_cdr( - OutputDriver(channels, glbl_fine_ts_width, lane_count, seqn_width)) + self.submodules.lane_dist = LaneDistributor(lane_count, seqn_width, + layouts.fifo_payload(channels), + [channel.interface.o.delay for channel in channels], + glbl_fine_ts_width, + enable_spread=enable_spread, + quash_channels=quash_channels, + interface=interface) + self.submodules.fifos = FIFOs(lane_count, fifo_depth, + layouts.fifo_payload(channels), report_buffer_space) + self.submodules.gates = Gates(lane_count, seqn_width, + layouts.fifo_payload(channels), + layouts.output_network_payload(channels, glbl_fine_ts_width)) + self.submodules.output_driver = OutputDriver(channels, glbl_fine_ts_width, + lane_count, seqn_width) for o, i in zip(self.lane_dist.output, self.fifos.input): self.comb += o.connect(i) diff --git a/artiq/gateware/rtio/sed/fifos.py b/artiq/gateware/rtio/sed/fifos.py index cbecccf07..3bf1bfc5a 100644 --- a/artiq/gateware/rtio/sed/fifos.py +++ b/artiq/gateware/rtio/sed/fifos.py @@ -2,7 +2,7 @@ from operator import or_ from functools import reduce from migen import * -from migen.genlib.fifo import * +from migen.genlib.fifo import SyncFIFOBuffered from artiq.gateware.rtio.sed import layouts @@ -11,7 +11,7 @@ __all__ = ["FIFOs"] class FIFOs(Module): - def __init__(self, lane_count, fifo_depth, layout_payload, mode, report_buffer_space=False): + def __init__(self, lane_count, fifo_depth, layout_payload, report_buffer_space=False): seqn_width = layouts.seqn_width(lane_count, fifo_depth) self.input = [Record(layouts.fifo_ingress(seqn_width, layout_payload)) for _ in range(lane_count)] @@ -23,16 +23,9 @@ class FIFOs(Module): # # # - if mode == "sync": - fifo_cls = SyncFIFOBuffered - elif mode == "async": - fifo_cls = AsyncFIFOBuffered - else: - raise ValueError - fifos = [] for input, output in zip(self.input, self.output): - fifo = fifo_cls(seqn_width + layout_len(layout_payload), fifo_depth) + fifo = SyncFIFOBuffered(seqn_width + layout_len(layout_payload), fifo_depth) self.submodules += fifo fifos.append(fifo) @@ -47,9 +40,6 @@ class FIFOs(Module): ] if report_buffer_space: - if mode != "sync": - raise NotImplementedError - def compute_max(elts): l = len(elts) if l == 1: diff --git a/artiq/gateware/rtio/tsc.py b/artiq/gateware/rtio/tsc.py index f2c316047..063583a3d 100644 --- a/artiq/gateware/rtio/tsc.py +++ b/artiq/gateware/rtio/tsc.py @@ -1,7 +1,7 @@ from migen import * class TSC(Module): - def __init__(self, mode, glbl_fine_ts_width=0): + def __init__(self, glbl_fine_ts_width=0): self.glbl_fine_ts_width = glbl_fine_ts_width # in rtio domain diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 448faefd7..1d33c6e2a 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -102,7 +102,7 @@ class StandaloneBase(MiniSoC, AMPSoC): def add_rtio(self, rtio_channels, sed_lanes=8): fix_serdes_timing_path(self.platform) - 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, lane_count=sed_lanes) self.csr_devices.append("rtio_core") self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) @@ -286,7 +286,7 @@ class MasterBase(MiniSoC, AMPSoC): self.comb += [self.virtual_leds.get(i + 1).eq(channel.rx_ready) for i, channel in enumerate(sfp_channels)] - 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 = [] @@ -480,7 +480,7 @@ class SatelliteBase(BaseSoC): self.comb += [self.virtual_leds.get(i).eq(channel.rx_ready) for i, channel in enumerate(sfp_channels)] - 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 = [] @@ -573,7 +573,7 @@ class SatelliteBase(BaseSoC): 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) self.csr_devices.append("routing_table") diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 037b9f108..4aac6e2ce 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -149,7 +149,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.config["HAS_DDS"] = None 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") self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) @@ -218,7 +218,7 @@ class _MasterBase(MiniSoC, AMPSoC): clk_freq=self.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) drtio_csr_group = [] drtioaux_csr_group = [] @@ -358,7 +358,7 @@ class _SatelliteBase(BaseSoC): clk_freq=self.clk_freq) self.csr_devices.append("drtio_transceiver") - 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 = [] @@ -456,7 +456,7 @@ class _SatelliteBase(BaseSoC): 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) self.csr_devices.append("routing_table") diff --git a/artiq/gateware/test/drtio/test_full_stack.py b/artiq/gateware/test/drtio/test_full_stack.py index 7cafe16a1..ade67f5a9 100644 --- a/artiq/gateware/test/drtio/test_full_stack.py +++ b/artiq/gateware/test/drtio/test_full_stack.py @@ -67,7 +67,7 @@ class DUT(Module): rtio.Channel.from_phy(self.phy1), rtio.Channel.from_phy(self.phy2), ] - self.submodules.tsc_satellite = rtio.TSC("sync") + self.submodules.tsc_satellite = rtio.TSC() self.submodules.satellite = DRTIOSatellite( self.tsc_satellite, self.transceivers.bob, rx_synchronizer) self.satellite.reset.storage.reset = 0 diff --git a/artiq/gateware/test/drtio/test_switching.py b/artiq/gateware/test/drtio/test_switching.py index 1f7876ade..942ff0c0e 100644 --- a/artiq/gateware/test/drtio/test_switching.py +++ b/artiq/gateware/test/drtio/test_switching.py @@ -40,12 +40,12 @@ class DUT(Module): def __init__(self, nwords): self.transceivers = DummyTransceiverPair(nwords) - self.submodules.tsc_master = rtio.TSC("async") + self.submodules.tsc_master = rtio.TSC() self.submodules.master = DRTIOMaster(self.tsc_master, self.transceivers.alice) rx_synchronizer = DummyRXSynchronizer() - self.submodules.tsc_satellite = rtio.TSC("sync") + self.submodules.tsc_satellite = rtio.TSC() self.submodules.satellite = DRTIOSatellite( self.tsc_satellite, self.transceivers.bob, rx_synchronizer) self.satellite.reset.storage.reset = 0 diff --git a/artiq/gateware/test/rtio/test_dma.py b/artiq/gateware/test/rtio/test_dma.py index a8ccac564..692e5be17 100644 --- a/artiq/gateware/test/rtio/test_dma.py +++ b/artiq/gateware/test/rtio/test_dma.py @@ -128,7 +128,7 @@ class FullStackTB(Module): self.submodules.memory = wishbone.SRAM( 256, init=sequence, bus=bus) self.submodules.dut = dma.DMA(bus, dw) - 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) diff --git a/artiq/gateware/test/rtio/test_input_collector.py b/artiq/gateware/test/rtio/test_input_collector.py index bf68a17e4..5f8c7b262 100644 --- a/artiq/gateware/test/rtio/test_input_collector.py +++ b/artiq/gateware/test/rtio/test_input_collector.py @@ -38,8 +38,8 @@ class DUT(Module): rtio.Channel.from_phy(self.phy0, ififo_depth=4), rtio.Channel.from_phy(self.phy1, ififo_depth=4) ] - self.submodules.tsc = ClockDomainsRenamer({"rtio": "sys"})(rtio.TSC("sync")) - self.submodules.input_collector = InputCollector(self.tsc, rtio_channels, "sync") + self.submodules.tsc = rtio.TSC() + self.submodules.input_collector = InputCollector(self.tsc, rtio_channels) @property def cri(self): diff --git a/artiq/gateware/test/rtio/test_sed_top.py b/artiq/gateware/test/rtio/test_sed_top.py index 5efc257a0..5c5002fd3 100644 --- a/artiq/gateware/test/rtio/test_sed_top.py +++ b/artiq/gateware/test/rtio/test_sed_top.py @@ -22,7 +22,7 @@ class DUT(Module): rtio.Channel.from_phy(self.phy1) ] - self.submodules.sed = SED(rtio_channels, 0, "sync", **kwargs) + self.submodules.sed = SED(rtio_channels, 0, **kwargs) self.sync += [ self.sed.coarse_timestamp.eq(self.sed.coarse_timestamp + 1), self.sed.minimum_coarse_timestamp.eq(self.sed.coarse_timestamp + 16) From 7dafdfe2f7d2ba26bfc090f9d630563c955bea0f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 5 Mar 2022 22:43:25 +0800 Subject: [PATCH 15/16] artiq_flash: fix bit2bin --- artiq/frontend/artiq_flash.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index 96203fa83..136b58c71 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -280,10 +280,7 @@ def main(): def convert_gateware(bit_filename): bin_handle, bin_filename = tempfile.mkstemp( prefix="artiq_", suffix="_" + os.path.basename(bit_filename)) - with open(bit_filename, "rb") as bit_file, \ - open(bin_handle, "wb") as bin_file: - if header: - bin_file.write(b"\x00"*8) + with open(bit_filename, "rb") as bit_file, open(bin_handle, "wb") as bin_file: bit2bin(bit_file, bin_file) atexit.register(lambda: os.unlink(bin_filename)) return bin_filename From 63f1a6d197b823e054c5c58125e94485bfc17e73 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Jan 2023 18:33:13 +0800 Subject: [PATCH 16/16] drtio: partially fix tests --- artiq/gateware/test/drtio/test_full_stack.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/gateware/test/drtio/test_full_stack.py b/artiq/gateware/test/drtio/test_full_stack.py index ade67f5a9..4c7d367b2 100644 --- a/artiq/gateware/test/drtio/test_full_stack.py +++ b/artiq/gateware/test/drtio/test_full_stack.py @@ -52,7 +52,7 @@ class DUT(Module): self.ttl1 = Signal() self.transceivers = DummyTransceiverPair(nwords) - self.submodules.tsc_master = rtio.TSC("async") + self.submodules.tsc_master = rtio.TSC() self.submodules.master = DRTIOMaster(self.tsc_master, self.transceivers.alice) self.submodules.master_ki = rtio.KernelInitiator(self.tsc_master, @@ -144,8 +144,8 @@ class OutputsTestbench: class TestFullStack(unittest.TestCase): - clocks = {"sys": 8, "rtio_rx": 5, - "rio": 5, "rio_phy": 5} + clocks = {"sys": 8, "rtio_rx": 8, + "rio": 8, "rio_phy": 8} def test_pulses(self): tb = OutputsTestbench()