forked from M-Labs/artiq
1
0
Fork 0

phaser: instantiate jesd204b core, wire up

This commit is contained in:
Robert Jördens 2016-10-06 12:00:01 +02:00
parent f62d60093e
commit 4d87f0e9e0
9 changed files with 167 additions and 81 deletions

View File

@ -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 * 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 * The CORDIC core has been reused from the PDQ2 gateware
https://github.com/m-labs/pdq2 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 Installation

View File

@ -27,6 +27,21 @@ def ad9516_read(addr: TInt32) -> TInt32:
raise NotImplementedError("syscall not simulated") 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: class AD9154:
"""AD9154-FMC-EBZ SPI support """AD9154-FMC-EBZ SPI support
@ -66,3 +81,17 @@ class AD9154:
def clock_read(self, addr): def clock_read(self, addr):
"""Read AD9516 SPI register at `addr`.""" """Read AD9516 SPI register at `addr`."""
return ad9516_read(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)

View File

@ -44,34 +44,28 @@
"class": "TTLInOut", "class": "TTLInOut",
"arguments": {"channel": 2} "arguments": {"channel": 2}
}, },
"sync": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLInOut",
"arguments": {"channel": 3}
},
"sawg0": { "sawg0": {
"type": "local", "type": "local",
"module": "artiq.coredevice.sawg", "module": "artiq.coredevice.sawg",
"class": "SAWG", "class": "SAWG",
"arguments": {"channel_base": 4, "parallelism": 4} "arguments": {"channel_base": 3, "parallelism": 4}
}, },
"sawg1": { "sawg1": {
"type": "local", "type": "local",
"module": "artiq.coredevice.sawg", "module": "artiq.coredevice.sawg",
"class": "SAWG", "class": "SAWG",
"arguments": {"channel_base": 7, "parallelism": 4} "arguments": {"channel_base": 6, "parallelism": 4}
}, },
"sawg2": { "sawg2": {
"type": "local", "type": "local",
"module": "artiq.coredevice.sawg", "module": "artiq.coredevice.sawg",
"class": "SAWG", "class": "SAWG",
"arguments": {"channel_base": 10, "parallelism": 4} "arguments": {"channel_base": 9, "parallelism": 4}
}, },
"sawg3": { "sawg3": {
"type": "local", "type": "local",
"module": "artiq.coredevice.sawg", "module": "artiq.coredevice.sawg",
"class": "SAWG", "class": "SAWG",
"arguments": {"channel_base": 13, "parallelism": 4} "arguments": {"channel_base": 12, "parallelism": 4}
} }
} }

View File

@ -1,7 +1,33 @@
from jesd204b.common import (JESD204BPhysicalSettings,
JESD204BTransportSettings,
JESD204BSettings)
from artiq.experiment import * from artiq.experiment import *
from artiq.coredevice.ad9516_reg import * from artiq.coredevice.ad9516_reg import *
from artiq.coredevice.ad9154_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): class StartupKernel(EnvExperiment):
def build(self): def build(self):
@ -11,26 +37,16 @@ class StartupKernel(EnvExperiment):
@kernel @kernel
def run(self): 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.core.reset()
self.ad9154.jesd_enable(0)
self.ad9154.init() self.ad9154.init()
self.clock_setup() self.clock_setup()
self.dac_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 @kernel
def clock_setup(self): 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_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_MIX_MODE, 0)
self.ad9154.dac_write(AD9154_DATA_FORMAT, AD9154_BINARY_FORMAT_SET(0)) # s16 self.ad9154.dac_write(AD9154_DATA_FORMAT, AD9154_BINARY_FORMAT_SET(0)) # s16
self.ad9154.dac_write(AD9154_DATAPATH_CTRL, self.ad9154.dac_write(AD9154_DATAPATH_CTRL,
@ -160,24 +176,28 @@ class StartupKernel(EnvExperiment):
self.ad9154.dac_write(AD9154_GENERAL_JRX_CTRL_0, self.ad9154.dac_write(AD9154_GENERAL_JRX_CTRL_0,
AD9154_LINK_EN_SET(0x0) | AD9154_LINK_PAGE_SET(0) | AD9154_LINK_EN_SET(0x0) | AD9154_LINK_PAGE_SET(0) |
AD9154_LINK_MODE_SET(0) | AD9154_CHECKSUM_MODE_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_DID, jesd_settings.did)
self.ad9154.dac_write(AD9154_ILS_BID, 0x00) # band id 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_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_SCR_L,
self.ad9154.dac_write(AD9154_ILS_F, 2 - 1) AD9154_L_1_SET(jesd_settings.phy.l - 1) |
self.ad9154.dac_write(AD9154_ILS_K, 16 - 1) AD9154_SCR_SET(1))
self.ad9154.dac_write(AD9154_ILS_M, 4 - 1) self.ad9154.dac_write(AD9154_ILS_F, jesd_settings.transport.f - 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_K, jesd_settings.transport.k - 1)
self.ad9154.dac_write(AD9154_ILS_NP, AD9154_NP_1_SET(16 - 1) | self.ad9154.dac_write(AD9154_ILS_M, jesd_settings.phy.m - 1)
AD9154_SUBCLASSV_SET(1)) self.ad9154.dac_write(AD9154_ILS_CS_N,
self.ad9154.dac_write(AD9154_ILS_S, AD9154_S_1_SET(1 - 1) | AD9154_JESDV_SET(1)) AD9154_N_1_SET(jesd_settings.phy.n - 1) |
self.ad9154.dac_write(AD9154_ILS_HD_CF, AD9154_HD_SET(0) | AD9154_CF_SET(0)) AD9154_CS_SET(0))
self.ad9154.dac_write(AD9154_ILS_CHECKSUM, self.ad9154.dac_write(AD9154_ILS_NP,
0x00 + 0x00 + 0x00 + 1 + (4 - 1) + # DID BID LID SCR L AD9154_NP_1_SET(jesd_settings.phy.np - 1) |
(2 - 1) + (16 - 1) + (4 - 1) + (16 - 1) + # F K M N AD9154_SUBCLASSV_SET(jesd_settings.phy.subclassv))
1 + (16 - 1) + 1 + (1 - 1) + 0 # SUBC NP JESDV S HD self.ad9154.dac_write(AD9154_ILS_S,
) AD9154_S_1_SET(jesd_settings.transport.s - 1) |
self.ad9154.dac_write(AD9154_LANEDESKEW, 0xf0) 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): for i in range(8):
self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_DIS_SET(0) | self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_DIS_SET(0) |
AD9154_DISABLE_ERR_CNTR_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) | self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_UCC_SET(0) |
AD9154_DISABLE_ERR_CNTR_UCC_SET(0) | AD9154_DISABLE_ERR_CNTR_UCC_SET(0) |
AD9154_RST_ERR_CNTR_UCC_SET(0) | AD9154_LANE_ADDR_UCC_SET(i)) 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) | self.ad9154.dac_write(AD9154_CTRLREG2, AD9154_ILAS_MODE_SET(0) |
AD9154_THRESHOLD_MASK_EN_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_KVAL, 1) # *4*K multiframes during ILAS
self.ad9154.dac_write(AD9154_LANEENABLE, 0xf0) self.ad9154.dac_write(AD9154_LANEENABLE, 0x0f)
self.ad9154.dac_write(AD9154_TERM_BLK1_CTRLREG0, 1) self.ad9154.dac_write(AD9154_TERM_BLK1_CTRLREG0, 1)
self.ad9154.dac_write(AD9154_TERM_BLK2_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_SERDES_SPI_REG, 1)
self.ad9154.dac_write(AD9154_CDR_OPERATING_MODE_REG_0, self.ad9154.dac_write(AD9154_CDR_OPERATING_MODE_REG_0,
AD9154_CDR_OVERSAMP_SET(0) | AD9154_CDR_RESERVED_SET(0x2) | 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, 0)
self.ad9154.dac_write(AD9154_CDR_RESET, 1) self.ad9154.dac_write(AD9154_CDR_RESET, 1)
self.ad9154.dac_write(AD9154_REF_CLK_DIVIDER_LDO, 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_BYPASS_FILT_SET(1) |
AD9154_SPI_LDO_REF_SEL_SET(0)) AD9154_SPI_LDO_REF_SEL_SET(0))
self.ad9154.dac_write(AD9154_LDO_FILTER_1, 0x62) # magic self.ad9154.dac_write(AD9154_LDO_FILTER_1, 0x62) # magic

View File

@ -11,6 +11,13 @@ from migen.build.xilinx.ise import XilinxISEToolchain
from migen.fhdl.specials import Keep from migen.fhdl.specials import Keep
from migen.genlib.io import DifferentialInput 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.csr import *
from misoc.interconnect import wishbone from misoc.interconnect import wishbone
from misoc.cores import gpio from misoc.cores import gpio
@ -395,13 +402,12 @@ class _PhaserCRG(Module, AutoCSR):
refclk_pads = platform.request("ad9154_refclk") refclk_pads = platform.request("ad9154_refclk")
platform.add_period_constraint(refclk_pads.p, 2.) platform.add_period_constraint(refclk_pads.p, 2.)
refclk = Signal() self.refclk = Signal()
refclk = Signal()
self.clock_domains.cd_refclk = ClockDomain() self.clock_domains.cd_refclk = ClockDomain()
self.specials += [ self.specials += [
Instance("IBUFDS_GTE2", i_CEB=0, Instance("IBUFDS_GTE2", i_CEB=0,
i_I=refclk_pads.p, i_IB=refclk_pads.n, o_O=refclk), i_I=refclk_pads.p, i_IB=refclk_pads.n, o_O=self.refclk),
Instance("BUFG", i_I=refclk, o_O=self.cd_refclk.clk), Instance("BUFG", i_I=self.refclk, o_O=self.cd_refclk.clk),
] ]
pll_locked = Signal() pll_locked = Signal()
@ -436,7 +442,10 @@ class _PhaserCRG(Module, AutoCSR):
class Phaser(_NIST_Ions): class Phaser(_NIST_Ions):
mem_map = {"ad9154_spi": 0x18000000} mem_map = {
"ad9154_spi": 0x50000000,
"jesd_control": 0x40000000,
}
mem_map.update(_NIST_Ions.mem_map) mem_map.update(_NIST_Ions.mem_map)
def __init__(self, cpu_type="or1k", **kwargs): def __init__(self, cpu_type="or1k", **kwargs):
@ -446,16 +455,6 @@ class Phaser(_NIST_Ions):
platform.add_extension(phaser.fmc_adapter_io) platform.add_extension(phaser.fmc_adapter_io)
sysref_pads = platform.request("ad9154_sysref") 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 = [] rtio_channels = []
@ -473,11 +472,6 @@ class Phaser(_NIST_Ions):
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=32, rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=32,
ofifo_depth=2)) 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) self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels)
ad9154_spi = self.platform.request("ad9154_spi") 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)] sawgs = [sawg.Channel(width=16, parallelism=4) for i in range(4)]
self.submodules += sawgs 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) rtio_channels.extend(rtio.Channel.from_phy(phy)
for sawg in sawgs for sawg in sawgs
for phy in sawg.phys) for phy in sawg.phys)
@ -511,6 +497,43 @@ class Phaser(_NIST_Ions):
rtio_channels.append(rtio.LogChannel()) rtio_channels.append(rtio.LogChannel())
self.add_rtio(rtio_channels, _PhaserCRG) 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(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(

View File

@ -54,4 +54,19 @@ uint8_t ad9516_read(uint16_t addr)
return ad9154_spi_data_read_read(); 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 */ #endif /* CONFIG_AD9154_DAC_CS */

View File

@ -10,5 +10,9 @@ uint8_t ad9154_read(uint16_t addr);
void ad9516_write(uint16_t addr, uint8_t data); void ad9516_write(uint16_t addr, uint8_t data);
uint8_t ad9516_read(uint16_t addr); uint8_t ad9516_read(uint16_t addr);
void jesd_enable(int en);
int jesd_ready(void);
void jesd_prbs(int p);
#endif #endif
#endif #endif

View File

@ -144,6 +144,9 @@ static const struct symbol runtime_exports[] = {
{"ad9154_read", &ad9154_read}, {"ad9154_read", &ad9154_read},
{"ad9516_write", &ad9516_write}, {"ad9516_write", &ad9516_write},
{"ad9516_read", &ad9516_read}, {"ad9516_read", &ad9516_read},
{"jesd_enable", &jesd_enable},
{"jesd_ready", &jesd_ready},
{"jesd_prbs", &jesd_prbs},
#endif #endif
/* end */ /* end */

View File

@ -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 | | 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 The board has one non-RTIO SPI bus that is accessible through
:mod:`artiq.coredevice.ad9154`. :mod:`artiq.coredevice.ad9154`.