forked from M-Labs/artiq-zynq
moved AXI SRAM to migen-axi
This commit is contained in:
parent
7b868e1c9d
commit
e43684a3ed
@ -1,163 +1,13 @@
|
|||||||
"""Auxiliary controller, common to satellite and master"""
|
"""Auxiliary controller, common to satellite and master"""
|
||||||
|
|
||||||
from operator import attrgetter
|
|
||||||
|
|
||||||
from migen import *
|
|
||||||
from migen.fhdl.simplify import FullMemoryWE
|
|
||||||
|
|
||||||
from misoc.interconnect.csr import *
|
|
||||||
from migen_axi.interconnect import axi
|
|
||||||
from artiq.gateware.drtio.aux_controller import Transmitter, Receiver
|
from artiq.gateware.drtio.aux_controller import Transmitter, Receiver
|
||||||
|
from migen.fhdl.simplify import FullMemoryWE
|
||||||
|
from misoc.interconnect.csr import *
|
||||||
|
from migen_axi.interconnect.sram import SRAM
|
||||||
|
from migen_axi.interconnect import axi
|
||||||
|
|
||||||
max_packet = 1024
|
max_packet = 1024
|
||||||
|
|
||||||
OUT_BURST_LEN = 10
|
|
||||||
IN_BURST_LEN = 4
|
|
||||||
|
|
||||||
class SRAM(Module):
|
|
||||||
def __init__(self, mem_or_size, read_only=False, init=None, bus=None):
|
|
||||||
|
|
||||||
# SRAM initialisation
|
|
||||||
|
|
||||||
if bus is None:
|
|
||||||
bus = axi.Interface()
|
|
||||||
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)
|
|
||||||
|
|
||||||
# memory
|
|
||||||
port = self.mem.get_port(write_capable=not read_only, we_granularity=8)
|
|
||||||
self.specials += self.mem, port
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
ar, aw, w, r, b = attrgetter("ar", "aw", "w", "r", "b")(bus)
|
|
||||||
|
|
||||||
# Dout : Data received from CPU, output by SRAM <- port.dat_r
|
|
||||||
# Din : Data driven into SRAM, written into CPU <- port.dat_w
|
|
||||||
self.dout_index = Signal.like(ar.len)
|
|
||||||
|
|
||||||
self.r_addr_incr = axi.Incr(ar)
|
|
||||||
self.w_addr_incr = axi.Incr(aw)
|
|
||||||
|
|
||||||
### Read
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
r.data.eq(port.dat_r),
|
|
||||||
port.adr.eq(self.r_addr_incr.addr)
|
|
||||||
]
|
|
||||||
|
|
||||||
# read control
|
|
||||||
self.submodules.read_fsm = read_fsm = FSM(reset_state="IDLE")
|
|
||||||
read_fsm.act("IDLE",
|
|
||||||
If(ar.valid,
|
|
||||||
port.adr.eq(self.r_addr_incr.addr),
|
|
||||||
ar.ready.eq(1),
|
|
||||||
NextState("READ_START"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
read_fsm.act("READ_START",
|
|
||||||
r.resp.eq(axi.Response.okay.value),
|
|
||||||
r.valid.eq(1),
|
|
||||||
If(r.ready,
|
|
||||||
NextState("READ"))
|
|
||||||
)
|
|
||||||
read_fsm.act("READ",
|
|
||||||
If(r.last & r.ready, # that's a smart way of skipping "LAST" state
|
|
||||||
NextState("IDLE")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.sync += [
|
|
||||||
If(read_fsm.ongoing("IDLE"),
|
|
||||||
self.dout_index.eq(0),
|
|
||||||
r.valid.eq(0), # shall it be reset too on IDLE?
|
|
||||||
ar.ready.eq(0),
|
|
||||||
r.last.eq(0)
|
|
||||||
).Else(If(r.ready & read_fsm.ongoing("READ"),
|
|
||||||
self.dout_index.eq(self.dout_index+1),
|
|
||||||
If(self.dout_index==ar.len, r.last.eq(1)) # and update last
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
### Write
|
|
||||||
|
|
||||||
if not read_only:
|
|
||||||
self.comb += [
|
|
||||||
port.dat_w.eq(w.data),
|
|
||||||
port.adr.eq(self.w_addr_incr.addr),
|
|
||||||
]
|
|
||||||
|
|
||||||
self.submodules.write_fsm = write_fsm = FSM(reset_state="IDLE")
|
|
||||||
write_fsm.act("IDLE",
|
|
||||||
w.ready.eq(0),
|
|
||||||
aw.ready.eq(0),
|
|
||||||
b.valid.eq(0),
|
|
||||||
If(aw.valid,
|
|
||||||
NextState("AW_VALID_WAIT")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
write_fsm.act("AW_VALID_WAIT", # wait for data
|
|
||||||
aw.ready.eq(1),
|
|
||||||
If(w.valid,
|
|
||||||
NextState("WRITE"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# write_fsm.act("DATA_WAIT",
|
|
||||||
# aw.valid.eq(0),
|
|
||||||
# If(self.din_ready,
|
|
||||||
# w.valid.eq(1),
|
|
||||||
# NextState("WRITE")
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
write_fsm.act("WRITE",
|
|
||||||
w.ready.eq(1),
|
|
||||||
If(w.ready & w.last,
|
|
||||||
NextState("WRITE_RESP")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
write_fsm.act("WRITE_RESP",
|
|
||||||
port.we.eq(0),
|
|
||||||
b.resp.eq(axi.Response.okay.value),
|
|
||||||
b.valid.eq(1),
|
|
||||||
If(b.ready,
|
|
||||||
NextState("IDLE")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.sync += If(w.ready & w.valid, port.we.eq(1))
|
|
||||||
|
|
||||||
# self.sync += [
|
|
||||||
# If(write_fsm.ongoing("IDLE"),
|
|
||||||
# self.din_index.eq(0)
|
|
||||||
# ), # but need to synchronise the address too)
|
|
||||||
# ]
|
|
||||||
|
|
||||||
|
|
||||||
# # generate write enable signal
|
|
||||||
# if not read_only:
|
|
||||||
# # replace with? stb -> w.strb we->w.ready? sel[i]-> r.valid
|
|
||||||
# self.comb += [port.we[i].eq(self.bus.cyc & self.bus.w.strb & self.bus.w.ready & self.bus.r.valid)
|
|
||||||
# for i in range(4)]
|
|
||||||
# # address and data
|
|
||||||
# self.comb += [
|
|
||||||
# self.bus.r.ready.eq(self.bus.r.valid), # AXI handshake?
|
|
||||||
# port.adr.eq(self.bus.ar.addr[:len(port.adr)]),
|
|
||||||
# self.bus.r.data.eq(port.dat_r)
|
|
||||||
# ]
|
|
||||||
# if not read_only:
|
|
||||||
# self.comb += port.dat_w.eq(self.bus.w.data),
|
|
||||||
# # generate ack
|
|
||||||
# self.sync += [
|
|
||||||
# self.bus.ack.eq(0),
|
|
||||||
# If(self.bus.cyc & self.bus.stb & ~self.bus.ack, self.bus.ack.eq(1))
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# TODO: FullMemoryWE should be applied by migen.build
|
# TODO: FullMemoryWE should be applied by migen.build
|
||||||
@FullMemoryWE()
|
@FullMemoryWE()
|
||||||
|
Loading…
Reference in New Issue
Block a user