mirror of
https://github.com/litex-hub/litex-boards.git
synced 2025-01-03 03:43:36 -05:00
99e2f04ee5
Collect --with-ethernet/--with-etherbone, --with-spi-sdcard/--with-sdcard, etc. into ArgumentParser.add_mutually_exclusive_group()s. That way, we get pretty --help output, and appropriate error messages if somebody tries to ask for something that doesn't make sense.
171 lines
7.4 KiB
Python
Executable file
171 lines
7.4 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
#
|
|
# This file is part of LiteX-Boards.
|
|
#
|
|
# Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
|
# Copyright (c) 2018-2019 David Shah <dave@ds0.me>
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
import os
|
|
import argparse
|
|
|
|
from migen import *
|
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
|
|
from litex_boards.platforms import versa_ecp5
|
|
|
|
from litex.build.lattice.trellis import trellis_args, trellis_argdict
|
|
|
|
from litex.soc.cores.clock import *
|
|
from litex.soc.integration.soc_core import *
|
|
from litex.soc.integration.soc_sdram import *
|
|
from litex.soc.integration.builder import *
|
|
from litex.soc.cores.led import LedChaser
|
|
|
|
from litedram.modules import MT41K64M16
|
|
from litedram.phy import ECP5DDRPHY
|
|
|
|
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII
|
|
|
|
# CRG ----------------------------------------------------------------------------------------------
|
|
|
|
class _CRG(Module):
|
|
def __init__(self, platform, sys_clk_freq):
|
|
self.rst = Signal()
|
|
self.clock_domains.cd_init = ClockDomain()
|
|
self.clock_domains.cd_por = ClockDomain(reset_less=True)
|
|
self.clock_domains.cd_sys = ClockDomain()
|
|
self.clock_domains.cd_sys2x = ClockDomain()
|
|
self.clock_domains.cd_sys2x_i = ClockDomain(reset_less=True)
|
|
|
|
# # #
|
|
|
|
self.stop = Signal()
|
|
self.reset = Signal()
|
|
|
|
# Clk / Rst
|
|
clk100 = platform.request("clk100")
|
|
rst_n = platform.request("rst_n")
|
|
|
|
# Power on reset
|
|
por_count = Signal(16, reset=2**16-1)
|
|
por_done = Signal()
|
|
self.comb += self.cd_por.clk.eq(clk100)
|
|
self.comb += por_done.eq(por_count == 0)
|
|
self.sync.por += If(~por_done, por_count.eq(por_count - 1))
|
|
|
|
# PLL
|
|
self.submodules.pll = pll = ECP5PLL()
|
|
self.comb += pll.reset.eq(~por_done | ~rst_n | self.rst)
|
|
pll.register_clkin(clk100, 100e6)
|
|
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
|
|
pll.create_clkout(self.cd_init, 25e6)
|
|
self.specials += [
|
|
Instance("ECLKSYNCB",
|
|
i_ECLKI = self.cd_sys2x_i.clk,
|
|
i_STOP = self.stop,
|
|
o_ECLKO = self.cd_sys2x.clk),
|
|
Instance("CLKDIVF",
|
|
p_DIV = "2.0",
|
|
i_ALIGNWD = 0,
|
|
i_CLKI = self.cd_sys2x.clk,
|
|
i_RST = self.reset,
|
|
o_CDIVX = self.cd_sys.clk),
|
|
AsyncResetSynchronizer(self.cd_sys, ~pll.locked | self.reset),
|
|
AsyncResetSynchronizer(self.cd_sys2x, ~pll.locked | self.reset),
|
|
]
|
|
|
|
# BaseSoC ------------------------------------------------------------------------------------------
|
|
|
|
class BaseSoC(SoCCore):
|
|
def __init__(self, sys_clk_freq=int(75e6), device="LFE5UM5G", with_ethernet=False, with_etherbone=False, eth_ip="192.168.1.50", eth_phy=0, toolchain="trellis", **kwargs):
|
|
platform = versa_ecp5.Platform(toolchain=toolchain, device=device)
|
|
|
|
# FIXME: adapt integrated rom size for Microwatt
|
|
if kwargs.get("cpu_type", None) == "microwatt":
|
|
kwargs["integrated_rom_size"] = 0xb000 if with_ethernet else 0x9000
|
|
|
|
# SoCCore -----------------------------------------_----------------------------------------
|
|
SoCCore.__init__(self, platform, sys_clk_freq,
|
|
ident = "LiteX SoC on Versa ECP5",
|
|
ident_version = True,
|
|
**kwargs)
|
|
|
|
# CRG --------------------------------------------------------------------------------------
|
|
self.submodules.crg = _CRG(platform, sys_clk_freq)
|
|
|
|
# DDR3 SDRAM -------------------------------------------------------------------------------
|
|
if not self.integrated_main_ram_size:
|
|
self.submodules.ddrphy = ECP5DDRPHY(
|
|
platform.request("ddram"),
|
|
sys_clk_freq=sys_clk_freq)
|
|
self.add_csr("ddrphy")
|
|
self.comb += self.crg.stop.eq(self.ddrphy.init.stop)
|
|
self.comb += self.crg.reset.eq(self.ddrphy.init.reset)
|
|
self.add_sdram("sdram",
|
|
phy = self.ddrphy,
|
|
module = MT41K64M16(sys_clk_freq, "1:2"),
|
|
origin = self.mem_map["main_ram"],
|
|
size = kwargs.get("max_sdram_size", 0x40000000),
|
|
l2_cache_size = kwargs.get("l2_size", 8192),
|
|
l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128),
|
|
l2_cache_reverse = True
|
|
)
|
|
|
|
# Ethernet / Etherbone ---------------------------------------------------------------------
|
|
if with_ethernet or with_etherbone:
|
|
self.submodules.ethphy = LiteEthPHYRGMII(
|
|
clock_pads = self.platform.request("eth_clocks", eth_phy),
|
|
pads = self.platform.request("eth", eth_phy))
|
|
self.add_csr("ethphy")
|
|
if with_ethernet:
|
|
self.add_ethernet(phy=self.ethphy)
|
|
if with_etherbone:
|
|
self.add_etherbone(phy=self.ethphy, ip_address=eth_ip)
|
|
|
|
# Leds -------------------------------------------------------------------------------------
|
|
self.submodules.leds = LedChaser(
|
|
pads = platform.request_all("user_led"),
|
|
sys_clk_freq = sys_clk_freq)
|
|
self.add_csr("leds")
|
|
|
|
# Build --------------------------------------------------------------------------------------------
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="LiteX SoC on Versa ECP5")
|
|
parser.add_argument("--build", action="store_true", help="Build bitstream")
|
|
parser.add_argument("--load", action="store_true", help="Load bitstream")
|
|
parser.add_argument("--toolchain", default="trellis", help="FPGA toolchain: trellis (default) or diamond")
|
|
parser.add_argument("--sys-clk-freq", default=75e6, help="System clock frequency (default: 75MHz)")
|
|
parser.add_argument("--device", default="LFE5UM5G", help="FPGA device (LFE5UM5G (default) or LFE5UM)")
|
|
ethopts = parser.add_mutually_exclusive_group()
|
|
ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support")
|
|
ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support")
|
|
parser.add_argument("--eth-ip", default="192.168.1.50", type=str, help="Ethernet/Etherbone IP address")
|
|
parser.add_argument("--eth-phy", default=0, type=int, help="Ethernet PHY: 0 (default) or 1")
|
|
builder_args(parser)
|
|
soc_sdram_args(parser)
|
|
trellis_args(parser)
|
|
args = parser.parse_args()
|
|
|
|
soc = BaseSoC(
|
|
sys_clk_freq = int(float(args.sys_clk_freq)),
|
|
device = args.device,
|
|
with_ethernet = args.with_ethernet,
|
|
with_etherbone = args.with_etherbone,
|
|
eth_ip = args.eth_ip,
|
|
eth_phy = args.eth_phy,
|
|
toolchain = args.toolchain,
|
|
**soc_sdram_argdict(args)
|
|
)
|
|
builder = Builder(soc, **builder_argdict(args))
|
|
builder_kargs = trellis_argdict(args) if args.toolchain == "trellis" else {}
|
|
builder.build(**builder_kargs, run=args.build)
|
|
|
|
if args.load:
|
|
prog = soc.platform.create_programmer()
|
|
prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".svf"))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|