3 # This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
4 # This file is Copyright (c) 2018 David Shah <dave@ds0.me>
12 from migen
.genlib
.resetsync
import AsyncResetSynchronizer
14 from litex
.build
.io
import DDROutput
16 from litex
.boards
.platforms
import ulx3s
18 from litex
.build
.lattice
.trellis
import trellis_args
, trellis_argdict
20 from litex
.soc
.cores
.clock
import *
21 from litex
.soc
.integration
.soc_core
import *
22 from litex
.soc
.integration
.soc_sdram
import *
23 from litex
.soc
.integration
.builder
import *
24 from litex
.soc
.cores
.led
import LedChaser
26 from litedram
import modules
as litedram_modules
27 from litedram
.phy
import GENSDRPHY
, HalfRateGENSDRPHY
29 # CRG ----------------------------------------------------------------------------------------------
32 def __init__(self
, platform
, sys_clk_freq
, with_usb_pll
=False, sdram_rate
="1:1"):
33 self
.clock_domains
.cd_sys
= ClockDomain()
34 if sdram_rate
== "1:2":
35 self
.clock_domains
.cd_sys2x
= ClockDomain()
36 self
.clock_domains
.cd_sys2x_ps
= ClockDomain(reset_less
=True)
38 self
.clock_domains
.cd_sys_ps
= ClockDomain(reset_less
=True)
43 clk25
= platform
.request("clk25")
44 rst
= platform
.request("rst")
47 self
.submodules
.pll
= pll
= ECP5PLL()
48 self
.comb
+= pll
.reset
.eq(rst
)
49 pll
.register_clkin(clk25
, 25e6
)
50 pll
.create_clkout(self
.cd_sys
, sys_clk_freq
)
51 if sdram_rate
== "1:2":
52 pll
.create_clkout(self
.cd_sys2x
, 2*sys_clk_freq
)
53 pll
.create_clkout(self
.cd_sys2x_ps
, 2*sys_clk_freq
, phase
=90)
55 pll
.create_clkout(self
.cd_sys_ps
, sys_clk_freq
, phase
=90)
56 self
.specials
+= AsyncResetSynchronizer(self
.cd_sys
, ~pll
.locked | rst
)
60 self
.submodules
.usb_pll
= usb_pll
= ECP5PLL()
61 usb_pll
.register_clkin(clk25
, 25e6
)
62 self
.clock_domains
.cd_usb_12
= ClockDomain()
63 self
.clock_domains
.cd_usb_48
= ClockDomain()
64 usb_pll
.create_clkout(self
.cd_usb_12
, 12e6
, margin
=0)
65 usb_pll
.create_clkout(self
.cd_usb_48
, 48e6
, margin
=0)
68 sdram_clk
= ClockSignal("sys2x_ps" if sdram_rate
== "1:2" else "sys_ps")
69 self
.specials
+= DDROutput(1, 0, platform
.request("sdram_clock"), sdram_clk
)
71 # Prevent ESP32 from resetting FPGA
72 self
.comb
+= platform
.request("wifi_gpio0").eq(1)
74 # BaseSoC ------------------------------------------------------------------------------------------
76 class BaseSoC(SoCCore
):
77 def __init__(self
, device
="LFE5U-45F", toolchain
="trellis",
78 sys_clk_freq
=int(50e6
), sdram_module_cls
="MT48LC16M16", sdram_rate
="1:1", **kwargs
):
80 platform
= ulx3s
.Platform(device
=device
, toolchain
=toolchain
)
82 # SoCCore ----------------------------------------------------------------------------------
83 SoCCore
.__init
__(self
, platform
, sys_clk_freq
,
84 ident
= "LiteX SoC on ULX3S",
88 # CRG --------------------------------------------------------------------------------------
89 with_usb_pll
= kwargs
.get("uart_name", None) == "usb_acm"
90 self
.submodules
.crg
= _CRG(platform
, sys_clk_freq
, with_usb_pll
, sdram_rate
=sdram_rate
)
92 # SDR SDRAM --------------------------------------------------------------------------------
93 if not self
.integrated_main_ram_size
:
94 sdrphy_cls
= HalfRateGENSDRPHY
if sdram_rate
== "1:2" else GENSDRPHY
95 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
96 self
.add_sdram("sdram",
98 module
= getattr(litedram_modules
, sdram_module_cls
)(sys_clk_freq
, sdram_rate
),
99 origin
= self
.mem_map
["main_ram"],
100 size
= kwargs
.get("max_sdram_size", 0x40000000),
101 l2_cache_size
= kwargs
.get("l2_size", 8192),
102 l2_cache_min_data_width
= kwargs
.get("min_l2_data_width", 128),
103 l2_cache_reverse
= True
106 # Leds -------------------------------------------------------------------------------------
107 self
.submodules
.leds
= LedChaser(
108 pads
= platform
.request_all("user_led"),
109 sys_clk_freq
= sys_clk_freq
)
112 # Build --------------------------------------------------------------------------------------------
115 parser
= argparse
.ArgumentParser(description
="LiteX SoC on ULX3S")
116 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
117 parser
.add_argument("--load", action
="store_true", help="Load bitstream")
118 parser
.add_argument("--toolchain", default
="trellis", help="Gateware toolchain to use, trellis (default) or diamond")
119 parser
.add_argument("--device", dest
="device", default
="LFE5U-45F", help="FPGA device, ULX3S can be populated with LFE5U-45F (default) or LFE5U-85F")
120 parser
.add_argument("--sys-clk-freq", default
=50e6
, help="System clock frequency (default=50MHz)")
121 parser
.add_argument("--sdram-module", default
="MT48LC16M16", help="SDRAM module: MT48LC16M16, AS4C32M16 or AS4C16M16 (default=MT48LC16M16)")
122 parser
.add_argument("--with-spi-sdcard", action
="store_true", help="Enable SPI-mode SDCard support")
123 parser
.add_argument("--with-sdcard", action
="store_true", help="Enable SDCard support")
124 parser
.add_argument("--sdram-rate", default
="1:1", help="SDRAM Rate 1:1 Full Rate (default), 1:2 Half Rate")
126 soc_sdram_args(parser
)
128 args
= parser
.parse_args()
130 soc
= BaseSoC(device
=args
.device
, toolchain
=args
.toolchain
,
131 sys_clk_freq
= int(float(args
.sys_clk_freq
)),
132 sdram_module_cls
= args
.sdram_module
,
133 sdram_rate
= args
.sdram_rate
,
134 **soc_sdram_argdict(args
))
135 assert not (args
.with_spi_sdcard
and args
.with_sdcard
)
136 if args
.with_spi_sdcard
:
140 builder
= Builder(soc
, **builder_argdict(args
))
141 builder_kargs
= trellis_argdict(args
) if args
.toolchain
== "trellis" else {}
142 builder
.build(**builder_kargs
, run
=args
.build
)
145 prog
= soc
.platform
.create_programmer()
146 prog
.load_bitstream(os
.path
.join(builder
.gateware_dir
, soc
.build_name
+ ".svf"))
148 if __name__
== "__main__":