sayma: use QPLL for 1GSPS JESD204B TX

* requires jesd204b changes as in https://github.com/HarryMakes/jesd204b/tree/gth
This commit is contained in:
Harry Ho 2020-12-15 17:55:59 +08:00 committed by Sébastien Bourdeauducq
parent b5405dfad6
commit 400af2c582
3 changed files with 118 additions and 20 deletions

View File

@ -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(())
} }

View File

@ -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)
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)
phys.append(phy) 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( 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,

View File

@ -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 = []