soc/interconnect: add AXILite SRAM
This commit is contained in:
parent
b692b2a3f1
commit
d8a242d86f
|
@ -743,19 +743,28 @@ class SoC(Module):
|
||||||
setattr(self.submodules, name, SoCController(**kwargs))
|
setattr(self.submodules, name, SoCController(**kwargs))
|
||||||
self.csr.add(name, use_loc_if_exists=True)
|
self.csr.add(name, use_loc_if_exists=True)
|
||||||
|
|
||||||
def add_ram(self, name, origin, size, contents=[], mode="rw"):
|
def add_ram(self, name, origin, size, contents=[], mode="rw", bus=None):
|
||||||
ram_bus = wishbone.Interface(data_width=self.bus.data_width)
|
if bus is None:
|
||||||
ram = wishbone.SRAM(size, bus=ram_bus, init=contents, read_only=(mode == "r"))
|
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.bus.add_slave(name, ram.bus, SoCRegion(origin=origin, size=size, mode=mode))
|
||||||
self.check_if_exists(name)
|
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(name),
|
||||||
colorer("added", color="green"),
|
colorer("added", color="green"),
|
||||||
self.bus.regions[name]))
|
self.bus.regions[name]))
|
||||||
setattr(self.submodules, name, ram)
|
setattr(self.submodules, name, ram)
|
||||||
|
|
||||||
def add_rom(self, name, origin, size, contents=[]):
|
def add_rom(self, name, origin, size, contents=[], bus=None):
|
||||||
self.add_ram(name, origin, size, contents, mode="r")
|
self.add_ram(name, origin, size, contents, mode="r", bus=bus)
|
||||||
|
|
||||||
def add_csr_bridge(self, origin):
|
def add_csr_bridge(self, origin):
|
||||||
self.submodules.csr_bridge = wishbone.Wishbone2CSR(
|
self.submodules.csr_bridge = wishbone.Wishbone2CSR(
|
||||||
|
|
|
@ -565,3 +565,92 @@ class AXILite2CSR(Module):
|
||||||
NextState("IDLE")
|
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")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue