forked from M-Labs/artiq
phaser: instantiate jesd204b core, wire up
This commit is contained in:
parent
f62d60093e
commit
4d87f0e9e0
|
@ -27,7 +27,7 @@ The additions and modifications to ARTIQ that were implemented for this project
|
|||
* In ARTIQ, the SAWG and Phaser code: https://github.com/m-labs/artiq/compare/phaser
|
||||
* The CORDIC core has been reused from the PDQ2 gateware
|
||||
https://github.com/m-labs/pdq2
|
||||
* The Migen/MiSoC JESD204B core: https://github.com/m-labs/jesd204
|
||||
* The Migen/MiSoC JESD204B core: https://github.com/m-labs/jesd204b
|
||||
|
||||
|
||||
Installation
|
||||
|
|
|
@ -27,6 +27,21 @@ def ad9516_read(addr: TInt32) -> TInt32:
|
|||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
@syscall(flags={"nounwind", "nowrite"})
|
||||
def jesd_enable(en: TInt32) -> TNone:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
@syscall(flags={"nounwind", "nowrite"})
|
||||
def jesd_ready() -> TInt32:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
@syscall(flags={"nounwind", "nowrite"})
|
||||
def jesd_prbs(prbs: TInt32) -> TNone:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
class AD9154:
|
||||
"""AD9154-FMC-EBZ SPI support
|
||||
|
||||
|
@ -66,3 +81,17 @@ class AD9154:
|
|||
def clock_read(self, addr):
|
||||
"""Read AD9516 SPI register at `addr`."""
|
||||
return ad9516_read(addr)
|
||||
|
||||
@kernel
|
||||
def jesd_enable(self, en):
|
||||
"""Enables the JESD204B core startup sequence."""
|
||||
jesd_enable(en)
|
||||
|
||||
@kernel
|
||||
def jesd_ready(self):
|
||||
"""Returns `True` if the JESD links are up."""
|
||||
return jesd_ready()
|
||||
|
||||
@kernel
|
||||
def jesd_prbs(self, prbs):
|
||||
jesd_prbs(prbs)
|
||||
|
|
|
@ -44,34 +44,28 @@
|
|||
"class": "TTLInOut",
|
||||
"arguments": {"channel": 2}
|
||||
},
|
||||
"sync": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLInOut",
|
||||
"arguments": {"channel": 3}
|
||||
},
|
||||
"sawg0": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.sawg",
|
||||
"class": "SAWG",
|
||||
"arguments": {"channel_base": 4, "parallelism": 4}
|
||||
"arguments": {"channel_base": 3, "parallelism": 4}
|
||||
},
|
||||
"sawg1": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.sawg",
|
||||
"class": "SAWG",
|
||||
"arguments": {"channel_base": 7, "parallelism": 4}
|
||||
"arguments": {"channel_base": 6, "parallelism": 4}
|
||||
},
|
||||
"sawg2": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.sawg",
|
||||
"class": "SAWG",
|
||||
"arguments": {"channel_base": 10, "parallelism": 4}
|
||||
"arguments": {"channel_base": 9, "parallelism": 4}
|
||||
},
|
||||
"sawg3": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.sawg",
|
||||
"class": "SAWG",
|
||||
"arguments": {"channel_base": 13, "parallelism": 4}
|
||||
"arguments": {"channel_base": 12, "parallelism": 4}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,33 @@
|
|||
from jesd204b.common import (JESD204BPhysicalSettings,
|
||||
JESD204BTransportSettings,
|
||||
JESD204BSettings)
|
||||
from artiq.experiment import *
|
||||
from artiq.coredevice.ad9516_reg import *
|
||||
from artiq.coredevice.ad9154_reg import *
|
||||
|
||||
# ad9154 mode 2:
|
||||
ps = JESD204BPhysicalSettings(
|
||||
l=4, # lanes
|
||||
m=4, # converters
|
||||
n=16, # bits/converter
|
||||
np=16, # bits/sample
|
||||
sc=250*1e6, # data clock, unused: FIXME
|
||||
)
|
||||
ts = JESD204BTransportSettings(
|
||||
f=2, # octets/(lane and frame)
|
||||
s=1, # samples/(converter and frame)
|
||||
k=16, # frames/multiframe
|
||||
cs=1, #
|
||||
)
|
||||
jesd_settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
|
||||
jesd_checksum = jesd_settings.get_configuration_data()[-1]
|
||||
jesd_data_freq = 250e6
|
||||
jesd_linerate = 5e9
|
||||
# external clk=2000MHz
|
||||
# pclock=250MHz
|
||||
# deviceclock_fpga=500MHz
|
||||
# deviceclock_dac=2000MHz
|
||||
|
||||
|
||||
class StartupKernel(EnvExperiment):
|
||||
def build(self):
|
||||
|
@ -11,26 +37,16 @@ class StartupKernel(EnvExperiment):
|
|||
|
||||
@kernel
|
||||
def run(self):
|
||||
# ad9154 mode 2:
|
||||
# M=4 converters
|
||||
# L=4 lanes
|
||||
# S=1 samples/converter and /frame
|
||||
# F=2 octets/lane and /frame
|
||||
# K=16 frames/multiframe (or 32)
|
||||
# HD=0 high density
|
||||
# N=16 bits/converter
|
||||
# NB=16 bits/sample
|
||||
#
|
||||
# external clk=2000MHz
|
||||
# pclock=250MHz
|
||||
# fdata=500MHz
|
||||
# fline=10GHz
|
||||
# deviceclock_fpga=500MHz
|
||||
# deviceclock_dac=2000MHz
|
||||
self.core.reset()
|
||||
self.ad9154.jesd_enable(0)
|
||||
self.ad9154.init()
|
||||
self.clock_setup()
|
||||
self.dac_setup()
|
||||
self.ad9154.jesd_prbs(0)
|
||||
t = now_mu() + seconds_to_mu(.1*s)
|
||||
while self.core.get_rtio_counter_mu() < t:
|
||||
pass
|
||||
self.ad9154.jesd_enable(1)
|
||||
|
||||
@kernel
|
||||
def clock_setup(self):
|
||||
|
@ -123,7 +139,7 @@ class StartupKernel(EnvExperiment):
|
|||
|
||||
self.ad9154.dac_write(AD9154_SPI_PAGEINDX, 0x3) # A and B dual
|
||||
|
||||
self.ad9154.dac_write(AD9154_INTERP_MODE, 3) # 4x
|
||||
self.ad9154.dac_write(AD9154_INTERP_MODE, 4) # 8x
|
||||
self.ad9154.dac_write(AD9154_MIX_MODE, 0)
|
||||
self.ad9154.dac_write(AD9154_DATA_FORMAT, AD9154_BINARY_FORMAT_SET(0)) # s16
|
||||
self.ad9154.dac_write(AD9154_DATAPATH_CTRL,
|
||||
|
@ -160,24 +176,28 @@ class StartupKernel(EnvExperiment):
|
|||
self.ad9154.dac_write(AD9154_GENERAL_JRX_CTRL_0,
|
||||
AD9154_LINK_EN_SET(0x0) | AD9154_LINK_PAGE_SET(0) |
|
||||
AD9154_LINK_MODE_SET(0) | AD9154_CHECKSUM_MODE_SET(0))
|
||||
self.ad9154.dac_write(AD9154_ILS_DID, 0x00) # device id
|
||||
self.ad9154.dac_write(AD9154_ILS_BID, 0x00) # band id
|
||||
self.ad9154.dac_write(AD9154_ILS_DID, jesd_settings.did)
|
||||
self.ad9154.dac_write(AD9154_ILS_BID, jesd_settings.bid)
|
||||
self.ad9154.dac_write(AD9154_ILS_LID0, 0x00) # lane id
|
||||
self.ad9154.dac_write(AD9154_ILS_SCR_L, AD9154_L_1_SET(4 - 1) | AD9154_SCR_SET(1))
|
||||
self.ad9154.dac_write(AD9154_ILS_F, 2 - 1)
|
||||
self.ad9154.dac_write(AD9154_ILS_K, 16 - 1)
|
||||
self.ad9154.dac_write(AD9154_ILS_M, 4 - 1)
|
||||
self.ad9154.dac_write(AD9154_ILS_CS_N, AD9154_N_1_SET(16 - 1) | AD9154_CS_SET(0))
|
||||
self.ad9154.dac_write(AD9154_ILS_NP, AD9154_NP_1_SET(16 - 1) |
|
||||
AD9154_SUBCLASSV_SET(1))
|
||||
self.ad9154.dac_write(AD9154_ILS_S, AD9154_S_1_SET(1 - 1) | AD9154_JESDV_SET(1))
|
||||
self.ad9154.dac_write(AD9154_ILS_HD_CF, AD9154_HD_SET(0) | AD9154_CF_SET(0))
|
||||
self.ad9154.dac_write(AD9154_ILS_CHECKSUM,
|
||||
0x00 + 0x00 + 0x00 + 1 + (4 - 1) + # DID BID LID SCR L
|
||||
(2 - 1) + (16 - 1) + (4 - 1) + (16 - 1) + # F K M N
|
||||
1 + (16 - 1) + 1 + (1 - 1) + 0 # SUBC NP JESDV S HD
|
||||
)
|
||||
self.ad9154.dac_write(AD9154_LANEDESKEW, 0xf0)
|
||||
self.ad9154.dac_write(AD9154_ILS_SCR_L,
|
||||
AD9154_L_1_SET(jesd_settings.phy.l - 1) |
|
||||
AD9154_SCR_SET(1))
|
||||
self.ad9154.dac_write(AD9154_ILS_F, jesd_settings.transport.f - 1)
|
||||
self.ad9154.dac_write(AD9154_ILS_K, jesd_settings.transport.k - 1)
|
||||
self.ad9154.dac_write(AD9154_ILS_M, jesd_settings.phy.m - 1)
|
||||
self.ad9154.dac_write(AD9154_ILS_CS_N,
|
||||
AD9154_N_1_SET(jesd_settings.phy.n - 1) |
|
||||
AD9154_CS_SET(0))
|
||||
self.ad9154.dac_write(AD9154_ILS_NP,
|
||||
AD9154_NP_1_SET(jesd_settings.phy.np - 1) |
|
||||
AD9154_SUBCLASSV_SET(jesd_settings.phy.subclassv))
|
||||
self.ad9154.dac_write(AD9154_ILS_S,
|
||||
AD9154_S_1_SET(jesd_settings.transport.s - 1) |
|
||||
AD9154_JESDV_SET(jesd_settings.phy.jesdv))
|
||||
self.ad9154.dac_write(AD9154_ILS_HD_CF,
|
||||
AD9154_HD_SET(0) | AD9154_CF_SET(0))
|
||||
self.ad9154.dac_write(AD9154_ILS_CHECKSUM, jesd_checksum)
|
||||
self.ad9154.dac_write(AD9154_LANEDESKEW, 0x0f)
|
||||
for i in range(8):
|
||||
self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_DIS_SET(0) |
|
||||
AD9154_DISABLE_ERR_CNTR_DIS_SET(0) |
|
||||
|
@ -197,22 +217,22 @@ class StartupKernel(EnvExperiment):
|
|||
self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_UCC_SET(0) |
|
||||
AD9154_DISABLE_ERR_CNTR_UCC_SET(0) |
|
||||
AD9154_RST_ERR_CNTR_UCC_SET(0) | AD9154_LANE_ADDR_UCC_SET(i))
|
||||
self.ad9154.dac_write(AD9154_CTRLREG1, 2) # F
|
||||
self.ad9154.dac_write(AD9154_CTRLREG1, jesd_settings.transport.f)
|
||||
self.ad9154.dac_write(AD9154_CTRLREG2, AD9154_ILAS_MODE_SET(0) |
|
||||
AD9154_THRESHOLD_MASK_EN_SET(0))
|
||||
self.ad9154.dac_write(AD9154_KVAL, 1) # 4*K multiframes during ILAS
|
||||
self.ad9154.dac_write(AD9154_LANEENABLE, 0xf0)
|
||||
self.ad9154.dac_write(AD9154_KVAL, 1) # *4*K multiframes during ILAS
|
||||
self.ad9154.dac_write(AD9154_LANEENABLE, 0x0f)
|
||||
|
||||
self.ad9154.dac_write(AD9154_TERM_BLK1_CTRLREG0, 1)
|
||||
self.ad9154.dac_write(AD9154_TERM_BLK2_CTRLREG0, 1)
|
||||
self.ad9154.dac_write(AD9154_SERDES_SPI_REG, 1)
|
||||
self.ad9154.dac_write(AD9154_CDR_OPERATING_MODE_REG_0,
|
||||
AD9154_CDR_OVERSAMP_SET(0) | AD9154_CDR_RESERVED_SET(0x2) |
|
||||
AD9154_ENHALFRATE_SET(1))
|
||||
AD9154_ENHALFRATE_SET(0))
|
||||
self.ad9154.dac_write(AD9154_CDR_RESET, 0)
|
||||
self.ad9154.dac_write(AD9154_CDR_RESET, 1)
|
||||
self.ad9154.dac_write(AD9154_REF_CLK_DIVIDER_LDO,
|
||||
AD9154_SPI_CDR_OVERSAMP_SET(0x0) |
|
||||
AD9154_SPI_CDR_OVERSAMP_SET(0x1) |
|
||||
AD9154_SPI_LDO_BYPASS_FILT_SET(1) |
|
||||
AD9154_SPI_LDO_REF_SEL_SET(0))
|
||||
self.ad9154.dac_write(AD9154_LDO_FILTER_1, 0x62) # magic
|
||||
|
|
|
@ -11,6 +11,13 @@ from migen.build.xilinx.ise import XilinxISEToolchain
|
|||
from migen.fhdl.specials import Keep
|
||||
from migen.genlib.io import DifferentialInput
|
||||
|
||||
from jesd204b.common import (JESD204BTransportSettings,
|
||||
JESD204BPhysicalSettings,
|
||||
JESD204BSettings)
|
||||
from jesd204b.phy import JESD204BPhyTX
|
||||
from jesd204b.core import JESD204BCoreTX
|
||||
from jesd204b.core import JESD204BCoreTXControl
|
||||
|
||||
from misoc.interconnect.csr import *
|
||||
from misoc.interconnect import wishbone
|
||||
from misoc.cores import gpio
|
||||
|
@ -395,13 +402,12 @@ class _PhaserCRG(Module, AutoCSR):
|
|||
|
||||
refclk_pads = platform.request("ad9154_refclk")
|
||||
platform.add_period_constraint(refclk_pads.p, 2.)
|
||||
refclk = Signal()
|
||||
refclk = Signal()
|
||||
self.refclk = Signal()
|
||||
self.clock_domains.cd_refclk = ClockDomain()
|
||||
self.specials += [
|
||||
Instance("IBUFDS_GTE2", i_CEB=0,
|
||||
i_I=refclk_pads.p, i_IB=refclk_pads.n, o_O=refclk),
|
||||
Instance("BUFG", i_I=refclk, o_O=self.cd_refclk.clk),
|
||||
i_I=refclk_pads.p, i_IB=refclk_pads.n, o_O=self.refclk),
|
||||
Instance("BUFG", i_I=self.refclk, o_O=self.cd_refclk.clk),
|
||||
]
|
||||
|
||||
pll_locked = Signal()
|
||||
|
@ -436,7 +442,10 @@ class _PhaserCRG(Module, AutoCSR):
|
|||
|
||||
|
||||
class Phaser(_NIST_Ions):
|
||||
mem_map = {"ad9154_spi": 0x18000000}
|
||||
mem_map = {
|
||||
"ad9154_spi": 0x50000000,
|
||||
"jesd_control": 0x40000000,
|
||||
}
|
||||
mem_map.update(_NIST_Ions.mem_map)
|
||||
|
||||
def __init__(self, cpu_type="or1k", **kwargs):
|
||||
|
@ -446,16 +455,6 @@ class Phaser(_NIST_Ions):
|
|||
platform.add_extension(phaser.fmc_adapter_io)
|
||||
|
||||
sysref_pads = platform.request("ad9154_sysref")
|
||||
#sysref = Signal()
|
||||
#self.specials += DifferentialInput(
|
||||
# sysref_pads.p, sysref_pads.n, sysref)
|
||||
sync_pads = platform.request("ad9154_sync")
|
||||
#sync = Signal()
|
||||
#self.specials += DifferentialInput(
|
||||
# sync_pads.p, sync_pads.n, sync)
|
||||
|
||||
#for i in range(4):
|
||||
# jesd_pads = platform.request("ad9154_jesd", i)
|
||||
|
||||
rtio_channels = []
|
||||
|
||||
|
@ -473,11 +472,6 @@ class Phaser(_NIST_Ions):
|
|||
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=32,
|
||||
ofifo_depth=2))
|
||||
|
||||
phy = ttl_serdes_7series.Input_8X(sync_pads.p, sync_pads.n)
|
||||
self.submodules += phy
|
||||
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=32,
|
||||
ofifo_depth=2))
|
||||
|
||||
self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels)
|
||||
|
||||
ad9154_spi = self.platform.request("ad9154_spi")
|
||||
|
@ -495,14 +489,6 @@ class Phaser(_NIST_Ions):
|
|||
sawgs = [sawg.Channel(width=16, parallelism=4) for i in range(4)]
|
||||
self.submodules += sawgs
|
||||
|
||||
# TODO: dummy, hookup jesd204b phy here
|
||||
o = Signal((16, True))
|
||||
for ch in sawgs: # gather up dangling outputs
|
||||
for oi in ch.o:
|
||||
o0, o = o, Signal.like(o)
|
||||
self.sync += o.eq(o0 + oi)
|
||||
self.sync.rio_phy += platform.request("user_led").eq(o[-1])
|
||||
|
||||
rtio_channels.extend(rtio.Channel.from_phy(phy)
|
||||
for sawg in sawgs
|
||||
for phy in sawg.phys)
|
||||
|
@ -511,6 +497,43 @@ class Phaser(_NIST_Ions):
|
|||
rtio_channels.append(rtio.LogChannel())
|
||||
self.add_rtio(rtio_channels, _PhaserCRG)
|
||||
|
||||
# jesd_sysref = Signal()
|
||||
# self.specials += DifferentialInput(
|
||||
# sysref_pads.p, sysref_pads.n, jesd_sysref)
|
||||
sync_pads = platform.request("ad9154_sync")
|
||||
jesd_sync = Signal()
|
||||
self.specials += DifferentialInput(
|
||||
sync_pads.p, sync_pads.n, jesd_sync)
|
||||
|
||||
ps = JESD204BPhysicalSettings(l=4, m=4, n=16, np=16, sc=250*1e6)
|
||||
ts = JESD204BTransportSettings(f=2, s=1, k=16, cs=1)
|
||||
jesd_settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
|
||||
jesd_linerate = 5e9
|
||||
jesd_refclk_freq = 500e6
|
||||
rtio_freq = 125*1000*1000
|
||||
jesd_phys = [JESD204BPhyTX(
|
||||
self.rtio_crg.refclk, jesd_refclk_freq,
|
||||
platform.request("ad9154_jesd", i),
|
||||
jesd_linerate, rtio_freq, i) for i in range(4)]
|
||||
self.submodules += jesd_phys
|
||||
for jesd_phy in jesd_phys:
|
||||
platform.add_period_constraint(
|
||||
jesd_phy.gtx.cd_tx.clk,
|
||||
40/jesd_linerate*1e9)
|
||||
self.platform.add_false_path_constraints(
|
||||
self.rtio_crg.cd_rtio.clk,
|
||||
jesd_phy.gtx.cd_tx.clk)
|
||||
self.submodules.jesd_core = JESD204BCoreTX(
|
||||
jesd_phys, jesd_settings, converter_data_width=32)
|
||||
self.comb += self.jesd_core.start.eq(jesd_sync)
|
||||
self.submodules.jesd_control = JESD204BCoreTXControl(self.jesd_core)
|
||||
self.register_kernel_cpu_csrdevice("jesd_control")
|
||||
for i, ch in enumerate(sawgs):
|
||||
conv = getattr(self.jesd_core.transport.sink,
|
||||
"converter{}".format(i))
|
||||
# while at 5 GBps, take every second sample... FIXME
|
||||
self.comb += conv.eq(Cat(ch.o[::2]))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
|
|
|
@ -54,4 +54,19 @@ uint8_t ad9516_read(uint16_t addr)
|
|||
return ad9154_spi_data_read_read();
|
||||
}
|
||||
|
||||
void jesd_enable(int en)
|
||||
{
|
||||
jesd_control_enable_write(en);
|
||||
}
|
||||
|
||||
int jesd_ready(void)
|
||||
{
|
||||
return jesd_control_ready_read();
|
||||
}
|
||||
|
||||
void jesd_prbs(int p)
|
||||
{
|
||||
jesd_control_prbs_config_write(p);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AD9154_DAC_CS */
|
||||
|
|
|
@ -10,5 +10,9 @@ uint8_t ad9154_read(uint16_t addr);
|
|||
void ad9516_write(uint16_t addr, uint8_t data);
|
||||
uint8_t ad9516_read(uint16_t addr);
|
||||
|
||||
void jesd_enable(int en);
|
||||
int jesd_ready(void);
|
||||
void jesd_prbs(int p);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -144,6 +144,9 @@ static const struct symbol runtime_exports[] = {
|
|||
{"ad9154_read", &ad9154_read},
|
||||
{"ad9516_write", &ad9516_write},
|
||||
{"ad9516_read", &ad9516_read},
|
||||
{"jesd_enable", &jesd_enable},
|
||||
{"jesd_ready", &jesd_ready},
|
||||
{"jesd_prbs", &jesd_prbs},
|
||||
#endif
|
||||
|
||||
/* end */
|
||||
|
|
|
@ -170,10 +170,8 @@ The Phaser adapter is an AD9154-FMC-EBZ, a 4 channel 2.4 GHz DAC on an FMC HPC c
|
|||
+--------------+------------+--------------+
|
||||
| 2 | SYSREF | Input |
|
||||
+--------------+------------+--------------+
|
||||
| 3 | SYNC | Input |
|
||||
+--------------+------------+--------------+
|
||||
|
||||
The SAWG channels start with RTIO channel number 4, each occupying 3 channels.
|
||||
The SAWG channels start with RTIO channel number 3, each occupying 3 channels.
|
||||
|
||||
The board has one non-RTIO SPI bus that is accessible through
|
||||
:mod:`artiq.coredevice.ad9154`.
|
||||
|
|
Loading…
Reference in New Issue