You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.4 KiB
Python

# Typically LPC FW reads/writes directly access system memory of a
# CPU. These accesses need to be offset and windowed to ensure the LPC
# access can only access what the CPU wants it to.
#
# This modules takes a wishbone master from the LPC for firmware
# reads/writes and translates it into something that can be used for
# DMA access into another master wishbone bus. Base and mask registers
# (accessible via an IO wishbone bus) configure this
from nmigen import Elaboratable, Module, Signal
from nmigen_soc.wishbone import Interface as WishboneInterface
from nmigen_soc.csr import Multiplexer as CSRMultiplexer
from nmigen_soc.csr import Element as CSRElement
from nmigen_soc.csr.wishbone import WishboneCSRBridge
from nmigen.back import verilog
class LPC_Ctrl(Elaboratable):
def __init__(self):
self.io_wb = WishboneInterface(data_width=32, addr_width=2, granularity=8)
self.lpc_wb = WishboneInterface(data_width=32, addr_width=26, granularity=8)
self.dma_wb = WishboneInterface(data_width=32, addr_width=30, granularity=8)
def elaborate(self, platform):
m = Module()
base_lo_csr = CSRElement(32, "rw")
base_lo = Signal(32, reset=192*1024*1024)
# Leave space for upper 32 bits, unused for now
base_hi_csr = CSRElement(32, "rw")
mask_lo_csr = CSRElement(32, "rw")
mask_lo = Signal(32, reset=0x3FFFFFF)
# Leave space for upper 32 bits, unused for now
mask_hi_csr = CSRElement(32, "rw")
m.submodules.mux = mux = CSRMultiplexer(addr_width=2, data_width=32)
mux.add(base_lo_csr)
mux.add(base_hi_csr)
mux.add(mask_lo_csr)
mux.add(mask_hi_csr)
m.submodules.bridge = bridge = WishboneCSRBridge(mux.bus)
m.d.comb += self.io_wb.connect(bridge.wb_bus)
m.d.comb += [
base_lo_csr.r_data.eq(base_lo),
mask_lo_csr.r_data.eq(mask_lo),
]
with m.If(base_lo_csr.w_stb):
m.d.sync += base_lo.eq(base_lo_csr.w_data)
with m.If(mask_lo_csr.w_stb):
m.d.sync += mask_lo.eq(mask_lo_csr.w_data)
m.d.comb += [
self.lpc_wb.connect(self.dma_wb),
# bask/mask are in bytes, so convert to wishbone addresses
self.dma_wb.adr.eq((self.lpc_wb.adr & (mask_lo >> 2)) | (base_lo >> 2))
]
return m
if __name__ == "__main__":
top = LPC_Ctrl()
with open("lpc_ctrl.v", "w") as f:
f.write(verilog.convert(top))