integration/soc: Cosmetic cleanup pass.

This commit is contained in:
Florent Kermarrec 2021-03-25 09:13:43 +01:00
parent 6e23fb1d99
commit c9ac5424f4
1 changed files with 116 additions and 105 deletions

View File

@ -75,8 +75,8 @@ class SoCRegion:
raise
if (origin == 0) and (size == 2**bus.address_width):
return lambda a : True
origin >>= int(log2(bus.data_width//8)) # bytes to words aligned
size >>= int(log2(bus.data_width//8)) # bytes to words aligned
origin >>= int(log2(bus.data_width//8)) # bytes to words aligned.
size >>= int(log2(bus.data_width//8)) # bytes to words aligned.
return lambda a: (a[log2_int(size):] == (origin >> log2_int(size)))
def __str__(self):
@ -112,7 +112,7 @@ class SoCBusHandler(Module):
self.logger = logging.getLogger(name)
self.logger.info("Creating Bus Handler...")
# Check Standard
# Check Bus Standard.
if standard not in self.supported_standard:
self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
colorer("Bus standard", color="red"),
@ -120,7 +120,7 @@ class SoCBusHandler(Module):
colorer(", ".join(self.supported_standard))))
raise
# Check Data Width
# Check Bus Data Width.
if data_width not in self.supported_data_width:
self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
colorer("Data Width", color="red"),
@ -128,7 +128,7 @@ class SoCBusHandler(Module):
colorer(", ".join(str(x) for x in self.supported_data_width))))
raise
# Check Address Width
# Check Bus Address Width.
if address_width not in self.supported_address_width:
self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
colorer("Address Width", color="red"),
@ -148,7 +148,7 @@ class SoCBusHandler(Module):
self.logger.info("{}-bit {} Bus, {}GiB Address Space.".format(
colorer(data_width), colorer(standard), colorer(2**address_width/2**30)))
# Adding reserved regions
# Add reserved regions.
self.logger.info("Adding {} Bus Regions...".format(colorer("reserved", color="cyan")))
for name, region in reserved_regions.items():
if isinstance(region, int):
@ -164,9 +164,10 @@ class SoCBusHandler(Module):
self.logger.error("{} already declared as Region:".format(colorer(name, color="red")))
self.logger.error(self)
raise
# Check if SoCIORegion
# Check if is SoCIORegion.
if isinstance(region, SoCIORegion):
self.io_regions[name] = region
# Check for overlap with others IO regions.
overlap = self.check_regions_overlap(self.io_regions)
if overlap is not None:
self.logger.error("IO Region {} between {} and {}:".format(
@ -180,15 +181,16 @@ class SoCBusHandler(Module):
colorer(name, color="underline"),
colorer("added", color="green"),
str(region)))
# Check if SoCRegion
# Check if is SoCRegion
elif isinstance(region, SoCRegion):
# If no origin specified, allocate region.
# If no Origin specified, allocate Region.
if region.origin is None:
allocated = True
region = self.alloc_region(name, region.size, region.cached)
self.regions[name] = region
# Else add region and check for overlaps.
# Else add Region.
else:
# If Region is an IO Region is not cached.
if not region.cached:
if not self.check_region_is_io(region):
self.logger.error("{} Region {}: {}.".format(
@ -198,6 +200,7 @@ class SoCBusHandler(Module):
self.logger.error(self)
raise
self.regions[name] = region
# Check for overlab with others IO regions.
overlap = self.check_regions_overlap(self.regions)
if overlap is not None:
self.logger.error("Region {} between {} and {}:".format(
@ -220,27 +223,27 @@ class SoCBusHandler(Module):
colorer("Cached" if cached else "IO"),
colorer("0x{:08x}".format(size))))
# Limit Search Regions
# Limit Search Regions.
if cached == False:
search_regions = self.io_regions
else:
search_regions = {"main": SoCRegion(origin=0x00000000, size=2**self.address_width-1)}
# Iterate on Search_Regions to find a Candidate
# Iterate on Search_Regions to find a Candidate.
for _, search_region in search_regions.items():
origin = search_region.origin
while (origin + size) < (search_region.origin + search_region.size_pow2):
# Create a Candicate.
candidate = SoCRegion(origin=origin, size=size, cached=cached)
overlap = False
# Check Candidate does not overlap with allocated existing regions
# Check Candidate does not overlap with allocated existing regions.
for _, allocated in self.regions.items():
if self.check_regions_overlap({"0": allocated, "1": candidate}) is not None:
origin = allocated.origin + allocated.size_pow2
overlap = True
break
if not overlap:
# If no overlap, the Candidate is selected
# If no overlap, the Candidate is selected.
return candidate
self.logger.error("Not enough Address Space to allocate Region.")
@ -283,7 +286,7 @@ class SoCBusHandler(Module):
def add_adapter(self, name, interface, direction="m2s"):
assert direction in ["m2s", "s2m"]
# Data width conversion
# Data width conversion.
if interface.data_width != self.data_width:
interface_cls = type(interface)
converter_cls = {
@ -300,7 +303,7 @@ class SoCBusHandler(Module):
else:
converted_interface = interface
# Wishbone <-> AXILite bridging
# Wishbone <-> AXILite bridging.
main_bus_cls = {
"wishbone": wishbone.Interface,
"axi-lite": axi.AXILiteInterface,
@ -321,7 +324,7 @@ class SoCBusHandler(Module):
self.submodules += bridge
if type(interface) != type(bridged_interface) or interface.data_width != bridged_interface.data_width:
fmt = "{name} Bus {converted} from {frombus} {frombits}-bit to {tobus} {tobits}-bit."
fmt = "{name} Bus {converted} from {from_bus} {from_bits}-bit to {to_bus} {to_bits}-bit."
bus_names = {
wishbone.Interface: "Wishbone",
axi.AXILiteInterface: "AXI Lite",
@ -329,10 +332,10 @@ class SoCBusHandler(Module):
self.logger.info(fmt.format(
name = colorer(name),
converted = colorer("converted", color="cyan"),
frombus = colorer(bus_names[type(interface)]),
frombits = colorer(interface.data_width),
tobus = colorer(bus_names[type(bridged_interface)]),
tobits = colorer(bridged_interface.data_width)))
from_bus = colorer(bus_names[type(interface)]),
from_bits = colorer(interface.data_width),
to_bus = colorer(bus_names[type(bridged_interface)]),
to_bits = colorer(bridged_interface.data_width)))
return bridged_interface
def add_master(self, name=None, master=None):
@ -403,7 +406,7 @@ class SoCBusHandler(Module):
r = r[:-1]
return r
# SoCLocHandler --------------------------------------------------------------------------------------
# SoCLocHandler ------------------------------------------------------------------------------------
class SoCLocHandler(Module):
# Creation -------------------------------------------------------------------------------------
@ -487,7 +490,7 @@ class SoCCSRHandler(SoCLocHandler):
self.logger = logging.getLogger("SoCCSRHandler")
self.logger.info("Creating CSR Handler...")
# Check Data Width
# Check CSR Data Width.
if data_width not in self.supported_data_width:
self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
colorer("Data Width", color="red"),
@ -495,7 +498,7 @@ class SoCCSRHandler(SoCLocHandler):
colorer(", ".join(str(x) for x in self.supported_data_width))))
raise
# Check Address Width
# Check CSR Address Width.
if address_width not in self.supported_address_width:
self.logger.error("Unsupported {} {} supporteds: {:s}".format(
colorer("Address Width", color="red"),
@ -503,7 +506,7 @@ class SoCCSRHandler(SoCLocHandler):
colorer(", ".join(str(x) for x in self.supported_address_width))))
raise
# Check Alignment
# Check CSR Alignment.
if alignment not in self.supported_alignment:
self.logger.error("Unsupported {}: {} supporteds: {:s}".format(
colorer("Alignment", color="red"),
@ -517,7 +520,7 @@ class SoCCSRHandler(SoCLocHandler):
colorer(data_width)))
raise
# Check Paging
# Check CSR Paging.
if paging not in self.supported_paging:
self.logger.error("Unsupported {} 0x{}, supporteds: {:s}".format(
colorer("Paging", color="red"),
@ -525,7 +528,7 @@ class SoCCSRHandler(SoCLocHandler):
colorer(", ".join("0x{:x}".format(x) for x in self.supported_paging))))
raise
# Check Ordering
# Check CSR Ordering.
if ordering not in self.supported_ordering:
self.logger.error("Unsupported {} {}, supporteds: {:s}".format(
colorer("Ordering", color="red"),
@ -533,7 +536,7 @@ class SoCCSRHandler(SoCLocHandler):
colorer(", ".join("{}".format(x) for x in self.supported_ordering))))
raise
# Create CSR Handler
# Create CSR Handler.
self.data_width = data_width
self.address_width = address_width
self.alignment = alignment
@ -549,7 +552,7 @@ class SoCCSRHandler(SoCLocHandler):
colorer(self.ordering),
colorer(self.n_locs)))
# Adding reserved CSRs
# Add reserved CSRs.
self.logger.info("Adding {} CSRs...".format(colorer("reserved", color="cyan")))
for name, n in reserved_csrs.items():
self.add(name, n)
@ -618,16 +621,16 @@ class SoCIRQHandler(SoCLocHandler):
self.logger.info("Creating IRQ Handler...")
self.enabled = False
# Check IRQ Number
# Check IRQ Number.
if n_irqs > 32:
self.logger.error("Unsupported IRQs number: {} supporteds: {:s}".format(
colorer(n_irqs, color="red"), colorer("Up to 32", color="green")))
raise
# Create IRQ Handler
# Create IRQ Handler.
self.logger.info("IRQ Handler (up to {} Locations).".format(colorer(n_irqs)))
# Adding reserved IRQs
# Adding reserved IRQs.
self.logger.info("Adding {} IRQs...".format(colorer("reserved", color="cyan")))
for name, n in reserved_irqs.items():
self.add(name, n)
@ -657,11 +660,7 @@ class SoCIRQHandler(SoCLocHandler):
# SoCController ------------------------------------------------------------------------------------
class SoCController(Module, AutoCSR):
def __init__(self,
with_reset = True,
with_scratch = True,
with_errors = True):
def __init__(self, with_reset=True, with_scratch=True, with_errors=True):
if with_reset:
self._reset = CSRStorage(1, description="""Any write to this register will reset the SoC.""")
if with_scratch:
@ -848,13 +847,15 @@ class SoC(Module):
self.add_config("CSR_ALIGNMENT", self.csr.alignment)
def add_cpu(self, name="vexriscv", variant="standard", cls=None, reset_address=None):
# Check that CPU is supported.
if name not in cpu.CPUS.keys():
self.logger.error("{} CPU {}, supporteds: {}.".format(
colorer(name),
colorer("not supported", color="red"),
colorer(", ".join(cpu.CPUS.keys()))))
raise
# Add CPU
# Add CPU.
if name == "external" and cls is None:
self.logger.error("{} CPU requires {} to be specified.".format(
colorer(name),
@ -868,11 +869,13 @@ class SoC(Module):
colorer(", ".join(cpu_cls.variants))))
raise
self.submodules.cpu = cpu_cls(self.platform, variant)
# Update SoC with CPU constraints
# Update SoC with CPU constraints.
for n, (origin, size) in enumerate(self.cpu.io_regions.items()):
self.bus.add_region("io{}".format(n), SoCIORegion(origin=origin, size=size, cached=False))
self.mem_map.update(self.cpu.mem_map) # FIXME
# Add Bus Masters/CSR/IRQs
# Add Bus Masters/CSR/IRQs.
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000)):
if reset_address is None:
reset_address = self.mem_map["rom"]
@ -886,7 +889,7 @@ class SoC(Module):
self.irq.add(name, loc)
self.add_config("CPU_HAS_INTERRUPT")
# Create optional DMA Bus (for Cache Coherence)
# Create optional DMA Bus (for Cache Coherence).
if hasattr(self.cpu, "dma_bus"):
self.submodules.dma_bus = SoCBusHandler(
name = "SoCDMABusHandler",
@ -898,17 +901,17 @@ class SoC(Module):
self.dma_bus.add_slave("dma", slave=dma_bus, region=SoCRegion(origin=0x00000000, size=0x100000000)) # FIXME: covers lower 4GB only
self.submodules += wishbone.Converter(dma_bus, self.cpu.dma_bus)
# Connect SoCController's reset to CPU reset
# Connect SoCController's reset to CPU reset.
if hasattr(self, "ctrl"):
if hasattr(self.ctrl, "reset"):
self.comb += self.cpu.reset.eq(self.ctrl.reset)
self.add_config("CPU_RESET_ADDR", reset_address)
# Add CPU's SoC components (if any)
# Add CPU's SoC components (if any).
if hasattr(self.cpu, "add_soc_components"):
self.cpu.add_soc_components(soc=self, soc_region_cls=SoCRegion) # FIXME: avoid passing SoCRegion.
# Add constants
# Add constants.
self.add_config("CPU_TYPE", str(name))
self.add_config("CPU_VARIANT", str(variant.split('+')[0]))
self.add_constant("CONFIG_CPU_HUMAN_NAME", getattr(self.cpu, "human_name", "Unknown"))
@ -1018,24 +1021,24 @@ class SoC(Module):
masters = list(self.csr.masters.values()),
slaves = self.csr_bankarray.get_buses())
# Add CSRs regions
# Add CSRs regions.
for name, csrs, mapaddr, rmap in self.csr_bankarray.banks:
self.csr.add_region(name, SoCCSRRegion(
origin = (self.bus.regions["csr"].origin + self.csr.paging*mapaddr),
busword = self.csr.data_width,
obj = csrs))
# Add Memory regions
# Add Memory regions.
for name, memory, mapaddr, mmap in self.csr_bankarray.srams:
self.csr.add_region(name + "_" + memory.name_override, SoCCSRRegion(
origin = (self.bus.regions["csr"].origin + self.csr.paging*mapaddr),
busword = self.csr.data_width,
obj = memory))
# Sort CSR regions by origin
# Sort CSR regions by origin.
self.csr.regions = {k: v for k, v in sorted(self.csr.regions.items(), key=lambda item: item[1].origin)}
# Add CSRs / Config items to constants
# Add CSRs / Config items to constants.
for name, constant in self.csr_bankarray.constants:
self.add_constant(name + "_" + constant.name, constant.value.value)
@ -1100,37 +1103,37 @@ class LiteXSoC(SoC):
def add_uart(self, name, baudrate=115200, fifo_depth=16):
from litex.soc.cores import uart
# Stub / Stream
# Stub / Stream.
if name in ["stub", "stream"]:
self.submodules.uart = uart.UART(tx_fifo_depth=0, rx_fifo_depth=0)
if name == "stub":
self.comb += self.uart.sink.ready.eq(1)
# UARTBone / Bridge
# UARTBone / Bridge.
elif name in ["uartbone", "bridge"]:
self.add_uartbone(baudrate=baudrate)
# Crossover
# Crossover.
elif name in ["crossover"]:
self.submodules.uart = uart.UARTCrossover(
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth)
# Crossover + Bridge
# Crossover + Bridge.
elif name in ["crossover+bridge"]:
self.add_uartbone(baudrate=baudrate)
self.submodules.uart = uart.UARTCrossover(
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth)
# Model/Sim
# Model/Sim.
elif name in ["model", "sim"]:
self.submodules.uart_phy = uart.RS232PHYModel(self.platform.request("serial"))
self.submodules.uart = uart.UART(self.uart_phy,
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth)
# JTAG Atlantic
# JTAG Atlantic.
elif name in ["jtag_atlantic"]:
from litex.soc.cores.jtag import JTAGAtlantic
self.submodules.uart_phy = JTAGAtlantic()
@ -1138,7 +1141,7 @@ class LiteXSoC(SoC):
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth)
# JTAG UART
# JTAG UART.
elif name in ["jtag_uart"]:
from litex.soc.cores.jtag import JTAGPHY
self.clock_domains.cd_sys_jtag = ClockDomain() # Run JTAG-UART in sys_jtag clock domain similar to
@ -1148,7 +1151,7 @@ class LiteXSoC(SoC):
tx_fifo_depth = fifo_depth,
rx_fifo_depth = fifo_depth)
# USB ACM (with ValentyUSB core)
# USB ACM (with ValentyUSB core).
elif name in ["usb_acm"]:
import valentyusb.usbcore.io as usbio
import valentyusb.usbcore.cpu.cdc_eptri as cdc_eptri
@ -1158,7 +1161,7 @@ class LiteXSoC(SoC):
self.comb += self.cd_sys_usb.clk.eq(ClockSignal("sys")) # sys clock domain but with rst disconnected.
self.submodules.uart = ClockDomainsRenamer("sys_usb")(cdc_eptri.CDCUsb(usb_iobuf))
# Classic UART
# Classical UART.
else:
self.submodules.uart_phy = uart.UARTPHY(
pads = self.platform.request(name),
@ -1201,14 +1204,14 @@ class LiteXSoC(SoC):
l2_cache_full_memory_we = True,
**kwargs):
# Imports
# Imports.
from litedram.common import LiteDRAMNativePort
from litedram.core import LiteDRAMCore
from litedram.frontend.wishbone import LiteDRAMWishbone2Native
from litedram.frontend.axi import LiteDRAMAXI2Native
from litedram.frontend.bist import LiteDRAMBISTGenerator, LiteDRAMBISTChecker
# LiteDRAM core
# LiteDRAM core.
self.submodules.sdram = LiteDRAMCore(
phy = phy,
geom_settings = module.geom_settings,
@ -1217,9 +1220,9 @@ class LiteXSoC(SoC):
**kwargs)
self.csr.add("sdram", use_loc_if_exists=True)
# Save SPD data to be able to verify it at runtime
# Save SPD data to be able to verify it at runtime.
if hasattr(module, "_spd_data"):
# pack the data into words of bus width
# Pack the data into words of bus width.
bytes_per_word = self.bus.data_width // 8
mem = [0] * ceil(len(module._spd_data) / bytes_per_word)
for i in range(len(mem)):
@ -1237,7 +1240,7 @@ class LiteXSoC(SoC):
contents = mem,
)
# LiteDRAM BIST
# LiteDRAM BIST.
if with_bist:
self.submodules.sdram_generator = LiteDRAMBISTGenerator(self.sdram.crossbar.get_port())
self.csr.add("sdram_generator")
@ -1246,14 +1249,14 @@ class LiteXSoC(SoC):
if not with_soc_interconnect: return
# Compute/Check SDRAM size
# Compute/Check SDRAM size.
sdram_size = 2**(module.geom_settings.bankbits +
module.geom_settings.rowbits +
module.geom_settings.colbits)*phy.settings.databits//8
if size is not None:
sdram_size = min(sdram_size, size)
# Add SDRAM region
# Add SDRAM region.
self.bus.add_region("main_ram", SoCRegion(origin=origin, size=sdram_size))
# Add CPU's direct memory buses (if not already declared) ----------------------------------
@ -1285,11 +1288,11 @@ class LiteXSoC(SoC):
self.logger.info("Converting MEM data width: {} to {} via Wishbone".format(
port.data_width,
self.cpu.mem_axi.data_width))
# FIXME: replace WB data-width converter with native AXI converter!!!
# FIXME: Replace WB data-width converter with native AXI converter.
mem_wb = wishbone.Interface(
data_width = self.cpu.mem_axi.data_width,
adr_width = 32-log2_int(self.cpu.mem_axi.data_width//8))
# NOTE: AXI2Wishbone FSMs must be reset with the CPU!
# FIXME: AXI2Wishbone FSMs must be reset with the CPU.
mem_a2w = ResetInserter()(axi.AXI2Wishbone(
axi = self.cpu.mem_axi,
wishbone = mem_wb,
@ -1349,7 +1352,7 @@ class LiteXSoC(SoC):
self.submodules += wishbone.Converter(wb_sdram, litedram_wb)
self.add_config("L2_SIZE", l2_cache_size)
# Wishbone Slave <--> LiteDRAM bridge
# Wishbone Slave <--> LiteDRAM bridge.
self.submodules.wishbone_bridge = LiteDRAMWishbone2Native(
wishbone = litedram_wb,
port = port,
@ -1361,23 +1364,26 @@ class LiteXSoC(SoC):
from liteeth.mac import LiteEthMAC
from liteeth.phy.model import LiteEthPHYModel
# MAC
# MAC.
ethmac = LiteEthMAC(
phy = phy,
dw = 32,
interface = "wishbone",
endianness = self.cpu.endianness,
with_preamble_crc = not software_debug,
nrxslots = nrxslots,
ntxslots = ntxslots)
ntxslots = ntxslots,
with_preamble_crc = not software_debug)
# Use PHY's eth_tx/eth_rx clock domains.
ethmac = ClockDomainsRenamer({
"eth_tx": phy_cd + "_tx",
"eth_rx": phy_cd + "_rx"})(ethmac)
setattr(self.submodules, name, ethmac)
ethmac_region_size = (ethmac.rx_slots.read()+ethmac.tx_slots.read())*ethmac.slot_size.read()
# Compute Regions size and add it to the SoC.
ethmac_region_size = (ethmac.rx_slots.read() + ethmac.tx_slots.read())*ethmac.slot_size.read()
ethmac_region = SoCRegion(origin=self.mem_map.get(name, None), size=ethmac_region_size, cached=False)
self.bus.add_slave(name=name, slave=ethmac.bus, region=ethmac_region)
self.csr.add(name, use_loc_if_exists=True)
# Add IRQs (if enabled).
if self.irq.enabled:
self.irq.add(name, use_loc_if_exists=True)
@ -1389,6 +1395,7 @@ class LiteXSoC(SoC):
self.platform.add_period_constraint(eth_tx_clk, 1e9/phy.tx_clk_freq)
self.platform.add_false_path_constraints(self.crg.cd_sys.clk, eth_rx_clk, eth_tx_clk)
# Dynamic IP (if enabled).
if dynamic_ip:
self.add_constant("ETH_DYNAMIC_IP")
@ -1414,13 +1421,14 @@ class LiteXSoC(SoC):
mac_address = mac_address,
ip_address = ip_address,
clk_freq = self.clk_freq)
# Use PHY's eth_tx/eth_rx clock domains.
ethcore = ClockDomainsRenamer({
"eth_tx": phy_cd + "_tx",
"eth_rx": phy_cd + "_rx",
"sys": phy_cd + "_rx"})(ethcore)
self.submodules.ethcore = ethcore
# Clock domain renaming
# Create Etherbone clock domain and run it from sys clock domain.
self.clock_domains.cd_etherbone = ClockDomain("etherbone")
self.comb += self.cd_etherbone.clk.eq(ClockSignal("sys"))
self.comb += self.cd_etherbone.rst.eq(ResetSignal("sys"))
@ -1483,14 +1491,16 @@ class LiteXSoC(SoC):
# Add SDCard -----------------------------------------------------------------------------------
def add_sdcard(self, name="sdcard", mode="read+write", use_emulator=False, software_debug=False):
assert mode in ["read", "write", "read+write"]
# Imports
# Imports.
from litesdcard.emulator import SDEmulator
from litesdcard.phy import SDPHY
from litesdcard.core import SDCore
from litesdcard.frontend.dma import SDBlock2MemDMA, SDMem2BlockDMA
# Emulator / Pads
# Checks.
assert mode in ["read", "write", "read+write"]
# Emulator / Pads.
if use_emulator:
sdemulator = SDEmulator(self.platform)
self.submodules += sdemulator
@ -1498,13 +1508,13 @@ class LiteXSoC(SoC):
else:
sdcard_pads = self.platform.request(name)
# Core
# Core.
self.submodules.sdphy = SDPHY(sdcard_pads, self.platform.device, self.clk_freq, cmd_timeout=10e-1, data_timeout=10e-1)
self.submodules.sdcore = SDCore(self.sdphy)
self.csr.add("sdphy", use_loc_if_exists=True)
self.csr.add("sdcore", use_loc_if_exists=True)
# Block2Mem DMA
# Block2Mem DMA.
if "read" in mode:
bus = wishbone.Interface(data_width=self.bus.data_width, adr_width=self.bus.address_width)
self.submodules.sdblock2mem = SDBlock2MemDMA(bus=bus, endianness=self.cpu.endianness)
@ -1513,7 +1523,7 @@ class LiteXSoC(SoC):
dma_bus.add_master("sdblock2mem", master=bus)
self.csr.add("sdblock2mem", use_loc_if_exists=True)
# Mem2Block DMA
# Mem2Block DMA.
if "write" in mode:
bus = wishbone.Interface(data_width=self.bus.data_width, adr_width=self.bus.address_width)
self.submodules.sdmem2block = SDMem2BlockDMA(bus=bus, endianness=self.cpu.endianness)
@ -1522,7 +1532,7 @@ class LiteXSoC(SoC):
dma_bus.add_master("sdmem2block", master=bus)
self.csr.add("sdmem2block", use_loc_if_exists=True)
# Interrupts
# Interrupts.
self.submodules.sdirq = EventManager()
self.sdirq.card_detect = EventSourcePulse(description="SDCard has been ejected/inserted.")
self.sdirq.block2mem_dma = EventSourcePulse(description="Block2Mem DMA terminated.")
@ -1535,18 +1545,18 @@ class LiteXSoC(SoC):
self.sdirq.mem2block_dma.trigger.eq(self.sdmem2block.irq),
]
# Software Debug
# Debug.
if software_debug:
self.add_constant("SDCARD_DEBUG")
# Add SATA -------------------------------------------------------------------------------------
def add_sata(self, name="sata", phy=None, mode="read+write"):
# Imports
# Imports.
from litesata.core import LiteSATACore
from litesata.frontend.arbitration import LiteSATACrossbar
from litesata.frontend.dma import LiteSATASector2MemDMA, LiteSATAMem2SectorDMA
# Checks
# Checks.
assert mode in ["read", "write", "read+write"]
sata_clk_freqs = {
"gen1": 75e6,
@ -1556,13 +1566,13 @@ class LiteXSoC(SoC):
sata_clk_freq = sata_clk_freqs[phy.gen]
assert self.clk_freq >= sata_clk_freq/2 # FIXME: /2 for 16-bit data-width, add support for 32-bit.
# Core
# Core.
self.submodules.sata_core = LiteSATACore(phy)
# Crossbar
# Crossbar.
self.submodules.sata_crossbar = LiteSATACrossbar(self.sata_core)
# Sector2Mem DMA
# Sector2Mem DMA.
if "read" in mode:
bus = wishbone.Interface(data_width=self.bus.data_width, adr_width=self.bus.address_width)
self.submodules.sata_sector2mem = LiteSATASector2MemDMA(
@ -1573,7 +1583,7 @@ class LiteXSoC(SoC):
dma_bus.add_master("sata_sector2mem", master=bus)
self.csr.add("sata_sector2mem", use_loc_if_exists=True)
# Mem2Sector DMA
# Mem2Sector DMA.
if "write" in mode:
bus = wishbone.Interface(data_width=self.bus.data_width, adr_width=self.bus.address_width)
self.submodules.sata_mem2sector = LiteSATAMem2SectorDMA(
@ -1584,7 +1594,7 @@ class LiteXSoC(SoC):
dma_bus.add_master("sata_mem2sector", master=bus)
self.csr.add("sata_mem2sector", use_loc_if_exists=True)
# Timing constraints
# Timing constraints.
self.platform.add_period_constraint(self.sata_phy.crg.cd_sata_tx.clk, 1e9/sata_clk_freq)
self.platform.add_period_constraint(self.sata_phy.crg.cd_sata_rx.clk, 1e9/sata_clk_freq)
self.platform.add_false_path_constraints(
@ -1594,24 +1604,25 @@ class LiteXSoC(SoC):
# Add PCIe -------------------------------------------------------------------------------------
def add_pcie(self, name="pcie", phy=None, ndmas=0, max_pending_requests=8, with_msi=True):
assert self.csr.data_width == 32
assert not hasattr(self, f"{name}_endpoint")
# Imports
from litepcie.core import LitePCIeEndpoint, LitePCIeMSI
from litepcie.frontend.dma import LitePCIeDMA
from litepcie.frontend.wishbone import LitePCIeWishboneMaster
# Endpoint
# Checks.
assert self.csr.data_width == 32
assert not hasattr(self, f"{name}_endpoint")
# Endpoint.
endpoint = LitePCIeEndpoint(phy, max_pending_requests=max_pending_requests)
setattr(self.submodules, f"{name}_endpoint", endpoint)
# MMAP
# MMAP.
mmap = LitePCIeWishboneMaster(self.pcie_endpoint, base_address=self.mem_map["csr"])
self.add_wb_master(mmap.wishbone)
setattr(self.submodules, f"{name}_mmap", mmap)
# MSI
# MSI.
if with_msi:
msi = LitePCIeMSI()
setattr(self.submodules, f"{name}_msi", msi)
@ -1619,7 +1630,7 @@ class LiteXSoC(SoC):
self.comb += msi.source.connect(phy.msi)
self.msis = {}
# DMAs
# DMAs.
for i in range(ndmas):
assert with_msi
dma = LitePCIeDMA(phy, endpoint,
@ -1631,13 +1642,13 @@ class LiteXSoC(SoC):
self.msis[f"{name.upper()}_DMA{i}_READER"] = dma.reader.irq
self.add_constant("DMA_CHANNELS", ndmas)
# Map/Connect IRQs
# Map/Connect IRQs.
if with_msi:
for i, (k, v) in enumerate(sorted(self.msis.items())):
self.comb += msi.irqs[i].eq(v)
self.add_constant(k + "_INTERRUPT", i)
# Timing constraints
# Timing constraints.
self.platform.add_false_path_constraints(self.crg.cd_sys.clk, phy.cd_pcie.clk)
# Add Video ColorBars Pattern ------------------------------------------------------------------