use PacketBuffer for udp loopback
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 9 Feb 2015 16:57:45 +0000 (17:57 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 9 Feb 2015 18:10:55 +0000 (19:10 +0100)
liteeth/common.py
liteeth/core/ip/__init__.py
targets/udp.py
test/test_la.py
test/test_udp.py

index 1cec3e4e109d5d3f6ab66be6996994fe5d6373cf..62edf71ad4bad764312d37780595dd5ebdc1f37e 100644 (file)
@@ -247,3 +247,81 @@ class BufferizeEndpoints(ModuleDecorator):
                        self.comb += Record.connect(source, buf.d)
                        setattr(self, name, buf.q)
 
+class EndpointPacketStatus(Module):
+       def __init__(self, endpoint):
+               self.start = Signal()
+               self.done = Signal()
+               self.ongoing = Signal()
+
+               ongoing = Signal()
+               self.comb += [
+                       self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack),
+                       self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack)
+               ]
+               self.sync += \
+                       If(self.start,
+                               ongoing.eq(1)
+                       ).Elif(self.done,
+                               ongoing.eq(0)
+                       )
+               self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done)
+
+class PacketBuffer(Module):
+       def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
+               self.sink = sink = Sink(description)
+               self.source = source = Source(description)
+
+               ###
+               sink_status = EndpointPacketStatus(self.sink)
+               source_status = EndpointPacketStatus(self.source)
+               self.submodules += sink_status, source_status
+
+               # store incoming packets
+               # cmds
+               def cmd_description():
+                       layout = [("error", 1)]
+                       return EndpointDescription(layout)
+               cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
+               self.submodules += cmd_fifo
+               self.comb += [
+                       cmd_fifo.sink.stb.eq(sink_status.done),
+                       cmd_fifo.sink.error.eq(sink.error)
+               ]
+
+               # data
+               data_fifo = SyncFIFO(description, data_depth, buffered=True)
+               self.submodules += data_fifo
+               self.comb += [
+                       Record.connect(self.sink, data_fifo.sink),
+                       data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack),
+                       self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack),
+               ]
+
+               # output packets
+               self.fsm = fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
+               fsm.act("IDLE",
+                       If(cmd_fifo.source.stb,
+                               NextState("SEEK_SOP")
+                       )
+               )
+               fsm.act("SEEK_SOP",
+                       If(~data_fifo.source.sop,
+                               data_fifo.source.ack.eq(1)
+                       ).Else(
+                               NextState("OUTPUT")
+                       )
+               )
+               fsm.act("OUTPUT",
+                       Record.connect(data_fifo.source, self.source),
+                       self.source.error.eq(cmd_fifo.source.error),
+                       If(source_status.done,
+                               cmd_fifo.source.ack.eq(1),
+                               NextState("IDLE")
+                       )
+               )
+
+               # compute almost full
+               if almost_full is not None:
+                       self.almost_full = Signal()
+                       self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full)
\ No newline at end of file
index 34f7ebd4473f6fd2c36340a791491d502b3225d2..64a386fd04a9269629fd2ad212e4e9b3a172122b 100644 (file)
@@ -69,7 +69,7 @@ class LiteEthIPTX(Module):
                self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=True)
                self.comb += [
                        checksum.ce.eq(sink.stb & sink.sop),
-                       checksum.reset.eq(source.stb & source.eop)
+                       checksum.reset.eq(source.stb & source.eop & source.ack)
                ]
 
                self.submodules.packetizer = packetizer = LiteEthIPV4Packetizer()
index cebc0143c3b966f6659006f6dc1c2a2b8829e3b2..27b605e04abe82f79154c4d61e55f58ab721b24b 100644 (file)
@@ -116,11 +116,10 @@ class UDPSoC(GenSoC, AutoCSR):
 
                # Create loopback on UDP port 6000
                loopback_port = self.core.udp.crossbar.get_port(6000)
-               loopback_fifo = SyncFIFO(eth_udp_user_description(8), 8192, buffered=True)
-               self.submodules += loopback_fifo
+               self.submodules.loopback_buffer = PacketBuffer(eth_udp_user_description(8), 8192, 8)
                self.comb += [
-                       Record.connect(loopback_port.source, loopback_fifo.sink),
-                       Record.connect(loopback_fifo.source, loopback_port.sink)
+                       Record.connect(loopback_port.source, self.loopback_buffer.sink),
+                       Record.connect(self.loopback_buffer.source, loopback_port.sink)
                ]
 
 class UDPSoCDevel(UDPSoC, AutoCSR):
@@ -174,6 +173,18 @@ class UDPSoCDevel(UDPSoC, AutoCSR):
                        self.core.ip.crossbar.master.sink.ip_address,
                        self.core.ip.crossbar.master.sink.protocol,
 
+                       self.loopback_buffer.sink.stb,
+                       self.loopback_buffer.sink.sop,
+                       self.loopback_buffer.sink.eop,
+                       self.loopback_buffer.sink.ack,
+                       self.loopback_buffer.sink.data,
+
+                       self.loopback_buffer.source.stb,
+                       self.loopback_buffer.source.sop,
+                       self.loopback_buffer.source.eop,
+                       self.loopback_buffer.source.ack,
+                       self.loopback_buffer.source.data,
+
                        self.phy.sink.stb,
                        self.phy.sink.sop,
                        self.phy.sink.eop,
@@ -197,7 +208,7 @@ class UDPSoCDevel(UDPSoC, AutoCSR):
                        self.core_arp_table_fsm_state,
                )
 
-               self.submodules.la = LiteScopeLA(debug, 2048)
+               self.submodules.la = LiteScopeLA(debug, 4096)
                self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
                atexit.register(self.exit, platform)
 
index b56343a60571e120c1955c64aba5e78c7af81b9b..e73f3713b68637cd39157e37a493ed49b57e04c3 100644 (file)
@@ -12,10 +12,13 @@ conditions = {}
 conditions = {
        "udpsocdevel_mac_rx_cdc_source_stb"     : 1
 }
+conditions = {
+       "core_udp_tx_fsm_state" : 1
+}
 la.configure_term(port=0, cond=conditions)
 la.configure_sum("term")
 # Run Logic Analyzer
-la.run(offset=64, length=1024)
+la.run(offset=2048, length=4000)
 
 while not la.done():
        pass
index 53ff1dc4d9d1fd4f6d4ce29d34f7d87a728021a6..666ab35c3d6fafdba24b73ec5a3aad5eb3d6b5ba 100644 (file)
@@ -51,7 +51,7 @@ rx_sock.bind(("", udp_port))
 def receive():
        rx_seed = 0
        while rx_seed < test_size:
-               data, addr = rx_sock.recvfrom(1024)
+               data, addr = rx_sock.recvfrom(8192)
                rx_packet = []
                for byte in data:
                        rx_packet.append(int(byte))
@@ -64,7 +64,7 @@ def send():
        while tx_seed < test_size:
                tx_packet, tx_seed = generate_packet(tx_seed, 1024)
                tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port))
-               time.sleep(0.001) # XXX: FIXME
+               time.sleep(0.001) # XXX: FIXME, Python limitation?
 
 receive_thread = threading.Thread(target=receive)
 receive_thread.start()
@@ -73,7 +73,7 @@ send_thread = threading.Thread(target=send)
 send_thread.start()
 
 try:
-       send_thread.join()
-       receive_thread.join()
+       send_thread.join(10)
+       receive_thread.join(0.1)
 except KeyboardInterrupt:
        pass