1 from liteeth
.common
import *
2 from liteeth
.generic
.depacketizer
import LiteEthDepacketizer
3 from liteeth
.generic
.packetizer
import LiteEthPacketizer
12 class LiteEthARPDepacketizer(LiteEthDepacketizer
):
14 LiteEthDepacketizer
.__init
__(self
,
15 eth_mac_description(8),
16 eth_arp_description(8),
20 class LiteEthARPPacketizer(LiteEthPacketizer
):
22 LiteEthPacketizer
.__init
__(self
,
23 eth_arp_description(8),
24 eth_mac_description(8),
28 class LiteEthARPTX(Module
):
29 def __init__(self
, mac_address
, ip_address
):
30 self
.sink
= sink
= Sink(_arp_table_layout
)
31 self
.source
= Source(eth_mac_description(8))
33 packetizer
= LiteEthARPPacketizer()
34 self
.submodules
+= packetizer
35 source
= packetizer
.sink
37 counter
= Counter(max=arp_packet_length
)
38 self
.submodules
+= counter
40 fsm
= FSM(reset_state
="IDLE")
41 self
.submodules
+= fsm
51 source
.hardware_type
.eq(arp_hwtype_ethernet
),
52 source
.protocol_type
.eq(arp_proto_ip
),
53 source
.hardware_address_length
.eq(6),
54 source
.protocol_address_length
.eq(4),
55 source
.source_mac_address
.eq(mac_address
),
56 source
.source_ip_address
.eq(ip_address
),
58 source
.operation
.eq(arp_opcode_reply
),
59 source
.destination_mac_address
.eq(sink
.mac_address
),
60 source
.destination_ip_address
.eq(sink
.ip_address
)
62 source
.operation
.eq(arp_opcode_request
),
63 source
.destination_mac_address
.eq(0xffffffffffff),
64 source
.destination_ip_address
.eq(sink
.ip_address
)
69 source
.sop
.eq(counter
.value
== 0),
70 source
.eop
.eq(counter
.value
== arp_packet_length
-1),
71 Record
.connect(packetizer
.source
, self
.source
),
72 self
.source
.destination_mac_address
.eq(source
.destination_mac_address
),
73 self
.source
.source_mac_address
.eq(mac_address
),
74 self
.source
.ethernet_type
.eq(ethernet_type_arp
),
75 If(self
.source
.stb
& self
.source
.ack
,
76 sink
.ack
.eq(source
.eop
),
84 class LiteEthARPRX(Module
):
85 def __init__(self
, mac_address
, ip_address
):
86 self
.sink
= Sink(eth_mac_description(8))
87 self
.source
= source
= Source(_arp_table_layout
)
89 depacketizer
= LiteEthARPDepacketizer()
90 self
.submodules
+= depacketizer
91 self
.comb
+= Record
.connect(self
.sink
, depacketizer
.sink
)
92 sink
= depacketizer
.source
94 fsm
= FSM(reset_state
="IDLE")
95 self
.submodules
+= fsm
98 If(sink
.stb
& sink
.sop
,
103 self
.comb
+= valid
.eq(
105 (sink
.hardware_type
== arp_hwtype_ethernet
) &
106 (sink
.protocol_type
== arp_proto_ip
) &
107 (sink
.hardware_address_length
== 6) &
108 (sink
.protocol_address_length
== 4) &
109 (sink
.destination_ip_address
== ip_address
)
113 self
.comb
+= Case(sink
.operation
, {
114 arp_opcode_request
: [request
.eq(1)],
115 arp_opcode_reply
: [reply
.eq(1)],
119 source
.ip_address
.eq(sink
.source_ip_address
),
120 source
.mac_address
.eq(sink
.source_mac_address
)
125 source
.reply
.eq(reply
),
126 source
.request
.eq(request
)
128 NextState("TERMINATE")
132 If(sink
.stb
& sink
.eop
,
137 arp_table_request_layout
= [
141 arp_table_response_layout
= [
146 class LiteEthARPTable(Module
):
148 self
.sink
= sink
= Sink(_arp_table_layout
) # from arp_rx
149 self
.source
= source
= Source(_arp_table_layout
) # to arp_tx
151 # Request/Response interface
152 self
.request
= request
= Sink(arp_table_request_layout
)
153 self
.response
= response
= Source(arp_table_response_layout
)
155 request_timeout
= Timeout(512) # XXX fix me 100ms?
156 request_pending
= FlipFlop()
157 self
.submodules
+= request_timeout
, request_pending
159 request_timeout
.ce
.eq(request_pending
.q
),
160 request_pending
.d
.eq(1)
163 # Note: Store only one ip/mac couple, replace this with
166 cached_ip_address
= Signal(32)
167 cached_mac_address
= Signal(48)
169 fsm
= FSM(reset_state
="IDLE")
170 self
.submodules
+= fsm
172 # Note: for simplicicy, if APR table is busy response from arp_rx
173 # is lost. This is compensated by the protocol (retrys)
174 If(sink
.stb
& sink
.request
,
175 NextState("SEND_REPLY")
176 ).Elif(sink
.stb
& sink
.reply
& request_pending
.q
,
177 NextState("UPDATE_TABLE")
178 ).Elif(request
.stb |
(request_pending
.q
& request_timeout
.reached
),
179 NextState("CHECK_TABLE")
182 fsm
.act("SEND_REPLY",
185 source
.ip_address
.eq(sink
.ip_address
),
190 fsm
.act("UPDATE_TABLE",
191 request_pending
.reset
.eq(1),
193 NextState("CHECK_TABLE")
197 cached_ip_address
.eq(sink
.ip_address
),
198 cached_mac_address
.eq(sink
.mac_address
)
202 fsm
.act("CHECK_TABLE",
203 # XXX: add a live time for cached_mac_address
204 If(request
.ip_address
== cached_ip_address
,
205 request
.ack
.eq(request
.stb
),
206 NextState("PRESENT_RESPONSE")
208 NextState("SEND_REQUEST")
211 fsm
.act("SEND_REQUEST",
213 source
.request
.eq(1),
214 source
.ip_address
.eq(request
.ip_address
),
216 request_timeout
.reset
.eq(1),
217 request_pending
.ce
.eq(1),
222 fsm
.act("PRESENT_RESPONSE",
224 response
.failed
.eq(0), # XXX add timeout to trigger failed
225 response
.mac_address
.eq(cached_mac_address
),
231 class LiteEthARP(Module
):
232 def __init__(self
, mac_address
, ip_address
):
233 self
.submodules
.tx
= LiteEthARPTX(mac_address
, ip_address
)
234 self
.submodules
.rx
= LiteEthARPRX(mac_address
, ip_address
)
235 self
.submodules
.table
= LiteEthARPTable()
237 Record
.connect(self
.rx
.source
, self
.table
.sink
),
238 Record
.connect(self
.table
.source
, self
.tx
.sink
)
240 self
.sink
, self
.source
= self
.rx
.sink
, self
.tx
.source
241 self
.request
, self
.response
= self
.table
.request
, self
.table
.response