arp: request/reply with model OK
This commit is contained in:
parent
a7d4427de4
commit
fa48346385
|
@ -80,7 +80,7 @@ class LiteEthARPTX(Module):
|
||||||
self.source.source_mac_address.eq(mac_address),
|
self.source.source_mac_address.eq(mac_address),
|
||||||
self.source.ethernet_type.eq(ethernet_type_arp),
|
self.source.ethernet_type.eq(ethernet_type_arp),
|
||||||
If(self.source.stb & self.source.ack,
|
If(self.source.stb & self.source.ack,
|
||||||
sink.ack.eq(1),
|
sink.ack.eq(source.eop),
|
||||||
counter.ce.eq(1),
|
counter.ce.eq(1),
|
||||||
If(self.source.eop,
|
If(self.source.eop,
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
|
@ -148,7 +148,6 @@ arp_table_request_layout = [
|
||||||
arp_table_response_layout = [
|
arp_table_response_layout = [
|
||||||
("failed", 1),
|
("failed", 1),
|
||||||
("mac_address", 48)
|
("mac_address", 48)
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
class LiteEthARPTable(Module):
|
class LiteEthARPTable(Module):
|
||||||
|
@ -159,15 +158,31 @@ class LiteEthARPTable(Module):
|
||||||
# Request/Response interface
|
# Request/Response interface
|
||||||
self.request = request = Sink(arp_table_request_layout)
|
self.request = request = Sink(arp_table_request_layout)
|
||||||
self.response = response = Source(arp_table_response_layout)
|
self.response = response = Source(arp_table_response_layout)
|
||||||
|
###
|
||||||
|
request_timeout = Timeout(512) # XXX fix me 100ms?
|
||||||
|
request_pending = FlipFlop()
|
||||||
|
self.submodules += request_timeout, request_pending
|
||||||
|
self.comb += [
|
||||||
|
request_timeout.ce.eq(request_pending.q),
|
||||||
|
request_pending.d.eq(1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Note: Store only one ip/mac couple, replace this with
|
||||||
|
# a real ARP table
|
||||||
|
update = Signal()
|
||||||
|
cached_ip_address = Signal(32)
|
||||||
|
cached_mac_address = Signal(48)
|
||||||
|
|
||||||
fsm = FSM(reset_state="IDLE")
|
fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
|
# Note: for simplicicy, if APR table is busy response from arp_rx
|
||||||
|
# is lost. This is compensated by the protocol (retrys)
|
||||||
If(sink.stb & sink.request,
|
If(sink.stb & sink.request,
|
||||||
NextState("SEND_REPLY")
|
NextState("SEND_REPLY")
|
||||||
).Elif(sink.stb & sink.reply,
|
).Elif(sink.stb & sink.reply & request_pending.q,
|
||||||
NextState("UPDATE_TABLE")
|
NextState("UPDATE_TABLE")
|
||||||
).Elif(request.stb,
|
).Elif(request.stb | (request_pending.q & request_timeout.reached),
|
||||||
NextState("CHECK_TABLE")
|
NextState("CHECK_TABLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -180,13 +195,21 @@ class LiteEthARPTable(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("UPDATE_TABLE",
|
fsm.act("UPDATE_TABLE",
|
||||||
# XXX update memory
|
request_pending.reset.eq(1),
|
||||||
NextState("IDLE")
|
update.eq(1),
|
||||||
|
NextState("CHECK_TABLE")
|
||||||
)
|
)
|
||||||
|
self.sync += [
|
||||||
|
If(update,
|
||||||
|
cached_ip_address.eq(sink.ip_address),
|
||||||
|
cached_mac_address.eq(sink.mac_address)
|
||||||
|
)
|
||||||
|
]
|
||||||
found = Signal()
|
found = Signal()
|
||||||
fsm.act("CHECK_TABLE",
|
fsm.act("CHECK_TABLE",
|
||||||
# XXX add a kind of CAM?
|
# XXX: add a live time for cached_mac_address
|
||||||
If(found,
|
If(request.ip_address == cached_ip_address,
|
||||||
|
request.ack.eq(request.stb),
|
||||||
NextState("PRESENT_RESPONSE")
|
NextState("PRESENT_RESPONSE")
|
||||||
).Else(
|
).Else(
|
||||||
NextState("SEND_REQUEST")
|
NextState("SEND_REQUEST")
|
||||||
|
@ -197,13 +220,16 @@ class LiteEthARPTable(Module):
|
||||||
source.request.eq(1),
|
source.request.eq(1),
|
||||||
source.ip_address.eq(request.ip_address),
|
source.ip_address.eq(request.ip_address),
|
||||||
If(source.ack,
|
If(source.ack,
|
||||||
|
request_timeout.reset.eq(1),
|
||||||
|
request_pending.ce.eq(1),
|
||||||
|
request.ack.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("PRESENT_RESPONSE",
|
fsm.act("PRESENT_RESPONSE",
|
||||||
response.stb.eq(1),
|
response.stb.eq(1),
|
||||||
response.failed.eq(0), # XXX add timeout to trigger failed
|
response.failed.eq(0), # XXX add timeout to trigger failed
|
||||||
response.mac_address.eq(0x12345678abcd), # XXX get mac address from table
|
response.mac_address.eq(cached_mac_address),
|
||||||
If(response.ack,
|
If(response.ack,
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
|
|
|
@ -129,6 +129,14 @@ def eth_udp_description(dw):
|
||||||
return EndpointDescription(layout, packetized=True)
|
return EndpointDescription(layout, packetized=True)
|
||||||
|
|
||||||
# Generic modules
|
# Generic modules
|
||||||
|
@DecorateModule(InsertReset)
|
||||||
|
@DecorateModule(InsertCE)
|
||||||
|
class FlipFlop(Module):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.d = Signal(**kwargs)
|
||||||
|
self.q = Signal(**kwargs)
|
||||||
|
self.sync += self.q.eq(self.d)
|
||||||
|
|
||||||
@DecorateModule(InsertReset)
|
@DecorateModule(InsertReset)
|
||||||
@DecorateModule(InsertCE)
|
@DecorateModule(InsertCE)
|
||||||
class Counter(Module):
|
class Counter(Module):
|
||||||
|
@ -147,8 +155,8 @@ class Timeout(Module):
|
||||||
self.reached = Signal()
|
self.reached = Signal()
|
||||||
###
|
###
|
||||||
value = Signal(max=length)
|
value = Signal(max=length)
|
||||||
self.sync += value.eq(value+1)
|
self.sync += If(~self.reached, value.eq(value+1))
|
||||||
self.comb += self.reached.eq(value == length)
|
self.comb += self.reached.eq(value == (length-1))
|
||||||
|
|
||||||
class BufferizeEndpoints(ModuleDecorator):
|
class BufferizeEndpoints(ModuleDecorator):
|
||||||
def __init__(self, submodule, *args):
|
def __init__(self, submodule, *args):
|
||||||
|
|
|
@ -18,11 +18,10 @@ class LiteEthDepacketizer(Module):
|
||||||
counter = Counter(max=header_length)
|
counter = Counter(max=header_length)
|
||||||
self.submodules += counter
|
self.submodules += counter
|
||||||
|
|
||||||
self.sync += [
|
self.sync += \
|
||||||
If(shift,
|
If(shift,
|
||||||
header.eq(Cat(header[8:], sink.data))
|
header.eq(Cat(header[8:], sink.data))
|
||||||
)
|
)
|
||||||
]
|
|
||||||
|
|
||||||
fsm = FSM(reset_state="IDLE")
|
fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
|
@ -47,8 +47,15 @@ class TB(Module):
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
selfp.arp.table.request.ip_address = 0x12345678
|
while selfp.arp.table.request.ack != 1:
|
||||||
selfp.arp.table.request.stb = 1
|
selfp.arp.table.request.stb = 1
|
||||||
|
selfp.arp.table.request.ip_address = 0x12345678
|
||||||
|
yield
|
||||||
|
selfp.arp.table.request.stb = 0
|
||||||
|
while selfp.arp.table.response.stb != 1:
|
||||||
|
selfp.arp.table.response.ack = 1
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
run_simulation(TB(), ncycles=1024, vcd_name="my.vcd", keep_files=True)
|
run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
|
||||||
|
|
Loading…
Reference in New Issue