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.ethernet_type.eq(ethernet_type_arp),
|
||||
If(self.source.stb & self.source.ack,
|
||||
sink.ack.eq(1),
|
||||
sink.ack.eq(source.eop),
|
||||
counter.ce.eq(1),
|
||||
If(self.source.eop,
|
||||
NextState("IDLE")
|
||||
|
@ -148,7 +148,6 @@ arp_table_request_layout = [
|
|||
arp_table_response_layout = [
|
||||
("failed", 1),
|
||||
("mac_address", 48)
|
||||
|
||||
]
|
||||
|
||||
class LiteEthARPTable(Module):
|
||||
|
@ -159,15 +158,31 @@ class LiteEthARPTable(Module):
|
|||
# Request/Response interface
|
||||
self.request = request = Sink(arp_table_request_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")
|
||||
self.submodules += fsm
|
||||
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,
|
||||
NextState("SEND_REPLY")
|
||||
).Elif(sink.stb & sink.reply,
|
||||
).Elif(sink.stb & sink.reply & request_pending.q,
|
||||
NextState("UPDATE_TABLE")
|
||||
).Elif(request.stb,
|
||||
).Elif(request.stb | (request_pending.q & request_timeout.reached),
|
||||
NextState("CHECK_TABLE")
|
||||
)
|
||||
)
|
||||
|
@ -180,13 +195,21 @@ class LiteEthARPTable(Module):
|
|||
)
|
||||
)
|
||||
fsm.act("UPDATE_TABLE",
|
||||
# XXX update memory
|
||||
NextState("IDLE")
|
||||
request_pending.reset.eq(1),
|
||||
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()
|
||||
fsm.act("CHECK_TABLE",
|
||||
# XXX add a kind of CAM?
|
||||
If(found,
|
||||
# XXX: add a live time for cached_mac_address
|
||||
If(request.ip_address == cached_ip_address,
|
||||
request.ack.eq(request.stb),
|
||||
NextState("PRESENT_RESPONSE")
|
||||
).Else(
|
||||
NextState("SEND_REQUEST")
|
||||
|
@ -197,13 +220,16 @@ class LiteEthARPTable(Module):
|
|||
source.request.eq(1),
|
||||
source.ip_address.eq(request.ip_address),
|
||||
If(source.ack,
|
||||
request_timeout.reset.eq(1),
|
||||
request_pending.ce.eq(1),
|
||||
request.ack.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
fsm.act("PRESENT_RESPONSE",
|
||||
response.stb.eq(1),
|
||||
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,
|
||||
NextState("IDLE")
|
||||
)
|
||||
|
|
|
@ -129,6 +129,14 @@ def eth_udp_description(dw):
|
|||
return EndpointDescription(layout, packetized=True)
|
||||
|
||||
# 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(InsertCE)
|
||||
class Counter(Module):
|
||||
|
@ -147,8 +155,8 @@ class Timeout(Module):
|
|||
self.reached = Signal()
|
||||
###
|
||||
value = Signal(max=length)
|
||||
self.sync += value.eq(value+1)
|
||||
self.comb += self.reached.eq(value == length)
|
||||
self.sync += If(~self.reached, value.eq(value+1))
|
||||
self.comb += self.reached.eq(value == (length-1))
|
||||
|
||||
class BufferizeEndpoints(ModuleDecorator):
|
||||
def __init__(self, submodule, *args):
|
||||
|
|
|
@ -18,11 +18,10 @@ class LiteEthDepacketizer(Module):
|
|||
counter = Counter(max=header_length)
|
||||
self.submodules += counter
|
||||
|
||||
self.sync += [
|
||||
self.sync += \
|
||||
If(shift,
|
||||
header.eq(Cat(header[8:], sink.data))
|
||||
)
|
||||
]
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
|
|
|
@ -47,8 +47,15 @@ class TB(Module):
|
|||
for i in range(100):
|
||||
yield
|
||||
|
||||
selfp.arp.table.request.ip_address = 0x12345678
|
||||
selfp.arp.table.request.stb = 1
|
||||
while selfp.arp.table.request.ack != 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__":
|
||||
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