soc/interconnect: add AXILite SRAM

This commit is contained in:
Jędrzej Boczar 2020-07-15 10:58:34 +02:00
parent b692b2a3f1
commit d8a242d86f
2 changed files with 104 additions and 6 deletions

View File

@ -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(

View File

@ -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")
)
)