From d8a242d86f56ff02c676f5678e060966840e0749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Boczar?= Date: Wed, 15 Jul 2020 10:58:34 +0200 Subject: [PATCH] soc/interconnect: add AXILite SRAM --- litex/soc/integration/soc.py | 21 ++++++--- litex/soc/interconnect/axi.py | 89 +++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 6 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 7111921cd..28ee0cc22 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -743,19 +743,28 @@ class SoC(Module): setattr(self.submodules, name, SoCController(**kwargs)) self.csr.add(name, use_loc_if_exists=True) - def add_ram(self, name, origin, size, contents=[], mode="rw"): - ram_bus = wishbone.Interface(data_width=self.bus.data_width) - ram = wishbone.SRAM(size, bus=ram_bus, init=contents, read_only=(mode == "r")) + def add_ram(self, name, origin, size, contents=[], mode="rw", bus=None): + if bus is None: + bus = wishbone.Interface(data_width=self.bus.data_width) + + if isinstance(bus, wishbone.Interface): + ram = wishbone.SRAM(size, bus=bus, init=contents, read_only=(mode == "r")) + elif isinstance(bus, axi.AXILiteInterface): + ram = axi.AXILiteSRAM(size, bus=bus, init=contents, read_only=(mode == "r")) + else: + raise TypeError(bus) + self.bus.add_slave(name, ram.bus, SoCRegion(origin=origin, size=size, mode=mode)) self.check_if_exists(name) - self.logger.info("RAM {} {} {}.".format( + self.logger.info("{} RAM {} {} {}.".format( + colorer("Wishbone" if isinstance(bus, wishbone.Interface) else "AXILite"), colorer(name), colorer("added", color="green"), self.bus.regions[name])) setattr(self.submodules, name, ram) - def add_rom(self, name, origin, size, contents=[]): - self.add_ram(name, origin, size, contents, mode="r") + def add_rom(self, name, origin, size, contents=[], bus=None): + self.add_ram(name, origin, size, contents, mode="r", bus=bus) def add_csr_bridge(self, origin): self.submodules.csr_bridge = wishbone.Wishbone2CSR( diff --git a/litex/soc/interconnect/axi.py b/litex/soc/interconnect/axi.py index 83f5044bf..a9ee719ca 100644 --- a/litex/soc/interconnect/axi.py +++ b/litex/soc/interconnect/axi.py @@ -565,3 +565,92 @@ class AXILite2CSR(Module): NextState("IDLE") ) ) + +# AXILite SRAM ------------------------------------------------------------------------------------- + +class AXILiteSRAM(Module): + def __init__(self, mem_or_size, read_only=None, init=None, bus=None): + if bus is None: + bus = AXILiteInterface() + self.bus = bus + + bus_data_width = len(self.bus.r.data) + if isinstance(mem_or_size, Memory): + assert(mem_or_size.width <= bus_data_width) + self.mem = mem_or_size + else: + self.mem = Memory(bus_data_width, mem_or_size//(bus_data_width//8), init=init) + + if read_only is None: + if hasattr(self.mem, "bus_read_only"): + read_only = self.mem.bus_read_only + else: + read_only = False + + ### + + # Create memory port + port = self.mem.get_port(write_capable=not read_only, we_granularity=8, + mode=READ_FIRST if read_only else WRITE_FIRST) + self.specials += self.mem, port + + # Generate write enable signal + if not read_only: + self.comb += port.dat_w.eq(self.bus.w.data), + self.comb += [port.we[i].eq(self.bus.w.valid & self.bus.w.ready & self.bus.w.strb[i]) + for i in range(bus_data_width//8)] + + # Access logic + adr_shift = log2_int(self.bus.data_width//8) + rdata = Signal.like(port.dat_r) + do_read = Signal() + do_write = Signal() + last_was_read = Signal() + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + # if last access was a read, do a write, and vice versa + If(self.bus.aw.valid & self.bus.ar.valid, + do_write.eq(last_was_read), + do_read.eq(~last_was_read), + ).Else( + do_write.eq(self.bus.aw.valid), + do_read.eq(self.bus.ar.valid), + ), + If(do_write, + NextValue(last_was_read, 0), + NextState("DO-WRITE"), + ).Elif(do_read, + port.adr.eq(self.bus.ar.addr[adr_shift:]), + NextValue(last_was_read, 1), + NextState("DO-READ"), + ) + ) + fsm.act("DO-READ", + self.bus.ar.ready.eq(1), + NextValue(rdata, port.dat_r), + NextState("SEND-READ-RESPONSE"), + ) + fsm.act("SEND-READ-RESPONSE", + self.bus.r.valid.eq(1), + self.bus.r.resp.eq(RESP_OKAY), + self.bus.r.data.eq(rdata), + If(self.bus.r.ready, + NextState("IDLE") + ) + ) + fsm.act("DO-WRITE", + port.adr.eq(self.bus.aw.addr[adr_shift:]), + If(self.bus.w.valid, + self.bus.aw.ready.eq(1), + self.bus.w.ready.eq(1), + NextState("SEND-WRITE-RESPONSE") + ) + ) + fsm.act("SEND-WRITE-RESPONSE", + self.bus.b.valid.eq(1), + self.bus.b.resp.eq(RESP_OKAY), + If(self.bus.b.ready, + NextState("IDLE") + ) + )