From 7bc03e5fbc4097a6a090c43756487a0e577e035f Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 26 Feb 2024 17:29:09 +0100 Subject: [PATCH] targets/litex_acorn_baseboard_mini: Make it similar to other targets and keep SoC + UART + DRAM + Ethernet. --- .../targets/litex_acorn_baseboard_mini.py | 203 ++++++++++-------- 1 file changed, 118 insertions(+), 85 deletions(-) diff --git a/litex_boards/targets/litex_acorn_baseboard_mini.py b/litex_boards/targets/litex_acorn_baseboard_mini.py index 0a77f6f..488c1b5 100755 --- a/litex_boards/targets/litex_acorn_baseboard_mini.py +++ b/litex_boards/targets/litex_acorn_baseboard_mini.py @@ -6,13 +6,12 @@ # Copyright (c) 2021-2024 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause -# Build/Use ---------------------------------------------------------------------------------------- - -import os - from migen import * -from litex.gen import LiteXModule +from litex.gen import * + +from litex.build.io import DifferentialInput +from litex.build.openocd import OpenOCD from litex_boards.platforms import sqrl_acorn @@ -23,104 +22,126 @@ from litex.soc.integration.builder import * from litex.soc.cores.clock import * from litex.soc.cores.led import LedChaser -from litex.build.generic_platform import Subsignal, Pins +from litex.build.generic_platform import IOStandard, Subsignal, Pins + +from litedram.modules import MT41K512M16 +from litedram.phy import s7ddrphy + from liteeth.phy.a7_gtp import QPLLSettings, QPLL from liteeth.phy.a7_1000basex import A7_1000BASEX +# Platform ----------------------------------------------------------------------------------------- + +class Platform(sqrl_acorn.Platform): + def create_programmer(self, name="openocd"): + return OpenOCD("openocd_xc7_ft2232.cfg", "bscan_spi_xc7a200t.bit") + +_serial_io = [ + ("serial", 0, + Subsignal("tx", Pins("G1"), IOStandard("LVCMOS33")), # CLK_REQ + Subsignal("rx", Pins("Y13"), IOStandard("LVCMOS18")), # SMB_ALERT_N + ), +] + # CRG ---------------------------------------------------------------------------------------------- -class CRG(Module): +class CRG(LiteXModule): def __init__(self, platform, sys_clk_freq): - self.rst = Signal() - self.clock_domains.cd_sys = ClockDomain() - self.clock_domains.cd_idelay = ClockDomain() + self.rst = Signal() + self.cd_sys = ClockDomain() + self.cd_sys4x = ClockDomain() + self.cd_sys4x_dqs = ClockDomain() + self.cd_idelay = ClockDomain() - # Clk/Rst - clk200 = platform.request("clk200") + # Clk/Rst. + clk200 = platform.request("clk200") + clk200_se = Signal() + self.specials += DifferentialInput(clk200.p, clk200.n, clk200_se) - # PLL - self.submodules.pll = pll = S7PLL() + # PLL. + self.pll = pll = S7PLL() self.comb += pll.reset.eq(self.rst) - pll.register_clkin(clk200, 200e6) - pll.create_clkout(self.cd_sys, sys_clk_freq, margin=0) - # Ignore sys_clk to pll.clkin path created by SoC's rst. - platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) + pll.register_clkin(clk200_se, 200e6) + pll.create_clkout(self.cd_sys, sys_clk_freq) + pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq) + pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90) + platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) # Ignore sys_clk to pll.clkin path created by SoC's rst. + + # IDelayCtrl. + self.comb += self.cd_idelay.clk.eq(clk200_se) + self.idelayctrl = S7IDELAYCTRL(self.cd_idelay) # BaseSoC ----------------------------------------------------------------------------------------- -class BaseSoC(SoCMini): - def __init__(self, variant="cle-215+", sys_clk_freq=156.25e6, with_led_chaser=True, **kwargs): - platform = sqrl_acorn.Platform(variant=variant) - assert sys_clk_freq == 156.25e6 - - # SoCCore ---------------------------------------------------------------------------------- - SoCMini.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on Acorn CLE-101/215(+)") +class BaseSoC(SoCCore): + def __init__(self, variant="cle-215+", sys_clk_freq=156.25e6, + with_ethernet = False, + with_etherbone = False, + eth_ip = "192.168.1.50", + remote_ip = None, + eth_dynamic_ip = False, + with_led_chaser = True, + **kwargs): + platform = Platform(variant=variant) + platform.add_extension(_serial_io, prepend=True) # CRG -------------------------------------------------------------------------------------- - self.submodules.crg = CRG(platform, sys_clk_freq) + self.crg = CRG(platform, sys_clk_freq) - # Etherbone -------------------------------------------------------------------------------- + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on Acorn CLE-101/215(+)", **kwargs) - _eth_io = [ - ("sfp", 0, - Subsignal("txp", Pins("D5")), - Subsignal("txn", Pins("C5")), - Subsignal("rxp", Pins("D11")), - Subsignal("rxn", Pins("C11")), - ), - ("sfp", 1, - Subsignal("txp", Pins("B4")), - Subsignal("txn", Pins("A4")), - Subsignal("rxp", Pins("B8")), - Subsignal("rxn", Pins("A8")), - ), - ] - platform.add_extension(_eth_io) + # DDR3 SDRAM ------------------------------------------------------------------------------- + if not self.integrated_main_ram_size: + self.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"), + memtype = "DDR3", + nphases = 4, + sys_clk_freq = sys_clk_freq) + self.add_sdram("sdram", + phy = self.ddrphy, + module = MT41K512M16(sys_clk_freq, "1:4"), + l2_cache_size = kwargs.get("l2_size", 8192) + ) - # phy - qpll_settings = QPLLSettings( - refclksel = 0b001, - fbdiv = 4, - fbdiv_45 = 4, - refclk_div = 1 - ) - qpll = QPLL(ClockSignal("sys"), qpll_settings) - print(qpll) - self.submodules += qpll + # Ethernet / Etherbone --------------------------------------------------------------------- + if with_ethernet or with_etherbone: + _eth_io = [ + ("sfp", 0, + Subsignal("txp", Pins("D5")), + Subsignal("txn", Pins("C5")), + Subsignal("rxp", Pins("D11")), + Subsignal("rxn", Pins("C11")), + ), + ] + platform.add_extension(_eth_io) - self.ethphy0 = A7_1000BASEX( - qpll_channel = qpll.channels[0], - data_pads = self.platform.request("sfp", 0), - sys_clk_freq = self.clk_freq, - rx_polarity = 1, # Inverted on Acorn - tx_polarity = 0 # Inverted on Acorn and on baseboard. - ) - platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks REQP-49]") - self.add_etherbone(name="etherbone0", - phy = self.ethphy0, - phy_cd = "ethphy0_eth", - mac_address = 0x10e2d5000000, - ip_address = "192.168.1.50" - ) + qpll_settings = QPLLSettings( + refclksel = 0b001, + fbdiv = 4, + fbdiv_45 = 4, + refclk_div = 1 + ) + qpll = QPLL(ClockSignal("sys"), qpll_settings) + print(qpll) + self.submodules += qpll - self.ethphy1 = A7_1000BASEX( - qpll_channel = qpll.channels[0], - data_pads = self.platform.request("sfp", 1), - sys_clk_freq = self.clk_freq, - rx_polarity = 1, # Inverted on Acorn - tx_polarity = 0 # Inverted on Acorn and on baseboard. - ) - platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks REQP-49]") - self.add_etherbone(name="etherbone1", - phy = self.ethphy1, - phy_cd = "ethphy1_eth", - mac_address = 0x10e2d5000001, - ip_address = "192.168.1.51" - ) + self.ethphy = A7_1000BASEX( + qpll_channel = qpll.channels[0], + data_pads = self.platform.request("sfp"), + sys_clk_freq = self.clk_freq, + rx_polarity = 1, # Inverted on Acorn. + tx_polarity = 0 # Inverted on Acorn and on baseboard. + ) + platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks REQP-49]") + + if with_etherbone: + self.add_etherbone(phy=self.ethphy, ip_address=eth_ip, with_ethmac=with_ethernet) + elif with_ethernet: + self.add_ethernet(phy=self.ethphy, dynamic_ip=eth_dynamic_ip, local_ip=eth_ip, remote_ip=remote_ip) # Leds ------------------------------------------------------------------------------------- if with_led_chaser: - self.submodules.leds = LedChaser( + self.leds = LedChaser( pads = platform.request_all("user_led"), sys_clk_freq = sys_clk_freq) @@ -129,16 +150,28 @@ class BaseSoC(SoCMini): def main(): from litex.build.parser import LiteXArgumentParser parser = LiteXArgumentParser(platform=sqrl_acorn.Platform, description="LiteX SoC on Acorn CLE-101/215(+).") - parser.add_target_argument("--flash", action="store_true", help="Flash bitstream.") - parser.add_target_argument("--variant", default="cle-215+", help="Board variant (cle-215+, cle-215 or cle-101).") + parser.add_target_argument("--flash", action="store_true", help="Flash bitstream.") + parser.add_target_argument("--variant", default="cle-215+", help="Board variant (cle-215+, cle-215 or cle-101).") + parser.add_target_argument("--sys-clk-freq", default=156.25e6, type=float, help="System clock frequency.") + parser.add_target_argument("--with-ethernet", action="store_true", help="Enable Ethernet support.") + parser.add_target_argument("--with-etherbone", action="store_true", help="Enable Etherbone support.") + parser.add_target_argument("--eth-ip", default="192.168.1.50", help="Ethernet/Etherbone IP address.") + parser.add_target_argument("--remote-ip", default="192.168.1.100", help="Remote IP address of TFTP server.") + parser.add_target_argument("--eth-dynamic-ip", action="store_true", help="Enable dynamic Ethernet IP addresses setting.") args = parser.parse_args() soc = BaseSoC( - variant = args.variant, + variant = args.variant, + sys_clk_freq = args.sys_clk_freq, + with_ethernet = args.with_ethernet, + with_etherbone = args.with_etherbone, + eth_ip = args.eth_ip, + remote_ip = args.remote_ip, + eth_dynamic_ip = args.eth_dynamic_ip, **parser.soc_argdict ) - builder = Builder(soc, **parser.builder_argdict) + builder = Builder(soc, **parser.builder_argdict) if args.build: builder.build(**parser.toolchain_argdict)