From fa483463855628604fc4aba2e522594786b61cf6 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 30 Jan 2015 12:02:01 +0100 Subject: [PATCH] arp: request/reply with model OK --- liteeth/arp/__init__.py | 44 ++++++++++++++++++++++++++------- liteeth/common.py | 12 +++++++-- liteeth/generic/depacketizer.py | 3 +-- liteeth/test/arp_tb.py | 13 +++++++--- 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/liteeth/arp/__init__.py b/liteeth/arp/__init__.py index 96d415c51..1fe170bff 100644 --- a/liteeth/arp/__init__.py +++ b/liteeth/arp/__init__.py @@ -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") ) diff --git a/liteeth/common.py b/liteeth/common.py index ddb14e2df..42e3ea0fb 100644 --- a/liteeth/common.py +++ b/liteeth/common.py @@ -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): diff --git a/liteeth/generic/depacketizer.py b/liteeth/generic/depacketizer.py index 39d111362..0713b36e8 100644 --- a/liteeth/generic/depacketizer.py +++ b/liteeth/generic/depacketizer.py @@ -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 diff --git a/liteeth/test/arp_tb.py b/liteeth/test/arp_tb.py index e11a11011..27e34a4aa 100644 --- a/liteeth/test/arp_tb.py +++ b/liteeth/test/arp_tb.py @@ -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)