forked from M-Labs/artiq
sayma: use QPLL for 1GSPS JESD204B TX
* requires jesd204b changes as in https://github.com/HarryMakes/jesd204b/tree/gth
This commit is contained in:
parent
b5405dfad6
commit
400af2c582
|
@ -87,7 +87,7 @@ const JESD_SETTINGS: JESDSettings = JESDSettings {
|
||||||
np: 16,
|
np: 16,
|
||||||
f: 2,
|
f: 2,
|
||||||
s: 2,
|
s: 2,
|
||||||
k: 16,
|
k: 32,
|
||||||
cs: 0,
|
cs: 0,
|
||||||
|
|
||||||
subclassv: 1,
|
subclassv: 1,
|
||||||
|
@ -349,6 +349,28 @@ pub fn setup(dacno: u8, linerate: u64) -> Result<(), &'static str> {
|
||||||
write(ad9154_reg::GENERAL_JRX_CTRL_0,
|
write(ad9154_reg::GENERAL_JRX_CTRL_0,
|
||||||
0x1*ad9154_reg::LINK_EN | 0*ad9154_reg::LINK_PAGE |
|
0x1*ad9154_reg::LINK_EN | 0*ad9154_reg::LINK_PAGE |
|
||||||
0*ad9154_reg::LINK_MODE | 0*ad9154_reg::CHECKSUM_MODE);
|
0*ad9154_reg::LINK_MODE | 0*ad9154_reg::CHECKSUM_MODE);
|
||||||
|
|
||||||
|
// JESD Checks
|
||||||
|
let jesd_checks = read(ad9154_reg::JESD_CHECKS);
|
||||||
|
if jesd_checks & ad9154_reg::ERR_DLYOVER == ad9154_reg::ERR_DLYOVER {
|
||||||
|
error!("LMFC_Delay > JESD_K Parameter")
|
||||||
|
}
|
||||||
|
if jesd_checks & ad9154_reg::ERR_WINLIMIT == ad9154_reg::ERR_WINLIMIT {
|
||||||
|
error!("Unsupported Window Limit")
|
||||||
|
}
|
||||||
|
if jesd_checks & ad9154_reg::ERR_JESDBAD == ad9154_reg::ERR_JESDBAD {
|
||||||
|
error!("Unsupported M/L/S/F Selection")
|
||||||
|
}
|
||||||
|
if jesd_checks & ad9154_reg::ERR_KUNSUPP == ad9154_reg::ERR_KUNSUPP {
|
||||||
|
error!("Unsupported K Values")
|
||||||
|
}
|
||||||
|
if jesd_checks & ad9154_reg::ERR_SUBCLASS == ad9154_reg::ERR_SUBCLASS {
|
||||||
|
error!("Unsupported SUBCLASSV Value")
|
||||||
|
}
|
||||||
|
if jesd_checks & ad9154_reg::ERR_INTSUPP == ad9154_reg::ERR_INTSUPP {
|
||||||
|
error!("Unsupported Interpolation Factor")
|
||||||
|
}
|
||||||
|
|
||||||
info!(" ...done");
|
info!(" ...done");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,11 @@ from misoc.interconnect.csr import *
|
||||||
from jesd204b.common import (JESD204BTransportSettings,
|
from jesd204b.common import (JESD204BTransportSettings,
|
||||||
JESD204BPhysicalSettings,
|
JESD204BPhysicalSettings,
|
||||||
JESD204BSettings)
|
JESD204BSettings)
|
||||||
from jesd204b.phy.gth import GTHChannelPLL as JESD204BGTHChannelPLL
|
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.phy import JESD204BPhyTX
|
||||||
from jesd204b.core import JESD204BCoreTX
|
from jesd204b.core import JESD204BCoreTX
|
||||||
from jesd204b.core import JESD204BCoreTXControl
|
from jesd204b.core import JESD204BCoreTXControl
|
||||||
|
@ -16,6 +20,7 @@ from jesd204b.core import JESD204BCoreTXControl
|
||||||
|
|
||||||
class UltrascaleCRG(Module, AutoCSR):
|
class UltrascaleCRG(Module, AutoCSR):
|
||||||
linerate = int(10e9) # linerate = 20*data_rate*4/8 = data_rate*10
|
linerate = int(10e9) # linerate = 20*data_rate*4/8 = data_rate*10
|
||||||
|
# data_rate = dac_rate/interp_factor
|
||||||
refclk_freq = int(250e6)
|
refclk_freq = int(250e6)
|
||||||
fabric_freq = int(125e6)
|
fabric_freq = int(125e6)
|
||||||
|
|
||||||
|
@ -41,30 +46,99 @@ PhyPads = namedtuple("PhyPads", "txp txn")
|
||||||
|
|
||||||
|
|
||||||
class UltrascaleTX(Module, AutoCSR):
|
class UltrascaleTX(Module, AutoCSR):
|
||||||
def __init__(self, platform, sys_crg, jesd_crg, dac):
|
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)
|
ps = JESD204BPhysicalSettings(l=8, m=4, n=16, np=16)
|
||||||
ts = JESD204BTransportSettings(f=2, s=2, k=16, cs=0)
|
ts = JESD204BTransportSettings(f=2, s=2, k=32, cs=0)
|
||||||
settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
|
settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
|
||||||
|
|
||||||
jesd_pads = platform.request("dac_jesd", dac)
|
jesd_pads = platform.request("dac_jesd", dac)
|
||||||
|
plls = []
|
||||||
phys = []
|
phys = []
|
||||||
for i in range(len(jesd_pads.txp)):
|
for i in range(len(jesd_pads.txp)):
|
||||||
cpll = JESD204BGTHChannelPLL(
|
pll = pll_cls(
|
||||||
jesd_crg.refclk, jesd_crg.refclk_freq, jesd_crg.linerate)
|
jesd_crg.refclk, jesd_crg.refclk_freq, jesd_crg.linerate)
|
||||||
self.submodules += cpll
|
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(
|
phy = JESD204BPhyTX(
|
||||||
cpll, PhyPads(jesd_pads.txp[i], jesd_pads.txn[i]),
|
pll, jesd_crg.refclk, PhyPads(jesd_pads.txp[i], jesd_pads.txn[i]),
|
||||||
jesd_crg.fabric_freq, transceiver="gth")
|
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,
|
platform.add_period_constraint(phy.transmitter.cd_tx.clk,
|
||||||
40*1e9/jesd_crg.linerate)
|
40*1e9/jesd_crg.linerate)
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
sys_crg.cd_sys.clk,
|
sys_crg.cd_sys.clk,
|
||||||
jesd_crg.cd_jesd.clk,
|
jesd_crg.cd_jesd.clk,
|
||||||
phy.transmitter.cd_tx.clk)
|
phy.transmitter.cd_tx.clk)
|
||||||
phys.append(phy)
|
# 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(
|
self.submodules.core = JESD204BCoreTX(
|
||||||
phys, settings, converter_data_width=128)
|
phys, settings, converter_data_width=128, tx_half=tx_half)
|
||||||
self.submodules.control = JESD204BCoreTXControl(self.core)
|
self.submodules.control = JESD204BCoreTXControl(self.core)
|
||||||
self.core.register_jsync(platform.request("dac_sync", dac))
|
self.core.register_jsync(platform.request("dac_sync", dac))
|
||||||
|
|
||||||
|
@ -111,7 +185,7 @@ class DDMTD(Module, AutoCSR):
|
||||||
i_RST=self.reset.storage,
|
i_RST=self.reset.storage,
|
||||||
o_LOCKED=helper_locked,
|
o_LOCKED=helper_locked,
|
||||||
|
|
||||||
# VCO at 1200MHz with 150MHz RTIO frequency
|
# VCO at 1000MHz/1200MHz with 125MHz/150MHz RTIO frequency
|
||||||
p_CLKFBOUT_MULT_F=8.0,
|
p_CLKFBOUT_MULT_F=8.0,
|
||||||
p_DIVCLK_DIVIDE=1,
|
p_DIVCLK_DIVIDE=1,
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,10 @@ class SatelliteBase(MiniSoC):
|
||||||
# JESD204 DAC Channel Group
|
# JESD204 DAC Channel Group
|
||||||
class JDCGSAWG(Module, AutoCSR):
|
class JDCGSAWG(Module, AutoCSR):
|
||||||
def __init__(self, platform, sys_crg, jesd_crg, dac):
|
def __init__(self, platform, sys_crg, jesd_crg, dac):
|
||||||
|
# Kintex Ultrascale GTH, speed grade -1C:
|
||||||
|
# QPLL0 linerate (D=1): 9.8 - 12.5 Gb/s
|
||||||
self.submodules.jesd = jesd204_tools.UltrascaleTX(
|
self.submodules.jesd = jesd204_tools.UltrascaleTX(
|
||||||
platform, sys_crg, jesd_crg, dac)
|
platform, sys_crg, jesd_crg, dac, pll_type="qpll", tx_half=True)
|
||||||
|
|
||||||
self.submodules.sawgs = [sawg.Channel(width=16, parallelism=8) for i in range(4)]
|
self.submodules.sawgs = [sawg.Channel(width=16, parallelism=8) for i in range(4)]
|
||||||
|
|
||||||
|
@ -203,7 +205,7 @@ class JDCGSAWG(Module, AutoCSR):
|
||||||
class JDCGPattern(Module, AutoCSR):
|
class JDCGPattern(Module, AutoCSR):
|
||||||
def __init__(self, platform, sys_crg, jesd_crg, dac):
|
def __init__(self, platform, sys_crg, jesd_crg, dac):
|
||||||
self.submodules.jesd = jesd204_tools.UltrascaleTX(
|
self.submodules.jesd = jesd204_tools.UltrascaleTX(
|
||||||
platform, sys_crg, jesd_crg, dac)
|
platform, sys_crg, jesd_crg, dac, pll_type="qpll", tx_half=True)
|
||||||
|
|
||||||
self.sawgs = []
|
self.sawgs = []
|
||||||
|
|
||||||
|
@ -243,7 +245,7 @@ class JDCGPattern(Module, AutoCSR):
|
||||||
class JDCGSyncDDS(Module, AutoCSR):
|
class JDCGSyncDDS(Module, AutoCSR):
|
||||||
def __init__(self, platform, sys_crg, jesd_crg, dac):
|
def __init__(self, platform, sys_crg, jesd_crg, dac):
|
||||||
self.submodules.jesd = jesd204_tools.UltrascaleTX(
|
self.submodules.jesd = jesd204_tools.UltrascaleTX(
|
||||||
platform, sys_crg, jesd_crg, dac)
|
platform, sys_crg, jesd_crg, dac, pll_type="qpll", tx_half=True)
|
||||||
self.coarse_ts = Signal(32)
|
self.coarse_ts = Signal(32)
|
||||||
|
|
||||||
self.sawgs = []
|
self.sawgs = []
|
||||||
|
|
Loading…
Reference in New Issue