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:
Florent Kermarrec 2022-05-03 19:03:55 +02:00
parent c93b4dc4dc
commit 0ce7f8354c
4 changed files with 300 additions and 0 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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()