Basic SoC for Opal Kelly XEM8320
This commit is contained in:
parent
f400179b5b
commit
e20391d366
|
@ -0,0 +1,156 @@
|
|||
#
|
||||
# This file is part of LiteX-Boards.
|
||||
#
|
||||
# Copyright (c) 2022 Andrew Elbert Wilson <Andrew.E.Wilson@ieee.org>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
from litex.build.generic_platform import *
|
||||
from litex.build.xilinx import XilinxPlatform, VivadoProgrammer
|
||||
|
||||
# IOs ----------------------------------------------------------------------------------------------
|
||||
|
||||
_io = [
|
||||
# Clk / Rst
|
||||
("sys_clk100", 0,
|
||||
Subsignal("p", Pins("T24"), IOStandard("LVDS")),
|
||||
Subsignal("n", Pins("U24"), IOStandard("LVDS"))
|
||||
),
|
||||
|
||||
("ddr_clk100", 0,
|
||||
Subsignal("p", Pins("AD20"), IOStandard("LVDS")),
|
||||
Subsignal("n", Pins("AE20"), IOStandard("LVDS"))
|
||||
),
|
||||
#NO RESET, maybe use okHOST USB later
|
||||
#("cpu_reset", 0, Pins("AN8"), IOStandard("LVCMOS18")),
|
||||
|
||||
# Leds
|
||||
("user_led", 0, Pins("G19"), IOStandard("LVCMOS18")),
|
||||
("user_led", 1, Pins("B16"), IOStandard("LVCMOS18")),
|
||||
("user_led", 2, Pins("F22"), IOStandard("LVCMOS18")),
|
||||
("user_led", 3, Pins("E22"), IOStandard("LVCMOS18")),
|
||||
("user_led", 4, Pins("M24"), IOStandard("LVCMOS18")),
|
||||
("user_led", 5, Pins("G22"), IOStandard("LVCMOS18")),
|
||||
|
||||
# Opal Kelly Host USBC interface
|
||||
("okHost", 0, # Uses the FrontPanel API
|
||||
Subsignal("okAA", Pins("T19")),
|
||||
Subsignal("okHU", Pins("U20 U26 T22")),
|
||||
Subsignal("okUH", Pins("V23 T23 U22 U25 U21")),
|
||||
Subsignal("okUHU", Pins("P26 P25 R26 R25 R23 R22 P21 P20",
|
||||
"R21 R20 P23 N23 T25 N24 N22 V26",
|
||||
"N19 V21 N21 W20 W26 W19 Y25 Y26",
|
||||
"Y22 V22 W21 AA23 Y23 AA24 W25 AA25")),
|
||||
Misc("SLEW=FAST"),
|
||||
IOStandard("LVCMOS18"),
|
||||
),
|
||||
|
||||
# TODO: Add SMA & SFP+
|
||||
|
||||
|
||||
# DDR4 SDRAM
|
||||
("ddram", 0,
|
||||
Subsignal("a", Pins(
|
||||
"AD18 AE17 AB17 AE18 AD19 AF17 Y17 AE16",
|
||||
"AA17 AC17 AC19 AC16 AF20 AD16"),
|
||||
IOStandard("SSTL12_DCI")),
|
||||
Subsignal("ba", Pins("AC18 AF18"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("bg", Pins("AB19"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("ras_n", Pins("AA18"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("cas_n", Pins("AF19"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("we_n", Pins("AA19"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("cs_n", Pins("AF22"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("act_n", Pins("Y18"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("dm", Pins("AE25 AE22"),
|
||||
IOStandard("POD12_DCI")),
|
||||
Subsignal("dq", Pins(
|
||||
"AF24 AB25 AB26 AC24 AF25 AB24 AD24 AD25",
|
||||
"AB21 AE21 AE23 AD23 AC23 AD21 AC22 AC21"),
|
||||
IOStandard("POD12_DCI"),
|
||||
Misc("PRE_EMPHASIS=RDRV_240"),
|
||||
Misc("EQUALIZATION=EQ_LEVEL2")),
|
||||
Subsignal("dqs_p", Pins("AC26 AA22"),
|
||||
IOStandard("DIFF_POD12_DCI"),
|
||||
Misc("PRE_EMPHASIS=RDRV_240"),
|
||||
Misc("EQUALIZATION=EQ_LEVEL2")),
|
||||
Subsignal("dqs_n", Pins("AD26 AB22"),
|
||||
IOStandard("DIFF_POD12_DCI"),
|
||||
Misc("PRE_EMPHASIS=RDRV_240"),
|
||||
Misc("EQUALIZATION=EQ_LEVEL2")),
|
||||
Subsignal("clk_p", Pins("Y20"), IOStandard("DIFF_SSTL12_DCI")),
|
||||
Subsignal("clk_n", Pins("Y21"), IOStandard("DIFF_SSTL12_DCI")),
|
||||
Subsignal("cke", Pins("AA20"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("odt", Pins("AB20"), IOStandard("SSTL12_DCI")),
|
||||
Subsignal("reset_n", Pins("AE26"), IOStandard("LVCMOS12")),
|
||||
Misc("SLEW=FAST"),
|
||||
),
|
||||
]
|
||||
|
||||
# Connectors ---------------------------------------------------------------------------------------
|
||||
|
||||
# TODO: SYZYGY Connectors & SYZYGY to PMODS!
|
||||
|
||||
|
||||
_connectors = [
|
||||
("pmod1", "AC14 AC13 AF15 AF14 AF13 AE13 H13 J13"),
|
||||
("pmod2", "AB15 AB16 W14 J14 AE15 W15 Y15 J15"),
|
||||
("pmod3", "G14 H14 W13 W12 AA13 Y13 H12 J12"),
|
||||
("pmod4", "AD14 AD13 W16 AD15 AB14 AA14 Y16 AA15"),
|
||||
]
|
||||
|
||||
def dvi_pmod_io(pmoda,pmodb):
|
||||
return [
|
||||
("dvi", 0,
|
||||
Subsignal("clk", Pins(f"{pmodb}:1")),
|
||||
Subsignal("de", Pins(f"{pmodb}:6")),
|
||||
Subsignal("hsync", Pins(f"{pmodb}:3")),
|
||||
Subsignal("vsync", Pins(f"{pmodb}:7")),
|
||||
Subsignal("b", Pins(f"{pmoda}:5 {pmoda}:1 {pmoda}:4 {pmoda}:0")),
|
||||
Subsignal("g", Pins(f"{pmoda}:7 {pmoda}:3 {pmoda}:6 {pmoda}:2")),
|
||||
Subsignal("r", Pins(f"{pmodb}:2 {pmodb}:5 {pmodb}:4 {pmodb}:0")),
|
||||
IOStandard("LVCMOS33"),
|
||||
)
|
||||
]
|
||||
|
||||
_dvi_pmod_io = dvi_pmod_io("pmod2","pmod1") # SDCARD PMOD on JD.
|
||||
|
||||
def sdcard_pmod_io(pmod):
|
||||
return [
|
||||
# SDCard PMOD:
|
||||
# - https://store.digilentinc.com/pmod-microsd-microsd-card-slot/
|
||||
# - https://github.com/antmicro/arty-expansion-board
|
||||
("spisdcard", 0,
|
||||
Subsignal("clk", Pins(f"{pmod}:3")),
|
||||
Subsignal("mosi", Pins(f"{pmod}:1"), Misc("PULLUP True")),
|
||||
Subsignal("cs_n", Pins(f"{pmod}:0"), Misc("PULLUP True")),
|
||||
Subsignal("miso", Pins(f"{pmod}:2"), Misc("PULLUP True")),
|
||||
Misc("SLEW=FAST"),
|
||||
IOStandard("LVCMOS33"),
|
||||
),
|
||||
("sdcard", 0,
|
||||
Subsignal("data", Pins(f"{pmod}:2 {pmod}:4 {pmod}:5 {pmod}:0"), Misc("PULLUP True")),
|
||||
Subsignal("cmd", Pins(f"{pmod}:1"), Misc("PULLUP True")),
|
||||
Subsignal("clk", Pins(f"{pmod}:3")),
|
||||
Subsignal("cd", Pins(f"{pmod}:6")),
|
||||
Misc("SLEW=FAST"),
|
||||
IOStandard("LVCMOS33"),
|
||||
),
|
||||
]
|
||||
|
||||
_sdcard_pmod_io = sdcard_pmod_io("pmod3") # SDCARD PMOD on JD.
|
||||
# Platform -----------------------------------------------------------------------------------------
|
||||
|
||||
class Platform(XilinxPlatform):
|
||||
default_clk_name = "sys_clk100"
|
||||
default_clk_period = 1e9/100e6
|
||||
|
||||
def __init__(self, toolchain="vivado"):
|
||||
XilinxPlatform.__init__(self, "xcau25p-ffvb676-2-e", _io, _connectors, toolchain=toolchain)
|
||||
|
||||
def create_programmer(self):
|
||||
return VivadoProgrammer()
|
||||
|
||||
def do_finalize(self, fragment):
|
||||
XilinxPlatform.do_finalize(self, fragment)
|
||||
self.add_period_constraint(self.lookup_request("sys_clk100", loose=True), 1e9/100e6)
|
||||
self.add_period_constraint(self.lookup_request("ddr_clk100", loose=True), 1e9/100e6)
|
||||
self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 64]")
|
|
@ -0,0 +1,64 @@
|
|||
interface ftdi
|
||||
ftdi_vid_pid 0x0403 0x6014
|
||||
ftdi_channel 0
|
||||
ftdi_layout_init 0x00e8 0x60eb
|
||||
reset_config none
|
||||
|
||||
#openocd missing support, added to local cfg file
|
||||
|
||||
set CHIP XCAU25P
|
||||
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME xcu
|
||||
}
|
||||
|
||||
# The cvarious chips in the Ultrascale family have different IR length.
|
||||
# Set $CHIP before including this file to determine the device.
|
||||
array set _XCU_DATA {
|
||||
XCAU25P {0x04A64093 6}
|
||||
}
|
||||
|
||||
if { ![info exists CHIP] } {
|
||||
error "set CHIP to one of "[concat [array names _XCU_DATA]]
|
||||
}
|
||||
|
||||
if { ![llength [array names _XCU_DATA $CHIP]] } {
|
||||
error "unknown CHIP: "$CHIP
|
||||
}
|
||||
|
||||
set _EXPID [lindex $_XCU_DATA($CHIP) 0]
|
||||
set _IRLEN [lindex $_XCU_DATA($CHIP) 1]
|
||||
|
||||
# the 4 top bits (28:31) are the die stepping/revisions. ignore it.
|
||||
jtag newtap $_CHIPNAME tap -irlen $_IRLEN -ignore-version -expected-id $_EXPID
|
||||
|
||||
pld device virtex2 $_CHIPNAME.tap 1
|
||||
|
||||
set XCU_JSHUTDOWN 0x0d
|
||||
set XCU_JPROGRAM 0x0b
|
||||
set XCU_JSTART 0x0c
|
||||
set XCU_BYPASS 0x3f
|
||||
|
||||
proc xcu_program {tap} {
|
||||
global XCU_JSHUTDOWN XCU_JPROGRAM XCU_JSTART XCU_BYPASS
|
||||
irscan $tap $XCU_JSHUTDOWN
|
||||
irscan $tap $XCU_JPROGRAM
|
||||
runtest 60000
|
||||
#JSTART prevents this from working...
|
||||
#irscan $tap $XCU_JSTART
|
||||
runtest 2000
|
||||
irscan $tap $XCU_BYPASS
|
||||
runtest 2000
|
||||
}
|
||||
|
||||
source [find cpld/jtagspi.cfg]
|
||||
adapter_khz 25000
|
||||
|
||||
|
||||
proc fpga_program {} {
|
||||
global _CHIPNAME
|
||||
xc7_program $_CHIPNAME.tap
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# This file is part of LiteX-Boards.
|
||||
#
|
||||
# Copyright (c) 2022 Andrew Elbert Wilson <Andrew.E.Wilson@ieee.org>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
import os
|
||||
|
||||
from migen import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
|
||||
from litex_boards.platforms import opalkelly_xem8320
|
||||
|
||||
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
|
||||
from litex.soc.cores.video import VideoDVIPHY
|
||||
from litedram.modules import MT40A512M16
|
||||
from litedram.phy import usddrphy
|
||||
|
||||
|
||||
|
||||
# CRG ----------------------------------------------------------------------------------------------
|
||||
|
||||
class _CRG(Module):
|
||||
def __init__(self, platform, sys_clk_freq):
|
||||
self.rst = Signal()
|
||||
self.clock_domains.cd_sys = ClockDomain()
|
||||
self.clock_domains.cd_sys4x = ClockDomain()
|
||||
self.clock_domains.cd_idelay = ClockDomain()
|
||||
self.clock_domains.cd_hdmi = ClockDomain()
|
||||
self.clock_domains.cd_hdmi5x = ClockDomain()
|
||||
|
||||
# # #
|
||||
clk100 = platform.request("ddr_clk100")
|
||||
|
||||
self.submodules.pll = pll = USMMCM(speedgrade=-2)
|
||||
self.comb += pll.reset.eq(self.rst)
|
||||
pll.register_clkin(clk100, 100e6)
|
||||
pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=False)
|
||||
pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq) #500
|
||||
pll.create_clkout(self.cd_hdmi, 25e6)
|
||||
pll.create_clkout(self.cd_hdmi5x, 5*25e6)
|
||||
|
||||
platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) # Ignore sys_clk to pll.clkin path created by SoC's rst.
|
||||
|
||||
# #option for second MMCM for video clocks
|
||||
# self.submodules.video_pll = video_pll = USMMCM(speedgrade=-2)
|
||||
# video_pll.reset.eq(self.rst)
|
||||
# video_pll.register_clkin(self.cd_sys.clk, sys_clk_freq)
|
||||
# video_pll.create_clkout(self.cd_hdmi, 25e6)
|
||||
# video_pll.create_clkout(self.cd_hdmi5x, 5*25e6)
|
||||
|
||||
self.submodules.idelayctrl = USIDELAYCTRL(cd_ref=self.cd_sys4x, cd_sys=self.cd_sys)
|
||||
|
||||
# BaseSoC ------------------------------------------------------------------------------------------
|
||||
|
||||
class BaseSoC(SoCCore):
|
||||
def __init__(self, sys_clk_freq=int(125e6), with_ethernet=False, with_etherbone=False,
|
||||
eth_ip="192.168.1.50", with_led_chaser=True,
|
||||
**kwargs):
|
||||
platform = opalkelly_xem8320.Platform()
|
||||
|
||||
# CRG --------------------------------------------------------------------------------------
|
||||
self.submodules.crg = _CRG(platform, sys_clk_freq)
|
||||
|
||||
kwargs["uart_name"] = "jtag_uart"
|
||||
|
||||
# TODO: add okHost FrontPanel API for UART, Data streaing, and Debug
|
||||
|
||||
# SoCCore ----------------------------------------------------------------------------------
|
||||
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on xem8320", **kwargs)
|
||||
|
||||
# DDR4 SDRAM -------------------------------------------------------------------------------
|
||||
if not self.integrated_main_ram_size:
|
||||
self.submodules.ddrphy = usddrphy.USPDDRPHY(platform.request("ddram"),
|
||||
memtype = "DDR4",
|
||||
sys_clk_freq = sys_clk_freq,
|
||||
iodelay_clk_freq = 500e6)
|
||||
self.add_sdram("sdram",
|
||||
phy = self.ddrphy,
|
||||
module = MT40A512M16(sys_clk_freq, "1:4"),
|
||||
size = 0x40000000,
|
||||
l2_cache_size = kwargs.get("l2_size", 8192)
|
||||
)
|
||||
|
||||
# TODO: add SFP+ cages for ethernet
|
||||
# Ethernet / Etherbone ---------------------------------------------------------------------
|
||||
# if with_ethernet or with_etherbone:
|
||||
# self.submodules.ethphy = KU_1000BASEX(self.crg.cd_eth.clk,
|
||||
# data_pads = self.platform.request("sfp", 0),
|
||||
# sys_clk_freq = self.clk_freq)
|
||||
# self.comb += self.platform.request("sfp_tx_disable_n", 0).eq(1)
|
||||
# self.platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks REQP-1753]")
|
||||
# if with_ethernet:
|
||||
# self.add_ethernet(phy=self.ethphy)
|
||||
# if with_etherbone:
|
||||
# self.add_etherbone(phy=self.ethphy, ip_address=eth_ip)
|
||||
|
||||
platform.add_extension(opalkelly_xem8320._dvi_pmod_io)
|
||||
self.submodules.videophy = VideoDVIPHY(platform.request("dvi"), clock_domain="hdmi")
|
||||
self.add_video_framebuffer(phy=self.videophy, timings="640x480@75Hz", clock_domain="hdmi")
|
||||
|
||||
|
||||
# Leds -------------------------------------------------------------------------------------
|
||||
if with_led_chaser:
|
||||
self.submodules.leds = LedChaser(
|
||||
pads = platform.request_all("user_led"),
|
||||
sys_clk_freq = sys_clk_freq)
|
||||
|
||||
# Build --------------------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
from litex.soc.integration.soc import LiteXSoCArgumentParser
|
||||
parser = LiteXSoCArgumentParser(description="LiteX SoC on XEM8320")
|
||||
target_group = parser.add_argument_group(title="Target options")
|
||||
target_group.add_argument("--build", action="store_true", help="Build design.")
|
||||
target_group.add_argument("--load", action="store_true", help="Load bitstream.")
|
||||
target_group.add_argument("--sys-clk-freq", default=125e6, help="System clock frequency.")
|
||||
#ethopts = target_group.add_mutually_exclusive_group()
|
||||
#ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support.")
|
||||
builder_args(parser)
|
||||
soc_core_args(parser)
|
||||
args = parser.parse_args()
|
||||
|
||||
soc = BaseSoC(
|
||||
sys_clk_freq = int(float(args.sys_clk_freq)),
|
||||
#with_ethernet = args.with_ethernet,
|
||||
#with_etherbone = args.with_etherbone,
|
||||
#eth_ip = args.eth_ip,
|
||||
#with_pcie = args.with_pcie,
|
||||
#with_sata = args.with_sata,
|
||||
**soc_core_argdict(args)
|
||||
)
|
||||
|
||||
soc.platform.add_extension(opalkelly_xem8320._sdcard_pmod_io)
|
||||
soc.add_spi_sdcard()
|
||||
|
||||
builder = Builder(soc, **builder_argdict(args))
|
||||
if args.build:
|
||||
builder.build()
|
||||
|
||||
if args.load:
|
||||
prog = soc.platform.create_programmer()
|
||||
prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))
|
||||
# TODO: add option for FrontPanel Programming
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue