Merge pull request #245 from racerxdl/feat/MuselabIceSugarPro

muselab_icesugar_pro: initial support
This commit is contained in:
enjoy-digital 2021-07-23 14:34:57 +02:00 committed by GitHub
commit 4d20cfe5cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 304 additions and 0 deletions

View File

@ -0,0 +1,126 @@
#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2021 Lucas Teske <lucas@teske.com.br>
# 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)

View File

@ -0,0 +1,178 @@
#!/usr/bin/env python3
#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2021 Lucas Teske <lucas@teske.com.br>
# 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()