diff --git a/liteeth/common.py b/liteeth/common.py index 1cec3e4e1..62edf71ad 100644 --- a/liteeth/common.py +++ b/liteeth/common.py @@ -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 diff --git a/liteeth/core/ip/__init__.py b/liteeth/core/ip/__init__.py index 34f7ebd44..64a386fd0 100644 --- a/liteeth/core/ip/__init__.py +++ b/liteeth/core/ip/__init__.py @@ -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() diff --git a/targets/udp.py b/targets/udp.py index cebc0143c..27b605e04 100644 --- a/targets/udp.py +++ b/targets/udp.py @@ -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) diff --git a/test/test_la.py b/test/test_la.py index b56343a60..e73f3713b 100644 --- a/test/test_la.py +++ b/test/test_la.py @@ -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 diff --git a/test/test_udp.py b/test/test_udp.py index 53ff1dc4d..666ab35c3 100644 --- a/test/test_udp.py +++ b/test/test_udp.py @@ -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