Add CrossLink-NX VIP board platform and target

This commit is contained in:
David Shah 2020-10-13 11:10:36 +01:00
parent 8e5b31646d
commit b278d8bccc
2 changed files with 472 additions and 0 deletions

View File

@ -0,0 +1,356 @@
#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2020 David Corrigan <davidcorrigan714@gmail.com>
# Copyright (c) 2020 Alan Green <avg@google.com>
# Copyright (c) 2020 David Shah <dave@ds0.me>
# SPDX-License-Identifier: BSD-2-Clause
from litex.build.generic_platform import *
from litex.build.lattice import LatticePlatform
from litex.build.lattice.programmer import LatticeProgrammer
# IOs ----------------------------------------------------------------------------------------------
_io = [
("clk12", 0, Pins("L16"), IOStandard("LVCMOS33")), # Ensure JP2 is installed
# Reference clocks. Why are there four 27MHz oscs. Is this really correct??
("clk27_0", 0, Pins("L5"), IOStandard("LVCMOS18")),
("clk27_1", 0, Pins("L7"), IOStandard("LVCMOS18")),
("clk27_2", 0, Pins("M2"), IOStandard("LVCMOS18")),
("clk27_3", 0, Pins("Y2"), IOStandard("LVCMOS18")),
# 8.1. General Purpose Push Buttons - all logic zero when pressed]
("cam_reset", 0, Pins("T1"), IOStandard("LVCMOS18")), # SW1
("gsrn", 0, Pins("G13"), IOStandard("LVCMOS33")), # SW3
("programn", 0, Pins("E11"), IOStandard("LVCMOS33")), # SW4
("user_btn", 0, Pins("L20"), IOStandard("LVCMOS33")), # SW5
("user_btn", 1, Pins("L19"), IOStandard("LVCMOS33")), # SW6
("serial", 0,
Subsignal("rx", Pins("F14"), IOStandard("LVCMOS33")),
Subsignal("tx", Pins("F16"), IOStandard("LVCMOS33")),
),
# Section 7.1 Status LEDs
("user_led", 0, Pins("G14"), IOStandard("LVCMOS33")), # Green
("user_led", 1, Pins("G15"), IOStandard("LVCMOS33")), # Green
("user_led", 2, Pins("L13"), IOStandard("LVCMOS33")), # Green
("user_led", 3, Pins("L14"), IOStandard("LVCMOS33")), # Green
# Section 8.1 DIP Switch
("user_dip_btn", 0, Pins("R5"), IOStandard("LVCMOS18")),
("user_dip_btn", 1, Pins("R6"), IOStandard("LVCMOS18")),
("user_dip_btn", 2, Pins("Y5"), IOStandard("LVCMOS18")),
("user_dip_btn", 3, Pins("W5"), IOStandard("LVCMOS18")),
# SPI Flash
("spiflash", 0,
Subsignal("cs_n", Pins("E13")),
Subsignal("clk", Pins("E12")),
Subsignal("mosi", Pins("D13")),
Subsignal("miso", Pins("D15")),
Subsignal("wp", Pins("D14")),
Subsignal("hold", Pins("D16")),
IOStandard("LVCMOS33")
),
("spiflash4x", 0,
Subsignal("cs_n", Pins("E13")),
Subsignal("clk", Pins("E12")),
Subsignal("dq", Pins("D13 D15 D14 D16")),
IOStandard("LVCMOS33")
),
# Camera I2C buses
("i2c", 0,
Subsignal("sda", Pins("N4")),
Subsignal("scl", Pins("N5")),
IOStandard("LVCMOS18")
),
("i2c", 1,
Subsignal("sda", Pins("N6")),
Subsignal("scl", Pins("N7")),
IOStandard("LVCMOS18")
),
("i2c", 2,
Subsignal("sda", Pins("P1")),
Subsignal("scl", Pins("P2")),
IOStandard("LVCMOS18")
),
("i2c", 3,
Subsignal("sda", Pins("P5")),
Subsignal("scl", Pins("P6")),
IOStandard("LVCMOS18")
),
# Shared camera control signals
("cam_ctrl",
Subsignal("cam_reset", Pins("T1")),
Subsignal("cam_frame_sync", Pins("U1")),
),
# MIPI camera modules
# Note that use of MIPI_DPHY standard for + and LVCMOS12H for - is copied from Lattice PDC
("camera", 0,
Subsignal("mclk", Pins("M3"), IOStandard("LVCMOS18")),
Subsignal("clkp", Pins("A2"), IOStandard("MIPI_DPHY")),
Subsignal("clkn", Pins("B1"), IOStandard("LVCMOS12H")),
Subsignal("dp", Pins("B2 A3 C2 A4"), IOStandard("MIPI_DPHY")),
Subsignal("dn", Pins("C1 B3 D1 B4"), IOStandard("LVCMOS12H")),
),
("camera", 1,
Subsignal("mclk", Pins("M4"), IOStandard("LVCMOS18")),
Subsignal("clkp", Pins("A8"), IOStandard("MIPI_DPHY")),
Subsignal("clkn", Pins("B8"), IOStandard("LVCMOS12H")),
Subsignal("dp", Pins("A7 A9 A6 A10"), IOStandard("MIPI_DPHY")),
Subsignal("dn", Pins("B7 B9 B6 B10"), IOStandard("LVCMOS12H")),
),
("camera", 2,
Subsignal("mclk", Pins("M5"), IOStandard("LVCMOS18")),
Subsignal("clkp", Pins("W11"), IOStandard("MIPI_DPHY")),
Subsignal("clkn", Pins("Y11"), IOStandard("LVCMOS12H")),
Subsignal("dp", Pins("V11 W13 U12 R12"), IOStandard("MIPI_DPHY")),
Subsignal("dn", Pins("U11 V12 T12 P12"), IOStandard("LVCMOS12H")),
),
("camera", 3,
Subsignal("mclk", Pins("M6"), IOStandard("LVCMOS18")),
Subsignal("clkp", Pins("T13"), IOStandard("MIPI_DPHY")),
Subsignal("clkn", Pins("T14"), IOStandard("LVCMOS12H")),
Subsignal("dp", Pins("Y15 U15 V17 P13"), IOStandard("MIPI_DPHY")),
Subsignal("dn", Pins("Y16 V16 U16 R13"), IOStandard("LVCMOS12H")),
),
]
# Connectors ---------------------------------------------------------------------------------------
_connectors = [
# Link to ECP5
("UPSTREAM", {
"D0": "N14",
"D1": "M14",
"D2": "M16",
"D3": "M15",
"D4": "N15",
"D5": "N16",
"D6": "M17",
"D7": "M18",
"D8": "M19",
"D9": "M20",
"D10": "N19",
"D11": "N20",
"D12": "P19",
"D13": "P20",
"D14": "P17",
"D15": "P18",
"D16": "R17",
"D17": "R18",
"D18": "U20",
"D19": "T20",
"D20": "W20",
"D21": "V20",
"D22": "T18",
"D23": "U18",
"D24": "V18",
"D25": "V19",
"D26": "W19",
"PCLK_DOWN": "Y19",
"GSRN": "G13",
"SDA": "E20",
"SCL": "F20",
"UP_GPIO39": "F18",
"UP_GPIO40": "G19",
"UP_GPIO41": "L15",
"UP_GPIO42": "D17",
}
),
# PMOD signal number:
# 1 2 3 4 7 8 9 10
("PMOD0", "D10 D9 D7 D8 D6 D5 D4 D3"),
("PMOD1", "E10 E9 E7 E8 E4 E3 E2 F1"),
("PMOD2", "J2 J1 K2 K1 K3 K4 E17 F13"),
]
# Platform -----------------------------------------------------------------------------------------
class Platform(LatticePlatform):
def __init__(self, device="LIFCL", **kwargs):
assert device in ["LIFCL"]
LatticePlatform.__init__(self, device + "-40-9BG400C", _io, _connectors, toolchain="radiant", **kwargs)
def create_programmer(self, mode = "direct"):
assert mode in ["direct","flash"]
xcf_template_direct = """<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
<ispXCF version="R1.2.0">
<Comment></Comment>
<Chain>
<Comm>JTAG</Comm>
<Device>
<SelectedProg value="TRUE"/>
<Pos>1</Pos>
<Vendor>Lattice</Vendor>
<Family>LIFCL</Family>
<Name>LIFCL-40</Name>
<IDCode>0x010f1043</IDCode>
<Package>All</Package>
<PON>LIFCL-40</PON>
<Bypass>
<InstrLen>8</InstrLen>
<InstrVal>11111111</InstrVal>
<BScanLen>1</BScanLen>
<BScanVal>0</BScanVal>
</Bypass>
<File>{bitstream_file}</File>
<JedecChecksum>N/A</JedecChecksum>
<MemoryType>Static Random Access Memory (SRAM)</MemoryType>
<Operation>Fast Configuration</Operation>
<Option>
<SVFVendor>JTAG STANDARD</SVFVendor>
<IOState>HighZ</IOState>
<PreloadLength>362</PreloadLength>
<IOVectorData>0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</IOVectorData>
<Usercode>0x00000000</Usercode>
<AccessMode>Direct Programming</AccessMode>
</Option>
</Device>
</Chain>
<ProjectOptions>
<Program>SEQUENTIAL</Program>
<Process>ENTIRED CHAIN</Process>
<OperationOverride>No Override</OperationOverride>
<StartTAP>TLR</StartTAP>
<EndTAP>TLR</EndTAP>
<VerifyUsercode value="FALSE"/>
<TCKDelay>3</TCKDelay>
</ProjectOptions>
<CableOptions>
<CableName>USB2</CableName>
<PortAdd>FTUSB-0</PortAdd>
</CableOptions>
</ispXCF>
"""
xcf_template_flash = """<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
<ispXCF version="R1.2.0">
<Comment></Comment>
<Chain>
<Comm>JTAG2SPI</Comm>
<Device>
<SelectedProg value="TRUE"/>
<Pos>1</Pos>
<Vendor>Lattice</Vendor>
<Family>LIFCL</Family>
<Name>LIFCL-40</Name>
<Package>All</Package>
<Bypass>
<InstrLen>8</InstrLen>
<InstrVal>11111111</InstrVal>
<BScanLen>1</BScanLen>
<BScanVal>0</BScanVal>
</Bypass>
<File>{bitstream_file}</File>
<MemoryType>External SPI Flash Memory (SPI FLASH)</MemoryType>
<Operation>Erase,Program,Verify</Operation>
<Option>
<SVFVendor>JTAG STANDARD</SVFVendor>
<Usercode>0x00000000</Usercode>
<AccessMode>Direct Programming</AccessMode>
</Option>
<FPGALoader>
<CPLDDevice>
<Device>
<Pos>1</Pos>
<Vendor>Lattice</Vendor>
<Family>LIFCL</Family>
<Name>LIFCL-40</Name>
<IDCode>0x010f1043</IDCode>
<Package>All</Package>
<PON>LIFCL-40</PON>
<Bypass>
<InstrLen>8</InstrLen>
<InstrVal>11111111</InstrVal>
<BScanLen>1</BScanLen>
<BScanVal>0</BScanVal>
</Bypass>
<MemoryType>Static Random Access Memory (SRAM)</MemoryType>
<Operation>Refresh Verify ID</Operation>
<Option>
<SVFVendor>JTAG STANDARD</SVFVendor>
<IOState>HighZ</IOState>
<PreloadLength>362</PreloadLength>
<IOVectorData>0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</IOVectorData>
<AccessMode>Direct Programming</AccessMode>
</Option>
</Device>
</CPLDDevice>
<FlashDevice>
<Device>
<Pos>1</Pos>
<Vendor>Macronix</Vendor>
<Family>SPI Serial Flash</Family>
<Name>MX25L12833F</Name>
<IDCode>0x18</IDCode>
<Package>8-pin SOP</Package>
<Operation>Erase,Program,Verify</Operation>
<File>{bitstream_file}</File>
<AddressBase>0x00000000</AddressBase>
<EndAddress>0x000F0000</EndAddress>
<DeviceSize>128</DeviceSize>
<DataSize>1016029</DataSize>
<NumberOfDevices>1</NumberOfDevices>
<ReInitialize value="FALSE"/>
</Device>
</FlashDevice>
<FPGADevice>
<Device>
<Pos>1</Pos>
<Name></Name>
<File>{bitstream_file}</File>
<LocalChainList>
<LocalDevice index="-99"
name="Unknown"
file="{bitstream_file}"/>
</LocalChainList>
<Option>
<SVFVendor>JTAG STANDARD</SVFVendor>
</Option>
</Device>
</FPGADevice>
</FPGALoader>
</Device>
</Chain>
<ProjectOptions>
<Program>SEQUENTIAL</Program>
<Process>ENTIRED CHAIN</Process>
<OperationOverride>No Override</OperationOverride>
<StartTAP>TLR</StartTAP>
<EndTAP>TLR</EndTAP>
<DisableCheckBoard value="TRUE"/>
<VerifyUsercode value="FALSE"/>
<TCKDelay>3</TCKDelay>
</ProjectOptions>
<CableOptions>
<CableName>USB2</CableName>
<PortAdd>FTUSB-0</PortAdd>
<USBID>Lattice ECP5 VIP Processor Board 0000 Serial FT4RXXZ5</USBID>
</CableOptions>
</ispXCF>
"""
if mode == "direct":
xcf_template = xcf_template_direct
if mode == "flash":
xcf_template = xcf_template_flash
return LatticeProgrammer(xcf_template)

View File

@ -0,0 +1,116 @@
#!/usr/bin/env python3
#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2020 David Corrigan <davidcorrigan714@gmail.com>
# Copyright (c) 2020 Alan Green <avg@google.com>
# Copyright (c) 2020 David Shah <dave@ds0.me>
#
# SPDX-License-Identifier: BSD-2-Clause
import os
import argparse
from migen import *
from migen.genlib.resetsync import AsyncResetSynchronizer
from litex_boards.platforms import crosslink_nx_vip
from litex.soc.cores.nxlram import NXLRAM
from litex.soc.cores.spi_flash import SpiFlash
from litex.build.io import CRG
from litex.build.generic_platform import *
from litex.soc.cores.clock import *
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.cores.led import LedChaser
kB = 1024
mB = 1024*kB
# CRG ----------------------------------------------------------------------------------------------
class _CRG(Module):
def __init__(self, platform, sys_clk_freq):
self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_por = ClockDomain()
# TODO: replace with PLL
# Clocking
self.submodules.sys_clk = sys_osc = NXOSCA()
sys_osc.create_hf_clk(self.cd_sys, sys_clk_freq)
platform.add_period_constraint(self.cd_sys.clk, 1e9/sys_clk_freq)
rst_n = platform.request("gsrn")
# Power On Reset
por_cycles = 4096
por_counter = Signal(log2_int(por_cycles), reset=por_cycles-1)
self.comb += self.cd_por.clk.eq(self.cd_sys.clk)
self.sync.por += If(por_counter != 0, por_counter.eq(por_counter - 1))
self.specials += AsyncResetSynchronizer(self.cd_por, ~rst_n)
self.specials += AsyncResetSynchronizer(self.cd_sys, (por_counter != 0))
# BaseSoC ------------------------------------------------------------------------------------------
class BaseSoC(SoCCore):
SoCCore.mem_map = {
"rom": 0x00000000,
"sram": 0x40000000,
"csr": 0xf0000000,
}
def __init__(self, sys_clk_freq, **kwargs):
platform = crosslink_nx_vip.Platform()
platform.add_platform_command("ldc_set_sysconfig {{MASTER_SPI_PORT=SERIAL}}")
# Disable Integrated SRAM since we want to instantiate LRAM specifically for it
kwargs["integrated_sram_size"] = 0
# SoCCore -----------------------------------------_----------------------------------------
SoCCore.__init__(self, platform, sys_clk_freq,
ident = "LiteX SoC on Crosslink-NX VIP Input Board",
ident_version = True,
**kwargs)
# CRG --------------------------------------------------------------------------------------
self.submodules.crg = _CRG(platform, sys_clk_freq)
# 128KB LRAM (used as SRAM) ---------------------------------------------------------------
size = 128*kB
self.submodules.spram = NXLRAM(32, size)
self.register_mem("sram", self.mem_map["sram"], self.spram.bus, size)
# Leds -------------------------------------------------------------------------------------
self.submodules.leds = LedChaser(
pads = Cat(*[platform.request("user_led", i) for i in range(4)]),
sys_clk_freq = sys_clk_freq)
self.add_csr("leds")
# Build --------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="LiteX SoC on Crosslink-NX Eval Board")
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=75e6, help="System clock frequency (default=75MHz)")
parser.add_argument("--prog-target", default="direct", help="Programming Target: direct or flash")
builder_args(parser)
soc_core_args(parser)
args = parser.parse_args()
soc = BaseSoC(sys_clk_freq=int(float(args.sys_clk_freq)), **soc_core_argdict(args))
builder = Builder(soc, **builder_argdict(args))
builder_kargs = {}
builder.build(**builder_kargs, run=args.build)
if args.load:
prog = soc.platform.create_programmer(args.prog_target)
prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".bit"))
if __name__ == "__main__":
main()