arp: rx and decoding OK
[litex.git] / liteeth / generic / depacketizer.py
1 from liteeth.common import *
2
3 def _decode_header(h_dict, h_signal, obj):
4 r = []
5 for k, v in sorted(h_dict.items()):
6 start = v.byte*8+v.offset
7 end = start+v.width
8 r.append(getattr(obj, k).eq(reverse_bytes(h_signal[start:end])))
9 return r
10
11 class LiteEthDepacketizer(Module):
12 def __init__(self, sink_description, source_description, header_type, header_length):
13 self.sink = sink = Sink(sink_description)
14 self.source = source = Source(source_description)
15 ###
16 shift = Signal()
17 header = Signal(header_length*8)
18 counter = Counter(max=header_length)
19 self.submodules += counter
20
21 self.sync += [
22 If(shift,
23 header.eq(Cat(header[8:], sink.data))
24 )
25 ]
26
27 fsm = FSM(reset_state="IDLE")
28 self.submodules += fsm
29
30 fsm.act("IDLE",
31 sink.ack.eq(1),
32 counter.reset.eq(1),
33 If(sink.stb,
34 shift.eq(1),
35 NextState("RECEIVE_HEADER")
36 )
37 )
38 fsm.act("RECEIVE_HEADER",
39 sink.ack.eq(1),
40 If(sink.stb,
41 counter.ce.eq(1),
42 shift.eq(1),
43 If(counter.value == header_length-2,
44 NextState("COPY")
45 )
46 )
47 )
48 self.sync += \
49 If(fsm.before_entering("COPY"),
50 source.sop.eq(1)
51 ).Elif(source.stb & source.ack,
52 source.sop.eq(0)
53 )
54 self.comb += [
55 source.eop.eq(sink.eop),
56 source.data.eq(sink.data),
57 source.error.eq(sink.error),
58 _decode_header(header_type, header, source)
59 ]
60 fsm.act("COPY",
61 sink.ack.eq(source.ack),
62 source.stb.eq(sink.stb),
63 If(source.stb & source.ack & source.eop,
64 NextState("IDLE")
65 )
66 )