mirror of
https://github.com/litex-hub/litex-boards.git
synced 2025-01-03 03:43:36 -05:00
ba01776432
- main_ram mem_map is now directly used by add_sdram when origin is None. - max_sdram_size/min_l2_data_width are no longer exposed as targets arguments this can still be used enforced directly in the few cases it is useful.
240 lines
9.8 KiB
Python
Executable file
240 lines
9.8 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
#
|
|
# This file is part of LiteX-Boards.
|
|
#
|
|
# Copyright (c) Greg Davill <greg.davill@gmail.com>
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
import os
|
|
import sys
|
|
import argparse
|
|
|
|
from migen import *
|
|
from migen.genlib.misc import WaitTimer
|
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
|
|
from litex_boards.platforms import orangecrab
|
|
|
|
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.builder import *
|
|
from litex.soc.cores.led import LedChaser
|
|
|
|
from litedram.modules import MT41K64M16, MT41K128M16, MT41K256M16, MT41K512M16
|
|
from litedram.phy import ECP5DDRPHY
|
|
|
|
# CRG ---------------------------------------------------------------------------------------------
|
|
|
|
class _CRG(Module):
|
|
def __init__(self, platform, sys_clk_freq, with_usb_pll=False):
|
|
self.rst = Signal()
|
|
self.clock_domains.cd_por = ClockDomain(reset_less=True)
|
|
self.clock_domains.cd_sys = ClockDomain()
|
|
|
|
# # #
|
|
|
|
# Clk / Rst
|
|
clk48 = platform.request("clk48")
|
|
rst_n = platform.request("usr_btn", loose=True)
|
|
if rst_n is None: rst_n = 1
|
|
|
|
# Power on reset
|
|
por_count = Signal(16, reset=2**16-1)
|
|
por_done = Signal()
|
|
self.comb += self.cd_por.clk.eq(clk48)
|
|
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(clk48, 48e6)
|
|
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
|
|
|
# USB PLL
|
|
if with_usb_pll:
|
|
self.clock_domains.cd_usb_12 = ClockDomain()
|
|
self.clock_domains.cd_usb_48 = ClockDomain()
|
|
usb_pll = ECP5PLL()
|
|
self.submodules += usb_pll
|
|
self.comb += usb_pll.reset.eq(~por_done)
|
|
usb_pll.register_clkin(clk48, 48e6)
|
|
usb_pll.create_clkout(self.cd_usb_48, 48e6)
|
|
usb_pll.create_clkout(self.cd_usb_12, 12e6)
|
|
|
|
# FPGA Reset (press usr_btn for 1 second to fallback to bootloader)
|
|
reset_timer = WaitTimer(int(48e6))
|
|
reset_timer = ClockDomainsRenamer("por")(reset_timer)
|
|
self.submodules += reset_timer
|
|
self.comb += reset_timer.wait.eq(~rst_n)
|
|
self.comb += platform.request("rst_n").eq(~reset_timer.done)
|
|
|
|
|
|
class _CRGSDRAM(Module):
|
|
def __init__(self, platform, sys_clk_freq, with_usb_pll=False):
|
|
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
|
|
clk48 = platform.request("clk48")
|
|
rst_n = platform.request("usr_btn", loose=True)
|
|
if rst_n is None: rst_n = 1
|
|
|
|
# Power on reset
|
|
por_count = Signal(16, reset=2**16-1)
|
|
por_done = Signal()
|
|
self.comb += self.cd_por.clk.eq(clk48)
|
|
self.comb += por_done.eq(por_count == 0)
|
|
self.sync.por += If(~por_done, por_count.eq(por_count - 1))
|
|
|
|
# PLL
|
|
sys2x_clk_ecsout = Signal()
|
|
self.submodules.pll = pll = ECP5PLL()
|
|
self.comb += pll.reset.eq(~por_done | ~rst_n | self.rst)
|
|
pll.register_clkin(clk48, 48e6)
|
|
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
|
|
pll.create_clkout(self.cd_init, 24e6)
|
|
self.specials += [
|
|
Instance("ECLKBRIDGECS",
|
|
i_CLK0 = self.cd_sys2x_i.clk,
|
|
i_SEL = 0,
|
|
o_ECSOUT = sys2x_clk_ecsout),
|
|
Instance("ECLKSYNCB",
|
|
i_ECLKI = sys2x_clk_ecsout,
|
|
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),
|
|
]
|
|
|
|
# USB PLL
|
|
if with_usb_pll:
|
|
self.clock_domains.cd_usb_12 = ClockDomain()
|
|
self.clock_domains.cd_usb_48 = ClockDomain()
|
|
usb_pll = ECP5PLL()
|
|
self.submodules += usb_pll
|
|
self.comb += usb_pll.reset.eq(~por_done)
|
|
usb_pll.register_clkin(clk48, 48e6)
|
|
usb_pll.create_clkout(self.cd_usb_48, 48e6)
|
|
usb_pll.create_clkout(self.cd_usb_12, 12e6)
|
|
|
|
# FPGA Reset (press usr_btn for 1 second to fallback to bootloader)
|
|
reset_timer = WaitTimer(int(48e6))
|
|
reset_timer = ClockDomainsRenamer("por")(reset_timer)
|
|
self.submodules += reset_timer
|
|
self.comb += reset_timer.wait.eq(~rst_n)
|
|
self.comb += platform.request("rst_n").eq(~reset_timer.done)
|
|
|
|
# BaseSoC ------------------------------------------------------------------------------------------
|
|
|
|
class BaseSoC(SoCCore):
|
|
def __init__(self, revision="0.2", device="25F", sdram_device="MT41K64M16",
|
|
sys_clk_freq=int(48e6), toolchain="trellis", **kwargs):
|
|
platform = orangecrab.Platform(revision=revision, device=device ,toolchain=toolchain)
|
|
|
|
# Serial -----------------------------------------------------------------------------------
|
|
if kwargs["uart_name"] in ["serial", "usb_acm"]:
|
|
kwargs["uart_name"] = "usb_acm"
|
|
# Defaults to USB ACM through ValentyUSB.
|
|
os.system("git clone https://github.com/litex-hub/valentyusb -b hw_cdc_eptri")
|
|
sys.path.append("valentyusb")
|
|
|
|
# SoCCore ----------------------------------------------------------------------------------
|
|
SoCCore.__init__(self, platform, sys_clk_freq,
|
|
ident = "LiteX SoC on OrangeCrab",
|
|
ident_version = True,
|
|
**kwargs)
|
|
|
|
# CRG --------------------------------------------------------------------------------------
|
|
with_usb_pll = kwargs.get("uart_name", None) == "usb_acm"
|
|
crg_cls = _CRGSDRAM if not self.integrated_main_ram_size else _CRG
|
|
self.submodules.crg = crg_cls(platform, sys_clk_freq, with_usb_pll)
|
|
|
|
# DDR3 SDRAM -------------------------------------------------------------------------------
|
|
if not self.integrated_main_ram_size:
|
|
available_sdram_modules = {
|
|
"MT41K64M16": MT41K64M16,
|
|
"MT41K128M16": MT41K128M16,
|
|
"MT41K256M16": MT41K256M16,
|
|
"MT41K512M16": MT41K512M16,
|
|
}
|
|
sdram_module = available_sdram_modules.get(sdram_device)
|
|
|
|
ddram_pads = platform.request("ddram")
|
|
self.submodules.ddrphy = ECP5DDRPHY(
|
|
pads = ddram_pads,
|
|
sys_clk_freq = sys_clk_freq,
|
|
cmd_delay = 0 if sys_clk_freq > 64e6 else 100)
|
|
self.ddrphy.settings.rtt_nom = "disabled"
|
|
if hasattr(ddram_pads, "vccio"):
|
|
self.comb += ddram_pads.vccio.eq(0b111111)
|
|
if hasattr(ddram_pads, "gnd"):
|
|
self.comb += ddram_pads.gnd.eq(0)
|
|
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 = sdram_module(sys_clk_freq, "1:2"),
|
|
size = 0x40000000,
|
|
l2_cache_size = kwargs.get("l2_size", 8192)
|
|
)
|
|
|
|
# Leds -------------------------------------------------------------------------------------
|
|
self.submodules.leds = LedChaser(
|
|
pads = platform.request_all("user_led"),
|
|
sys_clk_freq = sys_clk_freq)
|
|
|
|
# Build --------------------------------------------------------------------------------------------
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="LiteX SoC on OrangeCrab")
|
|
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 use, trellis (default) or diamond")
|
|
parser.add_argument("--sys-clk-freq", default=48e6, help="System clock frequency (default: 48MHz)")
|
|
parser.add_argument("--revision", default="0.2", help="Board Revision: 0.1 or 0.2 (default)")
|
|
parser.add_argument("--device", default="25F", help="ECP5 device (default: 25F)")
|
|
parser.add_argument("--sdram-device", default="MT41K64M16", help="SDRAM device (default: MT41K64M16)")
|
|
parser.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support")
|
|
builder_args(parser)
|
|
soc_core_args(parser)
|
|
trellis_args(parser)
|
|
args = parser.parse_args()
|
|
|
|
soc = BaseSoC(
|
|
toolchain = args.toolchain,
|
|
revision = args.revision,
|
|
device = args.device,
|
|
sdram_device = args.sdram_device,
|
|
sys_clk_freq = int(float(args.sys_clk_freq)),
|
|
**soc_core_argdict(args))
|
|
if args.with_spi_sdcard:
|
|
soc.add_spi_sdcard()
|
|
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 + ".bit"))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|