Skip to content

Commit

Permalink
migen/actorlib/packet: add Packetizer and Depacketizer
Browse files Browse the repository at this point in the history
enjoy-digital committed Apr 28, 2015

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 0da9311 commit 1cbc468
Showing 1 changed file with 163 additions and 1 deletion.
164 changes: 163 additions & 1 deletion migen/actorlib/packet.py
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
from migen.flow.actor import *
from migen.actorlib.fifo import SyncFIFO
from migen.genlib.fsm import FSM, NextState
from migen.genlib.misc import reverse_bytes
from migen.genlib.misc import reverse_bytes, Counter


class Status(Module):
@@ -135,6 +135,168 @@ def decode(self, signal, obj):
return r


class Packetizer(Module):
def __init__(self, sink_description, source_description, header):
self.sink = sink = Sink(sink_description)
self.source = source = Source(source_description)
self.header = Signal(header.length*8)

# # #

dw = flen(self.sink.data)

header_reg = Signal(header.length*8)
header_words = (header.length*8)//dw
load = Signal()
shift = Signal()
counter = Counter(max=max(header_words, 2))
self.submodules += counter

self.comb += header.encode(sink, self.header)
if header_words == 1:
self.sync += [
If(load,
header_reg.eq(self.header)
)
]
else:
self.sync += [
If(load,
header_reg.eq(self.header)
).Elif(shift,
header_reg.eq(Cat(header_reg[dw:], Signal(dw)))
)
]

fsm = FSM(reset_state="IDLE")
self.submodules += fsm

if header_words == 1:
idle_next_state = "COPY"
else:
idle_next_state = "SEND_HEADER"

fsm.act("IDLE",
sink.ack.eq(1),
counter.reset.eq(1),
If(sink.stb & sink.sop,
sink.ack.eq(0),
source.stb.eq(1),
source.sop.eq(1),
source.eop.eq(0),
source.data.eq(self.header[:dw]),
If(source.stb & source.ack,
load.eq(1),
NextState(idle_next_state)
)
)
)
if header_words != 1:
fsm.act("SEND_HEADER",
source.stb.eq(1),
source.sop.eq(0),
source.eop.eq(0),
source.data.eq(header_reg[dw:2*dw]),
If(source.stb & source.ack,
shift.eq(1),
counter.ce.eq(1),
If(counter.value == header_words-2,
NextState("COPY")
)
)
)
fsm.act("COPY",
source.stb.eq(sink.stb),
source.sop.eq(0),
source.eop.eq(sink.eop),
source.data.eq(sink.data),
source.error.eq(sink.error),
If(source.stb & source.ack,
sink.ack.eq(1),
If(source.eop,
NextState("IDLE")
)
)
)


class Depacketizer(Module):
def __init__(self, sink_description, source_description, header):
self.sink = sink = Sink(sink_description)
self.source = source = Source(source_description)
self.header = Signal(header.length*8)

# # #

dw = flen(sink.data)

header_words = (header.length*8)//dw

shift = Signal()
counter = Counter(max=max(header_words, 2))
self.submodules += counter

if header_words == 1:
self.sync += \
If(shift,
self.header.eq(sink.data)
)
else:
self.sync += \
If(shift,
self.header.eq(Cat(self.header[dw:], sink.data))
)

fsm = FSM(reset_state="IDLE")
self.submodules += fsm

if header_words == 1:
idle_next_state = "COPY"
else:
idle_next_state = "RECEIVE_HEADER"

fsm.act("IDLE",
sink.ack.eq(1),
counter.reset.eq(1),
If(sink.stb,
shift.eq(1),
NextState(idle_next_state)
)
)
if header_words != 1:
fsm.act("RECEIVE_HEADER",
sink.ack.eq(1),
If(sink.stb,
counter.ce.eq(1),
shift.eq(1),
If(counter.value == header_words-2,
NextState("COPY")
)
)
)
no_payload = Signal()
self.sync += \
If(fsm.before_entering("COPY"),
source.sop.eq(1),
no_payload.eq(sink.eop)
).Elif(source.stb & source.ack,
source.sop.eq(0)
)
self.comb += [
source.eop.eq(sink.eop | no_payload),
source.data.eq(sink.data),
source.error.eq(sink.error),
header.decode(self.header, source)
]
fsm.act("COPY",
sink.ack.eq(source.ack),
source.stb.eq(sink.stb | no_payload),
If(source.stb & source.ack & source.eop,
NextState("IDLE")
)
)


class Buffer(Module):
def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
self.sink = sink = Sink(description)

0 comments on commit 1cbc468

Please sign in to comment.