forked from litex-hub/litex-boards
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request litex-hub#245 from racerxdl/feat/MuselabIceSugarPro
muselab_icesugar_pro: initial support
- Loading branch information
Showing
2 changed files
with
304 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# | ||
# This file is part of LiteX-Boards. | ||
# | ||
# Copyright (c) 2021 Lucas Teske <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
# The Muselab IceSugar Pro PCB and IOs have been documented by @wuxx | ||
# https://github.com/wuxx/icesugar-pro | ||
|
||
from litex.build.generic_platform import * | ||
from litex.build.lattice import LatticePlatform | ||
from litex.build.lattice.programmer import EcpDapProgrammer | ||
|
||
# IOs ---------------------------------------------------------------------------------------------- | ||
|
||
_io = [ | ||
# Clk | ||
("clk25", 0, Pins("P6"), IOStandard("LVCMOS33")), | ||
|
||
# Led | ||
("user_led_n", 0, Pins("B11"), IOStandard("LVCMOS33")), # Red | ||
("user_led_n", 1, Pins("A11"), IOStandard("LVCMOS33")), # Green | ||
("user_led_n", 2, Pins("A12"), IOStandard("LVCMOS33")), # Blue | ||
|
||
("rgb_led", 0, | ||
Subsignal("r", Pins("B11")), | ||
Subsignal("g", Pins("A11")), | ||
Subsignal("b", Pins("A12")), | ||
IOStandard("LVCMOS33"), | ||
), | ||
|
||
# Reset button | ||
("cpu_reset_n", 0, Pins("L14"), IOStandard("LVCMOS33"), Misc("PULLMODE=UP")), | ||
|
||
# Serial | ||
("serial", 0, # iCELink | ||
Subsignal("tx", Pins("B9")), | ||
Subsignal("rx", Pins("A9")), | ||
IOStandard("LVCMOS33") | ||
), | ||
|
||
# SPIFlash (W25Q256JV (32MB)) | ||
("spiflash", 0, | ||
Subsignal("cs_n", Pins("N8")), | ||
# https://github.com/m-labs/nmigen-boards/pull/38 | ||
#Subsignal("clk", Pins("")), driven through USRMCLK | ||
Subsignal("mosi", Pins("T8")), | ||
Subsignal("miso", Pins("T7")), | ||
IOStandard("LVCMOS33"), | ||
), | ||
|
||
# SDRAM (IS42S16160B (32MB)) | ||
("sdram_clock", 0, Pins("R15"), IOStandard("LVCMOS33")), | ||
("sdram", 0, | ||
Subsignal("a", Pins( | ||
"H15 B13 B12 J16 J15 R12 K16 R13", | ||
"T13 K15 A13 R14 T14")), | ||
Subsignal("dq", Pins( | ||
"F16 E15 F15 D14 E16 C15 D16 B15", | ||
"R16 P16 P15 N16 N14 M16 M15 L15")), | ||
Subsignal("we_n", Pins("A15")), | ||
Subsignal("ras_n", Pins("B16")), | ||
Subsignal("cas_n", Pins("G16")), | ||
Subsignal("cs_n", Pins("A14")), | ||
Subsignal("cke", Pins("L16")), | ||
Subsignal("ba", Pins("G15 B14")), | ||
Subsignal("dm", Pins("C16 T15")), | ||
IOStandard("LVCMOS33"), | ||
Misc("SLEWRATE=FAST") | ||
), | ||
|
||
# SDCard | ||
("spisdcard", 0, | ||
Subsignal("clk", Pins("J12")), | ||
Subsignal("mosi", Pins("H12"), Misc("PULLMODE=UP")), | ||
Subsignal("cs_n", Pins("G12"), Misc("PULLMODE=UP")), | ||
Subsignal("miso", Pins("K12"), Misc("PULLMODE=UP")), | ||
Misc("SLEWRATE=FAST"), | ||
IOStandard("LVCMOS33"), | ||
), | ||
("sdcard", 0, | ||
Subsignal("clk", Pins("J12")), | ||
Subsignal("cmd", Pins("H12"), Misc("PULLMODE=UP")), | ||
Subsignal("data", Pins("K12 L12 F12 G12"), Misc("PULLMODE=UP")), | ||
Misc("SLEWRATE=FAST"), | ||
IOStandard("LVCMOS33") | ||
), | ||
|
||
# GPDI | ||
("gpdi", 0, | ||
Subsignal("clk_p", Pins("E2"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
# Subsignal("clk_n", Pins("D3"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
Subsignal("data0_p", Pins("G1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
# Subsignal("data0_n", Pins("F1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
Subsignal("data1_p", Pins("J1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
# Subsignal("data1_n", Pins("H2"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
Subsignal("data2_p", Pins("L1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
# Subsignal("data2_n", Pins("K2"), IOStandard("LVCMOS33"), Misc("DRIVE=4")), | ||
), | ||
] | ||
|
||
# from colorlight_i5.py adapted to icesugar pro | ||
# https://github.com/wuxx/icesugar-pro/blob/master/doc/iCESugar-pro-pinmap.png | ||
_connectors = [ | ||
("pmode", "N3 M2 L2 G2 P1 N1 M1 K1"), | ||
("pmodf", "T6 R5 R4 R3 P7 R6 T4 T3"), | ||
] | ||
|
||
# Platform ----------------------------------------------------------------------------------------- | ||
|
||
class Platform(LatticePlatform): | ||
default_clk_name = "clk25" | ||
default_clk_period = 1e9/25e6 | ||
|
||
def __init__(self, toolchain="trellis"): | ||
device = "LFE5U-25F-6BG256C" | ||
io = _io | ||
connectors = _connectors | ||
LatticePlatform.__init__(self, device, io, connectors=connectors, toolchain=toolchain) | ||
|
||
def create_programmer(self): | ||
return EcpDapProgrammer() | ||
|
||
def do_finalize(self, fragment): | ||
LatticePlatform.do_finalize(self, fragment) | ||
self.add_period_constraint(self.lookup_request("clk25", loose=True), 1e9/25e6) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# | ||
# This file is part of LiteX-Boards. | ||
# | ||
# Copyright (c) 2021 Lucas Teske <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import os | ||
import argparse | ||
import sys | ||
|
||
from migen import * | ||
|
||
from litex.build.io import DDROutput | ||
|
||
from litex_boards.platforms import muselab_icesugar_pro | ||
|
||
from litex.build.lattice.trellis import trellis_args, trellis_argdict | ||
|
||
from litex.soc.cores.clock import * | ||
from litex.soc.cores.spi_flash import SpiFlash | ||
from litex.soc.integration.soc_core import * | ||
from litex.soc.integration.builder import * | ||
from litex.soc.cores.video import VideoECP5HDMIPHY | ||
from litex.soc.cores.led import LedChaser | ||
|
||
from litex.soc.interconnect.csr import * | ||
|
||
from litedram.modules import IS42S16160 | ||
from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY | ||
|
||
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII | ||
|
||
# CRG ---------------------------------------------------------------------------------------------- | ||
|
||
class _CRG(Module): | ||
def __init__(self, platform, sys_clk_freq, use_internal_osc=False, with_video_pll=False, sdram_rate="1:1"): | ||
self.rst = Signal() | ||
self.clock_domains.cd_sys = ClockDomain() | ||
if sdram_rate == "1:2": | ||
self.clock_domains.cd_sys2x = ClockDomain() | ||
self.clock_domains.cd_sys2x_ps = ClockDomain(reset_less=True) | ||
else: | ||
self.clock_domains.cd_sys_ps = ClockDomain(reset_less=True) | ||
|
||
# # # | ||
|
||
# Clk / Rst | ||
if not use_internal_osc: | ||
clk = platform.request("clk25") | ||
clk_freq = 25e6 | ||
else: | ||
clk = Signal() | ||
div = 5 | ||
self.specials += Instance("OSCG", | ||
p_DIV = div, | ||
o_OSC = clk) | ||
clk_freq = 310e6/div | ||
|
||
rst_n = platform.request("cpu_reset_n") | ||
|
||
# PLL | ||
self.submodules.pll = pll = ECP5PLL() | ||
self.comb += pll.reset.eq(~rst_n | self.rst) | ||
pll.register_clkin(clk, clk_freq) | ||
pll.create_clkout(self.cd_sys, sys_clk_freq) | ||
if sdram_rate == "1:2": | ||
pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq) | ||
pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180) # Idealy 90° but needs to be increased. | ||
else: | ||
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=180) # Idealy 90° but needs to be increased. | ||
|
||
# Video PLL | ||
if with_video_pll: | ||
self.submodules.video_pll = video_pll = ECP5PLL() | ||
self.comb += video_pll.reset.eq(~rst_n | self.rst) | ||
video_pll.register_clkin(clk, clk_freq) | ||
self.clock_domains.cd_hdmi = ClockDomain() | ||
self.clock_domains.cd_hdmi5x = ClockDomain() | ||
video_pll.create_clkout(self.cd_hdmi, 40e6, margin=0) | ||
video_pll.create_clkout(self.cd_hdmi5x, 200e6, margin=0) | ||
|
||
# SDRAM clock | ||
sdram_clk = ClockSignal("sys2x_ps" if sdram_rate == "1:2" else "sys_ps") | ||
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk) | ||
|
||
# BaseSoC ------------------------------------------------------------------------------------------ | ||
|
||
class BaseSoC(SoCCore): | ||
mem_map = {**SoCCore.mem_map, **{"spiflash": 0xd0000000}} | ||
def __init__(self, sys_clk_freq=60e6, with_led_chaser=True, | ||
use_internal_osc=False, sdram_rate="1:1", with_video_terminal=False, | ||
with_video_framebuffer=False, **kwargs): | ||
platform = muselab_icesugar_pro.Platform() | ||
|
||
# SoCCore ---------------------------------------------------------------------------------- | ||
SoCCore.__init__(self, platform, int(sys_clk_freq), | ||
ident = "LiteX SoC on Muselab iCESugar Pro", | ||
ident_version = True, | ||
**kwargs) | ||
|
||
# CRG -------------------------------------------------------------------------------------- | ||
with_video_pll = with_video_terminal or with_video_framebuffer | ||
self.submodules.crg = _CRG(platform, sys_clk_freq, use_internal_osc=use_internal_osc, with_video_pll=with_video_pll, sdram_rate=sdram_rate) | ||
|
||
# Leds ------------------------------------------------------------------------------------- | ||
if with_led_chaser: | ||
ledn = platform.request_all("user_led_n") | ||
self.submodules.leds = LedChaser(pads=ledn, sys_clk_freq=sys_clk_freq) | ||
|
||
# SPI Flash -------------------------------------------------------------------------------- | ||
self.add_spi_flash(mode="1x", dummy_cycles=8) | ||
self.add_constant("SPIFLASH_PAGE_SIZE", 256) | ||
self.add_constant("SPIFLASH_SECTOR_SIZE", 4096) | ||
|
||
# SDR SDRAM -------------------------------------------------------------------------------- | ||
if not self.integrated_main_ram_size: | ||
sdrphy_cls = HalfRateGENSDRPHY if sdram_rate == "1:2" else GENSDRPHY | ||
self.submodules.sdrphy = sdrphy_cls(platform.request("sdram")) | ||
self.add_sdram("sdram", | ||
phy = self.sdrphy, | ||
module = IS42S16160(sys_clk_freq, sdram_rate), | ||
l2_cache_size = kwargs.get("l2_size", 8192) | ||
) | ||
|
||
# Video ------------------------------------------------------------------------------------ | ||
if with_video_terminal or with_video_framebuffer: | ||
self.submodules.videophy = VideoECP5HDMIPHY(platform.request("gpdi"), clock_domain="hdmi") | ||
if with_video_terminal: | ||
self.add_video_terminal(phy=self.videophy, timings="800x600@60Hz", clock_domain="hdmi") | ||
if with_video_framebuffer: | ||
self.add_video_framebuffer(phy=self.videophy, timings="800x600@60Hz", clock_domain="hdmi") | ||
|
||
# Build -------------------------------------------------------------------------------------------- | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description="LiteX SoC on Colorlight i5") | ||
parser.add_argument("--build", action="store_true", help="Build bitstream") | ||
parser.add_argument("--load", action="store_true", help="Load bitstream") | ||
parser.add_argument("--sys-clk-freq", default=60e6, help="System clock frequency (default: 60MHz)") | ||
sdopts = parser.add_mutually_exclusive_group() | ||
sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support") | ||
sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support") | ||
parser.add_argument("--use-internal-osc", action="store_true", help="Use internal oscillator") | ||
parser.add_argument("--sdram-rate", default="1:1", help="SDRAM Rate: 1:1 Full Rate (default), 1:2 Half Rate") | ||
viopts = parser.add_mutually_exclusive_group() | ||
viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (HDMI)") | ||
viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (HDMI)") | ||
builder_args(parser) | ||
soc_core_args(parser) | ||
trellis_args(parser) | ||
args = parser.parse_args() | ||
|
||
soc = BaseSoC( | ||
sys_clk_freq = int(float(args.sys_clk_freq)), | ||
use_internal_osc = args.use_internal_osc, | ||
sdram_rate = args.sdram_rate, | ||
l2_size = args.l2_size, | ||
with_video_terminal = args.with_video_terminal, | ||
with_video_framebuffer = args.with_video_framebuffer, | ||
**soc_core_argdict(args) | ||
) | ||
if args.with_spi_sdcard: | ||
soc.add_spi_sdcard() | ||
if args.with_sdcard: | ||
soc.add_sdcard() | ||
|
||
builder = Builder(soc, **builder_argdict(args)) | ||
|
||
builder.build(**trellis_argdict(args), 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() |