mirror of
https://github.com/litex-hub/litex-boards.git
synced 2025-01-03 03:43:36 -05:00
e980798437
This is useful in some case where were button input is force through hardware change to force DFU to be in reset at startup.
231 lines
9.2 KiB
Python
Executable file
231 lines
9.2 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
|
|
|
|
from migen import *
|
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
|
|
from litex.gen import *
|
|
from litex.gen.genlib.misc import WaitTimer
|
|
|
|
from litex_boards.platforms import gsd_orangecrab
|
|
|
|
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(LiteXModule):
|
|
def __init__(self, platform, sys_clk_freq, with_usb_pll=False, with_dfu_rst=True):
|
|
self.rst = Signal()
|
|
self.cd_por = ClockDomain()
|
|
self.cd_sys = ClockDomain()
|
|
|
|
# # #
|
|
|
|
# Clk / Rst
|
|
clk48 = platform.request("clk48")
|
|
rst_n = platform.request("usr_btn", loose=True)
|
|
if (rst_n is None) or (not with_dfu_rst): 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.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.cd_usb_12 = ClockDomain()
|
|
self.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)
|
|
if with_dfu_rst:
|
|
reset_timer = WaitTimer(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(LiteXModule):
|
|
def __init__(self, platform, sys_clk_freq, with_usb_pll=False, with_dfu_rst=True):
|
|
self.rst = Signal()
|
|
self.cd_init = ClockDomain()
|
|
self.cd_por = ClockDomain()
|
|
self.cd_sys = ClockDomain()
|
|
self.cd_sys2x = ClockDomain()
|
|
self.cd_sys2x_i = ClockDomain()
|
|
|
|
# # #
|
|
|
|
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) or (not with_dfu_rst): 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.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),
|
|
]
|
|
|
|
# USB PLL
|
|
if with_usb_pll:
|
|
self.cd_usb_12 = ClockDomain()
|
|
self.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)
|
|
if with_dfu_rst:
|
|
reset_timer = WaitTimer(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", sys_clk_freq=48e6, toolchain="trellis",
|
|
sdram_device = "MT41K64M16",
|
|
with_dfu_rst = True,
|
|
with_led_chaser = True,
|
|
**kwargs):
|
|
platform = gsd_orangecrab.Platform(revision=revision, device=device ,toolchain=toolchain)
|
|
|
|
# CRG --------------------------------------------------------------------------------------
|
|
crg_cls = _CRGSDRAM if kwargs.get("integrated_main_ram_size", 0) == 0 else _CRG
|
|
self.crg = crg_cls(platform, sys_clk_freq, with_usb_pll=True, with_dfu_rst=with_dfu_rst)
|
|
|
|
# SoCCore ----------------------------------------------------------------------------------
|
|
# Defaults to USB ACM through ValentyUSB.
|
|
kwargs["uart_name"] = "usb_acm"
|
|
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on OrangeCrab", **kwargs)
|
|
|
|
# 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.ddrphy = ECP5DDRPHY(
|
|
pads = ddram_pads,
|
|
sys_clk_freq = sys_clk_freq,
|
|
dm_remapping = {0:1, 1:0},
|
|
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"),
|
|
l2_cache_size = kwargs.get("l2_size", 8192)
|
|
)
|
|
|
|
# Leds -------------------------------------------------------------------------------------
|
|
if with_led_chaser:
|
|
self.leds = LedChaser(
|
|
pads = platform.request_all("user_led"),
|
|
sys_clk_freq = sys_clk_freq)
|
|
|
|
# Build --------------------------------------------------------------------------------------------
|
|
|
|
def main():
|
|
from litex.build.parser import LiteXArgumentParser
|
|
parser = LiteXArgumentParser(platform=gsd_orangecrab.Platform, description="LiteX SoC on OrangeCrab.")
|
|
parser.add_target_argument("--sys-clk-freq", default=48e6, type=float, help="System clock frequency.")
|
|
parser.add_target_argument("--revision", default="0.2", help="Board Revision (0.1 or 0.2).")
|
|
parser.add_target_argument("--device", default="25F", help="ECP5 device (25F, 45F or 85F).")
|
|
parser.add_target_argument("--sdram-device", default="MT41K64M16", help="SDRAM device (MT41K64M16, MT41K128M16, MT41K256M16 or MT41K512M16).")
|
|
parser.add_target_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.")
|
|
parser.add_target_argument("--without-dfu-rst", action="store_true", help="Disable DFU Reset when pressing Button for 1s.")
|
|
args = parser.parse_args()
|
|
|
|
soc = BaseSoC(
|
|
toolchain = args.toolchain,
|
|
revision = args.revision,
|
|
device = args.device,
|
|
sdram_device = args.sdram_device,
|
|
sys_clk_freq = args.sys_clk_freq,
|
|
with_dfu_rst = not args.without_dfu_rst,
|
|
**parser.soc_argdict)
|
|
if args.with_spi_sdcard:
|
|
soc.add_spi_sdcard()
|
|
builder = Builder(soc, **parser.builder_argdict)
|
|
if args.build:
|
|
builder.build(**parser.toolchain_argdict)
|
|
|
|
if args.load:
|
|
prog = soc.platform.create_programmer()
|
|
prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|