Skip to content

Commit 1cbc468

Browse files
committedApr 28, 2015
migen/actorlib/packet: add Packetizer and Depacketizer
1 parent 0da9311 commit 1cbc468

File tree

1 file changed

+163
-1
lines changed

1 file changed

+163
-1
lines changed
 

Diff for: ‎migen/actorlib/packet.py

+163-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from migen.flow.actor import *
55
from migen.actorlib.fifo import SyncFIFO
66
from migen.genlib.fsm import FSM, NextState
7-
from migen.genlib.misc import reverse_bytes
7+
from migen.genlib.misc import reverse_bytes, Counter
88

99

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

137137

138+
class Packetizer(Module):
139+
def __init__(self, sink_description, source_description, header):
140+
self.sink = sink = Sink(sink_description)
141+
self.source = source = Source(source_description)
142+
self.header = Signal(header.length*8)
143+
144+
# # #
145+
146+
dw = flen(self.sink.data)
147+
148+
header_reg = Signal(header.length*8)
149+
header_words = (header.length*8)//dw
150+
load = Signal()
151+
shift = Signal()
152+
counter = Counter(max=max(header_words, 2))
153+
self.submodules += counter
154+
155+
self.comb += header.encode(sink, self.header)
156+
if header_words == 1:
157+
self.sync += [
158+
If(load,
159+
header_reg.eq(self.header)
160+
)
161+
]
162+
else:
163+
self.sync += [
164+
If(load,
165+
header_reg.eq(self.header)
166+
).Elif(shift,
167+
header_reg.eq(Cat(header_reg[dw:], Signal(dw)))
168+
)
169+
]
170+
171+
fsm = FSM(reset_state="IDLE")
172+
self.submodules += fsm
173+
174+
if header_words == 1:
175+
idle_next_state = "COPY"
176+
else:
177+
idle_next_state = "SEND_HEADER"
178+
179+
fsm.act("IDLE",
180+
sink.ack.eq(1),
181+
counter.reset.eq(1),
182+
If(sink.stb & sink.sop,
183+
sink.ack.eq(0),
184+
source.stb.eq(1),
185+
source.sop.eq(1),
186+
source.eop.eq(0),
187+
source.data.eq(self.header[:dw]),
188+
If(source.stb & source.ack,
189+
load.eq(1),
190+
NextState(idle_next_state)
191+
)
192+
)
193+
)
194+
if header_words != 1:
195+
fsm.act("SEND_HEADER",
196+
source.stb.eq(1),
197+
source.sop.eq(0),
198+
source.eop.eq(0),
199+
source.data.eq(header_reg[dw:2*dw]),
200+
If(source.stb & source.ack,
201+
shift.eq(1),
202+
counter.ce.eq(1),
203+
If(counter.value == header_words-2,
204+
NextState("COPY")
205+
)
206+
)
207+
)
208+
fsm.act("COPY",
209+
source.stb.eq(sink.stb),
210+
source.sop.eq(0),
211+
source.eop.eq(sink.eop),
212+
source.data.eq(sink.data),
213+
source.error.eq(sink.error),
214+
If(source.stb & source.ack,
215+
sink.ack.eq(1),
216+
If(source.eop,
217+
NextState("IDLE")
218+
)
219+
)
220+
)
221+
222+
223+
class Depacketizer(Module):
224+
def __init__(self, sink_description, source_description, header):
225+
self.sink = sink = Sink(sink_description)
226+
self.source = source = Source(source_description)
227+
self.header = Signal(header.length*8)
228+
229+
# # #
230+
231+
dw = flen(sink.data)
232+
233+
header_words = (header.length*8)//dw
234+
235+
shift = Signal()
236+
counter = Counter(max=max(header_words, 2))
237+
self.submodules += counter
238+
239+
if header_words == 1:
240+
self.sync += \
241+
If(shift,
242+
self.header.eq(sink.data)
243+
)
244+
else:
245+
self.sync += \
246+
If(shift,
247+
self.header.eq(Cat(self.header[dw:], sink.data))
248+
)
249+
250+
fsm = FSM(reset_state="IDLE")
251+
self.submodules += fsm
252+
253+
if header_words == 1:
254+
idle_next_state = "COPY"
255+
else:
256+
idle_next_state = "RECEIVE_HEADER"
257+
258+
fsm.act("IDLE",
259+
sink.ack.eq(1),
260+
counter.reset.eq(1),
261+
If(sink.stb,
262+
shift.eq(1),
263+
NextState(idle_next_state)
264+
)
265+
)
266+
if header_words != 1:
267+
fsm.act("RECEIVE_HEADER",
268+
sink.ack.eq(1),
269+
If(sink.stb,
270+
counter.ce.eq(1),
271+
shift.eq(1),
272+
If(counter.value == header_words-2,
273+
NextState("COPY")
274+
)
275+
)
276+
)
277+
no_payload = Signal()
278+
self.sync += \
279+
If(fsm.before_entering("COPY"),
280+
source.sop.eq(1),
281+
no_payload.eq(sink.eop)
282+
).Elif(source.stb & source.ack,
283+
source.sop.eq(0)
284+
)
285+
self.comb += [
286+
source.eop.eq(sink.eop | no_payload),
287+
source.data.eq(sink.data),
288+
source.error.eq(sink.error),
289+
header.decode(self.header, source)
290+
]
291+
fsm.act("COPY",
292+
sink.ack.eq(source.ack),
293+
source.stb.eq(sink.stb | no_payload),
294+
If(source.stb & source.ack & source.eop,
295+
NextState("IDLE")
296+
)
297+
)
298+
299+
138300
class Buffer(Module):
139301
def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
140302
self.sink = sink = Sink(description)

0 commit comments

Comments
 (0)
Please sign in to comment.