diff --git a/src/gateware/ebaz4205.py b/src/gateware/ebaz4205.py new file mode 100644 index 00000000..be360daf --- /dev/null +++ b/src/gateware/ebaz4205.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python + +import argparse +from operator import itemgetter + +from migen import * +from migen.build.platforms import ebaz4205 +from migen.build.generic_platform import Pins, Subsignal, IOStandard, Misc +from migen_axi.integration.soc_core import SoCCore +from misoc.interconnect.csr import * + +from artiq.gateware import rtio +from artiq.gateware.rtio.phy import ttl_simple +from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path + +import dma +import analyzer + +from config import write_csr_file, write_mem_file, write_rustc_cfg_file + +_ps = [ + ( + "ps", + 0, + Subsignal("clk", Pins("E7"), IOStandard("LVCMOS33"), Misc("SLEW=FAST")), + Subsignal("por_b", Pins("C7"), IOStandard("LVCMOS33"), Misc("SLEW=FAST")), + Subsignal("srst_b", Pins("B10"), IOStandard("LVCMOS18"), Misc("SLEW=FAST")), + ) +] + +_ddr = [ + ( + "ddr", + 0, + Subsignal( + "a", + Pins("N2 K2 M3 K3 M4 L1 L4 K4 K1 J4 F5 G4 E4 D4 F4"), + IOStandard("SSTL15"), + ), + Subsignal("ba", Pins("L5 R4 J5"), IOStandard("SSTL15")), + Subsignal("cas_n", Pins("P5"), IOStandard("SSTL15")), + Subsignal("cke", Pins("N3"), IOStandard("SSTL15")), + Subsignal("cs_n", Pins("N1"), IOStandard("SSTL15")), + Subsignal("ck_n", Pins("M2"), IOStandard("DIFF_SSTL15"), Misc("SLEW=FAST")), + Subsignal("ck_p", Pins("L2"), IOStandard("DIFF_SSTL15"), Misc("SLEW=FAST")), + # Pins "T1 Y1" not connected + Subsignal("dm", Pins("A1 F1"), IOStandard("SSTL15_T_DCI"), Misc("SLEW=FAST")), + Subsignal( + "dq", + Pins("C3 B3 A2 A4 D3 D1 C1 E1 E2 E3 G3 H3 J3 H2 H1 J1"), + # Pins "P1 P3 R3 R1 T4 U4 U2 U3 V1 Y3 W1 Y4 Y2 W3 V2 V3" not connected + IOStandard("SSTL15_T_DCI"), + Misc("SLEW=FAST"), + ), + Subsignal( + "dqs_n", + Pins("B2 F2"), # Pins "T2 W4" not connected + IOStandard("DIFF_SSTL15_T_DCI"), + Misc("SLEW=FAST"), + ), + Subsignal( + "dqs_p", + Pins("C2 G2"), # Pins "R2 W5" not connected + IOStandard("DIFF_SSTL15_T_DCI"), + Misc("SLEW=FAST"), + ), + Subsignal("vrn", Pins("G5"), IOStandard("SSTL15_T_DCI"), Misc("SLEW=FAST")), + Subsignal("vrp", Pins("H5"), IOStandard("SSTL15_T_DCI"), Misc("SLEW=FAST")), + Subsignal("drst_n", Pins("B4"), IOStandard("SSTL15"), Misc("SLEW=FAST")), + Subsignal("odt", Pins("N5"), IOStandard("SSTL15")), + Subsignal("ras_n", Pins("P4"), IOStandard("SSTL15")), + Subsignal("we_n", Pins("M5"), IOStandard("SSTL15")), + ) +] + +# Connector J3 +_i2c = [ + ( + "i2c", + 0, + Subsignal("scl", Pins("U12"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("V13"), IOStandard("LVCMOS33")), + ) +] + + +class EBAZ4205(SoCCore): + def __init__(self, rtio_clk=125e6, acpki=False): + self.acpki = acpki + + platform = ebaz4205.Platform() + platform.toolchain.bitstream_commands.extend( + [ + "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", + ] + ) + platform.add_extension(_ps) + platform.add_extension(_ddr) + platform.add_extension(_i2c) + + gmii = platform.request("gmii") + platform.add_period_constraint(gmii.rx_clk, 10) + platform.add_period_constraint(gmii.tx_clk, 10) + platform.add_platform_command( + "set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets gmii_tx_clk_IBUF]" + ) + + ident = self.__class__.__name__ + if self.acpki: + ident = "acpki_" + ident + SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident) + fix_serdes_timing_path(platform) + self.config["RTIO_FREQUENCY"] = str(rtio_clk / 1e6) + platform.add_period_constraint(self.ps7.cd_sys.clk, 10) + + self.comb += [ + self.ps7.enet0.enet.gmii.tx_clk.eq(gmii.tx_clk), + self.ps7.enet0.enet.gmii.rx_clk.eq(gmii.rx_clk), + ] + self.clock_domains.cd_eth_rx = ClockDomain(reset_less=False) + self.clock_domains.cd_eth_tx = ClockDomain(reset_less=False) + self.comb += [ + ClockSignal("eth_rx").eq(gmii.rx_clk), + ClockSignal("eth_tx").eq(gmii.tx_clk), + ] + self.sync.eth_tx += [ + gmii.txd.eq(self.ps7.enet0.enet.gmii.txd), + gmii.tx_en.eq(self.ps7.enet0.enet.gmii.tx_en), + ] + self.sync.eth_rx += [ + self.ps7.enet0.enet.gmii.rxd.eq(gmii.rxd), + self.ps7.enet0.enet.gmii.rx_dv.eq(gmii.rx_dv), + ] + + # MDIO + mdio = platform.request("mdio") + self.comb += mdio.mdc.eq(self.ps7.enet0.enet.mdio.mdc) + self.specials += Instance( + "IOBUF", + i_I=self.ps7.enet0.enet.mdio.o, + io_IO=mdio.mdio, + o_O=self.ps7.enet0.enet.mdio.i, + i_T=~self.ps7.enet0.enet.mdio.t_n, + ) + + # I2C + i2c = self.platform.request("i2c") + self.specials += [ + # SCL + Instance( + "IOBUF", + i_I=self.ps7.i2c0.scl.o, + io_IO=i2c.scl, + o_O=self.ps7.i2c0.scl.i, + i_T=~self.ps7.i2c0.scl.t_n, + ), + # SDA + Instance( + "IOBUF", + i_I=self.ps7.i2c0.sda.o, + io_IO=i2c.sda, + o_O=self.ps7.i2c0.sda.i, + i_T=~self.ps7.i2c0.sda.t_n, + ), + ] + + self.rtio_channels = [] + 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(glbl_fine_ts_width=3) + self.submodules.rtio_core = rtio.Core(self.rtio_tsc, self.rtio_channels) + self.csr_devices.append("rtio_core") + if self.acpki: + import acpki + + self.config["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.config["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], + 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.rtio_analyzer = analyzer.Analyzer( + self.rtio_tsc, self.rtio_core.cri, self.ps7.s_axi_hp1 + ) + self.csr_devices.append("rtio_analyzer") + + +def main(): + parser = argparse.ArgumentParser( + description="ARTIQ port to the EBAZ4205 control card of Ebit E9+ BTC miner" + ) + parser.add_argument( + "-r", default=None, 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, + help="build Rust compiler configuration into the specified file", + ) + parser.add_argument( + "-g", default=None, help="build gateware into the specified directory" + ) + parser.add_argument("--rtio-clk", default=125e6, help="RTIO Clock Frequency (Hz)") + parser.add_argument( + "--acpki", default=False, action="store_true", help="enable ACPKI" + ) + args = parser.parse_args() + + soc = EBAZ4205(rtio_clk=int(args.rtio_clk), acpki=args.acpki) + soc.finalize() + + if args.r is not None: + write_csr_file(soc, args.r) + if args.m is not None: + write_mem_file(soc, args.m) + if args.c is not None: + write_rustc_cfg_file(soc, args.c) + if args.g is not None: + soc.build(build_dir=args.g) + + +if __name__ == "__main__": + main() diff --git a/src/libboard_artiq/Cargo.toml.tpl b/src/libboard_artiq/Cargo.toml.tpl index 995fc052..ab8270ff 100644 --- a/src/libboard_artiq/Cargo.toml.tpl +++ b/src/libboard_artiq/Cargo.toml.tpl @@ -10,6 +10,7 @@ name = "libboard_artiq" [features] target_zc706 = ["libboard_zynq/target_zc706", "libconfig/target_zc706"] target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libconfig/target_kasli_soc"] +target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libconfig/target_ebaz4205"] calibrate_wrpll_skew = [] [build-dependencies] diff --git a/src/runtime/Cargo.toml.tpl b/src/runtime/Cargo.toml.tpl index 9f539e04..c844131e 100644 --- a/src/runtime/Cargo.toml.tpl +++ b/src/runtime/Cargo.toml.tpl @@ -8,6 +8,7 @@ edition = "2018" [features] target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706", "libboard_artiq/target_zc706"] target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc", "libboard_artiq/target_kasli_soc"] +target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libsupport_zynq/target_ebaz4205", "libconfig/target_ebaz4205", "libboard_artiq/target_ebaz4205"] default = ["target_zc706"] [build-dependencies] diff --git a/src/runtime/src/rtio_clocking.rs b/src/runtime/src/rtio_clocking.rs index 06918b23..cf464c1b 100644 --- a/src/runtime/src/rtio_clocking.rs +++ b/src/runtime/src/rtio_clocking.rs @@ -1,6 +1,8 @@ +#[cfg(not(feature = "target_ebaz4205"))] use embedded_hal::blocking::delay::DelayMs; #[cfg(has_si5324)] use ksupport::i2c; +#[cfg(not(feature = "target_ebaz4205"))] use libboard_artiq::pl; #[cfg(has_si5324)] use libboard_artiq::si5324; @@ -10,7 +12,9 @@ use libboard_artiq::si549; use libboard_zynq::i2c::I2c; use libboard_zynq::timer::GlobalTimer; use libconfig::Config; -use log::{info, warn}; +use log::warn; +#[cfg(not(feature = "target_ebaz4205"))] +use log::info; #[derive(Debug, PartialEq, Copy, Clone)] #[allow(non_camel_case_types)] @@ -69,7 +73,7 @@ fn get_rtio_clock_cfg(cfg: &Config) -> RtioClock { res } -#[cfg(not(has_drtio))] +#[cfg(not(any(has_drtio, feature = "target_ebaz4205")))] fn init_rtio(timer: &mut GlobalTimer) { info!("Switching SYS clocks..."); unsafe { @@ -429,7 +433,7 @@ pub fn init(timer: &mut GlobalTimer, cfg: &Config) { #[cfg(has_drtio)] init_drtio(timer); - #[cfg(not(has_drtio))] + #[cfg(not(any(has_drtio, feature = "target_ebaz4205")))] init_rtio(timer); #[cfg(all(has_si549, has_wrpll))]