arp: rx and decoding OK
[litex.git] / liteeth / generic / packetizer.py
1 from liteeth.common import *
2
3 def _encode_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(h_signal[start:end].eq(reverse_bytes(getattr(obj, k))))
9 return r
10
11 class LiteEthPacketizer(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 header = Signal(header_length*8)
17 header_reg = Signal(header_length*8)
18 load = Signal()
19 shift = Signal()
20 counter = Counter(max=header_length)
21 self.submodules += counter
22
23 self.comb += _encode_header(header_type, header, sink)
24 self.sync += [
25 If(load,
26 header_reg.eq(header)
27 ).Elif(shift,
28 header_reg.eq(Cat(header_reg[8:], Signal(8)))
29 )
30 ]
31
32 fsm = FSM(reset_state="IDLE")
33 self.submodules += fsm
34
35 fsm.act("IDLE",
36 sink.ack.eq(1),
37 counter.reset.eq(1),
38 If(sink.stb & sink.sop,
39 sink.ack.eq(0),
40 source.stb.eq(1),
41 source.sop.eq(1),
42 source.eop.eq(0),
43 source.data.eq(header[:8]),
44 If(source.stb & source.ack,
45 load.eq(1),
46 NextState("SEND_HEADER"),
47 )
48 )
49 )
50 fsm.act("SEND_HEADER",
51 source.stb.eq(1),
52 source.sop.eq(0),
53 source.eop.eq(sink.eop),
54 source.data.eq(header_reg[8:16]),
55 If(source.stb & source.ack,
56 shift.eq(1),
57 counter.ce.eq(1),
58 If(counter.value == header_length-2,
59 NextState("COPY")
60 )
61 )
62 )
63 fsm.act("COPY",
64 source.stb.eq(sink.stb),
65 source.sop.eq(0),
66 source.eop.eq(sink.eop),
67 source.data.eq(sink.data),
68 source.error.eq(sink.error),
69 If(source.stb & source.ack,
70 sink.ack.eq(1),
71 If(source.eop,
72 NextState("IDLE")
73 )
74 )
75 )