liteeth MAC: add a TX return channel

This changes the liteeth SRAM reader to utilize a feedback channel
returning the slot of which a packet has been sent.

The event source is changed from a pulse to a level-based trigger,
such that it will continue asserted if a single packet has been
acknowledged, but additional packets have been sent.

This infrastructure allows to convey additional information about
transmitted packets, such as timestamps or errors.
This commit is contained in:
Leon Schuermann 2021-01-28 11:43:28 +01:00
parent 7ce1085b68
commit e5f713f5a0
1 changed files with 31 additions and 14 deletions

View File

@ -179,27 +179,40 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
lengthbits = bits_for(depth*4) # length in bytes lengthbits = bits_for(depth*4) # length in bytes
self.lengthbits = lengthbits self.lengthbits = lengthbits
# MAC Reader command channel
self._start = CSR() self._start = CSR()
self._ready = CSRStatus() self._ready = CSRStatus()
self._level = CSRStatus(log2_int(nslots) + 1) self._level = CSRStatus(log2_int(nslots) + 1)
self._slot = CSRStorage(slotbits, reset_less=True) self._slot = CSRStorage(slotbits, reset_less=True)
self._length = CSRStorage(lengthbits, reset_less=True) self._length = CSRStorage(lengthbits, reset_less=True)
# MAC Reader return channel
self._res_slot = CSRStatus(slotbits)
self.submodules.ev = EventManager() self.submodules.ev = EventManager()
self.ev.done = EventSourcePulse() self.ev.done = EventSourceLevel()
self.ev.finalize() self.ev.finalize()
# # # # # #
# Command FIFO # Command FIFO
fifo = stream.SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots) cmd_fifo = stream.SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
self.submodules += fifo self.submodules += cmd_fifo
self.comb += [ self.comb += [
fifo.sink.valid.eq(self._start.re), cmd_fifo.sink.valid.eq(self._start.re),
fifo.sink.slot.eq(self._slot.storage), cmd_fifo.sink.slot.eq(self._slot.storage),
fifo.sink.length.eq(self._length.storage), cmd_fifo.sink.length.eq(self._length.storage),
self._ready.status.eq(fifo.sink.ready), self._ready.status.eq(cmd_fifo.sink.ready),
self._level.status.eq(fifo.level) self._level.status.eq(cmd_fifo.level)
]
# Result FIFO (return channel)
res_fifo = stream.SyncFIFO([("slot", slotbits)], nslots)
self.submodules += res_fifo
self.comb += [
res_fifo.source.ready.eq(self.ev.done.clear),
self.ev.done.trigger.eq(res_fifo.source.valid),
self._res_slot.status.eq(res_fifo.source.slot),
] ]
# Length computation # Length computation
@ -210,12 +223,12 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
self.submodules.fsm = fsm = FSM(reset_state="IDLE") self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE", fsm.act("IDLE",
NextValue(counter, 0), NextValue(counter, 0),
If(fifo.source.valid, If(cmd_fifo.source.valid,
read_address.eq(0), read_address.eq(0),
NextState("SEND") NextState("SEND")
) )
) )
length_lsb = fifo.source.length[0:2] length_lsb = cmd_fifo.source.length[0:2]
if endianness == "big": if endianness == "big":
self.comb += If(source.last, self.comb += If(source.last,
Case(length_lsb, { Case(length_lsb, {
@ -234,7 +247,7 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
})) }))
fsm.act("SEND", fsm.act("SEND",
source.valid.eq(1), source.valid.eq(1),
source.last.eq(counter >= (fifo.source.length - 4)), source.last.eq(counter >= (cmd_fifo.source.length - 4)),
read_address.eq(counter), read_address.eq(counter),
If(source.ready, If(source.ready,
read_address.eq(counter + 4), read_address.eq(counter + 4),
@ -245,13 +258,17 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
) )
) )
fsm.act("END", fsm.act("END",
fifo.source.ready.eq(1), res_fifo.sink.valid.eq(1),
self.ev.done.trigger.eq(1), cmd_fifo.source.ready.eq(1),
NextState("IDLE") NextState("IDLE")
) )
self.comb += [
res_fifo.sink.slot.eq(cmd_fifo.source.slot)
]
# Memory # Memory
rd_slot = fifo.source.slot rd_slot = cmd_fifo.source.slot
mems = [None]*nslots mems = [None]*nslots
ports = [None]*nslots ports = [None]*nslots
for n in range(nslots): for n in range(nslots):