Add initial LimeSDR Mini V2 support (With SoC + USB3 (FT245PHYSynchronous)).
python3 -m litex_boards.targets.limesdr_mini_v2 --csr-csv=csr.csv --build --load litex_server --jtag --jtag-config=openocd_limesdr_mini_v2.cfg litex_term crossover __ _ __ _ __ / / (_) /____ | |/_/ / /__/ / __/ -_)> < /____/_/\__/\__/_/|_| Build your hardware, easily! (c) Copyright 2012-2022 Enjoy-Digital (c) Copyright 2007-2015 M-Labs BIOS built on May 3 2022 18:59:46 BIOS CRC passed (5f29afcc) LiteX git sha1: a4cc859d --=============== SoC ==================-- CPU: VexRiscv @ 80MHz BUS: WISHBONE 32-bit @ 4GiB CSR: 32-bit data ROM: 128KiB SRAM: 8KiB --============== Boot ==================-- Booting from serial... Press Q or ESC to abort boot completely. sL5DdSMmkekro Timeout No boot medium found --============= Console ================-- litex> ident Ident: LiteX SoC on LimeSDR-Mini-V2 2022-05-03 18:59:29
This commit is contained in:
parent
c93b4dc4dc
commit
0ce7f8354c
|
@ -152,6 +152,7 @@ Some of the suported boards, see yours? Give LiteX-Boards a try!
|
|||
├── lattice_machxo3
|
||||
├── lattice_versa_ecp5
|
||||
├── linsn_rv901t
|
||||
├── limesdr_mini_v2
|
||||
├── litex_acorn_baseboard
|
||||
├── logicbone
|
||||
├── marblemini
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
#
|
||||
# This file is part of LiteX-Boards.
|
||||
#
|
||||
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
from litex.build.generic_platform import *
|
||||
from litex.build.lattice import LatticePlatform
|
||||
from litex.build.lattice.programmer import OpenOCDJTAGProgrammer
|
||||
|
||||
# IOs ----------------------------------------------------------------------------------------------
|
||||
|
||||
_io = [
|
||||
# Clk.
|
||||
("clk40", 0, Pins("A9"), IOStandard("LVCMOS33")),
|
||||
|
||||
# Leds.
|
||||
("led_g_n", 0, Pins("R16"), IOStandard("LVCMOS33"), Misc("OPENDRAIN=ON")),
|
||||
("led_g_n", 1, Pins("M18"), IOStandard("LVCMOS33"), Misc("OPENDRAIN=ON")), # Shared with FPGA_GPIO4.
|
||||
("led_g_n", 2, Pins("T17"), IOStandard("LVCMOS33"), Misc("OPENDRAIN=ON")), # Shared with FPGA_GPIO6.
|
||||
("led_r_n", 0, Pins("V17"), IOStandard("LVCMOS33"), Misc("OPENDRAIN=ON")),
|
||||
("led_r_n", 1, Pins("R18"), IOStandard("LVCMOS33"), Misc("OPENDRAIN=ON")), # Shared with FPGA_GPIO5.
|
||||
("led_r_n", 2, Pins("R17"), IOStandard("LVCMOS33"), Misc("OPENDRAIN=ON")), # Shared with FPGA_GPIO7.
|
||||
|
||||
# Revision.
|
||||
("revision", 0,
|
||||
Subsignal("hardware", Pins("D4 M2 N4 J3")),
|
||||
Subsignal("bom", Pins("N1 M1 N2")),
|
||||
IOStandard("LVCMOS25")
|
||||
),
|
||||
|
||||
# GPIO.
|
||||
("gpio", 0, Pins("N15 N18 N16 N17 M18 R18 T17 R17"), IOStandard("LVCMOS33")),
|
||||
("egpio", 0, Pins("A10 A8"), IOStandard("LVCMOS33")),
|
||||
|
||||
# SPIFlash
|
||||
("spiflash", 0,
|
||||
Subsignal("cs_n", Pins("U17")),
|
||||
Subsignal("clk", Pins("U16")),
|
||||
Subsignal("miso", Pins("U18")),
|
||||
Subsignal("mosi", Pins("T18")),
|
||||
IOStandard("LVCMOS33"),
|
||||
),
|
||||
|
||||
# I2C.
|
||||
("i2c", 0,
|
||||
Subsignal("scl", Pins("C10"), Misc("OPENDRAIN=ON")),
|
||||
Subsignal("sda", Pins("B9"), Misc("OPENDRAIN=ON")),
|
||||
IOStandard("LVCMOS33"),
|
||||
),
|
||||
|
||||
# SPI.
|
||||
("spi", 0,
|
||||
# SPI.
|
||||
Subsignal("clk", Pins("M3")),
|
||||
Subsignal("lms_cs_n", Pins("N3")),
|
||||
Subsignal("dac_cs_n", Pins("L4")),
|
||||
Subsignal("mosi", Pins("L3")),
|
||||
Subsignal("miso", Pins("K3")),
|
||||
IOStandard("LVCMOS25"),
|
||||
),
|
||||
|
||||
# Temperature Sensor.
|
||||
("lms75_os", 0, Pins("K2"), IOStandard("LVCMOS25")),
|
||||
|
||||
# USB-FIFO.
|
||||
("usb_fifo_clk", 0, Pins("D17"), IOStandard("LVCMOS33")),
|
||||
("usb_fifo", 0,
|
||||
Subsignal("rst_n", Pins("M17")),
|
||||
Subsignal("data", Pins(
|
||||
"A13 B12 B15 C12 A16 A12 D18 B17",
|
||||
"F15 D16 D15 C13 H18 B13 J18 A15",
|
||||
"B18 C18 A17 K18 C15 L18 F18 C16",
|
||||
"G16 D13 G18 F16 C17 F17 K15 K17")),
|
||||
Subsignal("be", Pins("L15 J17 K16 H17")),
|
||||
Subsignal("rxf_n", Pins("H16")),
|
||||
Subsignal("txe_n", Pins("M16")),
|
||||
Subsignal("rd_n", Pins("H15")),
|
||||
Subsignal("wr_n", Pins("J16")),
|
||||
Subsignal("oe_n", Pins("L16")),
|
||||
IOStandard("LVCMOS33"),
|
||||
),
|
||||
|
||||
# RF-IC / LMS7002M.
|
||||
("lms7002m", 0,
|
||||
# Control.
|
||||
Subsignal("pwrdwn_n", Pins("C8")),
|
||||
Subsignal("rxen", Pins("D6")),
|
||||
Subsignal("txen", Pins("B7")),
|
||||
|
||||
# RX-Interface (LMS -> FPGA).
|
||||
Subsignal("diq1", Pins("J2 L1 K1 K4 G3 F4 J1 H1 G4 F2 G1 H2")),
|
||||
Subsignal("txnrx1", Pins("F1")),
|
||||
Subsignal("iqsel1", Pins("F3")),
|
||||
Subsignal("mclk1", Pins("H4")),
|
||||
Subsignal("fclk1", Pins("H3")),
|
||||
|
||||
# RX-Interface (FPGA -> LMS).
|
||||
Subsignal("diq2", Pins("A3 C2 A2 B4 C3 B2 D3 B1 A4 C1 C7 A6")),
|
||||
Subsignal("txnrx2", Pins("B6")),
|
||||
Subsignal("iqsel2", Pins("C4")),
|
||||
Subsignal("mclk2", Pins("D2")),
|
||||
Subsignal("fclk2", Pins("D1")),
|
||||
|
||||
# IOStandard/Slew Rate.
|
||||
IOStandard("LVCMOS25"),
|
||||
),
|
||||
]
|
||||
|
||||
# Platform -----------------------------------------------------------------------------------------
|
||||
|
||||
class Platform(LatticePlatform):
|
||||
default_clk_name = "clk40"
|
||||
default_clk_period = 1e9/40e6
|
||||
|
||||
def __init__(self, device="LFE5U", toolchain="trellis", **kwargs):
|
||||
assert device in ["LFE5U"]
|
||||
LatticePlatform.__init__(self, device + "-45F-8MG285C", _io, toolchain=toolchain, **kwargs)
|
||||
|
||||
def create_programmer(self):
|
||||
return OpenOCDJTAGProgrammer("openocd_limesdr_mini_v2.cfg")
|
||||
|
||||
def do_finalize(self, fragment):
|
||||
self.add_period_constraint(self.lookup_request("clk40", loose=True), 1e9/40e6)
|
|
@ -0,0 +1,10 @@
|
|||
interface ftdi
|
||||
ftdi_vid_pid 0x0403 0x6010
|
||||
ftdi_channel 0
|
||||
ftdi_layout_init 0xfff8 0xfffb
|
||||
reset_config none
|
||||
|
||||
adapter_khz 25000
|
||||
|
||||
set _CHIPNAME ecp5
|
||||
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41112043
|
|
@ -0,0 +1,165 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# This file is part of LiteX-Boards.
|
||||
#
|
||||
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
# Build/Use:
|
||||
# ./limesdr_mini_v2.py --csr-csv=csr.csv --build --load
|
||||
# litex_server --jtag --jtag-config=openocd_limesdr_mini_v2.cfg
|
||||
# litex_term crossover
|
||||
|
||||
from migen import *
|
||||
|
||||
from litex_boards.platforms import limesdr_mini_v2
|
||||
|
||||
from litex.build.lattice.trellis import trellis_args, trellis_argdict
|
||||
|
||||
from litex.soc.cores.clock import *
|
||||
from litex.soc.interconnect.csr import *
|
||||
from litex.soc.integration.soc_core import *
|
||||
from litex.soc.integration.builder import *
|
||||
from litex.soc.interconnect import stream
|
||||
|
||||
from litex.soc.cores.led import LedChaser
|
||||
from litex.soc.cores.bitbang import I2CMaster
|
||||
from litex.soc.cores.usb_fifo import FT245PHYSynchronous
|
||||
|
||||
from litescope import LiteScopeAnalyzer
|
||||
|
||||
# CRG ----------------------------------------------------------------------------------------------
|
||||
|
||||
class _CRG(Module):
|
||||
def __init__(self, platform, sys_clk_freq):
|
||||
self.rst = Signal()
|
||||
self.clock_domains.cd_sys = ClockDomain()
|
||||
self.clock_domains.cd_usb = ClockDomain()
|
||||
|
||||
# # #
|
||||
|
||||
# Clk.
|
||||
clk40 = platform.request("clk40")
|
||||
|
||||
# PLL.
|
||||
self.submodules.pll = pll = ECP5PLL()
|
||||
self.comb += pll.reset.eq(self.rst)
|
||||
pll.register_clkin(clk40, 40e6)
|
||||
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
||||
|
||||
# USB.
|
||||
self.comb += self.cd_usb.clk.eq(platform.request("usb_fifo_clk"))
|
||||
|
||||
# BoardInfo ----------------------------------------------------------------------------------------
|
||||
|
||||
class BoardInfo(Module, AutoCSR):
|
||||
def __init__(self, revision_pads):
|
||||
self.revision = CSRStorage(fields=[
|
||||
CSRField("hardware", size=4, description="Hardware Revision."),
|
||||
CSRField("bom", size=4, description="Bill of Material Revision."),
|
||||
])
|
||||
|
||||
# # #
|
||||
|
||||
self.comb += self.revision.fields.hardware.eq(revision_pads.hardware)
|
||||
self.comb += self.revision.fields.bom .eq(revision_pads.bom)
|
||||
|
||||
# BaseSoC ------------------------------------------------------------------------------------------
|
||||
|
||||
class BaseSoC(SoCCore):
|
||||
def __init__(self, sys_clk_freq=int(80e6), toolchain="trellis",
|
||||
with_usb_fifo = True, with_usb_fifo_loopback=False,
|
||||
with_led_chaser = True,
|
||||
**kwargs):
|
||||
platform = limesdr_mini_v2.Platform(toolchain=toolchain)
|
||||
|
||||
# SoCCore ----------------------------------------------------------------------------------
|
||||
kwargs["uart_name"] = "crossover"
|
||||
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on LimeSDR-Mini-V2", **kwargs)
|
||||
|
||||
# JTAGBone ---------------------------------------------------------------------------------
|
||||
self.add_jtagbone()
|
||||
|
||||
# CRG --------------------------------------------------------------------------------------
|
||||
self.submodules.crg = _CRG(platform, sys_clk_freq)
|
||||
|
||||
# Info -------------------------------------------------------------------------------------
|
||||
self.submodules.info = BoardInfo(platform.request("revision"))
|
||||
|
||||
# I2C Bus ----------------------------------------------------------------------------------
|
||||
# - Temperature Sensor (LM72 @ 0x48).
|
||||
# - Eeprom (M24128 @ 0x50) / Not populated.
|
||||
self.submodules.i2c = I2CMaster(platform.request("i2c"))
|
||||
|
||||
# USB-FIFO ---------------------------------------------------------------------------------
|
||||
if with_usb_fifo:
|
||||
usb_pads = platform.request("usb_fifo")
|
||||
self.submodules.usb_phy = usb_phy = FT245PHYSynchronous(
|
||||
pads = usb_pads,
|
||||
clk_freq = sys_clk_freq,
|
||||
fifo_depth = 8,
|
||||
read_time = 128,
|
||||
write_time = 128,
|
||||
)
|
||||
if with_usb_fifo_loopback:
|
||||
usb_loopback = stream.SyncFIFO([("data", 32)], 2048, buffered=True)
|
||||
self.submodules += usb_loopback
|
||||
self.comb += [
|
||||
usb_phy.source.connect(usb_loopback.sink),
|
||||
usb_loopback.source.connect(usb_phy.sink),
|
||||
]
|
||||
else:
|
||||
self.comb += usb_phy.source.ready.eq(1) # Accept incoming stream to validate Host -> FPGA.
|
||||
|
||||
analyzer_probes = usb_phy.get_litescope_probes()
|
||||
self.submodules.analyzer = LiteScopeAnalyzer(analyzer_probes,
|
||||
depth = 512,
|
||||
clock_domain = "usb",
|
||||
samplerate = sys_clk_freq,
|
||||
csr_csv = "analyzer.csv"
|
||||
)
|
||||
|
||||
# Debug -------------------------------------------------------------------------------
|
||||
egpio_pads = platform.request("egpio")
|
||||
self.comb += egpio_pads[0].eq(ClockSignal("sys"))
|
||||
self.comb += egpio_pads[1].eq(ClockSignal("usb"))
|
||||
|
||||
# Leds -------------------------------------------------------------------------------------
|
||||
if with_led_chaser:
|
||||
leds_g = Signal(4)
|
||||
leds_r = Signal(4)
|
||||
self.comb += platform.request_all("led_g_n").eq(~leds_g)
|
||||
self.comb += platform.request_all("led_r_n").eq(~leds_r)
|
||||
self.submodules.leds = LedChaser(Cat(leds_g, leds_r), sys_clk_freq)
|
||||
|
||||
# Build --------------------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
from litex.soc.integration.soc import LiteXSoCArgumentParser
|
||||
parser = LiteXSoCArgumentParser(description="LiteX SoC on LimeSDR-Mini-V2")
|
||||
target_group = parser.add_argument_group(title="Target options")
|
||||
target_group.add_argument("--build", action="store_true", help="Build bitstream.")
|
||||
target_group.add_argument("--load", action="store_true", help="Load bitstream.")
|
||||
target_group.add_argument("--toolchain", default="trellis", help="FPGA toolchain (trellis or diamond).")
|
||||
target_group.add_argument("--sys-clk-freq", default=80e6, help="System clock frequency.")
|
||||
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)),
|
||||
toolchain = args.toolchain,
|
||||
**soc_core_argdict(args)
|
||||
)
|
||||
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(builder.get_bitstream_filename(mode="sram", ext=".svf")) # FIXME
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue