mac/sram: Cleanup/Simplify LiteEthMACSRAMReader.

- Improve signal names.
- Use re on memories to simplify addressing (still need to anticipate read by 1 cycle).

Also do minor cleanups to LiteEthMACSRAMWriter.
This commit is contained in:
Florent Kermarrec 2021-10-05 09:43:51 +02:00
parent 89dbf17cb6
commit a00a200547

View file

@ -133,63 +133,74 @@ class LiteEthMACSRAMWriter(Module, AutoCSR):
]
if timestamp is not None:
# Latch Timestamp on start of packet.
self.sync += If(sink.length == 0, stat_fifo.sink.timestamp.eq(timestamp))
self.sync += If(length == 0, stat_fifo.sink.timestamp.eq(timestamp))
self.comb += self._timestamp.status.eq(stat_fifo.source.timestamp)
# Memory.
wr_slot = slot
wr_addr = length[int(math.log2(dw//8)):]
wr_data = Signal(len(sink.data))
# Create a Memory per Slot.
mems = [None] * nslots
ports = [None] * nslots
for n in range(nslots):
mems[n] = Memory(dw, depth)
mems[n] = Memory(dw, depth)
ports[n] = mems[n].get_port(write_capable=True)
self.specials += ports[n]
self.mems = mems
data = reverse_bytes(sink.data) if endianness == "big" else sink.data
# Endianness Handling.
self.comb += wr_data.eq({"big": reverse_bytes(sink.data), "little": sink.data}[endianness])
# Connect Memory ports.
cases = {}
for n, port in enumerate(ports):
cases[n] = [
ports[n].adr.eq(length[int(math.log2(dw//8)):]),
ports[n].dat_w.eq(data),
ports[n].adr.eq(wr_addr),
ports[n].dat_w.eq(wr_data),
If(sink.valid & write,
ports[n].we.eq(0xf)
ports[n].we.eq(2**len(ports[n].we) - 1)
)
]
self.comb += Case(slot, cases)
self.comb += Case(wr_slot, cases)
# MAC SRAM Reader ----------------------------------------------------------------------------------
class LiteEthMACSRAMReader(Module, AutoCSR):
def __init__(self, dw, depth, nslots=2, endianness="big", timestamp=None):
assert dw in [32, 64]
# Endpoint / Signals.
self.source = source = stream.Endpoint(eth_phy_description(dw))
slotbits = max(int(math.log2(nslots)), 1)
lengthbits = bits_for(depth * dw//8)
self.lengthbits = lengthbits
# Parameters Check / Compute.
assert dw in [32, 64]
slotbits = max(int(math.log2(nslots)), 1)
lengthbits = bits_for(depth * dw//8)
# CSRs.
self._start = CSR()
self._ready = CSRStatus()
self._level = CSRStatus(int(math.log2(nslots)) + 1)
self._slot = CSRStorage(slotbits, reset_less=True)
self._length = CSRStorage(lengthbits, reset_less=True)
# Optional Timestamp of the outgoing packets and expose value to software.
if timestamp is not None:
# Timestamp the outgoing packets when a Timestamp source is provided
# and expose value to a software.
timestampbits = len(timestamp)
self._timestamp_slot = CSRStatus(slotbits)
self._timestamp = CSRStatus(timestampbits)
# Event Manager.
self.submodules.ev = EventManager()
self.ev.done = EventSourcePulse() if timestamp is None else EventSourceLevel()
self.ev.finalize()
# # #
start = Signal()
read = Signal()
length = Signal(lengthbits)
# Command FIFO
# Command FIFO.
cmd_fifo = stream.SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
self.submodules += cmd_fifo
self.comb += [
@ -209,20 +220,6 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
self.comb += self._timestamp_slot.status.eq(stat_fifo.source.slot)
self.comb += self._timestamp.status.eq(stat_fifo.source.timestamp)
# Length computation
read_address = Signal(lengthbits)
counter = Signal(lengthbits)
# FSM
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
NextValue(counter, 0),
If(cmd_fifo.source.valid,
start.eq(1),
NextState("SEND")
)
)
# Encode Length to last_be.
length_lsb = cmd_fifo.source.length[0:int(math.log2(dw//8))]
if dw == 32:
@ -248,19 +245,28 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
})
)
fsm.act("SEND",
# FSM.
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
If(cmd_fifo.source.valid,
read.eq(1),
NextValue(length, dw//8),
NextState("READ")
)
)
fsm.act("READ",
source.valid.eq(1),
source.last.eq(counter >= (cmd_fifo.source.length - dw//8)),
read_address.eq(counter),
source.last.eq(length >= cmd_fifo.source.length),
If(source.ready,
read_address.eq(counter + dw//8),
NextValue(counter, counter + dw//8),
read.eq(1),
NextValue(length, length + dw//8),
If(source.last,
NextState("END")
NextState("TERMINATE")
)
)
)
fsm.act("END",
fsm.act("TERMINATE",
NextValue(length, 0),
self.ev.done.trigger.eq(1),
cmd_fifo.source.ready.eq(1),
NextState("IDLE")
@ -268,32 +274,37 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
if timestamp is not None:
# Latch Timestamp on start of outgoing packet.
self.sync += If(start, stat_fifo.sink.timestamp.eq(timestamp))
self.sync += If(length == 0, stat_fifo.sink.timestamp.eq(timestamp))
self.comb += stat_fifo.sink.valid.eq(fsm.ongoing("END"))
self.comb += stat_fifo.sink.slot.eq(cmd_fifo.source.slot)
# Trigger event when Status FIFO has contents (Override FSM assignment).
self.comb += self.ev.done.trigger.eq(stat_fifo.source.valid)
# Memory
# Memory.
rd_slot = cmd_fifo.source.slot
rd_addr = Signal(lengthbits)
rd_data = Signal(len(source.data))
# Create a Memory per Slot.
mems = [None]*nslots
ports = [None]*nslots
for n in range(nslots):
mems[n] = Memory(dw, depth)
ports[n] = mems[n].get_port()
ports[n] = mems[n].get_port(has_re=True)
self.specials += ports[n]
self.mems = mems
data = Signal().like(source.data)
# Connect Memory ports.
cases = {}
for n, port in enumerate(ports):
self.comb += ports[n].adr.eq(read_address[int(math.log2(dw//8)):])
cases[n] = [data.eq(port.dat_r)]
self.comb += ports[n].re.eq(read)
self.comb += ports[n].adr.eq(length[int(math.log2(dw//8)):])
cases[n] = [rd_data.eq(port.dat_r)]
self.comb += [
Case(rd_slot, cases),
source.data.eq(reverse_bytes(data) if endianness == "big" else data),
]
self.comb += Case(rd_slot, cases)
# Endianness Handling.
self.comb += source.data.eq({"big" : reverse_bytes(rd_data), "little": rd_data}[endianness])
# MAC SRAM -----------------------------------------------------------------------------------------