diff --git a/default.nix b/default.nix index e6a472f..350d932 100644 --- a/default.nix +++ b/default.nix @@ -8,13 +8,14 @@ let vivado = import { inherit pkgs; }; # FSBL configuration supplied by Vivado 2020.1 for these boards: fsblTargets = ["zc702" "zc706" "zed"]; + sat_variants = ["satellite" "acpki_satellite" "nist_clock_satellite" "nist_qc2_satellite"]; build = { target, variant, json ? null }: let szl = (import zynq-rs)."${target}-szl"; fsbl = import "${zynq-rs}/nix/fsbl.nix" { inherit pkgs; board = target; }; - fwtype = if variant == "satellite" then "satman" else "runtime"; + fwtype = if builtins.elem variant sat_variants then "satman" else "runtime"; firmware = rustPlatform.buildRustPackage rec { # note: due to fetchCargoTarball, cargoSha256 depends on package name @@ -134,15 +135,23 @@ let in ( (build { target = "zc706"; variant = "simple"; }) // - (build { target = "zc706"; variant = "nist_clock"; }) // - (build { target = "zc706"; variant = "nist_qc2"; }) // (build { target = "zc706"; variant = "master"; }) // (build { target = "zc706"; variant = "satellite"; }) // + (build { target = "zc706"; variant = "nist_clock"; }) // + (build { target = "zc706"; variant = "nist_clock_master"; }) // + (build { target = "zc706"; variant = "nist_clock_satellite"; }) // + (build { target = "zc706"; variant = "nist_qc2"; }) // + (build { target = "zc706"; variant = "nist_qc2_master"; }) // + (build { target = "zc706"; variant = "nist_qc2_satellite"; }) // (build { target = "zc706"; variant = "acpki_simple"; }) // - (build { target = "zc706"; variant = "acpki_nist_clock"; }) // - (build { target = "zc706"; variant = "acpki_nist_qc2"; }) // (build { target = "zc706"; variant = "acpki_master"; }) // (build { target = "zc706"; variant = "acpki_satellite"; }) // + (build { target = "zc706"; variant = "acpki_nist_clock"; }) // + (build { target = "zc706"; variant = "acpki_nist_clock_master"; }) // + (build { target = "zc706"; variant = "acpki_nist_clock_satellite"; }) // + (build { target = "zc706"; variant = "acpki_nist_qc2"; }) // + (build { target = "zc706"; variant = "acpki_nist_qc2_master"; }) // + (build { target = "zc706"; variant = "acpki_nist_qc2_satellite"; }) // (build { target = "kasli_soc"; variant = "demo"; json = ./demo.json; }) // (build { target = "kasli_soc"; variant = "master"; json = ./kasli-soc-master.json; }) // (build { target = "kasli_soc"; variant = "satellite"; json = ./kasli-soc-satellite.json; }) // diff --git a/src/gateware/zc706.py b/src/gateware/zc706.py index e869f2e..c24bfe7 100755 --- a/src/gateware/zc706.py +++ b/src/gateware/zc706.py @@ -127,142 +127,9 @@ class ZC706(SoCCore): self.ps7.s_axi_hp1) self.csr_devices.append("rtio_analyzer") - -class Simple(ZC706): - def __init__(self, **kwargs): - ZC706.__init__(self, **kwargs) - - platform = self.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)) - - self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) - rtio_channels.append(rtio.LogChannel()) - - self.add_rtio(rtio_channels) - - -# The NIST backplanes require setting VADJ to 3.3V by reprogramming the power supply. -# This also changes the I/O standard for some on-board LEDs. -leds_fmc33 = [ - ("user_led_33", 0, Pins("Y21"), IOStandard("LVCMOS33")), - ("user_led_33", 1, Pins("G2"), IOStandard("LVCMOS15")), - ("user_led_33", 2, Pins("W21"), IOStandard("LVCMOS33")), - ("user_led_33", 3, Pins("A17"), IOStandard("LVCMOS15")), -] - - -class NIST_CLOCK(ZC706): - """ - NIST clock hardware, with old backplane and 11 DDS channels - """ - def __init__(self, **kwargs): - ZC706.__init__(self, **kwargs) - - platform = self.platform - platform.add_extension(nist_clock.fmc_adapter_io) - platform.add_extension(leds_fmc33) - - rtio_channels = [] - - for i in range(4): - phy = ttl_simple.Output(platform.request("user_led_33", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - for i in range(16): - if i % 4 == 3: - phy = ttl_serdes_7series.InOut_8X(platform.request("ttl", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512)) - else: - phy = ttl_serdes_7series.Output_8X(platform.request("ttl", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - for i in range(2): - phy = ttl_serdes_7series.InOut_8X(platform.request("pmt", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512)) - - phy = ttl_simple.ClockGen(platform.request("la32_p")) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - for i in range(3): - phy = spi2.SPIMaster(self.platform.request("spi", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy( - phy, ififo_depth=128)) - - phy = dds.AD9914(platform.request("dds"), 11, onehot=True) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) - - self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) - rtio_channels.append(rtio.LogChannel()) - - self.add_rtio(rtio_channels) - - -class NIST_QC2(ZC706): - """ - NIST QC2 hardware, as used in Quantum I and Quantum II, with new backplane - and 24 DDS channels. Two backplanes are used. - """ - def __init__(self, **kwargs): - ZC706.__init__(self, **kwargs) - - platform = self.platform - platform.add_extension(nist_qc2.fmc_adapter_io) - platform.add_extension(leds_fmc33) - - rtio_channels = [] - - for i in range(4): - phy = ttl_simple.Output(platform.request("user_led_33", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - # All TTL channels are In+Out capable - for i in range(40): - phy = ttl_serdes_7series.InOut_8X(platform.request("ttl", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512)) - - # CLK0, CLK1 are for clock generators, on backplane SMP connectors - for i in range(2): - phy = ttl_simple.ClockGen( - platform.request("clkout", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - for i in range(4): - phy = spi2.SPIMaster(self.platform.request("spi", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy( - phy, ififo_depth=128)) - - for backplane_offset in range(2): - phy = dds.AD9914( - platform.request("dds", backplane_offset), 12, onehot=True) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) - - self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) - rtio_channels.append(rtio.LogChannel()) - - self.add_rtio(rtio_channels) - -class Master(SoCCore): +class _MasterBase(SoCCore): mem_map = { - # "cri_con": 0x10000000, - # "rtio": 0x20000000, - # "rtio_dma": 0x30000000, + "drtioaux": 0x40000000, } mem_map.update(SoCCore.mem_map) @@ -357,18 +224,9 @@ class Master(SoCCore): self.rtio_crg = RTIOCRG(self.platform, self.drtio_transceiver.rtio_clk_freq) - 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)) - self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) - rtio_channels.append(rtio.LogChannel()) - self.add_rtio(rtio_channels) - -class Satellite(SoCCore): +class _SatelliteBase(SoCCore): mem_map = { "drtioaux": 0x40000000, } @@ -474,17 +332,6 @@ class Satellite(SoCCore): platform.add_false_path_constraints( self.ps7.cd_sys.clk, gtx.rxoutclk) - 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)) - - self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) - rtio_channels.append(rtio.LogChannel()) - - self.add_rtio(rtio_channels) - def add_rtio(self, rtio_channels): # few changes from base add_rtio - moved tsc, no core @@ -514,7 +361,178 @@ class Satellite(SoCCore): self.csr_devices.append("routing_table") -VARIANTS = {cls.__name__.lower(): cls for cls in [Simple, NIST_CLOCK, NIST_QC2, Master, Satellite]} +class _Simple_RTIO: + def __init__(self): + platform = self.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)) + + self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) + rtio_channels.append(rtio.LogChannel()) + + self.add_rtio(rtio_channels) + +# The NIST backplanes require setting VADJ to 3.3V by reprogramming the power supply. +# This also changes the I/O standard for some on-board LEDs. +leds_fmc33 = [ + ("user_led_33", 0, Pins("Y21"), IOStandard("LVCMOS33")), + ("user_led_33", 1, Pins("G2"), IOStandard("LVCMOS15")), + ("user_led_33", 2, Pins("W21"), IOStandard("LVCMOS33")), + ("user_led_33", 3, Pins("A17"), IOStandard("LVCMOS15")), +] + +class _NIST_CLOCK_RTIO: + """ + NIST clock hardware, with old backplane and 11 DDS channels + """ + def __init__(self): + platform = self.platform + platform.add_extension(nist_clock.fmc_adapter_io) + platform.add_extension(leds_fmc33) + + rtio_channels = [] + + for i in range(4): + phy = ttl_simple.Output(platform.request("user_led_33", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + + for i in range(16): + if i % 4 == 3: + phy = ttl_serdes_7series.InOut_8X(platform.request("ttl", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512)) + else: + phy = ttl_serdes_7series.Output_8X(platform.request("ttl", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + + for i in range(2): + phy = ttl_serdes_7series.InOut_8X(platform.request("pmt", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512)) + + phy = ttl_simple.ClockGen(platform.request("la32_p")) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + + for i in range(3): + phy = spi2.SPIMaster(self.platform.request("spi", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy( + phy, ififo_depth=128)) + + phy = dds.AD9914(platform.request("dds"), 11, onehot=True) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) + + self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) + rtio_channels.append(rtio.LogChannel()) + + self.add_rtio(rtio_channels) + + +class _NIST_QC2_RTIO: + """ + NIST QC2 hardware, as used in Quantum I and Quantum II, with new backplane + and 24 DDS channels. Two backplanes are used. + """ + def __init__(self): + platform = self.platform + platform.add_extension(nist_qc2.fmc_adapter_io) + platform.add_extension(leds_fmc33) + + rtio_channels = [] + + for i in range(4): + phy = ttl_simple.Output(platform.request("user_led_33", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + + # All TTL channels are In+Out capable + for i in range(40): + phy = ttl_serdes_7series.InOut_8X(platform.request("ttl", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512)) + + # CLK0, CLK1 are for clock generators, on backplane SMP connectors + for i in range(2): + phy = ttl_simple.ClockGen( + platform.request("clkout", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + + for i in range(4): + phy = spi2.SPIMaster(self.platform.request("spi", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy( + phy, ififo_depth=128)) + + for backplane_offset in range(2): + phy = dds.AD9914( + platform.request("dds", backplane_offset), 12, onehot=True) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) + + self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) + rtio_channels.append(rtio.LogChannel()) + + self.add_rtio(rtio_channels) + + +class Simple(ZC706, _Simple_RTIO): + def __init__(self, acpki): + ZC706.__init__(self, acpki) + _Simple_RTIO.__init__(self) + +class Master(_MasterBase, _Simple_RTIO): + def __init__(self, acpki): + _MasterBase.__init__(self, acpki) + _Simple_RTIO.__init__(self) + +class Satellite(_SatelliteBase, _Simple_RTIO): + def __init__(self, acpki): + _SatelliteBase.__init__(self, acpki) + _Simple_RTIO.__init__(self) + +class NIST_CLOCK(ZC706, _NIST_CLOCK_RTIO): + def __init__(self, acpki): + ZC706.__init__(self, acpki) + _NIST_CLOCK_RTIO.__init__(self) + +class NIST_CLOCK_Master(_MasterBase, _NIST_CLOCK_RTIO): + def __init__(self, acpki): + _MasterBase.__init__(self, acpki) + _NIST_CLOCK_RTIO.__init__(self) + +class NIST_CLOCK_Satellite(_SatelliteBase, _NIST_CLOCK_RTIO): + def __init__(self, acpki): + _SatelliteBase.__init__(self, acpki) + _NIST_CLOCK_RTIO.__init__(self) + +class NIST_QC2(ZC706, _NIST_QC2_RTIO): + def __init__(self, acpki): + ZC706.__init__(self, acpki) + _NIST_QC2_RTIO.__init__(self) + +class NIST_QC2_Master(_MasterBase, _NIST_QC2_RTIO): + def __init__(self, acpki): + _MasterBase.__init__(self, acpki) + _NIST_QC2_RTIO.__init__(self) + +class NIST_QC2_Satellite(_SatelliteBase, _NIST_QC2_RTIO): + def __init__(self, acpki): + _SatelliteBase.__init__(self, acpki) + _NIST_QC2_RTIO.__init__(self) + + +VARIANTS = {cls.__name__.lower(): cls for cls in [Simple, Master, Satellite, + NIST_CLOCK, NIST_CLOCK_Master, NIST_CLOCK_Satellite, + NIST_QC2, NIST_QC2_Master, NIST_QC2_Satellite]} def write_csr_file(soc, filename):