arp: request/reply with model OK
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 30 Jan 2015 11:02:01 +0000 (12:02 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 30 Jan 2015 11:02:01 +0000 (12:02 +0100)
liteeth/arp/__init__.py
liteeth/common.py
liteeth/generic/depacketizer.py
liteeth/test/arp_tb.py

index 96d415c51ec2203e12aa4d58ea262da08538d90a..1fe170bffd9ba1aa1dde5ad4a909bc354278e6f9 100644 (file)
@@ -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")
                        )
index ddb14e2df3ae819a8d342131db31ca6a00faab50..42e3ea0fb3606a907ab4dc9e55c80a1f1ad4b21e 100644 (file)
@@ -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):
index 39d11136265f00b2d3ce4f5233de811d8b3e6edf..0713b36e8fb6eef37bfc33cb9cd18787de5e8645 100644 (file)
@@ -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
index e11a1101101000991cbe11c4311851493a018b53..27e34a4aa4cc9b69b0d7c7aa48bab61d30889354 100644 (file)
@@ -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)