From: Florent Kermarrec Date: Thu, 12 Feb 2015 00:12:52 +0000 (+0100) Subject: etherbone: cleanup X-Git-Tag: 24jan2021_ls180~2604^2~28 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e4958ffab3414e42c62edae2b228a015b00259de;p=litex.git etherbone: cleanup --- diff --git a/liteeth/common.py b/liteeth/common.py index 3c5e89da..25562dc1 100644 --- a/liteeth/common.py +++ b/liteeth/common.py @@ -140,14 +140,6 @@ def _remove_from_layout(layout, *args): if not remove: r.append(f) return r - -def eth_raw_description(dw): - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, packetized=True) - def eth_phy_description(dw): payload_layout = [ ("data", dw), @@ -280,6 +272,7 @@ def eth_etherbone_mmap_description(dw): ("data", dw) ] param_layout = [ + ("we", 1), ("count", 8), ("base_addr", 32), ("be", dw//8) diff --git a/liteeth/core/etherbone/__init__.py b/liteeth/core/etherbone/__init__.py index 9930eda2..8186193d 100644 --- a/liteeth/core/etherbone/__init__.py +++ b/liteeth/core/etherbone/__init__.py @@ -10,21 +10,23 @@ from liteeth.core.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) - self.submodules += dispatcher - arbiter = Arbiter([probe.source, record.source], packet.sink) - self.submodules += arbiter + self.submodules += dispatcher, arbiter - self.submodules.wishbone = wishbone = LiteEthEtherboneWishboneMaster() + # create mmap ŵishbone master + self.submodules.master = master = LiteEthEtherboneWishboneMaster() self.comb += [ - Record.connect(record.receiver.wr_source, wishbone.wr_sink), - Record.connect(record.receiver.rd_source, wishbone.rd_sink), - Record.connect(wishbone.wr_source, record.sender.wr_sink), - Record.connect(wishbone.rd_source, record.sender.rd_sink) + Record.connect(record.receiver.source, master.sink), + Record.connect(master.source, record.sender.sink) ] diff --git a/liteeth/core/etherbone/packet.py b/liteeth/core/etherbone/packet.py index e98a6429..1426db37 100644 --- a/liteeth/core/etherbone/packet.py +++ b/liteeth/core/etherbone/packet.py @@ -24,7 +24,7 @@ class LiteEthEtherbonePacketTX(Module): packetizer.sink.magic.eq(etherbone_magic), packetizer.sink.port_size.eq(32//8), - packetizer.sink.addr_size.eq(32//8), # XXX add a parameter? + 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), @@ -42,7 +42,7 @@ class LiteEthEtherbonePacketTX(Module): ) fsm.act("SEND", Record.connect(packetizer.source, source), - source.src_port.eq(0x1234), # XXX, + 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_len), diff --git a/liteeth/core/etherbone/probe.py b/liteeth/core/etherbone/probe.py index 84ba069a..a447532c 100644 --- a/liteeth/core/etherbone/probe.py +++ b/liteeth/core/etherbone/probe.py @@ -4,9 +4,8 @@ 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, diff --git a/liteeth/core/etherbone/record.py b/liteeth/core/etherbone/record.py index 15abe58d..2ce52517 100644 --- a/liteeth/core/etherbone/record.py +++ b/liteeth/core/etherbone/record.py @@ -19,11 +19,13 @@ class LiteEthEtherboneRecordDepacketizer(LiteEthDepacketizer): etherbone_record_header_len) class LiteEthEtherboneRecordReceiver(Module): - def __init__(self): + def __init__(self, buffer_depth=256): self.sink = sink = Sink(eth_etherbone_record_description(32)) - self.wr_source = wr_source = Source(eth_etherbone_mmap_description(32)) - self.rd_source = rd_source = Source(eth_etherbone_mmap_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(sink.data) @@ -32,30 +34,31 @@ class LiteEthEtherboneRecordReceiver(Module): self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", - sink.ack.eq(1), + fifo.source.ack.eq(1), counter.reset.eq(1), - If(sink.stb & sink.sop, + If(fifo.source.stb & fifo.source.sop, base_addr.ce.eq(1), - If(sink.wcount, + If(fifo.source.wcount, NextState("RECEIVE_WRITES") - ).Elif(sink.rcount, + ).Elif(fifo.source.rcount, NextState("RECEIVE_READS") ) ) ) fsm.act("RECEIVE_WRITES", - wr_source.stb.eq(sink.stb), - wr_source.sop.eq(counter.value == 0), - wr_source.eop.eq(counter.value == sink.wcount-1), - wr_source.count.eq(sink.wcount), - wr_source.be.eq(sink.byte_enable), - wr_source.addr.eq(base_addr.q + counter.value), - wr_source.data.eq(sink.data), - sink.ack.eq(wr_source.ack), - If(wr_source.stb & wr_source.ack, + 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 + 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(wr_source.eop, - If(sink.rcount, + If(source.eop, + If(fifo.source.rcount, NextState("RECEIVE_BASE_RET_ADDR") ).Else( NextState("IDLE") @@ -65,107 +68,108 @@ class LiteEthEtherboneRecordReceiver(Module): ) fsm.act("RECEIVE_BASE_RET_ADDR", counter.reset.eq(1), - If(sink.stb & sink.sop, + If(fifo.source.stb & fifo.source.sop, base_addr.ce.eq(1), NextState("RECEIVE_READS") ) ) fsm.act("RECEIVE_READS", - rd_source.stb.eq(sink.stb), - rd_source.sop.eq(counter.value == 0), - rd_source.eop.eq(counter.value == sink.rcount-1), - rd_source.count.eq(sink.rcount), - rd_source.base_addr.eq(base_addr.q), - rd_source.addr.eq(sink.data), - sink.ack.eq(rd_source.ack), - If(rd_source.stb & rd_source.ack, + 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), + fifo.source.ack.eq(source.ack), + If(source.stb & source.ack, counter.ce.eq(1), - If(rd_source.eop, + If(source.eop, NextState("IDLE") ) ) ) -# Note: for now only support writes from the FPGA class LiteEthEtherboneRecordSender(Module): - def __init__(self): - self.wr_sink = wr_sink = Sink(eth_etherbone_mmap_description(32)) - self.rd_sink = rd_sink = Sink(eth_etherbone_mmap_description(32)) + def __init__(self, buffer_depth=256): + self.sink = sink = Sink(eth_etherbone_mmap_description(32)) self.source = source = Source(eth_etherbone_record_description(32)) ### - self.submodules.wr_buffer = wr_buffer = PacketBuffer(eth_etherbone_mmap_description(32), 512) - self.comb += Record.connect(wr_sink, wr_buffer.sink) + pbuffer = PacketBuffer(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", - wr_buffer.source.ack.eq(1), - If(wr_buffer.source.stb & wr_buffer.source.sop, - wr_buffer.source.ack.eq(0), + 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(wr_buffer.source.be), - source.wcount.eq(wr_buffer.source.count), - source.rcount.eq(0) + 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(wr_buffer.source.stb), + source.stb.eq(pbuffer.source.stb), source.sop.eq(1), source.eop.eq(0), - source.data.eq(wr_buffer.source.base_addr), + source.data.eq(pbuffer.source.base_addr), If(source.ack, NextState("SEND_DATA") ) ) fsm.act("SEND_DATA", - source.stb.eq(wr_buffer.source.stb), + source.stb.eq(pbuffer.source.stb), source.sop.eq(0), - source.eop.eq(wr_buffer.source.eop), - source.data.eq(wr_buffer.source.data), + source.eop.eq(pbuffer.source.eop), + source.data.eq(pbuffer.source.data), If(source.stb & source.ack, - wr_buffer.source.ack.eq(1), + pbuffer.source.ack.eq(1), If(source.eop, NextState("IDLE") ) ) ) -# Note: for now only support 1 record per packet +# Limitation: For simplicity we only support 1 record per packet class LiteEthEtherboneRecord(Module): - def __init__(self): + 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 and decode records 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), - receiver.sink.data.eq(reverse_bytes(depacketizer.source.data)) # clarify this + Record.connect(depacketizer.source, receiver.sink) ] + if endianness is "big": + self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data)) - last_ip_address = Signal(32) # XXX for test - last_src_port = Signal(16) # XXX for test - last_dst_port = Signal(16) # XXX for test - + # 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), - last_src_port.eq(sink.src_port), - last_dst_port.eq(sink.dst_port) + last_ip_address.eq(sink.ip_address) ) ] + # mmap stream and encode and send records self.submodules.sender = sender = LiteEthEtherboneRecordSender() self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer() self.comb += [ Record.connect(sender.source, packetizer.sink), - packetizer.sink.data.eq(reverse_bytes(sender.source.data)), # clarify this Record.connect(packetizer.source, source), - source.length.eq(sender.source.wcount*4 + 4), - source.ip_address.eq(last_ip_address), - source.src_port.eq(last_src_port), - source.dst_port.eq(last_dst_port) + source.length.eq(sender.source.wcount*4 + 4), # XXX verify this + 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/core/etherbone/wishbone.py b/liteeth/core/etherbone/wishbone.py index 50cd175d..d49e4341 100644 --- a/liteeth/core/etherbone/wishbone.py +++ b/liteeth/core/etherbone/wishbone.py @@ -3,47 +3,44 @@ from migen.bus import wishbone class LiteEthEtherboneWishboneMaster(Module): def __init__(self): - self.wr_sink = wr_sink = Sink(eth_etherbone_mmap_description(32)) - self.rd_sink = rd_sink = Sink(eth_etherbone_mmap_description(32)) - self.wr_source = wr_source = Source(eth_etherbone_mmap_description(32)) - self.rd_source = rd_source = Source(eth_etherbone_mmap_description(32)) + self.sink = sink = Sink(eth_etherbone_mmap_description(32)) + self.source = source = Source(eth_etherbone_mmap_description(32)) self.bus = bus = wishbone.Interface() ###s - data = FlipFlop(32) - self.submodules += data + 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", - wr_sink.ack.eq(1), - rd_sink.ack.eq(1), - If(wr_sink.stb & wr_sink.sop, - wr_sink.ack.eq(0), - NextState("WRITE_DATA") - ).Elif(rd_sink.stb & rd_sink.sop, - rd_sink.ack.eq(0), - NextState("READ_DATA") + 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(wr_sink.addr), - bus.dat_w.eq(wr_sink.data), - bus.sel.eq(wr_sink.be), - bus.stb.eq(wr_sink.stb), + 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, - wr_sink.ack.eq(1), - If(wr_sink.eop, + sink.ack.eq(1), + If(sink.eop, NextState("IDLE") ) ) ) fsm.act("READ_DATA", - bus.adr.eq(rd_sink.addr), - bus.sel.eq(rd_sink.be), - bus.stb.eq(rd_sink.stb), + 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), @@ -51,17 +48,18 @@ class LiteEthEtherboneWishboneMaster(Module): ) ) fsm.act("SEND_DATA", - wr_source.stb.eq(rd_sink.stb), - wr_source.sop.eq(rd_sink.sop), - wr_source.eop.eq(rd_sink.eop), - wr_source.base_addr.eq(rd_sink.base_addr), - wr_source.addr.eq(rd_sink.addr), - wr_source.count.eq(rd_sink.count), - wr_source.be.eq(rd_sink.be), - wr_source.data.eq(data.q), - If(wr_source.stb & wr_source.ack, - rd_sink.ack.eq(1), - If(wr_source.eop, + 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/test/etherbone_tb.py b/liteeth/test/etherbone_tb.py index 1043753e..ce2a9f1c 100644 --- a/liteeth/test/etherbone_tb.py +++ b/liteeth/test/etherbone_tb.py @@ -26,7 +26,7 @@ class TB(Module): self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000) self.submodules.sram = wishbone.SRAM(1024) - self.submodules.interconnect = wishbone.InterconnectPointToPoint(self.etherbone.wishbone.bus, self.sram.bus) + self.submodules.interconnect = wishbone.InterconnectPointToPoint(self.etherbone.master.bus, self.sram.bus)