DRTIO port - gateware #140
|
@ -0,0 +1,85 @@
|
||||||
|
"""Auxiliary controller, common to satellite and master"""
|
||||||
|
|
||||||
|
from artiq.gateware.drtio.aux_controller import Transmitter, Receiver
|
||||||
|
from migen.fhdl.simplify import FullMemoryWE
|
||||||
|
from misoc.interconnect.csr import *
|
||||||
|
from migen_axi.interconnect.sram import SRAM
|
||||||
|
from migen_axi.interconnect import axi
|
||||||
|
|
||||||
|
max_packet = 1024
|
||||||
|
|
||||||
|
class _DRTIOAuxControllerBase(Module):
|
||||||
|
def __init__(self, link_layer):
|
||||||
|
self.bus = axi.Interface()
|
||||||
|
self.submodules.transmitter = Transmitter(link_layer, len(self.bus.w.data))
|
||||||
|
self.submodules.receiver = Receiver(link_layer, len(self.bus.w.data))
|
||||||
|
|
||||||
|
def get_csrs(self):
|
||||||
|
return self.transmitter.get_csrs() + self.receiver.get_csrs()
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: FullMemoryWE should be applied by migen.build
|
||||||
|
@FullMemoryWE()
|
||||||
|
class DRTIOAuxControllerAxi(_DRTIOAuxControllerBase):
|
||||||
|
def __init__(self, link_layer):
|
||||||
|
_DRTIOAuxControllerBase.__init__(self, link_layer)
|
||||||
|
|
||||||
|
tx_sdram_if = SRAM(self.transmitter.mem, read_only=False)
|
||||||
|
rx_sdram_if = SRAM(self.receiver.mem, read_only=True)
|
||||||
|
aw_decoder = axi.AddressDecoder(self.bus.aw,
|
||||||
|
[(lambda a: a[log2_int(max_packet)] == 0, tx_sdram_if.bus.aw),
|
||||||
|
(lambda a: a[log2_int(max_packet)] == 1, rx_sdram_if.bus.aw)],
|
||||||
|
register=True)
|
||||||
|
ar_decoder = axi.AddressDecoder(self.bus.ar,
|
||||||
|
[(lambda a: a[log2_int(max_packet)] == 0, tx_sdram_if.bus.ar),
|
||||||
|
(lambda a: a[log2_int(max_packet)] == 1, rx_sdram_if.bus.ar)],
|
||||||
|
register=True)
|
||||||
|
# unlike wb, axi address decoder only connects ar/aw lanes,
|
||||||
|
# the rest must also be connected!
|
||||||
|
# not quite unlike an address decoder itself.
|
||||||
|
|
||||||
|
# connect bus.b with tx.b
|
||||||
|
self.comb += [tx_sdram_if.bus.b.ready.eq(self.bus.b.ready),
|
||||||
|
self.bus.b.id.eq(tx_sdram_if.bus.b.id),
|
||||||
|
self.bus.b.resp.eq(tx_sdram_if.bus.b.resp),
|
||||||
|
self.bus.b.valid.eq(tx_sdram_if.bus.b.valid)]
|
||||||
|
# connect bus.w with tx.w
|
||||||
|
# no worries about w.valid and slave sel here, only tx will be written to
|
||||||
|
self.comb += [tx_sdram_if.bus.w.id.eq(self.bus.w.id),
|
||||||
|
tx_sdram_if.bus.w.data.eq(self.bus.w.data),
|
||||||
|
tx_sdram_if.bus.w.strb.eq(self.bus.w.strb),
|
||||||
|
tx_sdram_if.bus.w.last.eq(self.bus.w.last),
|
||||||
|
tx_sdram_if.bus.w.valid.eq(self.bus.w.valid),
|
||||||
|
self.bus.w.ready.eq(tx_sdram_if.bus.w.ready)]
|
||||||
|
# connect bus.r with rx.r and tx.r w/o data
|
||||||
|
self.comb += [self.bus.r.id.eq(rx_sdram_if.bus.r.id | tx_sdram_if.bus.r.id),
|
||||||
|
#self.bus.r.data.eq(rx_sdram_if.bus.r.data | tx_sdram_if.bus.r.data),
|
||||||
|
self.bus.r.resp.eq(rx_sdram_if.bus.r.resp | tx_sdram_if.bus.r.resp),
|
||||||
|
self.bus.r.last.eq(rx_sdram_if.bus.r.last | tx_sdram_if.bus.r.last),
|
||||||
|
self.bus.r.valid.eq(rx_sdram_if.bus.r.valid | tx_sdram_if.bus.r.valid),
|
||||||
|
rx_sdram_if.bus.r.ready.eq(self.bus.r.ready),
|
||||||
|
tx_sdram_if.bus.r.ready.eq(self.bus.r.ready)]
|
||||||
|
# connect read data after being masked
|
||||||
|
masked = [Replicate(rx_sdram_if.bus.r.valid,
|
||||||
|
len(self.bus.r.data)
|
||||||
|
) & rx_sdram_if.bus.r.data,
|
||||||
|
Replicate(tx_sdram_if.bus.r.valid,
|
||||||
|
len(self.bus.r.data)
|
||||||
|
) & tx_sdram_if.bus.r.data]
|
||||||
|
self.comb += self.bus.r.data.eq(reduce(or_, masked))
|
||||||
|
|
||||||
|
self.submodules += tx_sdram_if, rx_sdram_if, aw_decoder, ar_decoder
|
||||||
|
|
||||||
|
|
||||||
|
@FullMemoryWE()
|
||||||
|
class DRTIOAuxControllerBare(_DRTIOAuxControllerBase):
|
||||||
|
# Barebones version of the AuxController. No SRAM, no decoders.
|
||||||
|
# add memories manually from tx and rx in target code.
|
||||||
|
def get_tx_port(self):
|
||||||
|
return self.transmitter.mem.get_port(write_capable=True)
|
||||||
|
|
||||||
|
def get_rx_port(self):
|
||||||
|
return self.receiver.mem.get_port(write_capable=False)
|
||||||
|
|
||||||
|
def get_mem_size(self):
|
||||||
|
return max_packet
|
|
@ -15,11 +15,16 @@ from misoc.integration import cpu_interface
|
||||||
from artiq.coredevice import jsondesc
|
from artiq.coredevice import jsondesc
|
||||||
from artiq.gateware import rtio, eem_7series
|
from artiq.gateware import rtio, eem_7series
|
||||||
from artiq.gateware.rtio.phy import ttl_simple
|
from artiq.gateware.rtio.phy import ttl_simple
|
||||||
|
from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier
|
||||||
|
from artiq.gateware.drtio.transceiver import gtx_7series
|
||||||
|
from artiq.gateware.drtio.siphaser import SiPhaser7Series
|
||||||
|
from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer
|
||||||
|
from artiq.gateware.drtio import *
|
||||||
|
|
||||||
import dma
|
import dma
|
||||||
import analyzer
|
import analyzer
|
||||||
import acpki
|
import acpki
|
||||||
|
import drtio_aux_controller
|
||||||
|
|
||||||
class RTIOCRG(Module, AutoCSR):
|
class RTIOCRG(Module, AutoCSR):
|
||||||
def __init__(self, platform):
|
def __init__(self, platform):
|
||||||
|
@ -70,7 +75,7 @@ class RTIOCRG(Module, AutoCSR):
|
||||||
MultiReg(pll_locked, self.pll_locked.status)
|
MultiReg(pll_locked, self.pll_locked.status)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
eem_iostandard_dict = {
|
eem_iostandard_dict = {
|
||||||
0: "LVDS_25",
|
0: "LVDS_25",
|
||||||
1: "LVDS_25",
|
1: "LVDS_25",
|
||||||
|
@ -173,13 +178,289 @@ class GenericStandalone(SoCCore):
|
||||||
|
|
||||||
|
|
||||||
class GenericMaster(SoCCore):
|
class GenericMaster(SoCCore):
|
||||||
def __init__(self, description, **kwargs):
|
def __init__(self, description, acpki=False):
|
||||||
raise NotImplementedError
|
sys_clk_freq = 125e6
|
||||||
|
rtio_clk_freq = 125e6
|
||||||
|
|
||||||
|
self.acpki = acpki
|
||||||
|
self.rustc_cfg = dict()
|
||||||
|
|
||||||
|
platform = kasli_soc.Platform()
|
||||||
|
platform.toolchain.bitstream_commands.extend([
|
||||||
|
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
||||||
|
])
|
||||||
|
ident = self.__class__.__name__
|
||||||
|
if self.acpki:
|
||||||
|
ident = "acpki_" + ident
|
||||||
|
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
||||||
|
|
||||||
|
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||||
|
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||||
|
|
||||||
|
# kasli_soc has no SATA, but it has 4x SFP
|
||||||
|
# not sure yet why sfp0 is omitted in MasterMode
|
||||||
|
|||||||
|
data_pads = [platform.request("sfp", i) for i in range(4)]
|
||||||
|
|
||||||
|
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
||||||
|
clock_pads=platform.request("clk125_gtp"),
|
||||||
|
pads=data_pads,
|
||||||
|
sys_clk_freq=sys_clk_freq)
|
||||||
|
self.csr_devices.append("drtio_transceiver")
|
||||||
|
|
||||||
|
self.crg = self.ps7 # HACK for eem_7series to find the clock
|
||||||
|
self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq)
|
||||||
|
self.csr_devices.append("rtio_crg")
|
||||||
|
|
||||||
|
self.rtio_channels = []
|
||||||
|
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
||||||
|
if has_grabber:
|
||||||
|
self.grabber_csr_group = []
|
||||||
|
eem_7series.add_peripherals(self, description["peripherals"], iostandard=eem_iostandard)
|
||||||
|
for i in (0, 1):
|
||||||
|
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||||
|
user_led = self.platform.request("user_led", i)
|
||||||
|
phy = ttl_simple.Output(user_led)
|
||||||
|
self.submodules += phy
|
||||||
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
||||||
|
self.rtio_channels.append(rtio.LogChannel())
|
||||||
|
|
||||||
|
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||||
|
|
||||||
|
drtio_csr_group = []
|
||||||
|
drtioaux_csr_group = []
|
||||||
|
drtioaux_memory_group = []
|
||||||
|
self.drtio_cri = []
|
||||||
|
for i in range(len(self.drtio_transceiver.channels)):
|
||||||
|
core_name = "drtio" + str(i)
|
||||||
|
coreaux_name = "drtioaux" + str(i)
|
||||||
|
memory_name = "drtioaux" + str(i) + "_mem"
|
||||||
|
drtio_csr_group.append(core_name)
|
||||||
|
drtioaux_csr_group.append(coreaux_name)
|
||||||
|
drtioaux_memory_group.append(memory_name)
|
||||||
|
|
||||||
|
cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)})
|
||||||
|
|
||||||
|
core = cdr(DRTIOMaster(self.rtio_tsc, self.drtio_transceiver.channels[i]))
|
||||||
|
setattr(self.submodules, core_name, core)
|
||||||
|
self.drtio_cri.append(core.cri)
|
||||||
|
self.csr_devices.append(core_name)
|
||||||
|
|
||||||
|
coreaux = cdr(drtio_aux_controller.DRTIOAuxControllerBare(core.link_layer))
|
||||||
|
setattr(self.submodules, coreaux_name, coreaux)
|
||||||
|
self.csr_devices.append(coreaux_name)
|
||||||
|
|
||||||
|
size = coreaux.get_mem_size()
|
||||||
|
memory_address = self.axi2csr.register_port(coreaux.get_tx_port(), size)
|
||||||
|
self.axi2csr.register_port(coreaux.get_rx_port(), size)
|
||||||
|
self.add_memory_region(memory_name, self.mem_map["csr"] + memory_address, size * 2)
|
||||||
|
self.rustc_cfg["has_drtio"] = None
|
||||||
|
self.rustc_cfg["has_drtio_routing"] = None
|
||||||
|
self.add_csr_group("drtio", drtio_csr_group)
|
||||||
|
self.add_csr_group("drtioaux", drtioaux_csr_group)
|
||||||
|
self.add_memory_group("drtioaux_mem", drtioaux_memory_group)
|
||||||
|
|
||||||
|
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, self.rtio_channels)
|
||||||
|
self.csr_devices.append("rtio_core")
|
||||||
|
|
||||||
|
if self.acpki:
|
||||||
|
self.rustc_cfg["ki_impl"] = "acp"
|
||||||
|
self.submodules.rtio = acpki.KernelInitiator(self.rtio_tsc,
|
||||||
|
bus=self.ps7.s_axi_acp,
|
||||||
|
user=self.ps7.s_axi_acp_user,
|
||||||
|
evento=self.ps7.event.o)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
else:
|
||||||
|
self.rustc_cfg["ki_impl"] = "csr"
|
||||||
|
self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc, now64=True)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
|
||||||
|
self.submodules.rtio_dma = dma.DMA(self.ps7.s_axi_hp0)
|
||||||
|
self.csr_devices.append("rtio_dma")
|
||||||
|
|
||||||
|
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
||||||
|
[self.rtio.cri, self.rtio_dma.cri],
|
||||||
|
[self.rtio_core.cri] + self.drtio_cri,
|
||||||
|
enable_routing=True)
|
||||||
|
self.csr_devices.append("cri_con")
|
||||||
|
|
||||||
|
self.submodules.rtio_moninj = rtio.MonInj(self.rtio_channels)
|
||||||
|
self.csr_devices.append("rtio_moninj")
|
||||||
|
|
||||||
|
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
|
||||||
|
self.csr_devices.append("routing_table")
|
||||||
|
|
||||||
|
self.submodules.rtio_analyzer = analyzer.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
||||||
|
self.ps7.s_axi_hp1)
|
||||||
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
if has_grabber:
|
||||||
|
self.rustc_cfg["has_grabber"] = None
|
||||||
|
self.add_csr_group("grabber", self.grabber_csr_group)
|
||||||
|
|
||||||
|
|
||||||
class GenericSatellite(SoCCore):
|
class GenericSatellite(SoCCore):
|
||||||
def __init__(self, description, **kwargs):
|
def __init__(self, description, acpki=False):
|
||||||
raise NotImplementedError
|
sys_clk_freq = 125e6
|
||||||
|
rtio_clk_freq = 125e6
|
||||||
|
|
||||||
|
self.acpki = acpki
|
||||||
|
self.rustc_cfg = dict()
|
||||||
|
|
||||||
|
platform = kasli_soc.Platform()
|
||||||
|
platform.toolchain.bitstream_commands.extend([
|
||||||
|
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
||||||
|
])
|
||||||
|
ident = self.__class__.__name__
|
||||||
|
if self.acpki:
|
||||||
|
ident = "acpki_" + ident
|
||||||
|
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
||||||
|
|
||||||
|
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||||
|
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||||
|
|
||||||
|
self.crg = self.ps7 # HACK for eem_7series to find the clock
|
||||||
|
self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq)
|
||||||
|
self.csr_devices.append("rtio_crg")
|
||||||
|
|
||||||
|
data_pads = [platform.request("sfp", i) for i in range(4)]
|
||||||
|
|
||||||
|
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
||||||
|
clock_pads=platform.request("clk125_gtp"),
|
||||||
|
pads=data_pads,
|
||||||
|
sys_clk_freq=sys_clk_freq)
|
||||||
|
self.csr_devices.append("drtio_transceiver")
|
||||||
|
|
||||||
|
self.rtio_channels = []
|
||||||
|
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
||||||
|
if has_grabber:
|
||||||
|
self.grabber_csr_group = []
|
||||||
|
eem_7series.add_peripherals(self, description["peripherals"], iostandard=eem_iostandard)
|
||||||
|
for i in (0, 1):
|
||||||
|
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||||
|
user_led = self.platform.request("user_led", i)
|
||||||
|
phy = ttl_simple.Output(user_led)
|
||||||
|
self.submodules += phy
|
||||||
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
||||||
|
self.rtio_channels.append(rtio.LogChannel())
|
||||||
|
|
||||||
|
self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3)
|
||||||
|
|
||||||
|
drtioaux_csr_group = []
|
||||||
|
drtioaux_memory_group = []
|
||||||
|
drtiorep_csr_group = []
|
||||||
|
self.drtio_cri = []
|
||||||
|
for i in range(len(self.drtio_transceiver.channels)):
|
||||||
|
coreaux_name = "drtioaux" + str(i)
|
||||||
|
memory_name = "drtioaux" + str(i) + "_mem"
|
||||||
|
drtioaux_csr_group.append(coreaux_name)
|
||||||
|
drtioaux_memory_group.append(memory_name)
|
||||||
|
|
||||||
|
cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)})
|
||||||
|
|
||||||
|
if i == 0:
|
||||||
|
self.submodules.rx_synchronizer = cdr(XilinxRXSynchronizer())
|
||||||
|
core = cdr(DRTIOSatellite(
|
||||||
|
self.rtio_tsc, self.drtio_transceiver.channels[i],
|
||||||
|
self.rx_synchronizer))
|
||||||
|
self.submodules.drtiosat = core
|
||||||
|
self.csr_devices.append("drtiosat")
|
||||||
|
else:
|
||||||
|
corerep_name = "drtiorep" + str(i-1)
|
||||||
|
drtiorep_csr_group.append(corerep_name)
|
||||||
|
|
||||||
|
core = cdr(DRTIORepeater(
|
||||||
|
self.rtio_tsc, self.drtio_transceiver.channels[i]))
|
||||||
|
setattr(self.submodules, corerep_name, core)
|
||||||
|
self.drtio_cri.append(core.cri)
|
||||||
|
self.csr_devices.append(corerep_name)
|
||||||
|
|
||||||
|
coreaux = cdr(drtio_aux_controller.DRTIOAuxControllerBare(core.link_layer))
|
||||||
|
setattr(self.submodules, coreaux_name, coreaux)
|
||||||
|
self.csr_devices.append(coreaux_name)
|
||||||
|
|
||||||
|
mem_size = coreaux.get_mem_size()
|
||||||
|
tx_port = coreaux.get_tx_port()
|
||||||
|
rx_port = coreaux.get_rx_port()
|
||||||
|
memory_address = self.axi2csr.register_port(tx_port, mem_size)
|
||||||
|
# rcv in upper half of the memory, thus added second
|
||||||
|
self.axi2csr.register_port(rx_port, mem_size)
|
||||||
|
# and registered in PS interface
|
||||||
|
# manually, because software refers to rx/tx by halves of entire memory block, not names
|
||||||
|
self.add_memory_region(memory_name, self.mem_map["csr"] + memory_address, mem_size * 2)
|
||||||
|
self.rustc_cfg["has_drtio"] = None
|
||||||
|
self.rustc_cfg["has_drtio_routing"] = None
|
||||||
|
self.add_csr_group("drtioaux", drtioaux_csr_group)
|
||||||
|
self.add_memory_group("drtioaux_mem", drtioaux_memory_group)
|
||||||
|
self.add_csr_group("drtiorep", drtiorep_csr_group)
|
||||||
|
|
||||||
|
if self.acpki:
|
||||||
|
self.rustc_cfg["ki_impl"] = "acp"
|
||||||
|
self.submodules.rtio = acpki.KernelInitiator(self.rtio_tsc,
|
||||||
|
bus=self.ps7.s_axi_acp,
|
||||||
|
user=self.ps7.s_axi_acp_user,
|
||||||
|
evento=self.ps7.event.o)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
else:
|
||||||
|
self.rustc_cfg["ki_impl"] = "csr"
|
||||||
|
self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc, now64=True)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
|
||||||
|
self.submodules.rtio_dma = dma.DMA(self.ps7.s_axi_hp0)
|
||||||
|
self.csr_devices.append("rtio_dma")
|
||||||
|
|
||||||
|
self.submodules.local_io = SyncRTIO(self.rtio_tsc, self.rtio_channels)
|
||||||
|
self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors)
|
||||||
|
|
||||||
|
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
||||||
|
[self.drtiosat.cri],
|
||||||
|
[self.local_io.cri] + self.drtio_cri,
|
||||||
|
mode="sync", enable_routing=True)
|
||||||
|
self.csr_devices.append("cri_con")
|
||||||
|
|
||||||
|
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
|
||||||
|
self.csr_devices.append("routing_table")
|
||||||
|
|
||||||
|
self.submodules.rtio_moninj = rtio.MonInj(self.rtio_channels)
|
||||||
|
self.csr_devices.append("rtio_moninj")
|
||||||
|
|
||||||
|
rtio_clk_period = 1e9/rtio_clk_freq
|
||||||
|
self.rustc_cfg["rtio_frequency"] = str(rtio_clk_freq/1e6)
|
||||||
|
|
||||||
|
self.submodules.siphaser = SiPhaser7Series(
|
||||||
|
si5324_clkin=platform.request("cdr_clk"),
|
||||||
|
rx_synchronizer=self.rx_synchronizer,
|
||||||
|
ultrascale=False,
|
||||||
|
rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output)
|
||||||
|
self.csr_devices.append("siphaser")
|
||||||
|
self.rustc_cfg["has_si5324"] = None
|
||||||
|
self.rustc_cfg["has_siphaser"] = None
|
||||||
|
self.rustc_cfg["si5324_soft_reset"] = None
|
||||||
|
|
||||||
|
gtx0 = self.drtio_transceiver.gtxs[0]
|
||||||
|
platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period)
|
||||||
|
platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.crg.cd_sys.clk,
|
||||||
|
gtx0.txoutclk, gtx0.rxoutclk)
|
||||||
|
for gtx in self.drtio_transceiver.gtxs[1:]:
|
||||||
|
platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.crg.cd_sys.clk, gtx.rxoutclk)
|
||||||
|
|
||||||
|
if has_grabber:
|
||||||
|
self.rustc_cfg["has_grabber"] = None
|
||||||
|
self.add_csr_group("grabber", self.grabber_csr_group)
|
||||||
|
# no RTIO CRG here
|
||||||
|
|
||||||
|
|
||||||
|
def write_mem_file(soc, filename):
|
||||||
|
with open(filename, "w") as f:
|
||||||
|
f.write(cpu_interface.get_mem_rust(
|
||||||
|
soc.get_memory_regions(), soc.get_memory_groups(), None))
|
||||||
|
|
||||||
|
|
||||||
def write_csr_file(soc, filename):
|
def write_csr_file(soc, filename):
|
||||||
|
@ -204,6 +485,8 @@ def main():
|
||||||
help="build Rust interface into the specified file")
|
help="build Rust interface into the specified file")
|
||||||
parser.add_argument("-c", default=None,
|
parser.add_argument("-c", default=None,
|
||||||
help="build Rust compiler configuration into the specified file")
|
help="build Rust compiler configuration into the specified file")
|
||||||
|
parser.add_argument("-m", default=None,
|
||||||
|
help="build Rust memory interface into the specified file")
|
||||||
parser.add_argument("-g", default=None,
|
parser.add_argument("-g", default=None,
|
||||||
help="build gateware into the specified directory")
|
help="build gateware into the specified directory")
|
||||||
parser.add_argument("--acpki", default=False, action="store_true",
|
parser.add_argument("--acpki", default=False, action="store_true",
|
||||||
|
@ -230,6 +513,8 @@ def main():
|
||||||
|
|
||||||
if args.r is not None:
|
if args.r is not None:
|
||||||
write_csr_file(soc, args.r)
|
write_csr_file(soc, args.r)
|
||||||
|
if args.m is not None:
|
||||||
|
write_mem_file(soc, args.m)
|
||||||
if args.c is not None:
|
if args.c is not None:
|
||||||
write_rustc_cfg_file(soc, args.c)
|
write_rustc_cfg_file(soc, args.c)
|
||||||
if args.g is not None:
|
if args.g is not None:
|
||||||
|
|
|
@ -11,13 +11,20 @@ from migen_axi.integration.soc_core import SoCCore
|
||||||
from migen_axi.platforms import zc706
|
from migen_axi.platforms import zc706
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
from misoc.integration import cpu_interface
|
from misoc.integration import cpu_interface
|
||||||
|
from misoc.cores import gpio
|
||||||
|
|
||||||
from artiq.gateware import rtio, nist_clock, nist_qc2
|
from artiq.gateware import rtio, nist_clock, nist_qc2
|
||||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
||||||
|
from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier, fix_serdes_timing_path
|
||||||
|
from artiq.gateware.drtio.transceiver import gtx_7series
|
||||||
|
from artiq.gateware.drtio.siphaser import SiPhaser7Series
|
||||||
|
from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer
|
||||||
|
from artiq.gateware.drtio import *
|
||||||
|
|
||||||
import dma
|
import dma
|
||||||
import analyzer
|
import analyzer
|
||||||
import acpki
|
import acpki
|
||||||
|
import drtio_aux_controller
|
||||||
|
|
||||||
|
|
||||||
class RTIOCRG(Module, AutoCSR):
|
class RTIOCRG(Module, AutoCSR):
|
||||||
|
@ -64,23 +71,45 @@ class RTIOCRG(Module, AutoCSR):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# The NIST backplanes require setting VADJ to 3.3V by reprogramming the power supply.
|
||||||
|
# This also changes the I/O standard for some on-board LEDs.
|
||||||
|
leds_fmc33 = [
|
||||||
|
("user_led_33", 0, Pins("Y21"), IOStandard("LVCMOS33")),
|
||||||
|
("user_led_33", 1, Pins("G2"), IOStandard("LVCMOS15")),
|
||||||
|
("user_led_33", 2, Pins("W21"), IOStandard("LVCMOS33")),
|
||||||
|
("user_led_33", 3, Pins("A17"), IOStandard("LVCMOS15")),
|
||||||
|
]
|
||||||
|
|
||||||
|
# same deal as with LEDs - changed I/O standard.
|
||||||
|
si5324_fmc33 = [
|
||||||
|
("si5324_33", 0,
|
||||||
|
Subsignal("rst_n", Pins("W23"), IOStandard("LVCMOS33")),
|
||||||
|
Subsignal("int", Pins("AJ25"), IOStandard("LVCMOS33"))
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_zc706_platform(platform):
|
||||||
|
platform.toolchain.bitstream_commands.extend([
|
||||||
|
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
||||||
|
])
|
||||||
|
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||||
|
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||||
|
|
||||||
|
|
||||||
class ZC706(SoCCore):
|
class ZC706(SoCCore):
|
||||||
def __init__(self, acpki=False):
|
def __init__(self, acpki=False):
|
||||||
mwojcik marked this conversation as resolved
Outdated
sb10q
commented
Share with Kasli-SoC? Share with Kasli-SoC?
sb10q
commented
...or even put it in ...or even put it in ``artiq.gateware`` and share with the other boards.
mwojcik
commented
It's the same thing for artiq kasli, kc705 and sayma_rtm boards. I could separate it and save few lines everywhere, but where to put it, so it fits nicely? I'm thinking It's the same thing for artiq kasli, kc705 and sayma_rtm boards. I could separate it and save few lines everywhere, but where to put it, so it fits nicely? I'm thinking ``artiq.gateware.rtio.clock_multiplier``? or maybe just ``artiq.gateware.clock_multiplier``?
sb10q
commented
Maybe Maybe ``artiq.gateware.rtio.xilinx_clocking``, along with the SERDES rules?
|
|||||||
self.acpki = acpki
|
self.acpki = acpki
|
||||||
self.rustc_cfg = dict()
|
self.rustc_cfg = dict()
|
||||||
|
|
||||||
platform = zc706.Platform()
|
platform = zc706.Platform()
|
||||||
platform.toolchain.bitstream_commands.extend([
|
prepare_zc706_platform(platform)
|
||||||
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
|
||||||
])
|
|
||||||
ident = self.__class__.__name__
|
ident = self.__class__.__name__
|
||||||
if self.acpki:
|
if self.acpki:
|
||||||
ident = "acpki_" + ident
|
ident = "acpki_" + ident
|
||||||
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
||||||
|
|
||||||
mwojcik marked this conversation as resolved
Outdated
sb10q
commented
ditto ditto
|
|||||||
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
|
||||||
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
|
||||||
|
|
||||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
||||||
self.csr_devices.append("rtio_crg")
|
self.csr_devices.append("rtio_crg")
|
||||||
self.rustc_cfg["has_rtio_crg_clock_sel"] = None
|
self.rustc_cfg["has_rtio_crg_clock_sel"] = None
|
||||||
|
@ -122,10 +151,284 @@ class ZC706(SoCCore):
|
||||||
self.csr_devices.append("rtio_analyzer")
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
|
||||||
class Simple(ZC706):
|
class _MasterBase(SoCCore):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, acpki=False):
|
||||||
ZC706.__init__(self, **kwargs)
|
self.acpki = acpki
|
||||||
|
self.rustc_cfg = dict()
|
||||||
|
|
||||||
|
platform = zc706.Platform()
|
||||||
|
prepare_zc706_platform(platform)
|
||||||
|
ident = self.__class__.__name__
|
||||||
|
if self.acpki:
|
||||||
|
ident = "acpki_" + ident
|
||||||
|
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
||||||
|
|
||||||
|
platform.add_extension(si5324_fmc33)
|
||||||
|
|
||||||
|
self.sys_clk_freq = 125e6
|
||||||
|
|
||||||
|
platform = self.platform
|
||||||
|
|
||||||
|
self.comb += platform.request("sfp_tx_disable_n").eq(1)
|
||||||
|
data_pads = [
|
||||||
|
platform.request("sfp"),
|
||||||
|
platform.request("user_sma_mgt")
|
||||||
|
]
|
||||||
|
|
||||||
|
# 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock
|
||||||
|
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
||||||
|
clock_pads=platform.request("si5324_clkout"),
|
||||||
|
pads=data_pads,
|
||||||
|
sys_clk_freq=self.sys_clk_freq)
|
||||||
|
self.csr_devices.append("drtio_transceiver")
|
||||||
|
|
||||||
|
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||||
|
|
||||||
|
drtio_csr_group = []
|
||||||
|
drtioaux_csr_group = []
|
||||||
|
drtioaux_memory_group = []
|
||||||
|
self.drtio_cri = []
|
||||||
|
for i in range(len(self.drtio_transceiver.channels)):
|
||||||
|
core_name = "drtio" + str(i)
|
||||||
|
coreaux_name = "drtioaux" + str(i)
|
||||||
|
memory_name = "drtioaux" + str(i) + "_mem"
|
||||||
|
drtio_csr_group.append(core_name)
|
||||||
|
drtioaux_csr_group.append(coreaux_name)
|
||||||
|
drtioaux_memory_group.append(memory_name)
|
||||||
|
|
||||||
|
cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)})
|
||||||
|
|
||||||
|
core = cdr(DRTIOMaster(
|
||||||
|
self.rtio_tsc, self.drtio_transceiver.channels[i]))
|
||||||
|
setattr(self.submodules, core_name, core)
|
||||||
|
self.drtio_cri.append(core.cri)
|
||||||
|
self.csr_devices.append(core_name)
|
||||||
|
|
||||||
|
coreaux = cdr(drtio_aux_controller.DRTIOAuxControllerBare(core.link_layer))
|
||||||
|
setattr(self.submodules, coreaux_name, coreaux)
|
||||||
|
self.csr_devices.append(coreaux_name)
|
||||||
|
|
||||||
|
mem_size = coreaux.get_mem_size()
|
||||||
|
memory_address = self.axi2csr.register_port(coreaux.get_tx_port(), mem_size)
|
||||||
|
self.axi2csr.register_port(coreaux.get_rx_port(), mem_size)
|
||||||
|
self.add_memory_region(memory_name, self.mem_map["csr"] + memory_address, mem_size * 2)
|
||||||
|
self.rustc_cfg["has_drtio"] = None
|
||||||
|
self.rustc_cfg["has_drtio_routing"] = None
|
||||||
|
self.add_csr_group("drtio", drtio_csr_group)
|
||||||
|
self.add_csr_group("drtioaux", drtioaux_csr_group)
|
||||||
|
self.add_memory_group("drtioaux_mem", drtioaux_memory_group)
|
||||||
|
|
||||||
|
self.rustc_cfg["RTIO_FREQUENCY"] = str(self.drtio_transceiver.rtio_clk_freq/1e6)
|
||||||
|
|
||||||
|
self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324_33").rst_n)
|
||||||
|
self.csr_devices.append("si5324_rst_n")
|
||||||
|
self.rustc_cfg["has_si5324"] = None
|
||||||
|
self.rustc_cfg["si5324_as_synthesizer"] = None
|
||||||
|
|
||||||
|
rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq
|
||||||
|
# Constrain TX & RX timing for the first transceiver channel
|
||||||
|
# (First channel acts as master for phase alignment for all channels' TX)
|
||||||
|
gtx0 = self.drtio_transceiver.gtxs[0]
|
||||||
|
platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period)
|
||||||
|
platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.ps7.cd_sys.clk,
|
||||||
|
gtx0.txoutclk, gtx0.rxoutclk)
|
||||||
|
# Constrain RX timing for the each transceiver channel
|
||||||
|
# (Each channel performs single-lane phase alignment for RX)
|
||||||
|
for gtx in self.drtio_transceiver.gtxs[1:]:
|
||||||
|
platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.ps7.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk)
|
||||||
|
|
||||||
|
self.submodules.rtio_crg = RTIOClockMultiplier(self.sys_clk_freq)
|
||||||
|
self.csr_devices.append("rtio_crg")
|
||||||
|
fix_serdes_timing_path(self.platform)
|
||||||
|
|
||||||
|
def add_rtio(self, rtio_channels):
|
||||||
|
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||||
|
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels)
|
||||||
|
self.csr_devices.append("rtio_core")
|
||||||
|
|
||||||
|
if self.acpki:
|
||||||
|
self.rustc_cfg["ki_impl"] = "acp"
|
||||||
|
self.submodules.rtio = acpki.KernelInitiator(self.rtio_tsc,
|
||||||
|
bus=self.ps7.s_axi_acp,
|
||||||
|
user=self.ps7.s_axi_acp_user,
|
||||||
|
evento=self.ps7.event.o)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
else:
|
||||||
|
self.rustc_cfg["ki_impl"] = "csr"
|
||||||
|
self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc, now64=True)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
|
||||||
|
self.submodules.rtio_dma = dma.DMA(self.ps7.s_axi_hp0)
|
||||||
|
self.csr_devices.append("rtio_dma")
|
||||||
|
|
||||||
|
self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels)
|
||||||
sb10q
commented
You can use assume it is true at all times and simplify the code accordingly. Only NIST backplanes are supported on ZC706 and they need the 3.3V signals. You can use assume it is true at all times and simplify the code accordingly. Only NIST backplanes are supported on ZC706 and they need the 3.3V signals.
mwojcik
commented
So there won't be "simple" master/satellite? What about the board I've been testing it on, is it with a backplane? So there won't be "simple" master/satellite? What about the board I've been testing it on, is it with a backplane?
sb10q
commented
"Simple" targets were just for testing, on the same hardware that has the backplane installed (even if they don't use the backplane). "Simple" targets were just for testing, on the same hardware that has the backplane installed (even if they don't use the backplane).
Also fine to remove these targets, they were only there for the initial development.
mwojcik
commented
Okay, makes sense, I was somewhat worried about mismatched voltages for si5324. Although I don't think this is the place to be removing the simple targets, that should be done in another PR (not only unrelated functionally to drtio, it also touches gateware, nix scripts and readme). Okay, makes sense, I was somewhat worried about mismatched voltages for si5324. Although I don't think this is the place to be removing the simple targets, that should be done in another PR (not only unrelated functionally to drtio, it also touches gateware, nix scripts and readme).
sb10q
commented
Changing the IOSTANDARD here does not actually change the voltage produced by the FPGA I/O, and will not damage the Si5324. In fact it even works correctly in practice when the voltage in the CMOS/TTL IOSTANDARD is wrong. Changing the IOSTANDARD here does not actually change the voltage produced by the FPGA I/O, and will not damage the Si5324. In fact it even works correctly in practice when the voltage in the CMOS/TTL IOSTANDARD is wrong.
|
|||||||
|
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
||||||
|
[self.rtio.cri, self.rtio_dma.cri],
|
||||||
|
[self.local_io.cri] + self.drtio_cri,
|
||||||
|
mode="sync", enable_routing=True)
|
||||||
|
self.csr_devices.append("cri_con")
|
||||||
|
|
||||||
|
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
||||||
|
self.csr_devices.append("rtio_moninj")
|
||||||
|
|
||||||
|
self.submodules.rtio_analyzer = analyzer.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
||||||
|
self.ps7.s_axi_hp1)
|
||||||
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
|
||||||
|
self.csr_devices.append("routing_table")
|
||||||
|
|
||||||
|
|
||||||
|
class _SatelliteBase(SoCCore):
|
||||||
|
def __init__(self, acpki=False):
|
||||||
|
self.acpki = acpki
|
||||||
|
self.rustc_cfg = dict()
|
||||||
|
|
||||||
|
platform = zc706.Platform()
|
||||||
|
prepare_zc706_platform(platform)
|
||||||
|
ident = self.__class__.__name__
|
||||||
|
if self.acpki:
|
||||||
|
ident = "acpki_" + ident
|
||||||
|
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
||||||
|
|
||||||
|
platform.add_extension(si5324_fmc33)
|
||||||
|
|
||||||
|
self.sys_clk_freq = 125e6
|
||||||
|
platform = self.platform
|
||||||
|
|
||||||
|
# SFP
|
||||||
|
self.comb += platform.request("sfp_tx_disable_n").eq(0)
|
||||||
|
data_pads = [
|
||||||
|
platform.request("sfp"),
|
||||||
|
platform.request("user_sma_mgt")
|
||||||
|
]
|
||||||
|
|
||||||
|
self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3)
|
||||||
|
|
||||||
|
# 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock
|
||||||
|
self.submodules.drtio_transceiver = gtx_7series.GTX(
|
||||||
|
clock_pads=platform.request("si5324_clkout"),
|
||||||
|
pads=data_pads,
|
||||||
|
sys_clk_freq=self.sys_clk_freq)
|
||||||
|
self.csr_devices.append("drtio_transceiver")
|
||||||
|
|
||||||
|
drtioaux_csr_group = []
|
||||||
|
drtioaux_memory_group = []
|
||||||
|
drtiorep_csr_group = []
|
||||||
|
self.drtio_cri = []
|
||||||
|
for i in range(len(self.drtio_transceiver.channels)):
|
||||||
|
coreaux_name = "drtioaux" + str(i)
|
||||||
|
memory_name = "drtioaux" + str(i) + "_mem"
|
||||||
|
drtioaux_csr_group.append(coreaux_name)
|
||||||
|
drtioaux_memory_group.append(memory_name)
|
||||||
|
|
||||||
|
cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)})
|
||||||
|
|
||||||
|
# Satellite
|
||||||
|
if i == 0:
|
||||||
|
self.submodules.rx_synchronizer = cdr(XilinxRXSynchronizer())
|
||||||
|
core = cdr(DRTIOSatellite(
|
||||||
|
self.rtio_tsc, self.drtio_transceiver.channels[0], self.rx_synchronizer))
|
||||||
|
self.submodules.drtiosat = core
|
||||||
|
self.csr_devices.append("drtiosat")
|
||||||
|
# Repeaters
|
||||||
|
else:
|
||||||
|
corerep_name = "drtiorep" + str(i-1)
|
||||||
|
drtiorep_csr_group.append(corerep_name)
|
||||||
|
core = cdr(DRTIORepeater(
|
||||||
|
self.rtio_tsc, self.drtio_transceiver.channels[i]))
|
||||||
|
setattr(self.submodules, corerep_name, core)
|
||||||
|
self.drtio_cri.append(core.cri)
|
||||||
|
self.csr_devices.append(corerep_name)
|
||||||
|
|
||||||
|
coreaux = cdr(drtio_aux_controller.DRTIOAuxControllerBare(core.link_layer))
|
||||||
|
setattr(self.submodules, coreaux_name, coreaux)
|
||||||
|
self.csr_devices.append(coreaux_name)
|
||||||
|
|
||||||
|
mem_size = coreaux.get_mem_size()
|
||||||
|
tx_port = coreaux.get_tx_port()
|
||||||
|
rx_port = coreaux.get_rx_port()
|
||||||
|
memory_address = self.axi2csr.register_port(tx_port, mem_size)
|
||||||
|
# rcv in upper half of the memory, thus added second
|
||||||
|
self.axi2csr.register_port(rx_port, mem_size)
|
||||||
|
# and registered in PS interface
|
||||||
|
# manually, because software refers to rx/tx by halves of entire memory block, not names
|
||||||
|
self.add_memory_region(memory_name, self.mem_map["csr"] + memory_address, mem_size * 2)
|
||||||
|
self.rustc_cfg["has_drtio"] = None
|
||||||
|
self.rustc_cfg["has_drtio_routing"] = None
|
||||||
|
self.add_csr_group("drtioaux", drtioaux_csr_group)
|
||||||
|
self.add_csr_group("drtiorep", drtiorep_csr_group)
|
||||||
|
self.add_memory_group("drtioaux_mem", drtioaux_memory_group)
|
||||||
|
|
||||||
|
self.rustc_cfg["rtio_frequency"] = str(self.drtio_transceiver.rtio_clk_freq/1e6)
|
||||||
|
|
||||||
|
# Si5324 Phaser
|
||||||
|
self.submodules.siphaser = SiPhaser7Series(
|
||||||
|
si5324_clkin=platform.request("si5324_clkin"),
|
||||||
|
rx_synchronizer=self.rx_synchronizer,
|
||||||
|
ultrascale=False,
|
||||||
|
rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.ps7.cd_sys.clk, self.siphaser.mmcm_freerun_output)
|
||||||
|
self.csr_devices.append("siphaser")
|
||||||
|
self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324_33").rst_n)
|
||||||
|
self.csr_devices.append("si5324_rst_n")
|
||||||
|
self.rustc_cfg["has_si5324"] = None
|
||||||
|
self.rustc_cfg["has_siphaser"] = None
|
||||||
|
|
||||||
|
rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq
|
||||||
|
# Constrain TX & RX timing for the first transceiver channel
|
||||||
|
# (First channel acts as master for phase alignment for all channels' TX)
|
||||||
|
gtx0 = self.drtio_transceiver.gtxs[0]
|
||||||
sb10q
commented
There's the link on the MGT SMAs but I doubt anyone needs this. @dhslichter ? There's the link on the MGT SMAs but I doubt anyone needs this. @dhslichter ?
|
|||||||
|
platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period)
|
||||||
|
platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.ps7.cd_sys.clk,
|
||||||
|
gtx0.txoutclk, gtx0.rxoutclk)
|
||||||
|
# Constrain RX timing for the each transceiver channel
|
||||||
|
# (Each channel performs single-lane phase alignment for RX)
|
||||||
|
for gtx in self.drtio_transceiver.gtxs[1:]:
|
||||||
|
platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period)
|
||||||
|
platform.add_false_path_constraints(
|
||||||
|
self.ps7.cd_sys.clk, gtx.rxoutclk)
|
||||||
|
|
||||||
|
self.submodules.rtio_crg = RTIOClockMultiplier(self.sys_clk_freq)
|
||||||
|
self.csr_devices.append("rtio_crg")
|
||||||
|
fix_serdes_timing_path(self.platform)
|
||||||
|
|
||||||
|
def add_rtio(self, rtio_channels):
|
||||||
|
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
||||||
|
self.csr_devices.append("rtio_moninj")
|
||||||
|
|
||||||
|
if self.acpki:
|
||||||
|
self.rustc_cfg["ki_impl"] = "acp"
|
||||||
|
self.submodules.rtio = acpki.KernelInitiator(self.rtio_tsc,
|
||||||
|
bus=self.ps7.s_axi_acp,
|
||||||
|
user=self.ps7.s_axi_acp_user,
|
||||||
|
evento=self.ps7.event.o)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
else:
|
||||||
|
self.rustc_cfg["ki_impl"] = "csr"
|
||||||
|
self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc, now64=True)
|
||||||
|
self.csr_devices.append("rtio")
|
||||||
|
|
||||||
|
self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels)
|
||||||
|
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
||||||
|
[self.drtiosat.cri],
|
||||||
|
[self.local_io.cri] + self.drtio_cri,
|
||||||
|
mode="sync", enable_routing=True)
|
||||||
|
self.csr_devices.append("cri_con")
|
||||||
|
|
||||||
|
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
|
||||||
|
self.csr_devices.append("routing_table")
|
||||||
|
|
||||||
|
|
||||||
|
class _Simple_RTIO:
|
||||||
|
def __init__(self):
|
||||||
platform = self.platform
|
platform = self.platform
|
||||||
|
|
||||||
rtio_channels = []
|
rtio_channels = []
|
||||||
|
@ -140,23 +443,11 @@ class Simple(ZC706):
|
||||||
self.add_rtio(rtio_channels)
|
self.add_rtio(rtio_channels)
|
||||||
|
|
||||||
|
|
||||||
# The NIST backplanes require setting VADJ to 3.3V by reprogramming the power supply.
|
class _NIST_CLOCK_RTIO:
|
||||||
# This also changes the I/O standard for some on-board LEDs.
|
|
||||||
leds_fmc33 = [
|
|
||||||
("user_led_33", 0, Pins("Y21"), IOStandard("LVCMOS33")),
|
|
||||||
("user_led_33", 1, Pins("G2"), IOStandard("LVCMOS15")),
|
|
||||||
("user_led_33", 2, Pins("W21"), IOStandard("LVCMOS33")),
|
|
||||||
("user_led_33", 3, Pins("A17"), IOStandard("LVCMOS15")),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class NIST_CLOCK(ZC706):
|
|
||||||
"""
|
"""
|
||||||
NIST clock hardware, with old backplane and 11 DDS channels
|
NIST clock hardware, with old backplane and 11 DDS channels
|
||||||
"""
|
"""
|
||||||
def __init__(self, **kwargs):
|
def __init__(self):
|
||||||
ZC706.__init__(self, **kwargs)
|
|
||||||
|
|
||||||
platform = self.platform
|
platform = self.platform
|
||||||
platform.add_extension(nist_clock.fmc_adapter_io)
|
platform.add_extension(nist_clock.fmc_adapter_io)
|
||||||
platform.add_extension(leds_fmc33)
|
platform.add_extension(leds_fmc33)
|
||||||
|
@ -203,14 +494,12 @@ class NIST_CLOCK(ZC706):
|
||||||
self.add_rtio(rtio_channels)
|
self.add_rtio(rtio_channels)
|
||||||
|
|
||||||
|
|
||||||
class NIST_QC2(ZC706):
|
class _NIST_QC2_RTIO:
|
||||||
"""
|
"""
|
||||||
NIST QC2 hardware, as used in Quantum I and Quantum II, with new backplane
|
NIST QC2 hardware, as used in Quantum I and Quantum II, with new backplane
|
||||||
and 24 DDS channels. Two backplanes are used.
|
and 24 DDS channels. Two backplanes are used.
|
||||||
"""
|
"""
|
||||||
def __init__(self, **kwargs):
|
def __init__(self):
|
||||||
ZC706.__init__(self, **kwargs)
|
|
||||||
|
|
||||||
platform = self.platform
|
platform = self.platform
|
||||||
platform.add_extension(nist_qc2.fmc_adapter_io)
|
platform.add_extension(nist_qc2.fmc_adapter_io)
|
||||||
platform.add_extension(leds_fmc33)
|
platform.add_extension(leds_fmc33)
|
||||||
|
@ -253,7 +542,56 @@ class NIST_QC2(ZC706):
|
||||||
self.add_rtio(rtio_channels)
|
self.add_rtio(rtio_channels)
|
||||||
|
|
||||||
|
|
||||||
VARIANTS = {cls.__name__.lower(): cls for cls in [Simple, NIST_CLOCK, NIST_QC2]}
|
class Simple(ZC706, _Simple_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
ZC706.__init__(self, acpki)
|
||||||
|
_Simple_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class Master(_MasterBase, _Simple_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
_MasterBase.__init__(self, acpki)
|
||||||
|
_Simple_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class Satellite(_SatelliteBase, _Simple_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
_SatelliteBase.__init__(self, acpki)
|
||||||
|
_Simple_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class NIST_CLOCK(ZC706, _NIST_CLOCK_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
ZC706.__init__(self, acpki)
|
||||||
|
_NIST_CLOCK_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class NIST_CLOCK_Master(_MasterBase, _NIST_CLOCK_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
_MasterBase.__init__(self, acpki)
|
||||||
|
|
||||||
|
_NIST_CLOCK_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class NIST_CLOCK_Satellite(_SatelliteBase, _NIST_CLOCK_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
_SatelliteBase.__init__(self, acpki)
|
||||||
|
_NIST_CLOCK_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class NIST_QC2(ZC706, _NIST_QC2_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
ZC706.__init__(self, acpki)
|
||||||
|
_NIST_QC2_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class NIST_QC2_Master(_MasterBase, _NIST_QC2_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
_MasterBase.__init__(self, acpki)
|
||||||
|
_NIST_QC2_RTIO.__init__(self)
|
||||||
|
|
||||||
|
class NIST_QC2_Satellite(_SatelliteBase, _NIST_QC2_RTIO):
|
||||||
|
def __init__(self, acpki):
|
||||||
|
_SatelliteBase.__init__(self, acpki)
|
||||||
|
_NIST_QC2_RTIO.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
|
VARIANTS = {cls.__name__.lower(): cls for cls in [Simple, Master, Satellite,
|
||||||
|
NIST_CLOCK, NIST_CLOCK_Master, NIST_CLOCK_Satellite,
|
||||||
|
NIST_QC2, NIST_QC2_Master, NIST_QC2_Satellite]}
|
||||||
|
|
||||||
|
|
||||||
def write_csr_file(soc, filename):
|
def write_csr_file(soc, filename):
|
||||||
|
@ -261,6 +599,11 @@ def write_csr_file(soc, filename):
|
||||||
f.write(cpu_interface.get_csr_rust(
|
f.write(cpu_interface.get_csr_rust(
|
||||||
soc.get_csr_regions(), soc.get_csr_groups(), soc.get_constants()))
|
soc.get_csr_regions(), soc.get_csr_groups(), soc.get_constants()))
|
||||||
|
|
||||||
|
def write_mem_file(soc, filename):
|
||||||
|
with open(filename, "w") as f:
|
||||||
|
f.write(cpu_interface.get_mem_rust(
|
||||||
|
soc.get_memory_regions(), soc.get_memory_groups(), None))
|
||||||
|
|
||||||
|
|
||||||
def write_rustc_cfg_file(soc, filename):
|
def write_rustc_cfg_file(soc, filename):
|
||||||
with open(filename, "w") as f:
|
with open(filename, "w") as f:
|
||||||
|
@ -276,6 +619,8 @@ def main():
|
||||||
description="ARTIQ port to the ZC706 Zynq development kit")
|
description="ARTIQ port to the ZC706 Zynq development kit")
|
||||||
parser.add_argument("-r", default=None,
|
parser.add_argument("-r", default=None,
|
||||||
help="build Rust interface into the specified file")
|
help="build Rust interface into the specified file")
|
||||||
|
parser.add_argument("-m", default=None,
|
||||||
|
help="build Rust memory interface into the specified file")
|
||||||
parser.add_argument("-c", default=None,
|
parser.add_argument("-c", default=None,
|
||||||
help="build Rust compiler configuration into the specified file")
|
help="build Rust compiler configuration into the specified file")
|
||||||
parser.add_argument("-g", default=None,
|
parser.add_argument("-g", default=None,
|
||||||
|
@ -300,11 +645,12 @@ def main():
|
||||||
|
|
||||||
if args.r is not None:
|
if args.r is not None:
|
||||||
write_csr_file(soc, args.r)
|
write_csr_file(soc, args.r)
|
||||||
|
if args.m is not None:
|
||||||
|
write_mem_file(soc, args.m)
|
||||||
if args.c is not None:
|
if args.c is not None:
|
||||||
write_rustc_cfg_file(soc, args.c)
|
write_rustc_cfg_file(soc, args.c)
|
||||||
if args.g is not None:
|
if args.g is not None:
|
||||||
soc.build(build_dir=args.g)
|
soc.build(build_dir=args.g)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
It's omitted on Kasli because it's used for Ethernet.
Kasli-SoC has a dedicated RJ45 port.