From e61c229bbb01bdef969d565230b68463b80fc0c2 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 2 Oct 2015 10:32:53 +0200 Subject: [PATCH] simplify organization (try to regroup layers in single files) --- liteeth/core/{arp/__init__.py => arp.py} | 5 + liteeth/core/{icmp/__init__.py => icmp.py} | 4 + liteeth/core/{ip/__init__.py => ip.py} | 83 +++- liteeth/core/ip/checksum.py | 45 -- liteeth/core/ip/crossbar.py | 33 -- liteeth/core/{udp/__init__.py => udp.py} | 55 ++- liteeth/core/udp/crossbar.py | 51 -- liteeth/frontend/etherbone.py | 444 ++++++++++++++++++ liteeth/frontend/etherbone/__init__.py | 29 -- liteeth/frontend/etherbone/packet.py | 135 ------ liteeth/frontend/etherbone/probe.py | 26 - liteeth/frontend/etherbone/record.py | 183 -------- liteeth/frontend/etherbone/wishbone.py | 70 --- liteeth/phy/loopback.py | 31 -- .../dissector => software/dissectors}/bit.lua | 0 .../dissectors}/etherbone.lua | 0 16 files changed, 588 insertions(+), 606 deletions(-) rename liteeth/core/{arp/__init__.py => arp.py} (99%) rename liteeth/core/{icmp/__init__.py => icmp.py} (99%) rename liteeth/core/{ip/__init__.py => ip.py} (71%) delete mode 100644 liteeth/core/ip/checksum.py delete mode 100644 liteeth/core/ip/crossbar.py rename liteeth/core/{udp/__init__.py => udp.py} (70%) delete mode 100644 liteeth/core/udp/crossbar.py create mode 100644 liteeth/frontend/etherbone.py delete mode 100644 liteeth/frontend/etherbone/__init__.py delete mode 100644 liteeth/frontend/etherbone/packet.py delete mode 100644 liteeth/frontend/etherbone/probe.py delete mode 100644 liteeth/frontend/etherbone/record.py delete mode 100644 liteeth/frontend/etherbone/wishbone.py delete mode 100644 liteeth/phy/loopback.py rename liteeth/{frontend/etherbone/dissector => software/dissectors}/bit.lua (100%) rename liteeth/{frontend/etherbone/dissector => software/dissectors}/etherbone.lua (100%) diff --git a/liteeth/core/arp/__init__.py b/liteeth/core/arp.py similarity index 99% rename from liteeth/core/arp/__init__.py rename to liteeth/core/arp.py index bfce79e..b28c858 100644 --- a/liteeth/core/arp/__init__.py +++ b/liteeth/core/arp.py @@ -1,5 +1,6 @@ from liteeth.common import * + _arp_table_layout = [ ("reply", 1), ("request", 1), @@ -7,6 +8,7 @@ _arp_table_layout = [ ("mac_address", 48) ] +# arp tx class LiteEthARPPacketizer(Packetizer): def __init__(self): @@ -72,6 +74,7 @@ class LiteEthARPTX(Module): ) ) +# arp rx class LiteEthARPDepacketizer(Depacketizer): def __init__(self): @@ -134,6 +137,7 @@ class LiteEthARPRX(Module): ) ) +# arp table class LiteEthARPTable(Module): def __init__(self, clk_freq, max_requests=8): @@ -251,6 +255,7 @@ class LiteEthARPTable(Module): ) ) +# arp class LiteEthARP(Module): def __init__(self, mac, mac_address, ip_address, clk_freq): diff --git a/liteeth/core/icmp/__init__.py b/liteeth/core/icmp.py similarity index 99% rename from liteeth/core/icmp/__init__.py rename to liteeth/core/icmp.py index b72e018..6b81be5 100644 --- a/liteeth/core/icmp/__init__.py +++ b/liteeth/core/icmp.py @@ -1,5 +1,6 @@ from liteeth.common import * +# icmp tx class LiteEthICMPPacketizer(Packetizer): def __init__(self): @@ -47,6 +48,7 @@ class LiteEthICMPTX(Module): ) ) +# icmp rx class LiteEthICMPDepacketizer(Depacketizer): def __init__(self): @@ -114,6 +116,7 @@ class LiteEthICMPRX(Module): ) ) +# icmp echo class LiteEthICMPEcho(Module): def __init__(self): @@ -130,6 +133,7 @@ class LiteEthICMPEcho(Module): self.source.checksum.eq(~((~self.buffer.source.checksum)-0x0800)) ] +# icmp class LiteEthICMP(Module): def __init__(self, ip, ip_address): diff --git a/liteeth/core/ip/__init__.py b/liteeth/core/ip.py similarity index 71% rename from liteeth/core/ip/__init__.py rename to liteeth/core/ip.py index a181e0f..314873e 100644 --- a/liteeth/core/ip/__init__.py +++ b/liteeth/core/ip.py @@ -1,7 +1,84 @@ from liteeth.common import * -from liteeth.core.ip.checksum import * -from liteeth.core.ip.crossbar import * +from liteeth.crossbar import LiteEthCrossbar +# ip crossbar + +class LiteEthIPV4MasterPort: + def __init__(self, dw): + self.dw = dw + self.source = Source(eth_ipv4_user_description(dw)) + self.sink = Sink(eth_ipv4_user_description(dw)) + + +class LiteEthIPV4SlavePort: + def __init__(self, dw): + self.dw = dw + self.sink = Sink(eth_ipv4_user_description(dw)) + self.source = Source(eth_ipv4_user_description(dw)) + + +class LiteEthIPV4UserPort(LiteEthIPV4SlavePort): + def __init__(self, dw): + LiteEthIPV4SlavePort.__init__(self, dw) + + +class LiteEthIPV4Crossbar(LiteEthCrossbar): + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthIPV4MasterPort, "protocol") + + def get_port(self, protocol): + if protocol in self.users.keys(): + raise ValueError("Protocol {0:#x} already assigned".format(protocol)) + port = LiteEthIPV4UserPort(8) + self.users[protocol] = port + return port + +# ip checksum + +class LiteEthIPV4Checksum(Module): + def __init__(self, words_per_clock_cycle=1, skip_checksum=False): + self.reset = Signal() # XXX FIXME InsertReset generates incorrect verilog + self.ce = Signal() # XXX FIXME InsertCE generates incorrect verilog + self.header = Signal(ipv4_header.length*8) + self.value = Signal(16) + self.done = Signal() + + # # # + + s = Signal(17) + r = Signal(17) + n_cycles = 0 + for i in range(ipv4_header.length//2): + if skip_checksum and (i == ipv4_header.fields["checksum"].byte//2): + pass + else: + s_next = Signal(17) + r_next = Signal(17) + self.comb += s_next.eq(r + self.header[i*16:(i+1)*16]) + r_next_eq = r_next.eq(Cat(s_next[:16]+s_next[16], Signal())) + if (i%words_per_clock_cycle) != 0: + self.comb += r_next_eq + else: + self.sync += \ + If(self.reset, + r_next.eq(0) + ).Elif(self.ce & ~self.done, + r_next_eq + ) + n_cycles += 1 + s, r = s_next, r_next + self.comb += self.value.eq(~Cat(r[8:16], r[:8])) + + if not skip_checksum: + n_cycles += 1 + self.submodules.counter = counter = Counter(max=n_cycles+1) + self.comb += [ + counter.reset.eq(self.reset), + counter.ce.eq(self.ce & ~self.done), + self.done.eq(counter.value == n_cycles) + ] + +# ip tx class LiteEthIPV4Packetizer(Packetizer): def __init__(self): @@ -94,6 +171,7 @@ class LiteEthIPTX(Module): ) ) +# ip rx class LiteEthIPV4Depacketizer(Depacketizer): def __init__(self): @@ -171,6 +249,7 @@ class LiteEthIPRX(Module): ) ) +# ip class LiteEthIP(Module): def __init__(self, mac, mac_address, ip_address, arp_table): diff --git a/liteeth/core/ip/checksum.py b/liteeth/core/ip/checksum.py deleted file mode 100644 index 1faa171..0000000 --- a/liteeth/core/ip/checksum.py +++ /dev/null @@ -1,45 +0,0 @@ -from liteeth.common import * - - -class LiteEthIPV4Checksum(Module): - def __init__(self, words_per_clock_cycle=1, skip_checksum=False): - self.reset = Signal() # XXX FIXME InsertReset generates incorrect verilog - self.ce = Signal() # XXX FIXME InsertCE generates incorrect verilog - self.header = Signal(ipv4_header.length*8) - self.value = Signal(16) - self.done = Signal() - - # # # - - s = Signal(17) - r = Signal(17) - n_cycles = 0 - for i in range(ipv4_header.length//2): - if skip_checksum and (i == ipv4_header.fields["checksum"].byte//2): - pass - else: - s_next = Signal(17) - r_next = Signal(17) - self.comb += s_next.eq(r + self.header[i*16:(i+1)*16]) - r_next_eq = r_next.eq(Cat(s_next[:16]+s_next[16], Signal())) - if (i%words_per_clock_cycle) != 0: - self.comb += r_next_eq - else: - self.sync += \ - If(self.reset, - r_next.eq(0) - ).Elif(self.ce & ~self.done, - r_next_eq - ) - n_cycles += 1 - s, r = s_next, r_next - self.comb += self.value.eq(~Cat(r[8:16], r[:8])) - - if not skip_checksum: - n_cycles += 1 - self.submodules.counter = counter = Counter(max=n_cycles+1) - self.comb += [ - counter.reset.eq(self.reset), - counter.ce.eq(self.ce & ~self.done), - self.done.eq(counter.value == n_cycles) - ] diff --git a/liteeth/core/ip/crossbar.py b/liteeth/core/ip/crossbar.py deleted file mode 100644 index fa634c2..0000000 --- a/liteeth/core/ip/crossbar.py +++ /dev/null @@ -1,33 +0,0 @@ -from liteeth.common import * -from liteeth.crossbar import LiteEthCrossbar - - -class LiteEthIPV4MasterPort: - def __init__(self, dw): - self.dw = dw - self.source = Source(eth_ipv4_user_description(dw)) - self.sink = Sink(eth_ipv4_user_description(dw)) - - -class LiteEthIPV4SlavePort: - def __init__(self, dw): - self.dw = dw - self.sink = Sink(eth_ipv4_user_description(dw)) - self.source = Source(eth_ipv4_user_description(dw)) - - -class LiteEthIPV4UserPort(LiteEthIPV4SlavePort): - def __init__(self, dw): - LiteEthIPV4SlavePort.__init__(self, dw) - - -class LiteEthIPV4Crossbar(LiteEthCrossbar): - def __init__(self): - LiteEthCrossbar.__init__(self, LiteEthIPV4MasterPort, "protocol") - - def get_port(self, protocol): - if protocol in self.users.keys(): - raise ValueError("Protocol {0:#x} already assigned".format(protocol)) - port = LiteEthIPV4UserPort(8) - self.users[protocol] = port - return port diff --git a/liteeth/core/udp/__init__.py b/liteeth/core/udp.py similarity index 70% rename from liteeth/core/udp/__init__.py rename to liteeth/core/udp.py index 4897a8e..fa30a20 100644 --- a/liteeth/core/udp/__init__.py +++ b/liteeth/core/udp.py @@ -1,6 +1,57 @@ from liteeth.common import * -from liteeth.core.udp.crossbar import * +from liteeth.crossbar import LiteEthCrossbar +# udp crossbar + +class LiteEthUDPMasterPort: + def __init__(self, dw): + self.dw = dw + self.source = Source(eth_udp_user_description(dw)) + self.sink = Sink(eth_udp_user_description(dw)) + + +class LiteEthUDPSlavePort: + def __init__(self, dw): + self.dw = dw + self.sink = Sink(eth_udp_user_description(dw)) + self.source = Source(eth_udp_user_description(dw)) + + +class LiteEthUDPUserPort(LiteEthUDPSlavePort): + def __init__(self, dw): + LiteEthUDPSlavePort.__init__(self, dw) + + +class LiteEthUDPCrossbar(LiteEthCrossbar): + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port") + + def get_port(self, udp_port, dw=8): + if udp_port in self.users.keys(): + raise ValueError("Port {0:#x} already assigned".format(udp_port)) + user_port = LiteEthUDPUserPort(dw) + internal_port = LiteEthUDPUserPort(8) + if dw != 8: + converter = Converter(eth_udp_user_description(user_port.dw), + eth_udp_user_description(8)) + self.submodules += converter + self.comb += [ + Record.connect(user_port.sink, converter.sink), + Record.connect(converter.source, internal_port.sink) + ] + converter = Converter(eth_udp_user_description(8), + eth_udp_user_description(user_port.dw)) + self.submodules += converter + self.comb += [ + Record.connect(internal_port.source, converter.sink), + Record.connect(converter.source, user_port.source) + ] + self.users[udp_port] = internal_port + else: + self.users[udp_port] = user_port + return user_port + +# udp tx class LiteEthUDPPacketizer(Packetizer): def __init__(self): @@ -48,6 +99,7 @@ class LiteEthUDPTX(Module): ) ) +# udp rx class LiteEthUDPDepacketizer(Depacketizer): def __init__(self): @@ -114,6 +166,7 @@ class LiteEthUDPRX(Module): ) ) +# udp class LiteEthUDP(Module): def __init__(self, ip, ip_address): diff --git a/liteeth/core/udp/crossbar.py b/liteeth/core/udp/crossbar.py deleted file mode 100644 index 247d789..0000000 --- a/liteeth/core/udp/crossbar.py +++ /dev/null @@ -1,51 +0,0 @@ -from liteeth.common import * -from liteeth.crossbar import LiteEthCrossbar - - -class LiteEthUDPMasterPort: - def __init__(self, dw): - self.dw = dw - self.source = Source(eth_udp_user_description(dw)) - self.sink = Sink(eth_udp_user_description(dw)) - - -class LiteEthUDPSlavePort: - def __init__(self, dw): - self.dw = dw - self.sink = Sink(eth_udp_user_description(dw)) - self.source = Source(eth_udp_user_description(dw)) - - -class LiteEthUDPUserPort(LiteEthUDPSlavePort): - def __init__(self, dw): - LiteEthUDPSlavePort.__init__(self, dw) - - -class LiteEthUDPCrossbar(LiteEthCrossbar): - def __init__(self): - LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port") - - def get_port(self, udp_port, dw=8): - if udp_port in self.users.keys(): - raise ValueError("Port {0:#x} already assigned".format(udp_port)) - user_port = LiteEthUDPUserPort(dw) - internal_port = LiteEthUDPUserPort(8) - if dw != 8: - converter = Converter(eth_udp_user_description(user_port.dw), - eth_udp_user_description(8)) - self.submodules += converter - self.comb += [ - Record.connect(user_port.sink, converter.sink), - Record.connect(converter.source, internal_port.sink) - ] - converter = Converter(eth_udp_user_description(8), - eth_udp_user_description(user_port.dw)) - self.submodules += converter - self.comb += [ - Record.connect(internal_port.source, converter.sink), - Record.connect(converter.source, user_port.source) - ] - self.users[udp_port] = internal_port - else: - self.users[udp_port] = user_port - return user_port diff --git a/liteeth/frontend/etherbone.py b/liteeth/frontend/etherbone.py new file mode 100644 index 0000000..baa5f1e --- /dev/null +++ b/liteeth/frontend/etherbone.py @@ -0,0 +1,444 @@ +from liteeth.common import * +from migen.bus import wishbone + +# etherbone packet + +class LiteEthEtherbonePacketPacketizer(Packetizer): + def __init__(self): + Packetizer.__init__(self, + eth_etherbone_packet_description(32), + eth_udp_user_description(32), + etherbone_packet_header) + + +class LiteEthEtherbonePacketTX(Module): + def __init__(self, udp_port): + self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) + self.source = source = Source(eth_udp_user_description(32)) + + # # # + + self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer() + self.comb += [ + packetizer.sink.stb.eq(sink.stb), + packetizer.sink.sop.eq(sink.sop), + packetizer.sink.eop.eq(sink.eop), + sink.ack.eq(packetizer.sink.ack), + + packetizer.sink.magic.eq(etherbone_magic), + packetizer.sink.port_size.eq(32//8), + packetizer.sink.addr_size.eq(32//8), + packetizer.sink.pf.eq(sink.pf), + packetizer.sink.pr.eq(sink.pr), + packetizer.sink.nr.eq(sink.nr), + packetizer.sink.version.eq(etherbone_version), + + packetizer.sink.data.eq(sink.data) + ] + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + packetizer.source.ack.eq(1), + If(packetizer.source.stb & packetizer.source.sop, + packetizer.source.ack.eq(0), + NextState("SEND") + ) + ) + fsm.act("SEND", + Record.connect(packetizer.source, source), + source.src_port.eq(udp_port), + source.dst_port.eq(udp_port), + source.ip_address.eq(sink.ip_address), + source.length.eq(sink.length + etherbone_packet_header.length), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + + +class LiteEthEtherbonePacketDepacketizer(Depacketizer): + def __init__(self): + Depacketizer.__init__(self, + eth_udp_user_description(32), + eth_etherbone_packet_description(32), + etherbone_packet_header) + + +class LiteEthEtherbonePacketRX(Module): + def __init__(self): + self.sink = sink = Sink(eth_udp_user_description(32)) + self.source = source = Source(eth_etherbone_packet_user_description(32)) + + # # # + + self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer() + self.comb += Record.connect(sink, depacketizer.sink) + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.sop, + depacketizer.source.ack.eq(0), + NextState("CHECK") + ) + ) + valid = Signal() + self.sync += valid.eq( + depacketizer.source.stb & + (depacketizer.source.magic == etherbone_magic) + ) + fsm.act("CHECK", + If(valid, + NextState("PRESENT") + ).Else( + NextState("DROP") + ) + ) + self.comb += [ + source.sop.eq(depacketizer.source.sop), + source.eop.eq(depacketizer.source.eop), + + source.pf.eq(depacketizer.source.pf), + source.pr.eq(depacketizer.source.pr), + source.nr.eq(depacketizer.source.nr), + + source.data.eq(depacketizer.source.data), + + source.src_port.eq(sink.src_port), + source.dst_port.eq(sink.dst_port), + source.ip_address.eq(sink.ip_address), + source.length.eq(sink.length - etherbone_packet_header.length) + ] + fsm.act("PRESENT", + source.stb.eq(depacketizer.source.stb), + depacketizer.source.ack.eq(source.ack), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + fsm.act("DROP", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & + depacketizer.source.eop & + depacketizer.source.ack, + NextState("IDLE") + ) + ) + + +class LiteEthEtherbonePacket(Module): + def __init__(self, udp, udp_port): + self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port) + self.submodules.rx = rx = LiteEthEtherbonePacketRX() + udp_port = udp.crossbar.get_port(udp_port, dw=32) + self.comb += [ + Record.connect(tx.source, udp_port.sink), + Record.connect(udp_port.source, rx.sink) + ] + self.sink, self.source = self.tx.sink, self.rx.source + + +# etherbone probe + +class LiteEthEtherboneProbe(Module): + def __init__(self): + self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) + self.source = source = Source(eth_etherbone_packet_user_description(32)) + + # # # + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + sink.ack.eq(1), + If(sink.stb & sink.sop, + sink.ack.eq(0), + NextState("PROBE_RESPONSE") + ) + ) + fsm.act("PROBE_RESPONSE", + Record.connect(sink, source), + source.pf.eq(0), + source.pr.eq(1), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + +# etherbone record + +class LiteEthEtherboneRecordPacketizer(Packetizer): + def __init__(self): + Packetizer.__init__(self, + eth_etherbone_record_description(32), + eth_etherbone_packet_user_description(32), + etherbone_record_header) + + +class LiteEthEtherboneRecordDepacketizer(Depacketizer): + def __init__(self): + Depacketizer.__init__(self, + eth_etherbone_packet_user_description(32), + eth_etherbone_record_description(32), + etherbone_record_header) + + +class LiteEthEtherboneRecordReceiver(Module): + def __init__(self, buffer_depth=256): + self.sink = sink = Sink(eth_etherbone_record_description(32)) + self.source = source = Source(eth_etherbone_mmap_description(32)) + + # # # + + fifo = SyncFIFO(eth_etherbone_record_description(32), buffer_depth, + buffered=True) + self.submodules += fifo + self.comb += Record.connect(sink, fifo.sink) + + self.submodules.base_addr = base_addr = FlipFlop(32) + self.comb += base_addr.d.eq(fifo.source.data) + + self.submodules.counter = counter = Counter(max=512) + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + fifo.source.ack.eq(1), + counter.reset.eq(1), + If(fifo.source.stb & fifo.source.sop, + base_addr.ce.eq(1), + If(fifo.source.wcount, + NextState("RECEIVE_WRITES") + ).Elif(fifo.source.rcount, + NextState("RECEIVE_READS") + ) + ) + ) + fsm.act("RECEIVE_WRITES", + source.stb.eq(fifo.source.stb), + source.sop.eq(counter.value == 0), + source.eop.eq(counter.value == fifo.source.wcount-1), + source.count.eq(fifo.source.wcount), + source.be.eq(fifo.source.byte_enable), + source.addr.eq(base_addr.q[2:] + counter.value), + source.we.eq(1), + source.data.eq(fifo.source.data), + fifo.source.ack.eq(source.ack), + If(source.stb & source.ack, + counter.ce.eq(1), + If(source.eop, + If(fifo.source.rcount, + NextState("RECEIVE_BASE_RET_ADDR") + ).Else( + NextState("IDLE") + ) + ) + ) + ) + fsm.act("RECEIVE_BASE_RET_ADDR", + counter.reset.eq(1), + If(fifo.source.stb & fifo.source.sop, + base_addr.ce.eq(1), + NextState("RECEIVE_READS") + ) + ) + fsm.act("RECEIVE_READS", + source.stb.eq(fifo.source.stb), + source.sop.eq(counter.value == 0), + source.eop.eq(counter.value == fifo.source.rcount-1), + source.count.eq(fifo.source.rcount), + source.base_addr.eq(base_addr.q), + source.addr.eq(fifo.source.data[2:]), + fifo.source.ack.eq(source.ack), + If(source.stb & source.ack, + counter.ce.eq(1), + If(source.eop, + NextState("IDLE") + ) + ) + ) + + +class LiteEthEtherboneRecordSender(Module): + def __init__(self, buffer_depth=256): + self.sink = sink = Sink(eth_etherbone_mmap_description(32)) + self.source = source = Source(eth_etherbone_record_description(32)) + + # # # + + pbuffer = Buffer(eth_etherbone_mmap_description(32), buffer_depth) + self.submodules += pbuffer + self.comb += Record.connect(sink, pbuffer.sink) + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + pbuffer.source.ack.eq(1), + If(pbuffer.source.stb & pbuffer.source.sop, + pbuffer.source.ack.eq(0), + NextState("SEND_BASE_ADDRESS") + ) + ) + self.comb += [ + source.byte_enable.eq(pbuffer.source.be), + If(pbuffer.source.we, + source.wcount.eq(pbuffer.source.count) + ).Else( + source.rcount.eq(pbuffer.source.count) + ) + ] + + fsm.act("SEND_BASE_ADDRESS", + source.stb.eq(pbuffer.source.stb), + source.sop.eq(1), + source.eop.eq(0), + source.data.eq(pbuffer.source.base_addr), + If(source.ack, + NextState("SEND_DATA") + ) + ) + fsm.act("SEND_DATA", + source.stb.eq(pbuffer.source.stb), + source.sop.eq(0), + source.eop.eq(pbuffer.source.eop), + source.data.eq(pbuffer.source.data), + If(source.stb & source.ack, + pbuffer.source.ack.eq(1), + If(source.eop, + NextState("IDLE") + ) + ) + ) + + +class LiteEthEtherboneRecord(Module): + # Limitation: For simplicity we only support 1 record per packet + def __init__(self, endianness="big"): + self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) + self.source = source = Sink(eth_etherbone_packet_user_description(32)) + + # # # + + # receive record, decode it and generate mmap stream + self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer() + self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver() + self.comb += [ + Record.connect(sink, depacketizer.sink), + Record.connect(depacketizer.source, receiver.sink) + ] + if endianness is "big": + self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data)) + + # save last ip address + last_ip_address = Signal(32) + self.sync += [ + If(sink.stb & sink.sop & sink.ack, + last_ip_address.eq(sink.ip_address) + ) + ] + + # receive mmap stream, encode it and send records + self.submodules.sender = sender = LiteEthEtherboneRecordSender() + self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer() + self.comb += [ + Record.connect(sender.source, packetizer.sink), + Record.connect(packetizer.source, source), + # XXX improve this + source.length.eq(sender.source.wcount*4 + 4 + etherbone_record_header.length), + source.ip_address.eq(last_ip_address) + ] + if endianness is "big": + self.comb += packetizer.sink.data.eq(reverse_bytes(sender.source.data)) + + + +# etherbone wishbone + +class LiteEthEtherboneWishboneMaster(Module): + def __init__(self): + self.sink = sink = Sink(eth_etherbone_mmap_description(32)) + self.source = source = Source(eth_etherbone_mmap_description(32)) + self.bus = bus = wishbone.Interface() + + # # # + + self.submodules.data = data = FlipFlop(32) + self.comb += data.d.eq(bus.dat_r) + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + sink.ack.eq(1), + If(sink.stb & sink.sop, + sink.ack.eq(0), + If(sink.we, + NextState("WRITE_DATA") + ).Else( + NextState("READ_DATA") + ) + ) + ) + fsm.act("WRITE_DATA", + bus.adr.eq(sink.addr), + bus.dat_w.eq(sink.data), + bus.sel.eq(sink.be), + bus.stb.eq(sink.stb), + bus.we.eq(1), + bus.cyc.eq(1), + If(bus.stb & bus.ack, + sink.ack.eq(1), + If(sink.eop, + NextState("IDLE") + ) + ) + ) + fsm.act("READ_DATA", + bus.adr.eq(sink.addr), + bus.sel.eq(sink.be), + bus.stb.eq(sink.stb), + bus.cyc.eq(1), + If(bus.stb & bus.ack, + data.ce.eq(1), + NextState("SEND_DATA") + ) + ) + fsm.act("SEND_DATA", + source.stb.eq(sink.stb), + source.sop.eq(sink.sop), + source.eop.eq(sink.eop), + source.base_addr.eq(sink.base_addr), + source.addr.eq(sink.addr), + source.count.eq(sink.count), + source.be.eq(sink.be), + source.we.eq(1), + source.data.eq(data.q), + If(source.stb & source.ack, + sink.ack.eq(1), + If(source.eop, + NextState("IDLE") + ).Else( + NextState("READ_DATA") + ) + ) + ) + + +# etherbone + +class LiteEthEtherbone(Module): + def __init__(self, udp, udp_port): + # decode/encode etherbone packets + self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port) + + # packets can be probe (etherbone discovering) or records with + # writes and reads + self.submodules.probe = probe = LiteEthEtherboneProbe() + self.submodules.record = record = LiteEthEtherboneRecord() + + # arbitrate/dispatch probe/records packets + dispatcher = Dispatcher(packet.source, [probe.sink, record.sink]) + self.comb += dispatcher.sel.eq(~packet.source.pf) + arbiter = Arbiter([probe.source, record.source], packet.sink) + self.submodules += dispatcher, arbiter + + # create mmap ŵishbone master + self.submodules.master = master = LiteEthEtherboneWishboneMaster() + self.comb += [ + Record.connect(record.receiver.source, master.sink), + Record.connect(master.source, record.sender.sink) + ] diff --git a/liteeth/frontend/etherbone/__init__.py b/liteeth/frontend/etherbone/__init__.py deleted file mode 100644 index 56a00cf..0000000 --- a/liteeth/frontend/etherbone/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -from liteeth.common import * -from liteeth.frontend.etherbone.packet import * -from liteeth.frontend.etherbone.probe import * -from liteeth.frontend.etherbone.record import * -from liteeth.frontend.etherbone.wishbone import * - - -class LiteEthEtherbone(Module): - def __init__(self, udp, udp_port): - # decode/encode etherbone packets - self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port) - - # packets can be probe (etherbone discovering) or records with - # writes and reads - self.submodules.probe = probe = LiteEthEtherboneProbe() - self.submodules.record = record = LiteEthEtherboneRecord() - - # arbitrate/dispatch probe/records packets - dispatcher = Dispatcher(packet.source, [probe.sink, record.sink]) - self.comb += dispatcher.sel.eq(~packet.source.pf) - arbiter = Arbiter([probe.source, record.source], packet.sink) - self.submodules += dispatcher, arbiter - - # create mmap ŵishbone master - self.submodules.master = master = LiteEthEtherboneWishboneMaster() - self.comb += [ - Record.connect(record.receiver.source, master.sink), - Record.connect(master.source, record.sender.sink) - ] diff --git a/liteeth/frontend/etherbone/packet.py b/liteeth/frontend/etherbone/packet.py deleted file mode 100644 index 36cde5e..0000000 --- a/liteeth/frontend/etherbone/packet.py +++ /dev/null @@ -1,135 +0,0 @@ -from liteeth.common import * - - -class LiteEthEtherbonePacketPacketizer(Packetizer): - def __init__(self): - Packetizer.__init__(self, - eth_etherbone_packet_description(32), - eth_udp_user_description(32), - etherbone_packet_header) - - -class LiteEthEtherbonePacketTX(Module): - def __init__(self, udp_port): - self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) - self.source = source = Source(eth_udp_user_description(32)) - - # # # - - self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer() - self.comb += [ - packetizer.sink.stb.eq(sink.stb), - packetizer.sink.sop.eq(sink.sop), - packetizer.sink.eop.eq(sink.eop), - sink.ack.eq(packetizer.sink.ack), - - packetizer.sink.magic.eq(etherbone_magic), - packetizer.sink.port_size.eq(32//8), - packetizer.sink.addr_size.eq(32//8), - packetizer.sink.pf.eq(sink.pf), - packetizer.sink.pr.eq(sink.pr), - packetizer.sink.nr.eq(sink.nr), - packetizer.sink.version.eq(etherbone_version), - - packetizer.sink.data.eq(sink.data) - ] - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - packetizer.source.ack.eq(1), - If(packetizer.source.stb & packetizer.source.sop, - packetizer.source.ack.eq(0), - NextState("SEND") - ) - ) - fsm.act("SEND", - Record.connect(packetizer.source, source), - source.src_port.eq(udp_port), - source.dst_port.eq(udp_port), - source.ip_address.eq(sink.ip_address), - source.length.eq(sink.length + etherbone_packet_header.length), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) - - -class LiteEthEtherbonePacketDepacketizer(Depacketizer): - def __init__(self): - Depacketizer.__init__(self, - eth_udp_user_description(32), - eth_etherbone_packet_description(32), - etherbone_packet_header) - - -class LiteEthEtherbonePacketRX(Module): - def __init__(self): - self.sink = sink = Sink(eth_udp_user_description(32)) - self.source = source = Source(eth_etherbone_packet_user_description(32)) - - # # # - - self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer() - self.comb += Record.connect(sink, depacketizer.sink) - - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.sop, - depacketizer.source.ack.eq(0), - NextState("CHECK") - ) - ) - valid = Signal() - self.sync += valid.eq( - depacketizer.source.stb & - (depacketizer.source.magic == etherbone_magic) - ) - fsm.act("CHECK", - If(valid, - NextState("PRESENT") - ).Else( - NextState("DROP") - ) - ) - self.comb += [ - source.sop.eq(depacketizer.source.sop), - source.eop.eq(depacketizer.source.eop), - - source.pf.eq(depacketizer.source.pf), - source.pr.eq(depacketizer.source.pr), - source.nr.eq(depacketizer.source.nr), - - source.data.eq(depacketizer.source.data), - - source.src_port.eq(sink.src_port), - source.dst_port.eq(sink.dst_port), - source.ip_address.eq(sink.ip_address), - source.length.eq(sink.length - etherbone_packet_header.length) - ] - fsm.act("PRESENT", - source.stb.eq(depacketizer.source.stb), - depacketizer.source.ack.eq(source.ack), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) - fsm.act("DROP", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & - depacketizer.source.eop & - depacketizer.source.ack, - NextState("IDLE") - ) - ) - - -class LiteEthEtherbonePacket(Module): - def __init__(self, udp, udp_port): - self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port) - self.submodules.rx = rx = LiteEthEtherbonePacketRX() - udp_port = udp.crossbar.get_port(udp_port, dw=32) - self.comb += [ - Record.connect(tx.source, udp_port.sink), - Record.connect(udp_port.source, rx.sink) - ] - self.sink, self.source = self.tx.sink, self.rx.source diff --git a/liteeth/frontend/etherbone/probe.py b/liteeth/frontend/etherbone/probe.py deleted file mode 100644 index 24a4d8b..0000000 --- a/liteeth/frontend/etherbone/probe.py +++ /dev/null @@ -1,26 +0,0 @@ -from liteeth.common import * - - -class LiteEthEtherboneProbe(Module): - def __init__(self): - self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) - self.source = source = Source(eth_etherbone_packet_user_description(32)) - - # # # - - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - sink.ack.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - NextState("PROBE_RESPONSE") - ) - ) - fsm.act("PROBE_RESPONSE", - Record.connect(sink, source), - source.pf.eq(0), - source.pr.eq(1), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) diff --git a/liteeth/frontend/etherbone/record.py b/liteeth/frontend/etherbone/record.py deleted file mode 100644 index ca81ac5..0000000 --- a/liteeth/frontend/etherbone/record.py +++ /dev/null @@ -1,183 +0,0 @@ -from liteeth.common import * - - -class LiteEthEtherboneRecordPacketizer(Packetizer): - def __init__(self): - Packetizer.__init__(self, - eth_etherbone_record_description(32), - eth_etherbone_packet_user_description(32), - etherbone_record_header) - - -class LiteEthEtherboneRecordDepacketizer(Depacketizer): - def __init__(self): - Depacketizer.__init__(self, - eth_etherbone_packet_user_description(32), - eth_etherbone_record_description(32), - etherbone_record_header) - - -class LiteEthEtherboneRecordReceiver(Module): - def __init__(self, buffer_depth=256): - self.sink = sink = Sink(eth_etherbone_record_description(32)) - self.source = source = Source(eth_etherbone_mmap_description(32)) - - # # # - - fifo = SyncFIFO(eth_etherbone_record_description(32), buffer_depth, - buffered=True) - self.submodules += fifo - self.comb += Record.connect(sink, fifo.sink) - - self.submodules.base_addr = base_addr = FlipFlop(32) - self.comb += base_addr.d.eq(fifo.source.data) - - self.submodules.counter = counter = Counter(max=512) - - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - fifo.source.ack.eq(1), - counter.reset.eq(1), - If(fifo.source.stb & fifo.source.sop, - base_addr.ce.eq(1), - If(fifo.source.wcount, - NextState("RECEIVE_WRITES") - ).Elif(fifo.source.rcount, - NextState("RECEIVE_READS") - ) - ) - ) - fsm.act("RECEIVE_WRITES", - source.stb.eq(fifo.source.stb), - source.sop.eq(counter.value == 0), - source.eop.eq(counter.value == fifo.source.wcount-1), - source.count.eq(fifo.source.wcount), - source.be.eq(fifo.source.byte_enable), - source.addr.eq(base_addr.q[2:] + counter.value), - source.we.eq(1), - source.data.eq(fifo.source.data), - fifo.source.ack.eq(source.ack), - If(source.stb & source.ack, - counter.ce.eq(1), - If(source.eop, - If(fifo.source.rcount, - NextState("RECEIVE_BASE_RET_ADDR") - ).Else( - NextState("IDLE") - ) - ) - ) - ) - fsm.act("RECEIVE_BASE_RET_ADDR", - counter.reset.eq(1), - If(fifo.source.stb & fifo.source.sop, - base_addr.ce.eq(1), - NextState("RECEIVE_READS") - ) - ) - fsm.act("RECEIVE_READS", - source.stb.eq(fifo.source.stb), - source.sop.eq(counter.value == 0), - source.eop.eq(counter.value == fifo.source.rcount-1), - source.count.eq(fifo.source.rcount), - source.base_addr.eq(base_addr.q), - source.addr.eq(fifo.source.data[2:]), - fifo.source.ack.eq(source.ack), - If(source.stb & source.ack, - counter.ce.eq(1), - If(source.eop, - NextState("IDLE") - ) - ) - ) - - -class LiteEthEtherboneRecordSender(Module): - def __init__(self, buffer_depth=256): - self.sink = sink = Sink(eth_etherbone_mmap_description(32)) - self.source = source = Source(eth_etherbone_record_description(32)) - - # # # - - pbuffer = Buffer(eth_etherbone_mmap_description(32), buffer_depth) - self.submodules += pbuffer - self.comb += Record.connect(sink, pbuffer.sink) - - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - pbuffer.source.ack.eq(1), - If(pbuffer.source.stb & pbuffer.source.sop, - pbuffer.source.ack.eq(0), - NextState("SEND_BASE_ADDRESS") - ) - ) - self.comb += [ - source.byte_enable.eq(pbuffer.source.be), - If(pbuffer.source.we, - source.wcount.eq(pbuffer.source.count) - ).Else( - source.rcount.eq(pbuffer.source.count) - ) - ] - - fsm.act("SEND_BASE_ADDRESS", - source.stb.eq(pbuffer.source.stb), - source.sop.eq(1), - source.eop.eq(0), - source.data.eq(pbuffer.source.base_addr), - If(source.ack, - NextState("SEND_DATA") - ) - ) - fsm.act("SEND_DATA", - source.stb.eq(pbuffer.source.stb), - source.sop.eq(0), - source.eop.eq(pbuffer.source.eop), - source.data.eq(pbuffer.source.data), - If(source.stb & source.ack, - pbuffer.source.ack.eq(1), - If(source.eop, - NextState("IDLE") - ) - ) - ) - - -# Limitation: For simplicity we only support 1 record per packet -class LiteEthEtherboneRecord(Module): - def __init__(self, endianness="big"): - self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) - self.source = source = Sink(eth_etherbone_packet_user_description(32)) - - # # # - - # receive record, decode it and generate mmap stream - self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer() - self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver() - self.comb += [ - Record.connect(sink, depacketizer.sink), - Record.connect(depacketizer.source, receiver.sink) - ] - if endianness is "big": - self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data)) - - # save last ip address - last_ip_address = Signal(32) - self.sync += [ - If(sink.stb & sink.sop & sink.ack, - last_ip_address.eq(sink.ip_address) - ) - ] - - # receive mmap stream, encode it and send records - self.submodules.sender = sender = LiteEthEtherboneRecordSender() - self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer() - self.comb += [ - Record.connect(sender.source, packetizer.sink), - Record.connect(packetizer.source, source), - # XXX improve this - source.length.eq(sender.source.wcount*4 + 4 + etherbone_record_header.length), - source.ip_address.eq(last_ip_address) - ] - if endianness is "big": - self.comb += packetizer.sink.data.eq(reverse_bytes(sender.source.data)) diff --git a/liteeth/frontend/etherbone/wishbone.py b/liteeth/frontend/etherbone/wishbone.py deleted file mode 100644 index 3c18e3b..0000000 --- a/liteeth/frontend/etherbone/wishbone.py +++ /dev/null @@ -1,70 +0,0 @@ -from liteeth.common import * -from migen.bus import wishbone - - -class LiteEthEtherboneWishboneMaster(Module): - def __init__(self): - self.sink = sink = Sink(eth_etherbone_mmap_description(32)) - self.source = source = Source(eth_etherbone_mmap_description(32)) - self.bus = bus = wishbone.Interface() - - # # # - - self.submodules.data = data = FlipFlop(32) - self.comb += data.d.eq(bus.dat_r) - - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - sink.ack.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - If(sink.we, - NextState("WRITE_DATA") - ).Else( - NextState("READ_DATA") - ) - ) - ) - fsm.act("WRITE_DATA", - bus.adr.eq(sink.addr), - bus.dat_w.eq(sink.data), - bus.sel.eq(sink.be), - bus.stb.eq(sink.stb), - bus.we.eq(1), - bus.cyc.eq(1), - If(bus.stb & bus.ack, - sink.ack.eq(1), - If(sink.eop, - NextState("IDLE") - ) - ) - ) - fsm.act("READ_DATA", - bus.adr.eq(sink.addr), - bus.sel.eq(sink.be), - bus.stb.eq(sink.stb), - bus.cyc.eq(1), - If(bus.stb & bus.ack, - data.ce.eq(1), - NextState("SEND_DATA") - ) - ) - fsm.act("SEND_DATA", - source.stb.eq(sink.stb), - source.sop.eq(sink.sop), - source.eop.eq(sink.eop), - source.base_addr.eq(sink.base_addr), - source.addr.eq(sink.addr), - source.count.eq(sink.count), - source.be.eq(sink.be), - source.we.eq(1), - source.data.eq(data.q), - If(source.stb & source.ack, - sink.ack.eq(1), - If(source.eop, - NextState("IDLE") - ).Else( - NextState("READ_DATA") - ) - ) - ) diff --git a/liteeth/phy/loopback.py b/liteeth/phy/loopback.py deleted file mode 100644 index abdb936..0000000 --- a/liteeth/phy/loopback.py +++ /dev/null @@ -1,31 +0,0 @@ -from liteeth.common import * -from liteeth.generic import * - - -class LiteEthPHYLoopbackCRG(Module, AutoCSR): - def __init__(self): - self._reset = CSRStorage() - - # # # - - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()) - ] - - reset = self._reset.storage - self.comb += [ - self.cd_eth_rx.rst.eq(reset), - self.cd_eth_tx.rst.eq(reset) - ] - - -class LiteEthPHYLoopback(Module, AutoCSR): - def __init__(self): - self.dw = 8 - self.submodules.crg = LiteEthLoopbackPHYCRG() - self.sink = sink = Sink(eth_phy_description(8)) - self.source = source = Source(eth_phy_description(8)) - self.comb += Record.connect(self.sink, self.source) diff --git a/liteeth/frontend/etherbone/dissector/bit.lua b/liteeth/software/dissectors/bit.lua similarity index 100% rename from liteeth/frontend/etherbone/dissector/bit.lua rename to liteeth/software/dissectors/bit.lua diff --git a/liteeth/frontend/etherbone/dissector/etherbone.lua b/liteeth/software/dissectors/etherbone.lua similarity index 100% rename from liteeth/frontend/etherbone/dissector/etherbone.lua rename to liteeth/software/dissectors/etherbone.lua