def __init__(self, plat): super().__init__(plat, clk=200e6) adc_p = servo.ADCParams(width=16, channels=8, lanes=4, t_cnvh=4, t_conv=57, t_rtt=4) iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16, accu=48, shift=11, channel=3, profile=5) dds_p = servo.DDSParams(width=8 + 32 + 16 + 16, channels=adc_p.channels, clk=1) adc_pads = plat.request("adc_ser") dds_pads = plat.request("dds_ser") self.submodules.servo = servo.Servo(adc_pads, dds_pads, adc_p, iir_p, dds_p) plat.add_period_constraint(adc_pads.clkout_p, plat.default_clk_period) plat.add_false_path_constraints( plat.lookup_request(plat.default_clk_name), adc_pads.clkout_p) m_coeff = self.servo.iir.m_coeff.get_port(write_capable=True) m_state = self.servo.iir.m_state.get_port(write_capable=True) self.specials += m_coeff, m_state ins = [ m_state.adr, m_state.we, m_state.dat_w, m_coeff.adr, m_coeff.we, m_coeff.dat_w, self.servo.start ] for ctrl in self.servo.iir.ctrl: ins += ctrl.flatten() self.dummy_inputs(ins, 1) outs = [m_state.dat_r, m_coeff.dat_r] self.dummy_outputs(outs, self.servo.dds.done)
def add_std(cls, target, eems_sampler, eems_urukul, t_rtt=4, clk=1, shift=11, profile=5, iostandard="LVDS_25"): """Add a 8-channel Sampler-Urukul Servo :param t_rtt: upper estimate for clock round-trip propagation time from ``sck`` at the FPGA to ``clkout`` at the FPGA, measured in RTIO coarse cycles (default: 4). This is the sum of the round-trip cabling delay and the 8 ns max propagation delay on Sampler (ADC and LVDS drivers). Increasing ``t_rtt`` increases servo latency. With all other parameters at their default values, ``t_rtt`` values above 4 also increase the servo period (reduce servo bandwidth). :param clk: DDS SPI clock cycle half-width in RTIO coarse cycles (default: 1) :param shift: fixed-point scaling factor for IIR coefficients (default: 11) :param profile: log2 of the number of profiles for each DDS channel (default: 5) """ cls.add_extension(target, *(eems_sampler + sum(eems_urukul, [])), iostandard=iostandard) eem_sampler = "sampler{}".format(eems_sampler[0]) eem_urukul = ["urukul{}".format(i[0]) for i in eems_urukul] sampler_pads = servo_pads.SamplerPads(target.platform, eem_sampler) urukul_pads = servo_pads.UrukulPads(target.platform, *eem_urukul) target.submodules += sampler_pads, urukul_pads # timings in units of RTIO coarse period adc_p = servo.ADCParams( width=16, channels=8, lanes=4, t_cnvh=4, # account for SCK DDR to CONV latency # difference (4 cycles measured) t_conv=57 - 4, t_rtt=t_rtt + 4) iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16, accu=48, shift=shift, channel=3, profile=profile, dly=8) dds_p = servo.DDSParams(width=8 + 32 + 16 + 16, channels=adc_p.channels, clk=clk) su = servo.Servo(sampler_pads, urukul_pads, adc_p, iir_p, dds_p) su = ClockDomainsRenamer("rio_phy")(su) # explicitly name the servo submodule to enable the migen namer to derive # a name for the adc return clock domain setattr(target.submodules, "suservo_eem{}".format(eems_sampler[0]), su) ctrls = [rtservo.RTServoCtrl(ctrl) for ctrl in su.iir.ctrl] target.submodules += ctrls target.rtio_channels.extend( rtio.Channel.from_phy(ctrl) for ctrl in ctrls) mem = rtservo.RTServoMem(iir_p, su) target.submodules += mem target.rtio_channels.append(rtio.Channel.from_phy(mem, ififo_depth=4)) phy = spi2.SPIMaster( target.platform.request("{}_pgia_spi_p".format(eem_sampler)), target.platform.request("{}_pgia_spi_n".format(eem_sampler))) target.submodules += phy target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) for i in range(2): if len(eem_urukul) > i: spi_p, spi_n = (target.platform.request("{}_spi_p".format( eem_urukul[i])), target.platform.request("{}_spi_n".format( eem_urukul[i]))) else: # create a dummy bus spi_p = Record([("clk", 1), ("cs_n", 1)]) # mosi, cs_n spi_n = None phy = spi2.SPIMaster(spi_p, spi_n) target.submodules += phy target.rtio_channels.append( rtio.Channel.from_phy(phy, ififo_depth=4)) for j, eem_urukuli in enumerate(eem_urukul): pads = target.platform.request( "{}_dds_reset_sync_in".format(eem_urukuli)) target.specials += DifferentialOutput(0, pads.p, pads.n) for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): pads = target.platform.request("{}_{}".format( eem_urukuli, signal)) target.specials += DifferentialOutput( su.iir.ctrl[j * 4 + i].en_out, pads.p, pads.n)
def __init__(self, hw_rev=None, **kwargs): if hw_rev is None: hw_rev = "v1.1" _StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs) self.config["SI5324_AS_SYNTHESIZER"] = None # self.config["SI5324_EXT_REF"] = None self.config["RTIO_FREQUENCY"] = "125.0" if hw_rev == "v1.0": # EEM clock fan-out from Si5324, not MMCX self.comb += self.platform.request("clk_sel").eq(1) self.rtio_channels = [] # EEM0, EEM1: DIO eem.DIO.add_std(self, 0, ttl_serdes_7series.InOut_8X, ttl_serdes_7series.Output_8X) eem.DIO.add_std(self, 1, ttl_serdes_7series.Output_8X, ttl_serdes_7series.Output_8X) # EEM3, EEM2: Sampler self.platform.add_extension(eem.Sampler.io(3, 2)) sampler_pads = servo_pads.SamplerPads(self.platform, "sampler3") # EEM5, EEM4 and EEM7, EEM6: Urukul self.platform.add_extension(eem.Urukul.io_qspi(5, 4)) self.platform.add_extension(eem.Urukul.io_qspi(7, 6)) urukul_pads = servo_pads.UrukulPads(self.platform, "urukul5", "urukul7") adc_p = servo.ADCParams(width=16, channels=8, lanes=4, t_cnvh=4, # account for SCK pipeline latency t_conv=57 - 4, t_rtt=4 + 4) iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16, accu=48, shift=11, channel=3, profile=5) dds_p = servo.DDSParams(width=8 + 32 + 16 + 16, channels=adc_p.channels, clk=1) su = servo.Servo(sampler_pads, urukul_pads, adc_p, iir_p, dds_p) su = ClockDomainsRenamer("rio_phy")(su) self.submodules += sampler_pads, urukul_pads, su ctrls = [rtservo.RTServoCtrl(ctrl) for ctrl in su.iir.ctrl] self.submodules += ctrls self.rtio_channels.extend(rtio.Channel.from_phy(ctrl) for ctrl in ctrls) mem = rtservo.RTServoMem(iir_p, su) self.submodules += mem self.rtio_channels.append(rtio.Channel.from_phy(mem, ififo_depth=4)) # EEM3: Sampler phy = spi2.SPIMaster(self.platform.request("sampler3_pgia_spi_p"), self.platform.request("sampler3_pgia_spi_n")) self.submodules += phy self.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) # EEM5 + EEM4: Urukul phy = spi2.SPIMaster(self.platform.request("urukul5_spi_p"), self.platform.request("urukul5_spi_n")) self.submodules += phy self.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) pads = self.platform.request("urukul5_dds_reset") self.specials += DifferentialOutput(0, pads.p, pads.n) for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): pads = self.platform.request("urukul5_{}".format(signal)) self.specials += DifferentialOutput( su.iir.ctrl[i].en_out, pads.p, pads.n) # EEM7 + EEM6: Urukul phy = spi2.SPIMaster(self.platform.request("urukul7_spi_p"), self.platform.request("urukul7_spi_n")) self.submodules += phy self.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) pads = self.platform.request("urukul7_dds_reset") self.specials += DifferentialOutput(0, pads.p, pads.n) for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): pads = self.platform.request("urukul7_{}".format(signal)) self.specials += DifferentialOutput( su.iir.ctrl[i + 4].en_out, pads.p, pads.n) for i in (1, 2): sfp_ctl = self.platform.request("sfp_ctl", i) phy = ttl_simple.Output(sfp_ctl.led) self.submodules += phy self.rtio_channels.append(rtio.Channel.from_phy(phy)) self.config["HAS_RTIO_LOG"] = None self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.rtio_channels.append(rtio.LogChannel()) self.add_rtio(self.rtio_channels) self.platform.add_false_path_constraints( sampler_pads.clkout_p, self.rtio_crg.cd_rtio.clk) self.platform.add_false_path_constraints( sampler_pads.clkout_p, self.crg.cd_sys.clk)
def __init__(self, hw_rev=None, **kwargs): if hw_rev is None: hw_rev = "v1.1" _StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs) self.config["SI5324_AS_SYNTHESIZER"] = None # self.config["SI5324_EXT_REF"] = None self.config["RTIO_FREQUENCY"] = "125.0" platform = self.platform platform.add_extension(_dio("eem0")) platform.add_extension(_dio("eem1")) platform.add_extension(_sampler("eem3", "eem2")) platform.add_extension(_urukul_qspi("eem5", "eem4")) platform.add_extension(_urukul_qspi("eem7", "eem6")) try: # EEM clock fan-out from Si5324, not MMCX, only Kasli/v1.0 self.comb += platform.request("clk_sel").eq(1) except ConstraintError: pass rtio_channels = [] for i in range(16): eem, port = divmod(i, 8) pads = platform.request("eem{}".format(eem), port) if i < 4: cls = ttl_serdes_7series.InOut_8X else: cls = ttl_serdes_7series.Output_8X phy = cls(pads.p, pads.n) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy)) # EEM3, EEM2: Sampler sampler_pads = servo_pads.SamplerPads(self.platform, "eem3") # EEM5, EEM4 and EEM7, EEM6: Urukul urukul_pads = servo_pads.UrukulPads(self.platform, "eem5", "eem7") adc_p = servo.ADCParams( width=16, channels=8, lanes=4, t_cnvh=4, # account for SCK pipeline latency t_conv=57 - 4, t_rtt=4 + 4) iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16, accu=48, shift=11, channel=3, profile=5) dds_p = servo.DDSParams(width=8 + 32 + 16 + 16, channels=adc_p.channels, clk=1) su = servo.Servo(sampler_pads, urukul_pads, adc_p, iir_p, dds_p) su = ClockDomainsRenamer("rio_phy")(su) self.submodules += sampler_pads, urukul_pads, su ctrls = [rtservo.RTServoCtrl(ctrl) for ctrl in su.iir.ctrl] self.submodules += ctrls rtio_channels.extend(rtio.Channel.from_phy(ctrl) for ctrl in ctrls) mem = rtservo.RTServoMem(iir_p, su) self.submodules += mem rtio_channels.append(rtio.Channel.from_phy(mem, ififo_depth=4)) # EEM3: Sampler phy = spi2.SPIMaster(self.platform.request("eem3_pgia_spi_p"), self.platform.request("eem3_pgia_spi_n")) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) # EEM5 + EEM4: Urukul phy = spi2.SPIMaster(self.platform.request("eem5_spi_p"), self.platform.request("eem5_spi_n")) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) pads = platform.request("eem5_dds_reset") self.specials += DifferentialOutput(0, pads.p, pads.n) for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): pads = platform.request("eem5_{}".format(signal)) self.specials += DifferentialOutput(su.iir.ctrl[i].en_out, pads.p, pads.n) # EEM7 + EEM6: Urukul phy = spi2.SPIMaster(self.platform.request("eem7_spi_p"), self.platform.request("eem7_spi_n")) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) pads = platform.request("eem7_dds_reset") self.specials += DifferentialOutput(0, pads.p, pads.n) for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): pads = platform.request("eem7_{}".format(signal)) self.specials += DifferentialOutput(su.iir.ctrl[i + 4].en_out, pads.p, pads.n) for i in (1, 2): sfp_ctl = platform.request("sfp_ctl", i) phy = ttl_simple.Output(sfp_ctl.led) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy)) self.config["HAS_RTIO_LOG"] = None self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) rtio_channels.append(rtio.LogChannel()) self.add_rtio(rtio_channels) platform.add_false_path_constraints(sampler_pads.clkout_p, self.rtio_crg.cd_rtio.clk) platform.add_false_path_constraints(sampler_pads.clkout_p, self.crg.cd_sys.clk)
def add_std(cls, target, eems_sampler, eems_urukul0, eems_urukul1, t_rtt=4, clk=1, shift=11, profile=5): """Add a 8-channel Sampler-Urukul Servo :param t_rtt: upper estimate for clock round-trip propagation time from ``sck`` at the FPGA to ``clkout`` at the FPGA, measured in RTIO coarse cycles (default: 4). This is the sum of the round-trip cabling delay and the 8 ns max propagation delay on Sampler (ADC and LVDS drivers). Increasing ``t_rtt`` increases servo latency. With all other parameters at their default values, ``t_rtt`` values above 4 also increase the servo period (reduce servo bandwidth). :param clk: DDS SPI clock cycle half-width in RTIO coarse cycles (default: 1) :param shift: fixed-point scaling factor for IIR coefficients (default: 11) :param profile: log2 of the number of profiles for each DDS channel (default: 5) """ cls.add_extension(target, *(eems_sampler + eems_urukul0 + eems_urukul1)) eem_sampler = "sampler{}".format(eems_sampler[0]) eem_urukul0 = "urukul{}".format(eems_urukul0[0]) eem_urukul1 = "urukul{}".format(eems_urukul1[0]) sampler_pads = servo_pads.SamplerPads(target.platform, eem_sampler) urukul_pads = servo_pads.UrukulPads(target.platform, eem_urukul0, eem_urukul1) # timings in units of RTIO coarse period adc_p = servo.ADCParams( width=16, channels=8, lanes=4, t_cnvh=4, # account for SCK DDR to CONV latency # difference (4 cycles measured) t_conv=57 - 4, t_rtt=t_rtt + 4) iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16, accu=48, shift=shift, channel=3, profile=profile) dds_p = servo.DDSParams(width=8 + 32 + 16 + 16, channels=adc_p.channels, clk=clk) su = servo.Servo(sampler_pads, urukul_pads, adc_p, iir_p, dds_p) su = ClockDomainsRenamer("rio_phy")(su) target.submodules += sampler_pads, urukul_pads, su ctrls = [rtservo.RTServoCtrl(ctrl) for ctrl in su.iir.ctrl] target.submodules += ctrls target.rtio_channels.extend( rtio.Channel.from_phy(ctrl) for ctrl in ctrls) mem = rtservo.RTServoMem(iir_p, su) target.submodules += mem target.rtio_channels.append(rtio.Channel.from_phy(mem, ififo_depth=4)) phy = spi2.SPIMaster( target.platform.request("{}_pgia_spi_p".format(eem_sampler)), target.platform.request("{}_pgia_spi_n".format(eem_sampler))) target.submodules += phy target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) phy = spi2.SPIMaster( target.platform.request("{}_spi_p".format(eem_urukul0)), target.platform.request("{}_spi_n".format(eem_urukul0))) target.submodules += phy target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) pads = target.platform.request("{}_dds_reset".format(eem_urukul0)) target.specials += DifferentialOutput(0, pads.p, pads.n) for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): pads = target.platform.request("{}_{}".format(eem_urukul0, signal)) target.specials += DifferentialOutput(su.iir.ctrl[i].en_out, pads.p, pads.n) phy = spi2.SPIMaster( target.platform.request("{}_spi_p".format(eem_urukul1)), target.platform.request("{}_spi_n".format(eem_urukul1))) target.submodules += phy target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) pads = target.platform.request("{}_dds_reset".format(eem_urukul1)) target.specials += DifferentialOutput(0, pads.p, pads.n) for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): pads = target.platform.request("{}_{}".format(eem_urukul1, signal)) target.specials += DifferentialOutput(su.iir.ctrl[i + 4].en_out, pads.p, pads.n)