sayma: introduce WRPLL on RTM

This commit is contained in:
Sebastien Bourdeauducq 2019-12-08 15:30:00 +08:00
parent f35f658bc5
commit 46a776d06e
5 changed files with 84 additions and 35 deletions

View File

@ -1 +1,2 @@
from artiq.gateware.drtio.wrpll.core import WRPLL from artiq.gateware.drtio.wrpll.core import WRPLL
from artiq.gateware.drtio.wrpll.ddmtd import DDMTDSamplerExtFF, DDMTDSamplerGTP

View File

@ -23,19 +23,5 @@ class WRPLL(Module, AutoCSR):
ddmtd_counter = Signal(N) ddmtd_counter = Signal(N)
self.sync.helper += ddmtd_counter.eq(ddmtd_counter + 1) self.sync.helper += ddmtd_counter.eq(ddmtd_counter + 1)
if hasattr(ddmtd_inputs, "rec_clk"): self.submodules.ddmtd_helper = DDMTD(ddmtd_counter, ddmtd_inputs.rec_clk)
ddmtd_input_rec_clk = ddmtd_inputs.rec_clk self.submodules.ddmtd_main = DDMTD(ddmtd_counter, ddmtd_inputs.main_xo)
else:
ddmtd_input_rec_clk = Signal()
self.specials += Instance("IBUFDS",
i_I=ddmtd_inputs.rec_clk_p, i_IB=ddmtd_inputs.rec_clk_n,
o_O=ddmtd_input_rec_clk)
if hasattr(ddmtd_inputs, "main_xo"):
ddmtd_input_main_xo = ddmtd_inputs.main_xo
else:
ddmtd_input_main_xo = Signal()
self.specials += Instance("IBUFDS",
i_I=ddmtd_inputs.main_xo_p, i_IB=ddmtd_inputs.main_xo_n,
o_O=ddmtd_input_main_xo)
self.submodules.ddmtd_helper = DDMTD(ddmtd_counter, ddmtd_input_rec_clk)
self.submodules.ddmtd_main = DDMTD(ddmtd_counter, ddmtd_input_main_xo)

View File

@ -3,6 +3,47 @@ from migen.genlib.cdc import PulseSynchronizer, MultiReg
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
class DDMTDSamplerExtFF(Module):
def __init__(self, ddmtd_inputs):
# TODO: s/h timing at FPGA pads
if hasattr(ddmtd_inputs, "rec_clk"):
self.rec_clk = ddmtd_inputs.rec_clk
else:
self.rec_clk = Signal()
self.specials += Instance("IBUFDS",
i_I=ddmtd_inputs.rec_clk_p, i_IB=ddmtd_inputs.rec_clk_n,
o_O=self.rec_clk)
if hasattr(ddmtd_inputs, "main_xo"):
self.main_xo = ddmtd_inputs.main_xo
else:
self.main_xo = Signal()
self.specials += Instance("IBUFDS",
i_I=ddmtd_inputs.main_xo_p, i_IB=ddmtd_inputs.main_xo_n,
o_O=self.main_xo)
class DDMTDSamplerGTP(Module):
def __init__(self, gtp, main_xo_pads):
self.rec_clk = Signal()
self.main_xo = Signal()
# Getting this signal from IBUFDS_GTE2 is problematic because:
# 1. the clock gets divided by 2
# 2. the transceiver PLL craps out if an improper clock signal is applied,
# so we are disabling the buffer until the clock is stable.
# 3. UG482 says "The O and ODIV2 outputs are not phase matched to each other",
# which may or may not be a problem depending on what it actually means.
main_xo_se = Signal()
self.specials += Instance("IBUFDS",
i_I=main_xo_pads.p, i_IB=main_xo_pads.n,
o_O=main_xo_se)
self.sync.helper += [
self.rec_clk.eq(gtp.cd_rtio_rx0.clk),
self.main_xo.eq(main_xo_se)
]
class DDMTDEdgeDetector(Module): class DDMTDEdgeDetector(Module):
def __init__(self, input_signal): def __init__(self, input_signal):
self.rising = Signal() self.rising = Signal()

View File

@ -19,7 +19,7 @@ from artiq.gateware import jesd204_tools
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_ultrascale, sawg from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_ultrascale, sawg
from artiq.gateware.drtio.transceiver import gth_ultrascale from artiq.gateware.drtio.transceiver import gth_ultrascale
from artiq.gateware.drtio.siphaser import SiPhaser7Series from artiq.gateware.drtio.siphaser import SiPhaser7Series
from artiq.gateware.drtio.wrpll import WRPLL from artiq.gateware.drtio.wrpll import WRPLL, DDMTDSamplerExtFF
from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer
from artiq.gateware.drtio import * from artiq.gateware.drtio import *
from artiq.build_soc import * from artiq.build_soc import *
@ -136,11 +136,13 @@ class SatelliteBase(MiniSoC):
platform.request("ddmtd_main_dcxo_oe").eq(1), platform.request("ddmtd_main_dcxo_oe").eq(1),
platform.request("ddmtd_helper_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( self.submodules.wrpll = WRPLL(
helper_clk_pads=platform.request("ddmtd_helper_clk"), helper_clk_pads=platform.request("ddmtd_helper_clk"),
main_dcxo_i2c=platform.request("ddmtd_main_dcxo_i2c"), main_dcxo_i2c=platform.request("ddmtd_main_dcxo_i2c"),
helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c"), helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c"),
ddmtd_inputs=platform.request("ddmtd_inputs")) ddmtd_inputs=self.wrpll_sampler)
self.csr_devices.append("wrpll") self.csr_devices.append("wrpll")
else: else:
self.comb += platform.request("filtered_clk_sel").eq(1) self.comb += platform.request("filtered_clk_sel").eq(1)

View File

@ -19,6 +19,7 @@ from artiq.gateware import rtio
from artiq.gateware.rtio.phy import ttl_serdes_7series from artiq.gateware.rtio.phy import ttl_serdes_7series
from artiq.gateware.drtio.transceiver import gtp_7series from artiq.gateware.drtio.transceiver import gtp_7series
from artiq.gateware.drtio.siphaser import SiPhaser7Series 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.rx_synchronizer import XilinxRXSynchronizer
from artiq.gateware.drtio import * from artiq.gateware.drtio import *
from artiq.build_soc import add_identifier from artiq.build_soc import add_identifier
@ -73,7 +74,7 @@ class _SatelliteBase(BaseSoC):
} }
mem_map.update(BaseSoC.mem_map) mem_map.update(BaseSoC.mem_map)
def __init__(self, rtio_clk_freq, **kwargs): def __init__(self, rtio_clk_freq, *, with_wrpll, **kwargs):
BaseSoC.__init__(self, BaseSoC.__init__(self,
cpu_type="or1k", cpu_type="or1k",
**kwargs) **kwargs)
@ -132,21 +133,37 @@ class _SatelliteBase(BaseSoC):
self.add_memory_group("drtioaux_mem", ["drtioaux0_mem"]) self.add_memory_group("drtioaux_mem", ["drtioaux0_mem"])
self.config["RTIO_FREQUENCY"] = str(rtio_clk_freq/1e6) self.config["RTIO_FREQUENCY"] = str(rtio_clk_freq/1e6)
self.comb += platform.request("filtered_clk_sel").eq(1) if with_wrpll:
self.submodules.siphaser = SiPhaser7Series( self.comb += [
si5324_clkin=platform.request("si5324_clkin"), platform.request("filtered_clk_sel").eq(0),
rx_synchronizer=self.rx_synchronizer, platform.request("ddmtd_main_dcxo_oe").eq(1),
ref_clk=self.crg.cd_sys.clk, ref_div2=True, platform.request("ddmtd_helper_dcxo_oe").eq(1)
rtio_clk_freq=rtio_clk_freq) ]
platform.add_false_path_constraints( self.submodules.wrpll_sampler = DDMTDSamplerGTP(
self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) self.drtio_transceiver,
self.csr_devices.append("siphaser") platform.request("cdr_clk_clean_fabric"))
i2c = self.platform.request("i2c") self.submodules.wrpll = WRPLL(
self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) helper_clk_pads=platform.request("ddmtd_helper_clk"),
self.csr_devices.append("i2c") main_dcxo_i2c=platform.request("ddmtd_main_dcxo_i2c"),
self.config["I2C_BUS_COUNT"] = 1 helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c"),
self.config["HAS_SI5324"] = None ddmtd_inputs=self.wrpll_sampler)
self.config["SI5324_SOFT_RESET"] = None self.csr_devices.append("wrpll")
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")
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_SOFT_RESET"] = None
rtio_clk_period = 1e9/rtio_clk_freq rtio_clk_period = 1e9/rtio_clk_freq
gtp = self.drtio_transceiver.gtps[0] gtp = self.drtio_transceiver.gtps[0]
@ -245,10 +262,12 @@ def main():
soc_sayma_rtm_args(parser) soc_sayma_rtm_args(parser)
parser.add_argument("--rtio-clk-freq", parser.add_argument("--rtio-clk-freq",
default=150, type=int, help="RTIO clock frequency in MHz") default=150, type=int, help="RTIO clock frequency in MHz")
parser.add_argument("--with-wrpll", default=False, action="store_true")
parser.set_defaults(output_dir=os.path.join("artiq_sayma", "rtm")) parser.set_defaults(output_dir=os.path.join("artiq_sayma", "rtm"))
args = parser.parse_args() args = parser.parse_args()
soc = Satellite(rtio_clk_freq=1e6*args.rtio_clk_freq, soc = Satellite(
rtio_clk_freq=1e6*args.rtio_clk_freq, with_wrpll=args.with_wrpll,
**soc_sayma_rtm_argdict(args)) **soc_sayma_rtm_argdict(args))
builder = SatmanSoCBuilder(soc, **builder_argdict(args)) builder = SatmanSoCBuilder(soc, **builder_argdict(args))
try: try: