diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 536f97ab5a..531d2e0761 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -488,6 +488,32 @@ def add_remapper(self, name, interface, origin, size): )) return adapted_interface + + # Add Offset --------------------------------------------------------------------------------- + def add_offset(self, name, interface, offset): + interface_cls = type(interface) + offset_cls = { + wishbone.Interface : wishbone.Offset, + axi.AXILiteInterface : axi.AXILiteOffset, + axi.AXIInterface : axi.AXIOffset, + }[interface_cls] + + adapted_interface = interface_cls( + data_width = interface.data_width, + address_width = interface.address_width, + addressing = interface.addressing, + ) + + self.submodules += offset_cls(adapted_interface, interface, offset) + + fmt = "{name} Bus {offseted} by {offset}." + self.logger.info(fmt.format( + name = colorer(name), + offseted = colorer("offseted", color="cyan"), + offset = colorer(f"0x{offset:08x}"), + )) + + return adapted_interface def add_master(self, name=None, master=None, region=None): if name is None: @@ -509,7 +535,7 @@ def add_master(self, name=None, master=None, region=None): def add_controller(self, name=None, controller=None): self.add_master(self, name=name, master=controller) - def add_slave(self, name=None, slave=None, region=None): + def add_slave(self, name=None, slave=None, region=None, offset_base=False): no_name = name is None no_region = region is None if no_name and no_region: @@ -535,6 +561,8 @@ def add_slave(self, name=None, slave=None, region=None): colorer("already declared", color="red"))) self.logger.error(self) raise SoCError() + if offset_base: + slave = self.add_offset(name, slave, region.origin) slave = self.add_adapter(name, slave, "s2m") self.slaves[name] = slave self.logger.info("{} {} as Bus Slave.".format( @@ -2097,8 +2125,7 @@ def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=20e6, module=None, spiflash_core = LiteSPI(spiflash_phy, mmap_endianness=self.cpu.endianness, **kwargs) self.add_module(name=f"{name}_core", module=spiflash_core) spiflash_region = SoCRegion(origin=self.mem_map.get(name, None), size=module.total_size) - self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region) - self.comb += spiflash_core.mmap.offset.eq(self.bus.regions.get(name, None).origin) + self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region, offset_base=True) # Constants. self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq) @@ -2145,8 +2172,7 @@ def add_spi_ram(self, name="spiram", mode="4x", clk_freq=20e6, module=None, phy= # Create Wishbone Slave. wb_spiram = wishbone.Interface(data_width=32, address_width=32, addressing="word") - self.bus.add_slave(name=name, slave=wb_spiram, region=spiram_region) - self.comb += spiram_core.mmap.offset.eq(self.bus.regions.get(name, None).origin) + self.bus.add_slave(name=name, slave=wb_spiram, region=spiram_region, offset_base=True) # L2 Cache if l2_cache_size != 0: diff --git a/litex/soc/interconnect/axi/axi_full.py b/litex/soc/interconnect/axi/axi_full.py index 0c6c151fcd..236a75047d 100644 --- a/litex/soc/interconnect/axi/axi_full.py +++ b/litex/soc/interconnect/axi/axi_full.py @@ -155,6 +155,17 @@ def __init__(self, master, slave, origin=0, size=None): self.comb += slave.aw.addr.eq(origin | master.aw.addr & mask) self.comb += slave.ar.addr.eq(origin | master.ar.addr & mask) +# AXI Offset --------------------------------------------------------------------------------------- + +class AXIOffset(LiteXModule): + """Removes offset from AXI addresses.""" + def __init__(self, master, slave, offset=0x00000000): + + # Address Mask and Shift. + self.comb += master.connect(slave) + self.comb += slave.aw.addr.eq(master.aw.addr - offset) + self.comb += slave.ar.addr.eq(master.ar.addr - offset) + # AXI Bursts to Beats ------------------------------------------------------------------------------ class AXIBurst2Beat(LiteXModule): diff --git a/litex/soc/interconnect/axi/axi_lite.py b/litex/soc/interconnect/axi/axi_lite.py index b5aa754a3c..2c06a6c0ca 100644 --- a/litex/soc/interconnect/axi/axi_lite.py +++ b/litex/soc/interconnect/axi/axi_lite.py @@ -147,6 +147,17 @@ def __init__(self, master, slave, origin=0, size=None): self.comb += slave.aw.addr.eq(origin | master.aw.addr & mask) self.comb += slave.ar.addr.eq(origin | master.ar.addr & mask) +# AXI-Lite Offset ---------------------------------------------------------------------------------- + +class AXILiteOffset(LiteXModule): + """Removes offset from AXI Lite addresses.""" + def __init__(self, master, slave, offset=0x00000000): + + # Address Mask and Shift. + self.comb += master.connect(slave) + self.comb += slave.aw.addr.eq(master.aw.addr - offset) + self.comb += slave.ar.addr.eq(master.ar.addr - offset) + # AXI-Lite to Simple Bus --------------------------------------------------------------------------- def axi_lite_to_simple(axi_lite, port_adr, port_dat_r, port_dat_w=None, port_re=None, port_we=None): diff --git a/litex/soc/interconnect/wishbone.py b/litex/soc/interconnect/wishbone.py index da70fdc31e..74ab2aa9da 100644 --- a/litex/soc/interconnect/wishbone.py +++ b/litex/soc/interconnect/wishbone.py @@ -182,6 +182,26 @@ def __init__(self, master, slave, origin=0, size=None, src_regions=[], dst_regio If(active, slave.adr.eq(dst_adr >> adr_shift)) ] +# Wishbone Offset -------------------------------------------------------------------------------- + +class Offset(Module): + """Removes offset from Wishbone addresses.""" + def __init__(self, master, slave, offset=0x00000000): + # Parameters. + # ----------- + assert master.addressing == slave.addressing + + # Master to Slave. + # ---------------- + self.comb += master.connect(slave) + + # Origin Remapping. + # ----------------- + if master.addressing == "word": + offset >>= int(log2(len(master.dat_w)//8)) + # Apply Address Origin/Mask Remapping. + self.comb += slave.adr.eq(master.adr - offset) + # Wishbone Timeout --------------------------------------------------------------------------------- class Timeout(LiteXModule):