mirror of https://github.com/m-labs/artiq.git
remove phaser, adapt SAWG example to Sayma
This commit is contained in:
parent
5809e08686
commit
569484f888
|
@ -1,13 +1,11 @@
|
||||||
# The RTIO channel numbers here are for Phaser on KC705.
|
core_addr = "sayma1.lab.m-labs.hk"
|
||||||
|
|
||||||
core_addr = "kc705aux.lab.m-labs.hk"
|
|
||||||
|
|
||||||
device_db = {
|
device_db = {
|
||||||
"core": {
|
"core": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.core",
|
"module": "artiq.coredevice.core",
|
||||||
"class": "Core",
|
"class": "Core",
|
||||||
"arguments": {"host": core_addr, "ref_period": 5e-9/6}
|
"arguments": {"host": core_addr, "ref_period": 1/(150e6)}
|
||||||
},
|
},
|
||||||
"core_log": {
|
"core_log": {
|
||||||
"type": "controller",
|
"type": "controller",
|
||||||
|
@ -20,57 +18,96 @@ device_db = {
|
||||||
"module": "artiq.coredevice.cache",
|
"module": "artiq.coredevice.cache",
|
||||||
"class": "CoreCache"
|
"class": "CoreCache"
|
||||||
},
|
},
|
||||||
"ttl_sma": {
|
|
||||||
"type": "local",
|
|
||||||
"module": "artiq.coredevice.ttl",
|
|
||||||
"class": "TTLInOut",
|
|
||||||
"arguments": {"channel": 0}
|
|
||||||
},
|
|
||||||
"led": {
|
|
||||||
"type": "local",
|
|
||||||
"module": "artiq.coredevice.ttl",
|
|
||||||
"class": "TTLOut",
|
|
||||||
"arguments": {"channel": 1}
|
|
||||||
},
|
|
||||||
"sysref": {
|
|
||||||
"type": "local",
|
|
||||||
"module": "artiq.coredevice.ttl",
|
|
||||||
"class": "TTLInOut",
|
|
||||||
"arguments": {"channel": 2}
|
|
||||||
},
|
|
||||||
"converter_spi": {
|
"converter_spi": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.spi",
|
"module": "artiq.coredevice.spi",
|
||||||
"class": "NRTSPIMaster",
|
"class": "NRTSPIMaster",
|
||||||
},
|
},
|
||||||
"ad9154_spi": {
|
"ad9154_spi0": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ad9154_spi",
|
"module": "artiq.coredevice.ad9154_spi",
|
||||||
"class": "AD9154",
|
"class": "AD9154",
|
||||||
"arguments": {"spi_device": "converter_spi", "chip_select": 1}
|
"arguments": {"spi_device": "converter_spi", "chip_select": 2}
|
||||||
},
|
},
|
||||||
|
"ad9154_spi1": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.ad9154_spi",
|
||||||
|
"class": "AD9154",
|
||||||
|
"arguments": {"spi_device": "converter_spi", "chip_select": 3}
|
||||||
|
},
|
||||||
|
|
||||||
|
"led0": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.ttl",
|
||||||
|
"class": "TTLOut",
|
||||||
|
"arguments": {"channel": 0}
|
||||||
|
},
|
||||||
|
"led1": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.ttl",
|
||||||
|
"class": "TTLOut",
|
||||||
|
"arguments": {"channel": 1}
|
||||||
|
},
|
||||||
|
"ttl_sma0": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.ttl",
|
||||||
|
"class": "TTLOut",
|
||||||
|
"arguments": {"channel": 2}
|
||||||
|
},
|
||||||
|
"ttl_sma1": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.ttl",
|
||||||
|
"class": "TTLOut",
|
||||||
|
"arguments": {"channel": 3}
|
||||||
|
},
|
||||||
|
|
||||||
"sawg0": {
|
"sawg0": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.sawg",
|
"module": "artiq.coredevice.sawg",
|
||||||
"class": "SAWG",
|
"class": "SAWG",
|
||||||
"arguments": {"channel_base": 3, "parallelism": 2}
|
"arguments": {"channel_base": 4, "parallelism": 4}
|
||||||
},
|
},
|
||||||
"sawg1": {
|
"sawg1": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.sawg",
|
"module": "artiq.coredevice.sawg",
|
||||||
"class": "SAWG",
|
"class": "SAWG",
|
||||||
"arguments": {"channel_base": 13, "parallelism": 2}
|
"arguments": {"channel_base": 14, "parallelism": 4}
|
||||||
},
|
},
|
||||||
"sawg2": {
|
"sawg2": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.sawg",
|
"module": "artiq.coredevice.sawg",
|
||||||
"class": "SAWG",
|
"class": "SAWG",
|
||||||
"arguments": {"channel_base": 23, "parallelism": 2}
|
"arguments": {"channel_base": 24, "parallelism": 4}
|
||||||
},
|
},
|
||||||
"sawg3": {
|
"sawg3": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.sawg",
|
"module": "artiq.coredevice.sawg",
|
||||||
"class": "SAWG",
|
"class": "SAWG",
|
||||||
"arguments": {"channel_base": 33, "parallelism": 2}
|
"arguments": {"channel_base": 34, "parallelism": 4}
|
||||||
}
|
},
|
||||||
|
"sawg4": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.sawg",
|
||||||
|
"class": "SAWG",
|
||||||
|
"arguments": {"channel_base": 44, "parallelism": 4}
|
||||||
|
},
|
||||||
|
"sawg5": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.sawg",
|
||||||
|
"class": "SAWG",
|
||||||
|
"arguments": {"channel_base": 54, "parallelism": 4}
|
||||||
|
},
|
||||||
|
"sawg6": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.sawg",
|
||||||
|
"class": "SAWG",
|
||||||
|
"arguments": {"channel_base": 64, "parallelism": 4}
|
||||||
|
},
|
||||||
|
"sawg7": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.sawg",
|
||||||
|
"class": "SAWG",
|
||||||
|
"arguments": {"channel_base": 74, "parallelism": 4}
|
||||||
|
},
|
||||||
}
|
}
|
|
@ -4,8 +4,7 @@ from artiq.experiment import *
|
||||||
class SAWGTest(EnvExperiment):
|
class SAWGTest(EnvExperiment):
|
||||||
def build(self):
|
def build(self):
|
||||||
self.setattr_device("core")
|
self.setattr_device("core")
|
||||||
self.setattr_device("led")
|
self.setattr_device("ttl_sma0")
|
||||||
self.setattr_device("ttl_sma")
|
|
||||||
|
|
||||||
self.setattr_device("sawg0")
|
self.setattr_device("sawg0")
|
||||||
self.setattr_device("sawg1")
|
self.setattr_device("sawg1")
|
||||||
|
@ -15,7 +14,6 @@ class SAWGTest(EnvExperiment):
|
||||||
@kernel
|
@kernel
|
||||||
def run(self):
|
def run(self):
|
||||||
self.core.reset()
|
self.core.reset()
|
||||||
self.ttl_sma.output()
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
self.sawg0.amplitude1.set(0.)
|
self.sawg0.amplitude1.set(0.)
|
||||||
|
@ -30,21 +28,21 @@ class SAWGTest(EnvExperiment):
|
||||||
self.sawg1.amplitude1.set(.4)
|
self.sawg1.amplitude1.set(.4)
|
||||||
self.sawg1.frequency0.set(10*MHz)
|
self.sawg1.frequency0.set(10*MHz)
|
||||||
self.sawg1.phase0.set(0.)
|
self.sawg1.phase0.set(0.)
|
||||||
self.ttl_sma.pulse(200*ns)
|
self.ttl_sma0.pulse(200*ns)
|
||||||
self.sawg1.amplitude1.set(.1)
|
self.sawg1.amplitude1.set(.1)
|
||||||
delay(200*ns)
|
delay(200*ns)
|
||||||
self.sawg1.amplitude1.set(-.4)
|
self.sawg1.amplitude1.set(-.4)
|
||||||
self.ttl_sma.pulse(200*ns)
|
self.ttl_sma0.pulse(200*ns)
|
||||||
self.sawg1.amplitude1.set(.4)
|
self.sawg1.amplitude1.set(.4)
|
||||||
delay(200*ns)
|
delay(200*ns)
|
||||||
self.sawg1.phase0.set(.25)
|
self.sawg1.phase0.set(.25)
|
||||||
self.ttl_sma.pulse(200*ns)
|
self.ttl_sma0.pulse(200*ns)
|
||||||
self.sawg1.phase0.set(.5)
|
self.sawg1.phase0.set(.5)
|
||||||
delay(200*ns)
|
delay(200*ns)
|
||||||
self.sawg0.phase0.set(.5)
|
self.sawg0.phase0.set(.5)
|
||||||
self.ttl_sma.pulse(200*ns)
|
self.ttl_sma0.pulse(200*ns)
|
||||||
self.sawg1.frequency0.set(30*MHz)
|
self.sawg1.frequency0.set(30*MHz)
|
||||||
delay(200*ns)
|
delay(200*ns)
|
||||||
self.sawg1.frequency0.set(10*MHz)
|
self.sawg1.frequency0.set(10*MHz)
|
||||||
self.sawg1.phase0.set(0.)
|
self.sawg1.phase0.set(0.)
|
||||||
self.ttl_sma.pulse(200*ns)
|
self.ttl_sma0.pulse(200*ns)
|
|
@ -4,8 +4,8 @@ from artiq.experiment import *
|
||||||
class SAWGTestTwoTone(EnvExperiment):
|
class SAWGTestTwoTone(EnvExperiment):
|
||||||
def build(self):
|
def build(self):
|
||||||
self.setattr_device("core")
|
self.setattr_device("core")
|
||||||
self.setattr_device("led")
|
self.setattr_device("led0")
|
||||||
self.setattr_device("ttl_sma")
|
self.setattr_device("ttl_sma0")
|
||||||
|
|
||||||
self.setattr_device("sawg0")
|
self.setattr_device("sawg0")
|
||||||
self.setattr_device("sawg1")
|
self.setattr_device("sawg1")
|
||||||
|
@ -17,8 +17,6 @@ class SAWGTestTwoTone(EnvExperiment):
|
||||||
self.core.reset()
|
self.core.reset()
|
||||||
delay(1*ms)
|
delay(1*ms)
|
||||||
|
|
||||||
self.ttl_sma.output()
|
|
||||||
|
|
||||||
self.sawg0.reset()
|
self.sawg0.reset()
|
||||||
self.sawg1.reset()
|
self.sawg1.reset()
|
||||||
self.sawg2.reset()
|
self.sawg2.reset()
|
||||||
|
@ -38,8 +36,8 @@ class SAWGTestTwoTone(EnvExperiment):
|
||||||
order = 3
|
order = 3
|
||||||
|
|
||||||
delay(20*ms)
|
delay(20*ms)
|
||||||
self.led.on()
|
self.led0.on()
|
||||||
self.ttl_sma.on()
|
self.ttl_sma0.on()
|
||||||
self.sawg0.frequency0.set(10*MHz)
|
self.sawg0.frequency0.set(10*MHz)
|
||||||
self.sawg0.phase0.set(0.)
|
self.sawg0.phase0.set(0.)
|
||||||
self.sawg0.frequency1.set(1*MHz)
|
self.sawg0.frequency1.set(1*MHz)
|
||||||
|
@ -60,5 +58,5 @@ class SAWGTestTwoTone(EnvExperiment):
|
||||||
|
|
||||||
self.sawg1.amplitude1.set(.0)
|
self.sawg1.amplitude1.set(.0)
|
||||||
self.sawg1.amplitude2.set(.0)
|
self.sawg1.amplitude2.set(.0)
|
||||||
self.ttl_sma.off()
|
self.ttl_sma0.off()
|
||||||
self.led.off()
|
self.led0.off()
|
|
@ -5,7 +5,7 @@ from artiq.experiment import *
|
||||||
class Test(EnvExperiment):
|
class Test(EnvExperiment):
|
||||||
def build(self):
|
def build(self):
|
||||||
self.setattr_device("core")
|
self.setattr_device("core")
|
||||||
self.setattr_device("ad9154_spi")
|
self.ad9154_spi = self.get_device("ad9154_spi0")
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def run(self):
|
def run(self):
|
|
@ -1,74 +0,0 @@
|
||||||
from migen.build.generic_platform import *
|
|
||||||
|
|
||||||
|
|
||||||
ad9154_fmc_ebz = [
|
|
||||||
("ad9154_spi", 0,
|
|
||||||
# AD9154 should give control of SPI to FMC when USB cable is unplugged,
|
|
||||||
# It's the case, but the PIC18F24J50 is introducing noise on SPI SCK
|
|
||||||
# (???) To workaround that, add 2 jumpers:
|
|
||||||
# - on XP1, between pin 5 and 6 (will keep the PIC in reset)
|
|
||||||
# - on JP3 (will force output enable on FXLA108)
|
|
||||||
Subsignal("clk", Pins("HPC:LA03_P")),
|
|
||||||
Subsignal("cs_n", Pins("HPC:LA04_N", "HPC:LA05_P")),
|
|
||||||
Subsignal("mosi", Pins("HPC:LA03_N")),
|
|
||||||
Subsignal("miso", Pins("HPC:LA04_P")),
|
|
||||||
Subsignal("en", Pins("HPC:LA05_N")),
|
|
||||||
IOStandard("LVCMOS25"),
|
|
||||||
),
|
|
||||||
("ad9154_txen", 0, Pins("HPC:LA07_P"), IOStandard("LVCMOS25")),
|
|
||||||
("ad9154_txen", 1, Pins("HPC:LA07_N"), IOStandard("LVCMOS25")),
|
|
||||||
("ad9154_refclk", 0,
|
|
||||||
Subsignal("p", Pins("HPC:GBTCLK0_M2C_P")),
|
|
||||||
Subsignal("n", Pins("HPC:GBTCLK0_M2C_N")),
|
|
||||||
),
|
|
||||||
("ad9154_sysref", 0,
|
|
||||||
Subsignal("p", Pins("HPC:LA00_CC_P")),
|
|
||||||
Subsignal("n", Pins("HPC:LA00_CC_N")),
|
|
||||||
IOStandard("LVDS_25"),
|
|
||||||
Misc("DIFF_TERM=TRUE"),
|
|
||||||
),
|
|
||||||
("ad9154_sync", 0,
|
|
||||||
Subsignal("p", Pins("HPC:LA01_CC_P")),
|
|
||||||
Subsignal("n", Pins("HPC:LA01_CC_N")),
|
|
||||||
IOStandard("LVDS_25"),
|
|
||||||
Misc("DIFF_TERM=TRUE"),
|
|
||||||
),
|
|
||||||
("ad9154_sync", 1,
|
|
||||||
Subsignal("p", Pins("HPC:LA02_P")),
|
|
||||||
Subsignal("n", Pins("HPC:LA02_N")),
|
|
||||||
IOStandard("LVDS_25"),
|
|
||||||
Misc("DIFF_TERM=TRUE"),
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 0, # AD9154's SERDIN7
|
|
||||||
Subsignal("txp", Pins("HPC:DP0_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP0_C2M_N"))
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 1, # AD9154's SERDIN6
|
|
||||||
Subsignal("txp", Pins("HPC:DP1_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP1_C2M_N"))
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 2, # AD9154's SERDIN5
|
|
||||||
Subsignal("txp", Pins("HPC:DP2_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP2_C2M_N"))
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 3, # AD9154's SERDIN4
|
|
||||||
Subsignal("txp", Pins("HPC:DP3_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP3_C2M_N"))
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 4, # AD9154's SERDIN2
|
|
||||||
Subsignal("txp", Pins("HPC:DP4_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP4_C2M_N"))
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 5, # AD9154's SERDIN0
|
|
||||||
Subsignal("txp", Pins("HPC:DP5_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP5_C2M_N"))
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 6, # AD9154's SERDIN1
|
|
||||||
Subsignal("txp", Pins("HPC:DP6_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP6_C2M_N"))
|
|
||||||
),
|
|
||||||
("ad9154_jesd", 7, # AD9154's SERDIN3
|
|
||||||
Subsignal("txp", Pins("HPC:DP7_C2M_P")),
|
|
||||||
Subsignal("txn", Pins("HPC:DP7_C2M_N"))
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,271 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
from migen import *
|
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
||||||
from migen.genlib.cdc import MultiReg
|
|
||||||
|
|
||||||
from jesd204b.common import (JESD204BTransportSettings,
|
|
||||||
JESD204BPhysicalSettings,
|
|
||||||
JESD204BSettings)
|
|
||||||
from jesd204b.phy.gtx import GTXQuadPLL
|
|
||||||
from jesd204b.phy import JESD204BPhyTX
|
|
||||||
from jesd204b.core import JESD204BCoreTX
|
|
||||||
from jesd204b.core import JESD204BCoreTXControl
|
|
||||||
|
|
||||||
from misoc.interconnect.csr import *
|
|
||||||
from misoc.cores import gpio
|
|
||||||
from misoc.cores import spi as spi_csr
|
|
||||||
from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict
|
|
||||||
from misoc.integration.builder import builder_args, builder_argdict
|
|
||||||
|
|
||||||
from artiq.gateware.amp import AMPSoC, build_artiq_soc
|
|
||||||
from artiq.gateware import rtio
|
|
||||||
from artiq.gateware.ad9154_fmc_ebz import ad9154_fmc_ebz
|
|
||||||
from artiq.gateware.rtio.phy import (ttl_simple, ttl_serdes_7series,
|
|
||||||
sawg)
|
|
||||||
from artiq import __version__ as artiq_version
|
|
||||||
|
|
||||||
|
|
||||||
class _PhaserCRG(Module, AutoCSR):
|
|
||||||
def __init__(self, platform, refclk):
|
|
||||||
self._clock_sel = CSRStorage()
|
|
||||||
self._pll_reset = CSRStorage(reset=1)
|
|
||||||
self._pll_locked = CSRStatus()
|
|
||||||
self.clock_domains.cd_rtio = ClockDomain()
|
|
||||||
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
|
||||||
|
|
||||||
external_clk = Signal()
|
|
||||||
user_sma_clock = platform.request("user_sma_clock")
|
|
||||||
platform.add_period_constraint(user_sma_clock.p, 20/3)
|
|
||||||
self.specials += Instance("IBUFDS",
|
|
||||||
i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
|
|
||||||
o_O=external_clk)
|
|
||||||
|
|
||||||
pll_locked = Signal()
|
|
||||||
rtio_clk = Signal()
|
|
||||||
rtiox4_clk = Signal()
|
|
||||||
self.specials += [
|
|
||||||
Instance("PLLE2_ADV",
|
|
||||||
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
|
||||||
|
|
||||||
p_REF_JITTER1=0.01, p_REF_JITTER2=0.01,
|
|
||||||
p_CLKIN1_PERIOD=20/3, p_CLKIN2_PERIOD=20/3,
|
|
||||||
i_CLKIN1=refclk, i_CLKIN2=external_clk,
|
|
||||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
|
||||||
i_CLKINSEL=~self._clock_sel.storage,
|
|
||||||
|
|
||||||
# VCO @ 1.2GHz when using 150MHz input
|
|
||||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
|
||||||
i_CLKFBIN=self.cd_rtio.clk,
|
|
||||||
i_RST=self._pll_reset.storage,
|
|
||||||
|
|
||||||
o_CLKFBOUT=rtio_clk,
|
|
||||||
|
|
||||||
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
|
||||||
o_CLKOUT0=rtiox4_clk),
|
|
||||||
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
|
||||||
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
|
||||||
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
|
||||||
MultiReg(pll_locked, self._pll_locked.status)
|
|
||||||
]
|
|
||||||
self.cd_rtio.clk.attr.add("keep")
|
|
||||||
platform.add_period_constraint(self.cd_rtio.clk, 20/3)
|
|
||||||
|
|
||||||
|
|
||||||
class AD9154JESD(Module, AutoCSR):
|
|
||||||
def __init__(self, platform):
|
|
||||||
self.jreset = CSRStorage(reset=1)
|
|
||||||
|
|
||||||
ps = JESD204BPhysicalSettings(l=4, m=4, n=16, np=16)
|
|
||||||
ts = JESD204BTransportSettings(f=2, s=1, k=16, cs=1)
|
|
||||||
settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
|
|
||||||
linerate = 6e9
|
|
||||||
refclk_freq = 150e6
|
|
||||||
fabric_freq = 150*1000*1000
|
|
||||||
|
|
||||||
refclk = Signal()
|
|
||||||
self.clock_domains.cd_jesd = ClockDomain()
|
|
||||||
refclk_pads = platform.request("ad9154_refclk")
|
|
||||||
|
|
||||||
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_jesd.clk),
|
|
||||||
AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage),
|
|
||||||
]
|
|
||||||
self.cd_jesd.clk.attr.add("keep")
|
|
||||||
platform.add_period_constraint(self.cd_jesd.clk, 1e9/refclk_freq)
|
|
||||||
|
|
||||||
qpll = GTXQuadPLL(refclk, refclk_freq, linerate)
|
|
||||||
self.submodules += qpll
|
|
||||||
self.phys = []
|
|
||||||
for i in range(4):
|
|
||||||
phy = JESD204BPhyTX(
|
|
||||||
qpll, platform.request("ad9154_jesd", i), fabric_freq)
|
|
||||||
phy.transmitter.cd_tx.clk.attr.add("keep")
|
|
||||||
platform.add_period_constraint(phy.transmitter.cd_tx.clk,
|
|
||||||
40*1e9/linerate)
|
|
||||||
platform.add_false_path_constraints(self.cd_jesd.clk,
|
|
||||||
phy.transmitter.cd_tx.clk)
|
|
||||||
self.phys.append(phy)
|
|
||||||
to_jesd = ClockDomainsRenamer("jesd")
|
|
||||||
self.submodules.core = to_jesd(JESD204BCoreTX(self.phys, settings,
|
|
||||||
converter_data_width=32))
|
|
||||||
self.submodules.control = to_jesd(JESD204BCoreTXControl(self.core))
|
|
||||||
self.core.register_jsync(platform.request("ad9154_sync"))
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
platform.request("ad9154_txen", 0).eq(1),
|
|
||||||
platform.request("ad9154_txen", 1).eq(1),
|
|
||||||
platform.request("user_led", 3).eq(self.core.jsync),
|
|
||||||
]
|
|
||||||
|
|
||||||
# blinking leds for transceiver reset status
|
|
||||||
for i in range(4):
|
|
||||||
counter = Signal(max=fabric_freq)
|
|
||||||
self.comb += platform.request("user_led", 4 + i).eq(counter[-1])
|
|
||||||
sync = getattr(self.sync, "phy{}_tx".format(i))
|
|
||||||
sync += [
|
|
||||||
counter.eq(counter - 1),
|
|
||||||
If(counter == 0,
|
|
||||||
counter.eq(fabric_freq - 1)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class AD9154(Module, AutoCSR):
|
|
||||||
def __init__(self, platform):
|
|
||||||
self.submodules.jesd = AD9154JESD(platform)
|
|
||||||
|
|
||||||
self.sawgs = [sawg.Channel(width=16, parallelism=2) for i in range(4)]
|
|
||||||
self.submodules += self.sawgs
|
|
||||||
|
|
||||||
# self.sawgs[0].connect_y(self.sawgs[1])
|
|
||||||
# self.sawgs[1].connect_y(self.sawgs[0])
|
|
||||||
# self.sawgs[2].connect_y(self.sawgs[3])
|
|
||||||
# self.sawgs[3].connect_y(self.sawgs[2])
|
|
||||||
|
|
||||||
for conv, ch in zip(self.jesd.core.sink.flatten(), self.sawgs):
|
|
||||||
self.sync.jesd += conv.eq(Cat(ch.o))
|
|
||||||
|
|
||||||
|
|
||||||
class Phaser(MiniSoC, AMPSoC):
|
|
||||||
mem_map = {
|
|
||||||
"cri_con": 0x10000000,
|
|
||||||
"rtio": 0x20000000,
|
|
||||||
"rtio_dma": 0x30000000,
|
|
||||||
"mailbox": 0x70000000,
|
|
||||||
"ad9154": 0x50000000,
|
|
||||||
}
|
|
||||||
mem_map.update(MiniSoC.mem_map)
|
|
||||||
|
|
||||||
def __init__(self, cpu_type="or1k", **kwargs):
|
|
||||||
MiniSoC.__init__(self,
|
|
||||||
cpu_type=cpu_type,
|
|
||||||
sdram_controller_type="minicon",
|
|
||||||
l2_size=128*1024,
|
|
||||||
ident=artiq_version,
|
|
||||||
ethmac_nrxslots=4,
|
|
||||||
ethmac_ntxslots=4,
|
|
||||||
**kwargs)
|
|
||||||
AMPSoC.__init__(self)
|
|
||||||
self.platform.toolchain.bitstream_commands.extend([
|
|
||||||
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
|
||||||
])
|
|
||||||
|
|
||||||
platform = self.platform
|
|
||||||
platform.add_extension(ad9154_fmc_ebz)
|
|
||||||
|
|
||||||
self.submodules.leds = gpio.GPIOOut(Cat(
|
|
||||||
platform.request("user_led", 0),
|
|
||||||
platform.request("user_led", 1)))
|
|
||||||
self.csr_devices.append("leds")
|
|
||||||
|
|
||||||
i2c = platform.request("i2c")
|
|
||||||
self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda])
|
|
||||||
self.csr_devices.append("i2c")
|
|
||||||
self.config["I2C_BUS_COUNT"] = 1
|
|
||||||
|
|
||||||
ad9154_spi = platform.request("ad9154_spi")
|
|
||||||
self.comb += ad9154_spi.en.eq(1)
|
|
||||||
self.submodules.converter_spi = spi_csr.SPIMaster(ad9154_spi)
|
|
||||||
self.csr_devices.append("converter_spi")
|
|
||||||
self.config["HAS_AD9516"] = None
|
|
||||||
self.config["CONVERTER_SPI_AD9516_CS"] = 1
|
|
||||||
self.config["CONVERTER_SPI_FIRST_AD9154_CS"] = 0
|
|
||||||
|
|
||||||
self.submodules.ad9154_0 = AD9154(platform)
|
|
||||||
self.csr_devices.append("ad9154_0")
|
|
||||||
self.config["HAS_AD9154"] = None
|
|
||||||
self.add_csr_group("ad9154", ["ad9154_0"])
|
|
||||||
|
|
||||||
rtio_channels = []
|
|
||||||
|
|
||||||
phy = ttl_serdes_7series.InOut_8X(
|
|
||||||
platform.request("user_sma_gpio_n"))
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=128))
|
|
||||||
|
|
||||||
phy = ttl_simple.Output(platform.request("user_led", 2))
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
|
||||||
|
|
||||||
sysref_pads = platform.request("ad9154_sysref")
|
|
||||||
phy = ttl_serdes_7series.Input_8X(sysref_pads.p, sysref_pads.n)
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=32,
|
|
||||||
ofifo_depth=2))
|
|
||||||
|
|
||||||
self.config["RTIO_FIRST_SAWG_CHANNEL"] = len(rtio_channels)
|
|
||||||
rtio_channels.extend(rtio.Channel.from_phy(phy)
|
|
||||||
for sawg in self.ad9154_0.sawgs
|
|
||||||
for phy in sawg.phys)
|
|
||||||
|
|
||||||
self.config["HAS_RTIO_LOG"] = None
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels)
|
|
||||||
rtio_channels.append(rtio.LogChannel())
|
|
||||||
|
|
||||||
self.submodules.rtio_crg = _PhaserCRG(
|
|
||||||
platform, self.ad9154_0.jesd.cd_jesd.clk)
|
|
||||||
self.csr_devices.append("rtio_crg")
|
|
||||||
self.submodules.rtio_core = rtio.Core(rtio_channels)
|
|
||||||
self.csr_devices.append("rtio_core")
|
|
||||||
self.submodules.rtio = rtio.KernelInitiator()
|
|
||||||
self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")(
|
|
||||||
rtio.DMA(self.get_native_sdram_if()))
|
|
||||||
self.register_kernel_cpu_csrdevice("rtio")
|
|
||||||
self.register_kernel_cpu_csrdevice("rtio_dma")
|
|
||||||
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
|
||||||
[self.rtio.cri, self.rtio_dma.cri],
|
|
||||||
[self.rtio_core.cri])
|
|
||||||
self.register_kernel_cpu_csrdevice("cri_con")
|
|
||||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
|
||||||
self.csr_devices.append("rtio_moninj")
|
|
||||||
self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_core.cri,
|
|
||||||
self.get_native_sdram_if())
|
|
||||||
self.csr_devices.append("rtio_analyzer")
|
|
||||||
|
|
||||||
platform.add_false_path_constraints(
|
|
||||||
self.crg.cd_sys.clk, self.rtio_crg.cd_rtio.clk)
|
|
||||||
platform.add_false_path_constraints(
|
|
||||||
self.crg.cd_sys.clk, self.ad9154_0.jesd.cd_jesd.clk)
|
|
||||||
for phy in self.ad9154_0.jesd.phys:
|
|
||||||
platform.add_false_path_constraints(
|
|
||||||
self.crg.cd_sys.clk, phy.transmitter.cd_tx.clk)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="ARTIQ device binary builder / KC705 phaser demo")
|
|
||||||
builder_args(parser)
|
|
||||||
soc_kc705_args(parser)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
soc = Phaser(**soc_kc705_argdict(args))
|
|
||||||
build_artiq_soc(soc, builder_argdict(args))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,12 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
BUILD_SETTINGS_FILE=$HOME/.m-labs/build_settings.sh
|
|
||||||
[ -f $BUILD_SETTINGS_FILE ] && . $BUILD_SETTINGS_FILE
|
|
||||||
|
|
||||||
SOC_PREFIX=$PREFIX/lib/python3.5/site-packages/artiq/binaries/kc705-phaser
|
|
||||||
mkdir -p $SOC_PREFIX
|
|
||||||
|
|
||||||
V=1 $PYTHON -m artiq.gateware.targets.phaser --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE
|
|
||||||
cp misoc_phaser_kc705/gateware/top.bit $SOC_PREFIX
|
|
||||||
cp misoc_phaser_kc705/software/bios/bios.bin $SOC_PREFIX
|
|
||||||
cp misoc_phaser_kc705/software/runtime/runtime.fbi $SOC_PREFIX
|
|
|
@ -1,23 +0,0 @@
|
||||||
package:
|
|
||||||
name: artiq-kc705-phaser
|
|
||||||
version: {{ environ.get("GIT_DESCRIBE_TAG", "") }}
|
|
||||||
|
|
||||||
source:
|
|
||||||
git_url: ../..
|
|
||||||
|
|
||||||
build:
|
|
||||||
noarch: generic
|
|
||||||
ignore_prefix_files: True
|
|
||||||
number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}
|
|
||||||
string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_FULL_HASH", "")[:8] }}
|
|
||||||
|
|
||||||
requirements:
|
|
||||||
build:
|
|
||||||
- artiq-dev {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_FULL_HASH", "")[:8]) if "GIT_DESCRIBE_TAG" in environ else "" }}
|
|
||||||
run:
|
|
||||||
- artiq {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_FULL_HASH", "")[:8]) if "GIT_DESCRIBE_TAG" in environ else "" }}
|
|
||||||
|
|
||||||
about:
|
|
||||||
home: https://m-labs.hk/artiq
|
|
||||||
license: LGPL
|
|
||||||
summary: 'Bitstream, BIOS and runtime for Phaser on the KC705 board'
|
|
|
@ -144,87 +144,3 @@ The QC2 hardware uses TCA6424A I2C I/O expanders to define the directions of its
|
||||||
To avoid I/O contention, the startup kernel should first program the TCA6424A expanders and then call ``output()`` on all ``TTLInOut`` channels that should be configured as outputs.
|
To avoid I/O contention, the startup kernel should first program the TCA6424A expanders and then call ``output()`` on all ``TTLInOut`` channels that should be configured as outputs.
|
||||||
|
|
||||||
See :mod:`artiq.coredevice.i2c` for more details.
|
See :mod:`artiq.coredevice.i2c` for more details.
|
||||||
|
|
||||||
|
|
||||||
.. _phaser:
|
|
||||||
|
|
||||||
Phaser
|
|
||||||
++++++
|
|
||||||
|
|
||||||
The Phaser adapter is an AD9154-FMC-EBZ, a 4 channel 2.4 GHz DAC on an FMC HPC card.
|
|
||||||
|
|
||||||
Phaser is a proof-of-concept design of a GHz-datarate, multi-channel, interpolating, multi-tone, direct digital synthesizer (DDS) compatible with ARTIQ's RTIO channels.
|
|
||||||
Ultimately it will be the basis for the ARTIQ Sayma Smart Arbitrary Waveform Generator project. See https://github.com/m-labs/sinara.
|
|
||||||
|
|
||||||
*Features*:
|
|
||||||
|
|
||||||
* up to 4 channels
|
|
||||||
* up to 500 MHz data rate per channel (KC705 limitation)
|
|
||||||
* up to 8x interpolation to 2.4 GHz DAC sample rate
|
|
||||||
* Real-time sample-coherent control over amplitude, frequency, phase of each channel through ARTIQ RTIO commands
|
|
||||||
* Full configurability of the AD9154 and AD9516 through SPI with ARTIQ kernel support
|
|
||||||
* All SPI registers and register bits exposed as human readable names
|
|
||||||
* Parametrized JESD204B core (also capable of operation with eight lanes)
|
|
||||||
* The code can be reconfigured. Possible example configurations are: support 2 channels at 1 GHz datarate, support 4 channels at 300 MHz data rate, no interpolation, and using mix mode to stress the second and third Nyquist zones (150-300 MHz and 300-450 MHz). Please contact M-Labs if you need help with this.
|
|
||||||
|
|
||||||
The hardware required is a KC705 with an AD9154-FMC-EBZ plugged into the HPC connector and a low-noise sample rate reference clock.
|
|
||||||
|
|
||||||
This work was supported by the Army Research Lab and the University of Maryland.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
............
|
|
||||||
|
|
||||||
These installation instructions are a short form of those in the ARTIQ manual.
|
|
||||||
|
|
||||||
* See the chapter on setting up a :ref:`development environment <develop-from-conda>`.
|
|
||||||
* When compiling the binaries, use the ``phaser`` target: ``python -m artiq.gateware.targets.phaser``
|
|
||||||
* From time to time and on request there may be pre-built binaries in the ``artiq-kc705-phaser`` package on the M-Labs conda package label.
|
|
||||||
|
|
||||||
Setup
|
|
||||||
.....
|
|
||||||
|
|
||||||
* Setup the KC705 (jumpers, etc.) observing the ARTIQ manual. VADJ does not need to be changed.
|
|
||||||
* On the AD9154-FMC-EBZ put jumpers:
|
|
||||||
|
|
||||||
- on XP1, between pin 5 and 6 (will keep the PIC in reset)
|
|
||||||
- on JP3 (will force output enable on FXLA108)
|
|
||||||
|
|
||||||
* Refer to the ARTIQ documentation to configure the MAC and IP addresses and other settings. If the board was running stock ARTIQ before, the settings will be kept.
|
|
||||||
* A 300 MHz clock of roughly 10 dBm (0.2 to 3.4 V peak-to-peak into 50 Ohm) must be connected to the AD9154-FMC-EBZ J1. The input is 50 Ohm terminated. The RTIO clock, DAC deviceclock, FPGA deviceclock, and SYSREF are derived from this signal.
|
|
||||||
* The RTIO coarse clock (the rate of the RTIO timestamp counter) is 150 MHz. The RTIO ``ref_period`` is 1/150 MHz = 5ns/6. The RTIO ``ref_multiplier`` is ``8``. C.f. ``device_db.py`` for both variables. The JED204B DAC data rate and DAC device clock are both 300 MHz. The JESD204B line rate is 6 GHz.
|
|
||||||
* Configure an oscilloscope to trigger at 0.5 V on rising edge of ttl_sma (user_gpio_n on the KC705 board). Monitor DAC0 (J17) on the oscilloscope set for 100 mV/div and 200 ns/div.
|
|
||||||
* An example device database, several status and test scripts are provided in ``artiq/examples/phaser/``. ::
|
|
||||||
|
|
||||||
cd artiq/examples/phaser
|
|
||||||
|
|
||||||
* Edit ``device_db.py`` to match the hostname or IP address of the core device.
|
|
||||||
* Use ``ping`` and ``flterm`` to verify that the core device starts up and boots correctly.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
.....
|
|
||||||
|
|
||||||
* Run ``artiq_run repository/demo.py`` for an example that exercises several different use cases of synchronized phase, amplitude, and frequency updates.
|
|
||||||
for an example that exercises several different use cases of synchronized phase, amplitude, and frequency updates.
|
|
||||||
* Run ``artiq_run repository/demo_2tone.py`` for an example that emits a shaped two-tone pulse.
|
|
||||||
* Implement your own experiments using the SAWG channels.
|
|
||||||
* Verify clock stability between the sample rate reference clock and the DAC outputs.
|
|
||||||
|
|
||||||
RTIO channels
|
|
||||||
.............
|
|
||||||
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
| RTIO channel | TTL line | Capability |
|
|
||||||
+==============+============+==============+
|
|
||||||
| 0 | SMA_GPIO_N | Input+Output |
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
| 1 | LED | Output |
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
| 2 | SYSREF | Input |
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
| 3 | SYNC | Input |
|
|
||||||
+--------------+------------+--------------+
|
|
||||||
|
|
||||||
The SAWG channels start with RTIO channel number 3, each SAWG channel occupying 10 RTIO channels.
|
|
||||||
|
|
||||||
The board has one non-RTIO SPI bus that is accessible through
|
|
||||||
:mod:`artiq.coredevice.ad9154`.
|
|
||||||
|
|
Loading…
Reference in New Issue