55f6241492e34067570cc7db697163d4fcf6ef3a
[litex.git] / liteeth / core / udp / __init__.py
1 from liteeth.common import *
2 from liteeth.generic.depacketizer import LiteEthDepacketizer
3 from liteeth.generic.packetizer import LiteEthPacketizer
4 from liteeth.generic.crossbar import LiteEthCrossbar
5 from liteeth.core.udp.common import *
6
7 class LiteEthUDPDepacketizer(LiteEthDepacketizer):
8 def __init__(self):
9 LiteEthDepacketizer.__init__(self,
10 eth_ipv4_user_description(8),
11 eth_udp_description(8),
12 udp_header,
13 udp_header_len)
14
15 class LiteEthUDPPacketizer(LiteEthPacketizer):
16 def __init__(self):
17 LiteEthPacketizer.__init__(self,
18 eth_udp_description(8),
19 eth_ipv4_user_description(8),
20 udp_header,
21 udp_header_len)
22
23 class LiteEthUDPCrossbar(LiteEthCrossbar):
24 def __init__(self):
25 LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port")
26
27 def get_port(self, udp_port, dw=8):
28 if udp_port in self.users.keys():
29 raise ValueError("Port {0:#x} already assigned".format(udp_port))
30 user_port = LiteEthUDPUserPort(dw)
31 internal_port = LiteEthUDPUserPort(8)
32 if dw != 8:
33 converter = Converter(eth_udp_user_description(user_port.dw), eth_udp_user_description(8))
34 self.submodules += converter
35 self.comb += [
36 Record.connect(user_port.sink, converter.sink),
37 Record.connect(converter.source, internal_port.sink)
38 ]
39 converter = Converter(eth_udp_user_description(8), eth_udp_user_description(user_port.dw))
40 self.submodules += converter
41 self.comb += [
42 Record.connect(internal_port.source, converter.sink),
43 Record.connect(converter.source, user_port.source)
44 ]
45 self.users[udp_port] = internal_port
46 else:
47 self.users[udp_port] = user_port
48 return user_port
49
50 class LiteEthUDPTX(Module):
51 def __init__(self, ip_address):
52 self.sink = sink = Sink(eth_udp_user_description(8))
53 self.source = source = Source(eth_ipv4_user_description(8))
54 ###
55 self.submodules.packetizer = packetizer = LiteEthUDPPacketizer()
56 self.comb += [
57 packetizer.sink.stb.eq(sink.stb),
58 packetizer.sink.sop.eq(sink.sop),
59 packetizer.sink.eop.eq(sink.eop),
60 sink.ack.eq(packetizer.sink.ack),
61 packetizer.sink.src_port.eq(sink.src_port),
62 packetizer.sink.dst_port.eq(sink.dst_port),
63 packetizer.sink.length.eq(sink.length + udp_header_len),
64 packetizer.sink.checksum.eq(0), # Disabled (MAC CRC is enough)
65 packetizer.sink.data.eq(sink.data)
66 ]
67
68 self.submodules.fsm = fsm = FSM(reset_state="IDLE")
69 fsm.act("IDLE",
70 packetizer.source.ack.eq(1),
71 If(packetizer.source.stb & packetizer.source.sop,
72 packetizer.source.ack.eq(0),
73 NextState("SEND")
74 )
75 )
76 fsm.act("SEND",
77 Record.connect(packetizer.source, source),
78 source.length.eq(packetizer.sink.length),
79 source.protocol.eq(udp_protocol),
80 source.ip_address.eq(sink.ip_address),
81 If(source.stb & source.eop & source.ack,
82 NextState("IDLE")
83 )
84 )
85
86 class LiteEthUDPRX(Module):
87 def __init__(self, ip_address):
88 self.sink = sink = Sink(eth_ipv4_user_description(8))
89 self.source = source = Source(eth_udp_user_description(8))
90 ###
91 self.submodules.depacketizer = depacketizer = LiteEthUDPDepacketizer()
92 self.comb += Record.connect(sink, depacketizer.sink)
93
94 self.submodules.fsm = fsm = FSM(reset_state="IDLE")
95 fsm.act("IDLE",
96 depacketizer.source.ack.eq(1),
97 If(depacketizer.source.stb & depacketizer.source.sop,
98 depacketizer.source.ack.eq(0),
99 NextState("CHECK")
100 )
101 )
102 valid = Signal()
103 self.sync += valid.eq(
104 depacketizer.source.stb &
105 (sink.protocol == udp_protocol)
106 )
107
108 fsm.act("CHECK",
109 If(valid,
110 NextState("PRESENT")
111 ).Else(
112 NextState("DROP")
113 )
114 )
115 self.comb += [
116 source.sop.eq(depacketizer.source.sop),
117 source.eop.eq(depacketizer.source.eop),
118 source.src_port.eq(depacketizer.source.src_port),
119 source.dst_port.eq(depacketizer.source.dst_port),
120 source.ip_address.eq(sink.ip_address),
121 source.length.eq(depacketizer.source.length - udp_header_len),
122 source.data.eq(depacketizer.source.data),
123 source.error.eq(depacketizer.source.error)
124 ]
125 fsm.act("PRESENT",
126 source.stb.eq(depacketizer.source.stb),
127 depacketizer.source.ack.eq(source.ack),
128 If(source.stb & source.eop & source.ack,
129 NextState("IDLE")
130 )
131 )
132 fsm.act("DROP",
133 depacketizer.source.ack.eq(1),
134 If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack,
135 NextState("IDLE")
136 )
137 )
138
139 class LiteEthUDP(Module):
140 def __init__(self, ip, ip_address):
141 self.submodules.tx = tx = LiteEthUDPTX(ip_address)
142 self.submodules.rx = rx = LiteEthUDPRX(ip_address)
143 ip_port = ip.crossbar.get_port(udp_protocol)
144 self.comb += [
145 Record.connect(tx.source, ip_port.sink),
146 Record.connect(ip_port.source, rx.sink)
147 ]
148 self.submodules.crossbar = crossbar = LiteEthUDPCrossbar()
149 self.comb += [
150 Record.connect(crossbar.master.source, tx.sink),
151 Record.connect(rx.source, crossbar.master.sink)
152 ]