From 7ed698422ec49bc8c1adbf944899b31b3578e370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Sowi=C5=84ski?= Date: Fri, 24 Mar 2023 15:35:44 +0100 Subject: [PATCH] Added support for Digilent Genesys 2 --- RELEASE_NOTES.rst | 1 + artiq/firmware/libboard_misoc/net_settings.rs | 2 + artiq/firmware/libboard_misoc/spiflash.rs | 2 +- artiq/firmware/runtime/rtio_clocking.rs | 14 ++- artiq/frontend/artiq_flash.py | 37 +++++- artiq/gateware/targets/digilent_genesys2.py | 113 ++++++++++++++++++ 6 files changed, 165 insertions(+), 4 deletions(-) create mode 100755 artiq/gateware/targets/digilent_genesys2.py diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 8ccbc33470..3cda7626ca 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -16,6 +16,7 @@ Highlights: For earlier hardware versions, specify the hardware version in the device database file (e.g. ``"hw_rev": "v2.1"``) to use the correct conversion factor. - Metlino and Sayma support has been dropped due to complications with synchronous RTIO clocking. + - Digilent Genesys 2, Xilinx Kintex 7 development board with single FMC HPC connector. * CPU (on softcore platforms) and AXI bus (on Zynq) are now clocked synchronously with the RTIO clock, to facilitate implementation of local processing on DRTIO satellites, and to slightly reduce RTIO latency. diff --git a/artiq/firmware/libboard_misoc/net_settings.rs b/artiq/firmware/libboard_misoc/net_settings.rs index bab8fb28b2..780e5dbad3 100644 --- a/artiq/firmware/libboard_misoc/net_settings.rs +++ b/artiq/firmware/libboard_misoc/net_settings.rs @@ -75,6 +75,8 @@ pub fn get_adresses() -> NetAddresses { } #[cfg(soc_platform = "kc705")] { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]); } + #[cfg(soc_platform = "digilent_genesys2")] + { hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x03]); } } } diff --git a/artiq/firmware/libboard_misoc/spiflash.rs b/artiq/firmware/libboard_misoc/spiflash.rs index 598d96633a..75a1023dd2 100644 --- a/artiq/firmware/libboard_misoc/spiflash.rs +++ b/artiq/firmware/libboard_misoc/spiflash.rs @@ -114,7 +114,7 @@ pub unsafe fn write(mut addr: usize, mut data: &[u8]) { } } -#[cfg(any(soc_platform = "kasli", soc_platform = "kc705"))] +#[cfg(any(soc_platform = "kasli", soc_platform = "kc705", soc_platform = "digilent_genesys2"))] pub unsafe fn reload () -> ! { csr::icap::iprog_write(1); loop {} diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index f094e53832..5d7e928831 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -1,9 +1,14 @@ + +#[cfg(has_si5324)] use board_misoc::config; +#[cfg(has_si5324)] use board_artiq::si5324; +#[cfg(has_si5324)] use board_misoc::{csr, clock}; #[derive(Debug, PartialEq)] #[allow(non_camel_case_types)] +#[cfg(has_si5324)] pub enum RtioClock { Default, Int_125, @@ -15,6 +20,7 @@ pub enum RtioClock { } #[allow(unreachable_code)] +#[cfg(has_si5324)] fn get_rtio_clock_cfg() -> RtioClock { config::read_str("rtio_clock", |result| { let res = match result { @@ -92,6 +98,7 @@ const SI5324_EXT_INPUT: si5324::Input = si5324::Input::Ckin2; #[cfg(all(soc_platform = "kc705"))] const SI5324_EXT_INPUT: si5324::Input = si5324::Input::Ckin2; +#[cfg(has_si5324)] fn setup_si5324_pll(cfg: RtioClock) { let (si5324_settings, si5324_ref_input) = match cfg { RtioClock::Ext0_Synth0_10to125 => { // 125 MHz output from 10 MHz CLKINx reference, 504 Hz BW @@ -194,6 +201,7 @@ fn setup_si5324_pll(cfg: RtioClock) { si5324::setup(&si5324_settings, si5324_ref_input).expect("cannot initialize Si5324"); } +#[cfg(has_si5324)] fn setup_si5324(clock_cfg: RtioClock) { let switched = unsafe { csr::crg::switch_done_read() @@ -225,8 +233,10 @@ fn setup_si5324(clock_cfg: RtioClock) { pub fn init() { - let clock_cfg = get_rtio_clock_cfg(); - setup_si5324(clock_cfg); + #[cfg(has_si5324)] { + let clock_cfg = get_rtio_clock_cfg(); + setup_si5324(clock_cfg); + } #[cfg(has_drtio)] { diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index 136b58c717..a970ca2d9d 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -59,7 +59,7 @@ def get_argparser(): help="SSH host to jump through") parser.add_argument("-t", "--target", default="kasli", help="target board, default: %(default)s, one of: " - "kasli kc705") + "kasli kc705 genesys2") parser.add_argument("-I", "--preinit-command", default=[], action="append", help="add a pre-initialization OpenOCD command. " "Useful for selecting a board when several are connected.") @@ -230,6 +230,34 @@ def start(self): "xc7_program xc7.tap") +class ProgrammerGenesys2(Programmer): + _sector_size = 0x10000 + + def __init__(self, client, preinit_script): + Programmer.__init__(self, client, preinit_script) + + add_commands(self._board_script, + "adapter driver ftdi", + "ftdi vid_pid 0x0403 0x6010", + "ftdi channel 1", + "ftdi layout_init 0x00e8 0x60eb", + "reset_config none", + "adapter speed 25000", + "transport select jtag", + "source {}".format(self._transfer_script("cpld/xilinx-xc7.cfg")), + "source {}".format(self._transfer_script("fpga/xilinx-xadc.cfg")), + "source {}".format(self._transfer_script("cpld/jtagspi.cfg"))) + self.add_flash_bank("spi0", "xc7", index=0) + + add_commands(self._script, "xadc_report xc7.tap") + + def load_proxy(self): + self.load(find_proxy_bitfile("bscan_spi_xc7k325t.bit"), pld=0) + + def start(self): + add_commands(self._script, "xc7_program xc7.tap") + + def main(): args = get_argparser().parse_args() common_args.init_logger_from_args(args) @@ -249,6 +277,13 @@ def main(): "storage": ("spi0", 0xb30000), "firmware": ("spi0", 0xb40000), }, + "genesys2": { + "programmer": ProgrammerGenesys2, + "gateware": ("spi0", 0x000000), + "bootloader": ("spi0", 0xaf0000), + "storage": ("spi0", 0xb30000), + "firmware": ("spi0", 0xb40000), + }, }[args.target] if not args.action: diff --git a/artiq/gateware/targets/digilent_genesys2.py b/artiq/gateware/targets/digilent_genesys2.py new file mode 100755 index 0000000000..8d89b1182b --- /dev/null +++ b/artiq/gateware/targets/digilent_genesys2.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 + +import argparse + +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.genlib.cdc import MultiReg +from migen.build.generic_platform import * + +from misoc.interconnect.csr import * +from misoc.cores import gpio, timer +from misoc.targets.digilent_genesys2 import MiniSoC +from misoc.integration.builder import builder_args, builder_argdict +from misoc.integration.soc_sdram import * + +from artiq.gateware.amp import AMPSoC +from artiq.gateware import rtio +from artiq.gateware.rtio.phy import ttl_simple +from artiq.build_soc import * + + +class _StandaloneBase(MiniSoC, AMPSoC): + mem_map = { + "cri_con": 0x10000000, + "rtio": 0x20000000, + "rtio_dma": 0x30000000, + "mailbox": 0x70000000 + } + mem_map.update(MiniSoC.mem_map) + + def __init__(self, gateware_identifier_str=None, **kwargs): + MiniSoC.__init__(self, + cpu_type="vexriscv", + cpu_bus_width=64, + sdram_controller_type="minicon", + l2_size=128*1024, + integrated_sram_size=8192, + ethmac_nrxslots=4, + ethmac_ntxslots=4, + **kwargs) + AMPSoC.__init__(self) + add_identifier(self, gateware_identifier_str=gateware_identifier_str) + + self.submodules.timer1 = timer.Timer() + self.csr_devices.append("timer1") + self.interrupt_devices.append("timer1") + + self.submodules.leds = gpio.GPIOOut(Cat( + self.platform.request("user_led", 0), + self.platform.request("user_led", 1))) + self.csr_devices.append("leds") + + def add_rtio(self, rtio_channels): + self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) + self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) + self.csr_devices.append("rtio_core") + self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) + self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( + rtio.DMA(self.get_native_sdram_if(), self.cpu_dw)) + 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") + + # Only add MonInj core if there is anything to monitor + if any([len(c.probes) for c in rtio_channels]): + self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) + self.csr_devices.append("rtio_moninj") + + self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, + self.get_native_sdram_if(), cpu_dw=self.cpu_dw) + self.csr_devices.append("rtio_analyzer") + + +class TestVariant(_StandaloneBase): + def __init__(self, gateware_identifier_str=None, **kwargs): + _StandaloneBase.__init__(self, gateware_identifier_str, **kwargs) + + rtio_channels = [] + for i in range(2, 7): + phy = ttl_simple.Output(self.platform.request("user_led", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + for i in range(8): + phy = ttl_simple.InOut(self.platform.request("user_sw", i)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + + self.config["HAS_RTIO_LOG"] = None + self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) + rtio_channels.append(rtio.LogChannel()) + + self.add_rtio(rtio_channels) + + +def main(): + parser = argparse.ArgumentParser( + description="ARTIQ device binary builder for Digilent Genesys2 systems") + builder_args(parser) + soc_sdram_args(parser) + parser.set_defaults(output_dir="artiq_genesys2") + parser.add_argument("--gateware-identifier-str", default=None, + help="Override ROM identifier") + args = parser.parse_args() + + soc = TestVariant(gateware_identifier_str=args.gateware_identifier_str, **soc_sdram_argdict(args)) + build_artiq_soc(soc, builder_argdict(args)) + + +if __name__ == "__main__": + main()