add Acorn CLE 215+ platform/target.

This commit is contained in:
Florent Kermarrec 2020-05-06 07:49:21 +02:00
parent da61aabc5b
commit a049fa6856
2 changed files with 284 additions and 0 deletions

View File

@ -0,0 +1,91 @@
# This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
# The Acorn CLE 215+ is a cryptocurrency mining accelerator card from SQRL that can be repurposed
# as a generic FPGA PCIe development board: http://www.squirrelsresearch.com/acorn-cle-215-plus
from litex.build.generic_platform import *
from litex.build.xilinx import XilinxPlatform
from litex.build.openocd import OpenOCD
# IOs ----------------------------------------------------------------------------------------------
_io = [
# clk / rst
("clk200", 0,
Subsignal("p", Pins("J19"), IOStandard("DIFF_SSTL15")),
Subsignal("n", Pins("H19"), IOStandard("DIFF_SSTL15"))
),
# leds
("user_led", 0, Pins("G3"), IOStandard("LVCMOS33")),
("user_led", 1, Pins("H3"), IOStandard("LVCMOS33")),
("user_led", 2, Pins("G4"), IOStandard("LVCMOS33")),
("user_led", 3, Pins("H4"), IOStandard("LVCMOS33")),
# spiflash
("spiflash", 0,
Subsignal("cs_n", Pins("T19")),
Subsignal("mosi", Pins("P22")),
Subsignal("miso", Pins("R22")),
Subsignal("wp", Pins("P21")),
Subsignal("hold", Pins("R21")),
IOStandard("LVCMOS33")
),
# pcie
("pcie_clkreq_n", 0, Pins("G1"), IOStandard("LVCMOS33")),
("pcie_x4", 0,
Subsignal("rst_n", Pins("J1"), IOStandard("LVCMOS33"), Misc("PULLUP=TRUE")),
Subsignal("clk_p", Pins("F6")),
Subsignal("clk_n", Pins("E6")),
Subsignal("rx_p", Pins("B10 B8 D11 D9")),
Subsignal("rx_n", Pins("A10 A8 C11 C9")),
Subsignal("tx_p", Pins("B6 B4 D5 D7")),
Subsignal("tx_n", Pins("A6 A4 C5 C7"))
),
# dram
("ddram", 0,
Subsignal("a", Pins(
"M15 L21 M16 L18 K21 M18 M21 N20",
"M20 N19 J21 M22 K22 N18 N22 J22"),
IOStandard("SSTL15")),
Subsignal("ba", Pins("L19 J20 L20"), IOStandard("SSTL15")),
Subsignal("ras_n", Pins("H20"), IOStandard("SSTL15")),
Subsignal("cas_n", Pins("K18"), IOStandard("SSTL15")),
Subsignal("we_n", Pins("L16"), IOStandard("SSTL15")),
Subsignal("dm", Pins("A19 G22"), IOStandard("SSTL15")),
Subsignal("dq", Pins(
"D19 B20 E19 A20 F19 C19 F20 C18",
"E22 G21 D20 E21 C22 D21 B22 D22"),
IOStandard("SSTL15"),
Misc("IN_TERM=UNTUNED_SPLIT_50")),
Subsignal("dqs_p", Pins("F18 B21"), IOStandard("DIFF_SSTL15")),
Subsignal("dqs_n", Pins("E18 A21"), IOStandard("DIFF_SSTL15")),
Subsignal("clk_p", Pins("K17"), IOStandard("DIFF_SSTL15")),
Subsignal("clk_n", Pins("J17"), IOStandard("DIFF_SSTL15")),
Subsignal("cke", Pins("H22"), IOStandard("SSTL15")),
Subsignal("odt", Pins("K19"), IOStandard("SSTL15")),
Subsignal("reset_n", Pins("K16"), IOStandard("LVCMOS15")),
#Subsignal("cs_n", Pins(""), IOStandard("SSTL15")),
Misc("SLEW=FAST"),
),
]
# Platform -----------------------------------------------------------------------------------------
class Platform(XilinxPlatform):
default_clk_name = "clk200"
default_clk_period = 1e9/200e6
def __init__(self):
XilinxPlatform.__init__(self, "xc7a200t-fbg484-2", _io, toolchain="vivado")
self.add_platform_command("set_property INTERNAL_VREF 0.750 [get_iobanks 34]")
def create_programmer(self):
return OpenOCD("openocd_xilinx_xc7.cfg", "bscan_spi_xc7a200t.bit")
def do_finalize(self, fragment):
XilinxPlatform.do_finalize(self, fragment)
self.add_period_constraint(self.lookup_request("clk200", loose=True), 1e9/200e6)

View File

@ -0,0 +1,193 @@
#!/usr/bin/env python3
# This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
import os
import argparse
import sys
from migen import *
from migen.genlib.misc import WaitTimer
from litex.build import tools
from litex_boards.platforms import acorn_cle_215
from litex.soc.interconnect.csr import *
from litex.soc.integration.soc_core import *
from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
from litex.soc.integration.export import *
from litex.soc.cores.clock import *
from litex.soc.cores.dna import DNA
from litex.soc.cores.xadc import XADC
from litex.soc.cores.icap import ICAP
from litedram.modules import MT41K256M16
from litedram.phy import s7ddrphy
from litepcie.phy.s7pciephy import S7PCIEPHY
from litepcie.core import LitePCIeEndpoint, LitePCIeMSI
from litepcie.frontend.dma import LitePCIeDMA
from litepcie.frontend.wishbone import LitePCIeWishboneBridge
# CRG ----------------------------------------------------------------------------------------------
class CRG(Module, AutoCSR):
def __init__(self, platform, sys_clk_freq):
self.rst = CSR()
self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
self.clock_domains.cd_clk200 = ClockDomain()
# Clk/Rst
clk200 = platform.request("clk200")
# Delay software reset by 10us to ensure write has been acked on PCIe.
rst_delay = WaitTimer(int(10e-6*sys_clk_freq))
self.submodules += rst_delay
self.sync += If(self.rst.re, rst_delay.wait.eq(1))
# PLL
self.submodules.pll = pll = S7PLL()
self.comb += pll.reset.eq(rst_delay.done)
pll.register_clkin(clk200, 200e6)
pll.create_clkout(self.cd_sys, sys_clk_freq)
pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq)
pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90)
pll.create_clkout(self.cd_clk200, 200e6)
self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_clk200)
# PCIeSoC -----------------------------------------------------------------------------------------
class PCIeSoC(SoCCore):
def __init__(self, platform, **kwargs):
sys_clk_freq = int(100e6)
# SoCCore ----------------------------------------------------------------------------------
SoCCore.__init__(self, platform, sys_clk_freq,
ident = "LiteX SoC on Acorn CLE 215+",
ident_version = True,
**kwargs)
# CRG --------------------------------------------------------------------------------------
self.submodules.crg = CRG(platform, sys_clk_freq)
self.add_csr("crg")
# DNA --------------------------------------------------------------------------------------
self.submodules.dna = DNA()
self.dna.add_timing_constraints(platform, sys_clk_freq, self.crg.cd_sys.clk)
self.add_csr("dna")
# XADC -------------------------------------------------------------------------------------
self.submodules.xadc = XADC()
self.add_csr("xadc")
# ICAP -------------------------------------------------------------------------------------
self.submodules.icap = ICAP(platform)
self.icap.add_timing_constraints(platform, sys_clk_freq, self.crg.cd_sys.clk)
self.add_csr("icap")
# DDR3 SDRAM -------------------------------------------------------------------------------
if not self.integrated_main_ram_size:
self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"),
memtype = "DDR3",
nphases = 4,
sys_clk_freq = sys_clk_freq,
iodelay_clk_freq = 200e6)
self.add_csr("ddrphy")
self.add_sdram("sdram",
phy = self.ddrphy,
module = MT41K256M16(sys_clk_freq, "1:4"),
origin = self.mem_map["main_ram"],
size = kwargs.get("max_sdram_size", 0x40000000),
l2_cache_size = kwargs.get("l2_size", 8192),
l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128),
l2_cache_reverse = True
)
# PCIe -------------------------------------------------------------------------------------
# PHY
self.submodules.pcie_phy = S7PCIEPHY(platform, platform.request("pcie_x4"),
data_width = 64,
bar0_size = 0x20000)
platform.add_false_path_constraints(self.crg.cd_sys.clk, self.pcie_phy.cd_pcie.clk)
self.add_csr("pcie_phy")
# Endpoint
self.submodules.pcie_endpoint = LitePCIeEndpoint(self.pcie_phy)
# Wishbone bridge
self.submodules.pcie_bridge = LitePCIeWishboneBridge(self.pcie_endpoint,
base_address = self.mem_map["csr"])
self.add_wb_master(self.pcie_bridge.wishbone)
# DMA0
self.submodules.pcie_dma0 = LitePCIeDMA(self.pcie_phy, self.pcie_endpoint,
with_buffering = True, buffering_depth=1024,
with_loopback = True)
self.add_csr("pcie_dma0")
# DMA1
self.submodules.pcie_dma1 = LitePCIeDMA(self.pcie_phy, self.pcie_endpoint,
with_buffering = True, buffering_depth=1024,
with_loopback = True)
self.add_csr("pcie_dma1")
self.add_constant("DMA_CHANNELS", 2)
# MSI
self.submodules.pcie_msi = LitePCIeMSI()
self.add_csr("pcie_msi")
self.comb += self.pcie_msi.source.connect(self.pcie_phy.msi)
self.interrupts = {
"PCIE_DMA0_WRITER": self.pcie_dma0.writer.irq,
"PCIE_DMA0_READER": self.pcie_dma0.reader.irq,
"PCIE_DMA1_WRITER": self.pcie_dma1.writer.irq,
"PCIE_DMA1_READER": self.pcie_dma1.reader.irq,
}
for i, (k, v) in enumerate(sorted(self.interrupts.items())):
self.comb += self.pcie_msi.irqs[i].eq(v)
self.add_constant(k + "_INTERRUPT", i)
def generate_software_headers(self):
csr_header = get_csr_header(self.csr_regions, self.constants, with_access_functions=False)
tools.write_to_file("csr.h", csr_header)
soc_header = get_soc_header(self.constants, with_access_functions=False)
tools.write_to_file("soc.h", soc_header)
mem_header = get_mem_header(self.mem_regions)
tools.write_to_file("mem.h", mem_header)
# Build --------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="LiteX SoC on LiteX SoC on Acorn CLE 215+")
parser.add_argument("--build", action="store_true", help="Build bitstream")
parser.add_argument("--load", action="store_true", help="Load bitstream")
builder_args(parser)
soc_sdram_args(parser)
args = parser.parse_args()
# Enforce arguments
args.uart_name = "crossover"
args.csr_data_width = 32
platform = acorn_cle_215.Platform()
soc = PCIeSoC(platform, **soc_sdram_argdict(args))
builder = Builder(soc, **builder_argdict(args))
vns = builder.build(run=args.build)
soc.generate_software_headers()
if args.load:
prog = soc.platform.create_programmer()
prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit"))
if __name__ == "__main__":
main()