From 0a38b8c74a66672674e0c42c33d50b61004fb3d5 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 16 Feb 2015 10:26:43 +0100 Subject: [PATCH] add LiteX external core and remove ethmac --- .gitmodules | 3 + extcores/__init__.py | 4 + extcores/litex | 1 + misoclib/ethmac/__init__.py | 111 ------------ misoclib/ethmac/common.py | 14 -- misoclib/ethmac/last_be.py | 39 ----- misoclib/ethmac/phy/gmii.py | 76 --------- misoclib/ethmac/phy/loopback.py | 33 ---- misoclib/ethmac/phy/mii.py | 128 -------------- misoclib/ethmac/preamble.py | 145 ---------------- misoclib/ethmac/sram.py | 251 ---------------------------- misoclib/ethmac/test/__init__.py | 0 misoclib/ethmac/test/common.py | 120 ------------- misoclib/ethmac/test/crc_tb.py | 83 --------- misoclib/ethmac/test/ethmac_tb.py | 123 -------------- misoclib/ethmac/test/preamble_tb.py | 82 --------- targets/kc705.py | 11 +- targets/mlabs_video.py | 11 +- 18 files changed, 22 insertions(+), 1213 deletions(-) create mode 100644 extcores/__init__.py create mode 160000 extcores/litex delete mode 100644 misoclib/ethmac/__init__.py delete mode 100644 misoclib/ethmac/common.py delete mode 100644 misoclib/ethmac/last_be.py delete mode 100644 misoclib/ethmac/phy/gmii.py delete mode 100644 misoclib/ethmac/phy/loopback.py delete mode 100644 misoclib/ethmac/phy/mii.py delete mode 100644 misoclib/ethmac/preamble.py delete mode 100644 misoclib/ethmac/sram.py delete mode 100644 misoclib/ethmac/test/__init__.py delete mode 100644 misoclib/ethmac/test/common.py delete mode 100644 misoclib/ethmac/test/crc_tb.py delete mode 100644 misoclib/ethmac/test/ethmac_tb.py delete mode 100644 misoclib/ethmac/test/preamble_tb.py diff --git a/.gitmodules b/.gitmodules index aa337e22..2c959c21 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "software/compiler-rt"] path = software/compiler-rt url = http://llvm.org/git/compiler-rt.git +[submodule "extcores/litex"] + path = extcores/litex + url = https://github.com/enjoy-digital/litex diff --git a/extcores/__init__.py b/extcores/__init__.py new file mode 100644 index 00000000..e653425c --- /dev/null +++ b/extcores/__init__.py @@ -0,0 +1,4 @@ +import os, sys +sys.path.append(os.path.join("extcores", "litex", "litescope")) +sys.path.append(os.path.join("extcores", "litex", "liteeth")) +sys.path.append(os.path.join("extcores", "litex", "litesata")) \ No newline at end of file diff --git a/extcores/litex b/extcores/litex new file mode 160000 index 00000000..dddb984e --- /dev/null +++ b/extcores/litex @@ -0,0 +1 @@ +Subproject commit dddb984ecd08953e38eb96aff8daff23da96efd2 diff --git a/misoclib/ethmac/__init__.py b/misoclib/ethmac/__init__.py deleted file mode 100644 index a7ea0c2c..00000000 --- a/misoclib/ethmac/__init__.py +++ /dev/null @@ -1,111 +0,0 @@ -# This file is Copyright (c) 2014 Florent Kermarrec -# License: BSD - -from migen.fhdl.std import * - -from migen.bus import wishbone -from migen.actorlib.fifo import AsyncFIFO -from migen.actorlib.structuring import Converter, Pipeline -from migen.bank.eventmanager import SharedIRQ -from migen.bank.description import * -from migen.fhdl.simplify import * - -from misoclib.ethmac.common import * -from misoclib.ethmac.preamble import PreambleInserter, PreambleChecker -from migen.actorlib.crc import CRC32Inserter, CRC32Checker -from misoclib.ethmac.last_be import TXLastBE, RXLastBE -from misoclib.ethmac.sram import SRAMWriter, SRAMReader - -class EthMAC(Module, AutoCSR): - def __init__(self, phy, interface="wishbone", with_hw_preamble_crc=True, endianness="be"): - # Preamble / CRC (optional) - if with_hw_preamble_crc: - self._hw_preamble_crc = CSRStatus(reset=1) - # Preamble insert/check - preamble_inserter = PreambleInserter(phy.dw) - preamble_checker = PreambleChecker(phy.dw) - self.submodules += RenameClockDomains(preamble_inserter, "eth_tx") - self.submodules += RenameClockDomains(preamble_checker, "eth_rx") - - # CRC insert/check - crc32_inserter = CRC32Inserter(eth_description(phy.dw)) - crc32_checker = CRC32Checker(eth_description(phy.dw)) - self.submodules += RenameClockDomains(crc32_inserter, "eth_tx") - self.submodules += RenameClockDomains(crc32_checker, "eth_rx") - - # Delimiters - tx_last_be = TXLastBE(phy.dw) - rx_last_be = RXLastBE(phy.dw) - self.submodules += RenameClockDomains(tx_last_be, "eth_tx") - self.submodules += RenameClockDomains(rx_last_be, "eth_rx") - - # Converters - reverse = endianness == "be" - tx_converter = Converter(eth_description(32), eth_description(phy.dw), reverse=reverse) - rx_converter = Converter(eth_description(phy.dw), eth_description(32), reverse=reverse) - self.submodules += RenameClockDomains(tx_converter, "eth_tx") - self.submodules += RenameClockDomains(rx_converter, "eth_rx") - - # Cross Domain Crossing - tx_cdc = AsyncFIFO(eth_description(32), 4) - rx_cdc = AsyncFIFO(eth_description(32), 4) - self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"}) - self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"}) - - # Graph - if with_hw_preamble_crc: - rx_pipeline = [phy, preamble_checker, crc32_checker, rx_last_be, rx_converter, rx_cdc] - tx_pipeline = [tx_cdc, tx_converter, tx_last_be, crc32_inserter, preamble_inserter, phy] - else: - rx_pipeline = [phy, rx_last_be, rx_converter, rx_cdc] - tx_pipeline = [tx_cdc, tx_converter, tx_last_be, phy] - self.submodules.rx_pipeline = Pipeline(*rx_pipeline) - self.submodules.tx_pipeline = Pipeline(*tx_pipeline) - - if interface == "wishbone": - nrxslots = 2 - ntxslots = 2 - - self.bus = wishbone.Interface() - - # SRAM Memories - sram_depth = buffer_depth//(32//8) - self.submodules.sram_writer = SRAMWriter(sram_depth, nrxslots) - self.submodules.sram_reader = SRAMReader(sram_depth, ntxslots) - self.submodules.ev = SharedIRQ(self.sram_writer.ev, self.sram_reader.ev) - - # Connect to pipelines - self.comb += [ - self.rx_pipeline.source.connect(self.sram_writer.sink), - self.sram_reader.source.connect(self.tx_pipeline.sink) - ] - - # Interface - wb_rx_sram_ifs = [wishbone.SRAM(self.sram_writer.mems[n], read_only=True) - for n in range(nrxslots)] - # TODO: FullMemoryWE should move to Mibuild - wb_tx_sram_ifs = [FullMemoryWE(wishbone.SRAM(self.sram_reader.mems[n], read_only=False)) - for n in range(ntxslots)] - wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs - - wb_slaves = [] - decoderoffset = log2_int(sram_depth) - decoderbits = log2_int(len(wb_sram_ifs)) - for n, wb_sram_if in enumerate(wb_sram_ifs): - def slave_filter(a, v=n): - return a[decoderoffset:decoderoffset+decoderbits] == v - wb_slaves.append((slave_filter, wb_sram_if.bus)) - self.submodules += wb_sram_if - wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True) - self.submodules += wb_con - - elif interface == "lasmi": - raise NotImplementedError - - elif interface == "expose": - # expose pipelines endpoints - self.sink = tx_pipeline.sink - self.source = rx_pipeline.source - - else: - raise ValueError("EthMAC only supports Wishbone, LASMI or expose interfaces") diff --git a/misoclib/ethmac/common.py b/misoclib/ethmac/common.py deleted file mode 100644 index 177943ee..00000000 --- a/misoclib/ethmac/common.py +++ /dev/null @@ -1,14 +0,0 @@ -from migen.fhdl.std import * -from migen.flow.actor import EndpointDescription - -eth_mtu = 1532 -eth_preamble = 0xD555555555555555 -buffer_depth = 2**log2_int(eth_mtu, need_pow2=False) - -def eth_description(dw): - layout = [ - ("d", dw), - ("last_be", dw//8), - ("error", dw//8) - ] - return EndpointDescription(layout, packetized=True) diff --git a/misoclib/ethmac/last_be.py b/misoclib/ethmac/last_be.py deleted file mode 100644 index da55faee..00000000 --- a/misoclib/ethmac/last_be.py +++ /dev/null @@ -1,39 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.record import * -from migen.flow.actor import Sink, Source - -from misoclib.ethmac.common import * - -class TXLastBE(Module): - def __init__(self, d_w): - self.sink = sink = Sink(eth_description(d_w)) - self.source = source = Source(eth_description(d_w)) - - ### - - ongoing = Signal() - self.sync += \ - If(self.sink.stb & self.sink.ack, - If(sink.sop, - ongoing.eq(1) - ).Elif(sink.last_be, - ongoing.eq(0) - ) - ) - self.comb += [ - Record.connect(self.sink, self.source), - self.source.eop.eq(self.sink.last_be), - self.source.stb.eq(self.sink.stb & (self.sink.sop | ongoing)) - ] - -class RXLastBE(Module): - def __init__(self, d_w): - self.sink = sink = Sink(eth_description(d_w)) - self.source = source = Source(eth_description(d_w)) - - ### - - self.comb += [ - Record.connect(self.sink, self.source), - self.source.last_be.eq(self.sink.eop) - ] diff --git a/misoclib/ethmac/phy/gmii.py b/misoclib/ethmac/phy/gmii.py deleted file mode 100644 index ebdd0235..00000000 --- a/misoclib/ethmac/phy/gmii.py +++ /dev/null @@ -1,76 +0,0 @@ -from migen.fhdl.std import * -from migen.flow.actor import Sink, Source -from migen.bank.description import * -from migen.genlib.resetsync import AsyncResetSynchronizer - -from misoclib.ethmac.common import * - -class GMIIPHYTX(Module): - def __init__(self, pads): - self.sink = sink = Sink(eth_description(8)) - - ### - - self.sync += [ - pads.tx_er.eq(0), - pads.tx_en.eq(sink.stb), - pads.tx_data.eq(sink.d) - ] - self.comb += sink.ack.eq(1) - -class GMIIPHYRX(Module): - def __init__(self, pads): - self.source = source = Source(eth_description(8)) - - ### - - dv_d = Signal() - self.sync += dv_d.eq(pads.dv) - - sop = Signal() - eop = Signal() - self.comb += [ - sop.eq(pads.dv & ~dv_d), - eop.eq(~pads.dv & dv_d) - ] - self.sync += [ - source.stb.eq(pads.dv), - source.sop.eq(sop), - source.d.eq(pads.rx_data) - ] - self.comb += source.eop.eq(eop) - -# CRG is the only Xilinx specific module. -# TODO: use generic code or add support for others vendors -class GMIIPHYCRG(Module, AutoCSR): - def __init__(self, clock_pads, pads): - self._reset = CSRStorage() - - ### - - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.specials += [ - Instance("ODDR", - p_DDR_CLK_EDGE="SAME_EDGE", - i_C=ClockSignal("eth_tx"), i_CE=1, i_S=0, i_R=0, - i_D1=1, i_D2=0, o_Q=clock_pads.gtx, - ), - Instance("BUFG", i_I=clock_pads.rx, o_O=self.cd_eth_rx.clk), - ] - self.comb += self.cd_eth_tx.clk.eq(self.cd_eth_rx.clk) - - reset = self._reset.storage - self.comb += pads.rst_n.eq(~reset) - self.specials += [ - AsyncResetSynchronizer(self.cd_eth_tx, reset), - AsyncResetSynchronizer(self.cd_eth_rx, reset), - ] - -class GMIIPHY(Module, AutoCSR): - def __init__(self, clock_pads, pads): - self.dw = 8 - self.submodules.crg = GMIIPHYCRG(clock_pads, pads) - self.submodules.tx = RenameClockDomains(GMIIPHYTX(pads), "eth_tx") - self.submodules.rx = RenameClockDomains(GMIIPHYRX(pads), "eth_rx") - self.sink, self.source = self.tx.sink, self.rx.source diff --git a/misoclib/ethmac/phy/loopback.py b/misoclib/ethmac/phy/loopback.py deleted file mode 100644 index 50c9f995..00000000 --- a/misoclib/ethmac/phy/loopback.py +++ /dev/null @@ -1,33 +0,0 @@ -from migen.fhdl.std import * -from migen.flow.actor import Sink, Source -from migen.bank.description import * -from migen.genlib.record import * - -from misoclib.ethmac.common import * - -class LoopbackPHYCRG(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 LoopbackPHY(Module, AutoCSR): - def __init__(self): - self.dw = 8 - self.submodules.crg = LoopbackPHYCRG() - self.sink = sink = Sink(eth_description(8)) - self.source = source = Source(eth_description(8)) - self.comb += Record.connect(self.sink, self.source) diff --git a/misoclib/ethmac/phy/mii.py b/misoclib/ethmac/phy/mii.py deleted file mode 100644 index 17f2ba7b..00000000 --- a/misoclib/ethmac/phy/mii.py +++ /dev/null @@ -1,128 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.fsm import FSM, NextState -from migen.flow.actor import Sink, Source -from migen.bank.description import * -from migen.genlib.resetsync import AsyncResetSynchronizer - -from misoclib.ethmac.common import * - -class MIIPHYTX(Module): - def __init__(self, pads): - self.sink = sink = Sink(eth_description(8)) - - ### - - tx_en_r = Signal() - tx_data_r = Signal(4) - self.sync += [ - pads.tx_er.eq(0), - pads.tx_en.eq(tx_en_r), - pads.tx_data.eq(tx_data_r), - ] - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - fsm.act("IDLE", - sink.ack.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - NextState("SEND_LO") - ) - ) - fsm.act("SEND_LO", - tx_data_r.eq(sink.d[0:4]), - tx_en_r.eq(1), - NextState("SEND_HI") - ) - fsm.act("SEND_HI", - tx_data_r.eq(sink.d[4:8]), - tx_en_r.eq(1), - sink.ack.eq(1), - If(sink.stb & sink.eop, - NextState("IDLE") - ).Else( - NextState("SEND_LO") - ) - ) - -class MIIPHYRX(Module): - def __init__(self, pads): - self.source = source = Source(eth_description(8)) - - ### - - sop = source.sop - set_sop = Signal() - clr_sop = Signal() - self.sync += \ - If(clr_sop, - sop.eq(0) - ).Elif(set_sop, - sop.eq(1) - ) - - lo = Signal(4) - hi = Signal(4) - load_nibble = Signal(2) - self.sync += \ - If(load_nibble[0], - lo.eq(pads.rx_data) - ).Elif(load_nibble[1], - hi.eq(pads.rx_data) - ) - self.comb += [ - source.d.eq(Cat(lo, hi)) - ] - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - fsm.act("IDLE", - set_sop.eq(1), - If(pads.dv, - load_nibble.eq(0b01), - NextState("LOAD_HI") - ) - ) - fsm.act("LOAD_LO", - source.stb.eq(1), - If(pads.dv, - clr_sop.eq(1), - load_nibble.eq(0b01), - NextState("LOAD_HI") - ).Else( - source.eop.eq(1), - NextState("IDLE") - ) - ) - fsm.act("LOAD_HI", - load_nibble.eq(0b10), - NextState("LOAD_LO") - ) - -class MIIPHYCRG(Module, AutoCSR): - def __init__(self, clock_pads, pads): - self._reset = CSRStorage() - - ### - - self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy) - - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx) - self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx) - - reset = self._reset.storage - self.comb += pads.rst_n.eq(~reset) - self.specials += [ - AsyncResetSynchronizer(self.cd_eth_tx, reset), - AsyncResetSynchronizer(self.cd_eth_rx, reset), - ] - -class MIIPHY(Module, AutoCSR): - def __init__(self, clock_pads, pads): - self.dw = 8 - self.submodules.crg = MIIPHYCRG(clock_pads, pads) - self.submodules.tx = RenameClockDomains(MIIPHYTX(pads), "eth_tx") - self.submodules.rx = RenameClockDomains(MIIPHYRX(pads), "eth_rx") - self.sink, self.source = self.tx.sink, self.rx.source diff --git a/misoclib/ethmac/preamble.py b/misoclib/ethmac/preamble.py deleted file mode 100644 index fe2078fe..00000000 --- a/misoclib/ethmac/preamble.py +++ /dev/null @@ -1,145 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.fsm import FSM, NextState -from migen.genlib.misc import chooser -from migen.genlib.record import * -from migen.flow.actor import Sink, Source - -from misoclib.ethmac.common import * - -class PreambleInserter(Module): - def __init__(self, d_w): - self.sink = Sink(eth_description(d_w)) - self.source = Source(eth_description(d_w)) - - ### - - preamble = Signal(64, reset=eth_preamble) - cnt_max = (64//d_w)-1 - cnt = Signal(max=cnt_max+1) - clr_cnt = Signal() - inc_cnt = Signal() - - self.sync += \ - If(clr_cnt, - cnt.eq(0) - ).Elif(inc_cnt, - cnt.eq(cnt+1) - ) - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - fsm.act("IDLE", - self.sink.ack.eq(1), - clr_cnt.eq(1), - If(self.sink.stb & self.sink.sop, - self.sink.ack.eq(0), - NextState("INSERT"), - ) - ) - fsm.act("INSERT", - self.source.stb.eq(1), - self.source.sop.eq(cnt==0), - chooser(preamble, cnt, self.source.d), - If(cnt == cnt_max, - If(self.source.ack, NextState("COPY")) - ).Else( - inc_cnt.eq(self.source.ack) - ) - ) - fsm.act("COPY", - Record.connect(self.sink, self.source), - self.source.sop.eq(0), - - If(self.sink.stb & self.sink.eop & self.source.ack, - NextState("IDLE"), - ) - ) - -class PreambleChecker(Module): - def __init__(self, d_w): - self.sink = Sink(eth_description(d_w)) - self.source = Source(eth_description(d_w)) - - ### - - preamble = Signal(64, reset=eth_preamble) - cnt_max = (64//d_w) - 1 - cnt = Signal(max=cnt_max+1) - clr_cnt = Signal() - inc_cnt = Signal() - - self.sync += \ - If(clr_cnt, - cnt.eq(0) - ).Elif(inc_cnt, - cnt.eq(cnt+1) - ) - - discard = Signal() - clr_discard = Signal() - set_discard = Signal() - - self.sync += \ - If(clr_discard, - discard.eq(0) - ).Elif(set_discard, - discard.eq(1) - ) - - sop = Signal() - clr_sop = Signal() - set_sop = Signal() - self.sync += \ - If(clr_sop, - sop.eq(0) - ).Elif(set_sop, - sop.eq(1) - ) - - ref = Signal(d_w) - match = Signal() - self.comb += [ - chooser(preamble, cnt, ref), - match.eq(self.sink.d == ref) - ] - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - self.sink.ack.eq(1), - clr_cnt.eq(1), - clr_discard.eq(1), - If(self.sink.stb & self.sink.sop, - clr_cnt.eq(0), - inc_cnt.eq(1), - clr_discard.eq(0), - set_discard.eq(~match), - NextState("CHECK"), - ) - ) - fsm.act("CHECK", - self.sink.ack.eq(1), - If(self.sink.stb, - set_discard.eq(~match), - If(cnt == cnt_max, - If(discard | (~match), - NextState("IDLE") - ).Else( - set_sop.eq(1), - NextState("COPY") - ) - ).Else( - inc_cnt.eq(1) - ) - ) - ) - fsm.act("COPY", - Record.connect(self.sink, self.source), - self.source.sop.eq(sop), - clr_sop.eq(self.source.stb & self.source.ack), - - If(self.source.stb & self.source.eop & self.source.ack, - NextState("IDLE"), - ) - ) diff --git a/misoclib/ethmac/sram.py b/misoclib/ethmac/sram.py deleted file mode 100644 index 32c76f3c..00000000 --- a/misoclib/ethmac/sram.py +++ /dev/null @@ -1,251 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.fifo import SyncFIFO -from migen.genlib.fsm import FSM, NextState -from migen.genlib.misc import chooser -from migen.flow.actor import Sink, Source -from migen.bank.description import * -from migen.bank.eventmanager import * - -from misoclib.ethmac.common import * - -class SRAMWriter(Module, AutoCSR): - def __init__(self, depth, nslots=2): - self.sink = sink = Sink(eth_description(32)) - self.crc_error = Signal() - - slotbits = max(log2_int(nslots), 1) - lengthbits = log2_int(depth*4) # length in bytes - - self._slot = CSRStatus(slotbits) - self._length = CSRStatus(lengthbits) - - self.submodules.ev = EventManager() - self.ev.available = EventSourceLevel() - self.ev.finalize() - - ### - - # packet dropped if no slot available - sink.ack.reset = 1 - - # length computation - cnt = Signal(lengthbits) - clr_cnt = Signal() - inc_cnt = Signal() - inc_val = Signal(3) - self.comb += \ - If(sink.last_be[3], - inc_val.eq(1) - ).Elif(sink.last_be[2], - inc_val.eq(2) - ).Elif(sink.last_be[1], - inc_val.eq(3) - ).Else( - inc_val.eq(4) - ) - self.sync += \ - If(clr_cnt, - cnt.eq(0) - ).Elif(inc_cnt, - cnt.eq(cnt+inc_val) - ) - - # slot computation - slot = Signal(slotbits) - inc_slot = Signal() - self.sync += \ - If(inc_slot, - If(slot == nslots-1, - slot.eq(0), - ).Else( - slot.eq(slot+1) - ) - ) - ongoing = Signal() - discard = Signal() - - # status fifo - fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots) - self.submodules += fifo - - # fsm - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - inc_cnt.eq(sink.stb), - If(sink.stb & sink.sop, - ongoing.eq(1), - If(fifo.writable, - NextState("WRITE") - ) - ) - ) - fsm.act("WRITE", - inc_cnt.eq(sink.stb), - ongoing.eq(1), - If(sink.stb & sink.eop, - If((sink.error & sink.last_be) != 0, - NextState("DISCARD") - ).Else( - NextState("TERMINATE") - ) - ) - ) - fsm.act("DISCARD", - clr_cnt.eq(1), - NextState("IDLE") - ) - fsm.act("TERMINATE", - clr_cnt.eq(1), - inc_slot.eq(1), - fifo.we.eq(1), - fifo.din.slot.eq(slot), - fifo.din.length.eq(cnt), - NextState("IDLE") - ) - - self.comb += [ - fifo.re.eq(self.ev.available.clear), - self.ev.available.trigger.eq(fifo.readable), - self._slot.status.eq(fifo.dout.slot), - self._length.status.eq(fifo.dout.length), - ] - - # memory - mems = [None]*nslots - ports = [None]*nslots - for n in range(nslots): - mems[n] = Memory(32, depth) - ports[n] = mems[n].get_port(write_capable=True) - self.specials += ports[n] - self.mems = mems - - cases = {} - for n, port in enumerate(ports): - cases[n] = [ - ports[n].adr.eq(cnt[2:]), - ports[n].dat_w.eq(sink.d), - If(sink.stb & ongoing, - ports[n].we.eq(0xf) - ) - ] - self.comb += Case(slot, cases) - - -class SRAMReader(Module, AutoCSR): - def __init__(self, depth, nslots=2): - self.source = source = Source(eth_description(32)) - - slotbits = max(log2_int(nslots), 1) - lengthbits = log2_int(depth*4) # length in bytes - self.lengthbits = lengthbits - - self._start = CSR() - self._ready = CSRStatus() - self._slot = CSRStorage(slotbits) - self._length = CSRStorage(lengthbits) - - self.submodules.ev = EventManager() - self.ev.done = EventSourcePulse() - self.ev.finalize() - - ### - - # command fifo - fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots) - self.submodules += fifo - self.comb += [ - fifo.we.eq(self._start.re), - fifo.din.slot.eq(self._slot.storage), - fifo.din.length.eq(self._length.storage), - self._ready.status.eq(fifo.writable) - ] - - # length computation - cnt = Signal(lengthbits) - clr_cnt = Signal() - inc_cnt = Signal() - - self.sync += \ - If(clr_cnt, - cnt.eq(0) - ).Elif(inc_cnt, - cnt.eq(cnt+4) - ) - - # fsm - first = Signal() - last = Signal() - last_d = Signal() - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - clr_cnt.eq(1), - If(fifo.readable, - NextState("CHECK") - ) - ) - fsm.act("CHECK", - If(~last_d, - NextState("SEND"), - ).Else( - NextState("END"), - ) - ) - length_lsb = fifo.dout.length[0:2] - fsm.act("SEND", - source.stb.eq(1), - source.sop.eq(first), - source.eop.eq(last), - If(last, - If(length_lsb == 3, - source.last_be.eq(0b0010) - ).Elif(length_lsb == 2, - source.last_be.eq(0b0100) - ).Elif(length_lsb == 1, - source.last_be.eq(0b1000) - ).Else( - source.last_be.eq(0b0001) - ) - ), - If(source.ack, - inc_cnt.eq(~last), - NextState("CHECK") - ) - ) - fsm.act("END", - fifo.re.eq(1), - self.ev.done.trigger.eq(1), - NextState("IDLE") - ) - - # first/last computation - self.sync += [ - If(fsm.ongoing("IDLE"), - first.eq(1) - ).Elif(source.stb & source.ack, - first.eq(0) - ) - ] - self.comb += last.eq(cnt + 4 >= fifo.dout.length) - self.sync += last_d.eq(last) - - # memory - rd_slot = fifo.dout.slot - - mems = [None]*nslots - ports = [None]*nslots - for n in range(nslots): - mems[n] = Memory(32, depth) - ports[n] = mems[n].get_port() - self.specials += ports[n] - self.mems = mems - - cases = {} - for n, port in enumerate(ports): - self.comb += ports[n].adr.eq(cnt[2:]) - cases[n] = [source.d.eq(port.dat_r)] - self.comb += Case(rd_slot, cases) diff --git a/misoclib/ethmac/test/__init__.py b/misoclib/ethmac/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/misoclib/ethmac/test/common.py b/misoclib/ethmac/test/common.py deleted file mode 100644 index 13123700..00000000 --- a/misoclib/ethmac/test/common.py +++ /dev/null @@ -1,120 +0,0 @@ -import random, copy - -from migen.fhdl.std import * -from migen.flow.actor import Sink, Source -from migen.genlib.record import * - -from misoclib.ethmac.common import * - -def seed_to_data(seed, random=True): - if random: - return (seed * 0x31415979 + 1) & 0xffffffff - else: - return seed - -def check(p1, p2): - p1 = copy.deepcopy(p1) - p2 = copy.deepcopy(p2) - if isinstance(p1, int): - return 0, 1, int(p1 != p2) - else: - if len(p1) >= len(p2): - ref, res = p1, p2 - else: - ref, res = p2, p1 - shift = 0 - while((ref[0] != res[0]) and (len(res)>1)): - res.pop(0) - shift += 1 - length = min(len(ref), len(res)) - errors = 0 - for i in range(length): - if ref.pop(0) != res.pop(0): - errors += 1 - return shift, length, errors - -def randn(max_n): - return random.randint(0, max_n-1) - -class Packet(list): - def __init__(self, init=[]): - self.ongoing = False - self.done = False - for data in init: - self.append(data) - -class PacketStreamer(Module): - def __init__(self, description): - self.source = Source(description) - ### - self.packets = [] - self.packet = Packet() - self.packet.done = 1 - - def send(self, packet): - packet = copy.deepcopy(packet) - self.packets.append(packet) - - def do_simulation(self, selfp): - if len(self.packets) and self.packet.done: - self.packet = self.packets.pop(0) - if not self.packet.ongoing and not self.packet.done: - selfp.source.stb = 1 - selfp.source.sop = 1 - selfp.source.d = self.packet.pop(0) - self.packet.ongoing = True - elif selfp.source.stb == 1 and selfp.source.ack == 1: - selfp.source.sop = 0 - selfp.source.eop = (len(self.packet) == 1) - if len(self.packet) > 0: - selfp.source.stb = 1 - selfp.source.d = self.packet.pop(0) - else: - self.packet.done = 1 - selfp.source.stb = 0 - -class PacketLogger(Module): - def __init__(self, description): - self.sink = Sink(description) - ### - self.packet = Packet() - - def receive(self): - self.packet.done = 0 - while self.packet.done == 0: - yield - - def do_simulation(self, selfp): - selfp.sink.ack = 1 - if selfp.sink.stb == 1 and selfp.sink.sop == 1: - self.packet = Packet() - self.packet.append(selfp.sink.d) - elif selfp.sink.stb: - self.packet.append(selfp.sink.d) - if selfp.sink.stb == 1 and selfp.sink.eop == 1: - self.packet.done = True - -class AckRandomizer(Module): - def __init__(self, description, level=0): - self.level = level - - self.sink = Sink(description) - self.source = Source(description) - - self.run = Signal() - - self.comb += \ - If(self.run, - Record.connect(self.sink, self.source) - ).Else( - self.source.stb.eq(0), - self.sink.ack.eq(0), - ) - - def do_simulation(self, selfp): - n = randn(100) - if n < self.level: - selfp.run = 0 - else: - selfp.run = 1 - diff --git a/misoclib/ethmac/test/crc_tb.py b/misoclib/ethmac/test/crc_tb.py deleted file mode 100644 index 5d185ac1..00000000 --- a/misoclib/ethmac/test/crc_tb.py +++ /dev/null @@ -1,83 +0,0 @@ -from migen.fhdl.std import * -from migen.actorlib.crc import * - -from misoclib.ethmac.common import * -from misoclib.ethmac.test.common import * - -payload = [ - 0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12, - 0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00, - 0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11, - 0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00, - 0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C, - 0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 -] - -crc = [ - 0x7A, 0xD5, 0x6B, 0xB3 -] - -mux = { - "inserter": 0, - "checker": 1, - "both": 2 -} - -class TB(Module): - def __init__(self, random_level=50): - sm = self.submodules - sm.streamer = PacketStreamer(eth_description(8)) - sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level) - sm.logger = PacketLogger(eth_description(8)) - sm.logger_randomizer = AckRandomizer(eth_description(8), random_level) - - self.comb += [ - self.streamer.source.connect(self.streamer_randomizer.sink), - self.logger_randomizer.source.connect(self.logger.sink) - ] - - sm.crc32_inserter = CRC32Inserter(eth_description(8)) - sm.crc32_checker = CRC32Checker(eth_description(8)) - - self.mux = Signal(2) - self.comb += [ - If(self.mux == mux["inserter"], - self.streamer_randomizer.source.connect(self.crc32_inserter.sink), - self.crc32_inserter.source.connect(self.logger_randomizer.sink) - ).Elif(self.mux == mux["checker"], - self.streamer_randomizer.source.connect(self.crc32_checker.sink), - self.crc32_checker.source.connect(self.logger_randomizer.sink) - ).Elif(self.mux == mux["both"], - self.streamer_randomizer.source.connect(self.crc32_inserter.sink), - self.crc32_inserter.source.connect(self.crc32_checker.sink), - self.crc32_checker.source.connect(self.logger_randomizer.sink) - ) - ] - - def gen_simulation(self, selfp): - selfp.mux = mux["inserter"] - print("streamer --> crc32_inserter --> logger:") - self.streamer.send(Packet(payload)) - yield from self.logger.receive() - s, l, e = check(payload+crc, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - - selfp.mux = mux["checker"] - print("streamer --> crc32_checker --> logger:") - self.streamer.send(Packet(payload+crc)) - yield from self.logger.receive() - s, l, e = check(payload, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - - selfp.mux = mux["both"] - print("streamer --> crc32_inserter --> crc32_checker --> logger:") - self.streamer.send(Packet(payload)) - yield from self.logger.receive() - s, l, e = check(payload, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - -if __name__ == "__main__": - from migen.sim.generic import run_simulation - run_simulation(TB(), ncycles=1000, vcd_name="my.vcd") diff --git a/misoclib/ethmac/test/ethmac_tb.py b/misoclib/ethmac/test/ethmac_tb.py deleted file mode 100644 index 5c1b2d46..00000000 --- a/misoclib/ethmac/test/ethmac_tb.py +++ /dev/null @@ -1,123 +0,0 @@ -from migen.fhdl.std import * -from migen.bus import wishbone -from migen.bus.transactions import * -from migen.sim.generic import run_simulation - -from misoclib.ethmac import EthMAC -from misoclib.ethmac.phy import loopback - -from misoclib.ethmac.test.common import * - -class WishboneMaster: - def __init__(self, obj): - self.obj = obj - self.dat = 0 - - def write(self, adr, dat): - self.obj.cyc = 1 - self.obj.stb = 1 - self.obj.adr = adr - self.obj.we = 1 - self.obj.sel = 0xF - self.obj.dat_w = dat - while self.obj.ack == 0: - yield - self.obj.cyc = 0 - self.obj.stb = 0 - yield - - def read(self, adr): - self.obj.cyc = 1 - self.obj.stb = 1 - self.obj.adr = adr - self.obj.we = 0 - self.obj.sel = 0xF - self.obj.dat_w = 0 - while self.obj.ack == 0: - yield - self.dat = self.obj.dat_r - self.obj.cyc = 0 - self.obj.stb = 0 - yield - -class SRAMReaderDriver: - def __init__(self, obj): - self.obj = obj - - def start(self, slot, length): - self.obj._slot.storage = slot - self.obj._length.storage = length - self.obj._start.re = 1 - yield - self.obj._start.re = 0 - yield - - def wait_done(self): - while self.obj.ev.done.pending == 0: - yield - - def clear_done(self): - self.obj.ev.done.clear = 1 - yield - self.obj.ev.done.clear = 0 - yield - -class TB(Module): - def __init__(self): - self.submodules.ethphy = loopback.LoopbackPHY() - self.submodules.ethmac = EthMAC(phy=self.ethphy, with_hw_preamble_crc=True) - - # use sys_clk for each clock_domain - 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_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] - - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 - - wishbone_master = WishboneMaster(selfp.ethmac.bus) - sram_reader_driver = SRAMReaderDriver(selfp.ethmac.sram_reader) - - sram_writer_slots_offset = [0x000, 0x200] - sram_reader_slots_offset = [0x400, 0x600] - - length = 1500-2 - - tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0] - - errors = 0 - - for slot in range(2): - print("slot {}:".format(slot)) - # fill tx memory - for i in range(length//4+1): - dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big") - yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat) - - # send tx payload & wait - yield from sram_reader_driver.start(slot, length) - yield from sram_reader_driver.wait_done() - yield from sram_reader_driver.clear_done() - - # get rx payload (loopback on PHY Model) - rx_payload = [] - for i in range(length//4+1): - yield from wishbone_master.read(sram_writer_slots_offset[slot]+i) - dat = wishbone_master.dat - rx_payload += list(dat.to_bytes(4, byteorder='big')) - - # check results - s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))]) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - -if __name__ == "__main__": - run_simulation(TB(), vcd_name="my.vcd") diff --git a/misoclib/ethmac/test/preamble_tb.py b/misoclib/ethmac/test/preamble_tb.py deleted file mode 100644 index 85bd7e64..00000000 --- a/misoclib/ethmac/test/preamble_tb.py +++ /dev/null @@ -1,82 +0,0 @@ -from migen.fhdl.std import * - -from misoclib.ethmac.common import * -from misoclib.ethmac.preamble import * -from misoclib.ethmac.test.common import * - -preamble = [ - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5 -] - -payload = [ - 0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12, - 0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00, - 0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11, - 0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00, - 0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C, - 0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 -] - -mux = { - "inserter": 0, - "checker": 1, - "both": 2 -} - -class TB(Module): - def __init__(self, random_level=50): - sm = self.submodules - sm.streamer = PacketStreamer(eth_description(8)) - sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level) - sm.logger = PacketLogger(eth_description(8)) - sm.logger_randomizer = AckRandomizer(eth_description(8), random_level) - - self.comb += [ - self.streamer.source.connect(self.streamer_randomizer.sink), - self.logger_randomizer.source.connect(self.logger.sink) - ] - - sm.preamble_inserter = PreambleInserter(8) - sm.preamble_checker = PreambleChecker(8) - - self.mux = Signal(2) - self.comb += [ - If(self.mux == mux["inserter"], - self.streamer_randomizer.source.connect(self.preamble_inserter.sink), - self.preamble_inserter.source.connect(self.logger_randomizer.sink) - ).Elif(self.mux == mux["checker"], - self.streamer_randomizer.source.connect(self.preamble_checker.sink), - self.preamble_checker.source.connect(self.logger_randomizer.sink) - ).Elif(self.mux == mux["both"], - self.streamer_randomizer.source.connect(self.preamble_inserter.sink), - self.preamble_inserter.source.connect(self.preamble_checker.sink), - self.preamble_checker.source.connect(self.logger_randomizer.sink) - ) - ] - def gen_simulation(self, selfp): - selfp.mux = mux["inserter"] - print("streamer --> preamble_inserter --> logger:") - self.streamer.send(Packet(payload)) - yield from self.logger.receive() - s, l, e = check(preamble+payload, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - - selfp.mux = mux["checker"] - print("streamer --> preamble_checker --> logger:") - self.streamer.send(Packet(preamble+payload)) - yield from self.logger.receive() - s, l, e = check(payload, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - - selfp.mux = mux["both"] - print("streamer --> preamble_inserter --> preamble_checker --> logger:") - self.streamer.send(Packet(payload)) - yield from self.logger.receive() - s, l, e = check(payload, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - -if __name__ == "__main__": - from migen.sim.generic import run_simulation - run_simulation(TB(), ncycles=1000, vcd_name="my.vcd") diff --git a/targets/kc705.py b/targets/kc705.py index 4411601e..f6aa143c 100644 --- a/targets/kc705.py +++ b/targets/kc705.py @@ -1,10 +1,13 @@ from migen.fhdl.std import * from migen.genlib.resetsync import AsyncResetSynchronizer -from misoclib import sdram, spiflash, ethmac +from misoclib import sdram, spiflash from misoclib.sdram.phy import k7ddrphy from misoclib.gensoc import SDRAMSoC -from misoclib.ethmac.phy import gmii + +from extcores import * +from liteeth.phy.gmii import LiteEthPHYGMII +from liteeth.mac import LiteEthMAC class _CRG(Module): def __init__(self, platform): @@ -121,8 +124,8 @@ class MiniSoC(BaseSoC): def __init__(self, platform, **kwargs): BaseSoC.__init__(self, platform, **kwargs) - self.submodules.ethphy = gmii.GMIIPHY(platform.request("eth_clocks"), platform.request("eth")) - self.submodules.ethmac = ethmac.EthMAC(phy=self.ethphy, with_hw_preamble_crc=True) + self.submodules.ethphy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth")) + self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone") self.add_wb_slave(lambda a: a[26:29] == 3, self.ethmac.bus) self.add_cpu_memory_region("ethmac_mem", 0xb0000000, 0x2000) diff --git a/targets/mlabs_video.py b/targets/mlabs_video.py index 9ca4e882..0738cd1a 100644 --- a/targets/mlabs_video.py +++ b/targets/mlabs_video.py @@ -4,10 +4,13 @@ from fractions import Fraction from migen.fhdl.std import * from mibuild.generic_platform import ConstraintError -from misoclib import sdram, mxcrg, norflash16, ethmac, framebuffer, gpio +from misoclib import sdram, mxcrg, norflash16, framebuffer, gpio from misoclib.sdram.phy import s6ddrphy from misoclib.gensoc import SDRAMSoC -from misoclib.ethmac.phy import mii + +from extcores import * +from liteeth.phy.mii import LiteEthPHYMII +from liteeth.mac import LiteEthMAC class _MXClockPads: def __init__(self, platform): @@ -91,8 +94,8 @@ class MiniSoC(BaseSoC): self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2))) self.submodules.leds = gpio.GPIOOut(Cat(platform.request("user_led", i) for i in range(2))) - self.submodules.ethphy = mii.MIIPHY(platform.request("eth_clocks"), platform.request("eth")) - self.submodules.ethmac = ethmac.EthMAC(phy=self.ethphy, with_hw_preamble_crc=False) + self.submodules.ethphy = LiteEthPHYMII(platform.request("eth_clocks"), platform.request("eth")) + self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone") self.add_wb_slave(lambda a: a[26:29] == 3, self.ethmac.bus) self.add_cpu_memory_region("ethmac_mem", 0xb0000000, 0x2000) -- 2.30.2