Skip to content

Commit

Permalink
Added support for Digilent Genesys 2
Browse files Browse the repository at this point in the history
Based on:
- m-labs/misoc#130
- m-labs/migen#264

Signed-off-by: Mikołaj Sowiński <msowinski@technosystem.com.pl>
  • Loading branch information
kaolpr committed Jan 16, 2023
1 parent e9c65ab commit 76e26a4
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 3 deletions.
6 changes: 4 additions & 2 deletions RELEASE_NOTES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
Release notes
=============

ARTIQ-8 (Unreleased)
--------------------
Unreleased
----------

Highlights:

Expand All @@ -23,6 +23,8 @@ Highlights:
support legacy installations, but may be removed in a future release.
* Added channel names to RTIO errors.
* Full Python 3.10 support.
* New hardware support:
- Digilent Genesys 2, Xilinx Kintex 7 development board with single FMC HPC connector.

ARTIQ-7
-------
Expand Down
2 changes: 2 additions & 0 deletions artiq/firmware/libboard_misoc/net_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,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]); }
}
}

Expand Down
2 changes: 1 addition & 1 deletion artiq/firmware/libboard_misoc/spiflash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
7 changes: 7 additions & 0 deletions artiq/frontend/artiq_flash.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,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:
Expand Down
156 changes: 156 additions & 0 deletions artiq/gateware/targets/digilent_genesys2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/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 _RTIOCRG(Module, AutoCSR):
def __init__(self, platform, rtio_internal_clk):
# TODO: See if we can get rid of it?
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)

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_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
i_CLKIN1=rtio_internal_clk, i_CLKIN2=0,
# Warning: CLKINSEL=0 means CLKIN2 is selected
i_CLKINSEL=1,

# VCO @ 1GHz when using 125MHz 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)
]


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_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk)
self.csr_devices.append("rtio_crg")
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")
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")
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
self.csr_devices.append("rtio_moninj")

self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
self.platform.add_false_path_constraints(
self.crg.cd_sys.clk,
self.rtio_crg.cd_rtio.clk)

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()

0 comments on commit 76e26a4

Please sign in to comment.