change name to LiteEth (LiteEthernet is too long...)
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 27 Jan 2015 23:36:09 +0000 (00:36 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 28 Jan 2015 00:36:38 +0000 (01:36 +0100)
55 files changed:
LICENSE
README
liteeth/__init__.py [new file with mode: 0644]
liteeth/arp/__init__.py [new file with mode: 0644]
liteeth/common.py [new file with mode: 0644]
liteeth/etherbone/__init__.py [new file with mode: 0644]
liteeth/ip/__init__.py [new file with mode: 0644]
liteeth/mac/__init__.py [new file with mode: 0644]
liteeth/mac/common.py [new file with mode: 0644]
liteeth/mac/core/__init__.py [new file with mode: 0644]
liteeth/mac/core/crc.py [new file with mode: 0644]
liteeth/mac/core/last_be.py [new file with mode: 0644]
liteeth/mac/core/preamble.py [new file with mode: 0644]
liteeth/mac/frontend/__init__.py [new file with mode: 0644]
liteeth/mac/frontend/sram.py [new file with mode: 0644]
liteeth/mac/frontend/wishbone.py [new file with mode: 0644]
liteeth/mac/test/Makefile [new file with mode: 0644]
liteeth/mac/test/__init__.py [new file with mode: 0644]
liteeth/mac/test/common.py [new file with mode: 0644]
liteeth/mac/test/crc_tb.py [new file with mode: 0644]
liteeth/mac/test/ethmac_tb.gtkw [new file with mode: 0644]
liteeth/mac/test/ethmac_tb.py [new file with mode: 0644]
liteeth/mac/test/preamble_tb.py [new file with mode: 0644]
liteeth/phy/__init__.py [new file with mode: 0644]
liteeth/phy/gmii.py [new file with mode: 0644]
liteeth/phy/loopback.py [new file with mode: 0644]
liteeth/phy/mii.py [new file with mode: 0644]
liteeth/udp/__init__.py [new file with mode: 0644]
liteethernet/__init__.py [deleted file]
liteethernet/arp/__init__.py [deleted file]
liteethernet/common.py [deleted file]
liteethernet/etherbone/__init__.py [deleted file]
liteethernet/ip/__init__.py [deleted file]
liteethernet/mac/__init__.py [deleted file]
liteethernet/mac/common.py [deleted file]
liteethernet/mac/core/__init__.py [deleted file]
liteethernet/mac/core/crc.py [deleted file]
liteethernet/mac/core/last_be.py [deleted file]
liteethernet/mac/core/preamble.py [deleted file]
liteethernet/mac/frontend/__init__.py [deleted file]
liteethernet/mac/frontend/sram.py [deleted file]
liteethernet/mac/frontend/wishbone.py [deleted file]
liteethernet/mac/test/Makefile [deleted file]
liteethernet/mac/test/__init__.py [deleted file]
liteethernet/mac/test/common.py [deleted file]
liteethernet/mac/test/crc_tb.py [deleted file]
liteethernet/mac/test/ethmac_tb.gtkw [deleted file]
liteethernet/mac/test/ethmac_tb.py [deleted file]
liteethernet/mac/test/preamble_tb.py [deleted file]
liteethernet/phy/__init__.py [deleted file]
liteethernet/phy/gmii.py [deleted file]
liteethernet/phy/loopback.py [deleted file]
liteethernet/phy/mii.py [deleted file]
liteethernet/udp/__init__.py [deleted file]
setup.py

diff --git a/LICENSE b/LICENSE
index 95ac4a6a3452441a1ba5086035a090757ee06da6..cbbfe8bedb8ad8156dfa51e2f1241263b2e3a485 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Unless otherwise noted, LiteScope is copyright (C) 2015 Florent Kermarrec.
+Unless otherwise noted, LiteEth is copyright (C) 2015 Florent Kermarrec.
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
diff --git a/README b/README
index 194275ce7c325d29c4b36df5d82260f28cf49ff4..b11ff35ec899e9259d1f68b5f2b2736e637b6ab5 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
-          __   _ __      ______  __                    __
-         / /  (_) /____ / __/ /_/ /  ___ _______  ___ / /_
-        / /__/ / __/ -_) _// __/ _ \/ -_) __/ _ \/ -_) __/
-       /____/_/\__/\__/___/\__/_//_/\__/_/ /_//_/\__/\__/
+                __   _ __      ______  __
+               / /  (_) /____ / __/ /_/ /
+              / /__/ / __/ -_) _// __/ _ \
+             /____/_/\__/\__/___/\__/_//_/
 
            Copyright 2012-2015 / EnjoyDigital
                 florent@enjoy-digital.fr
@@ -11,9 +11,9 @@
 
 [> Intro
 ---------
-LiteEthernet provides a small footprint and configurable Ethernet core.
+LiteEth provides a small footprint and configurable Ethernet core.
 
-LiteEthernet is part of LiteX libraries whose aims are to lower entry level of
+LiteEth is part of LiteX libraries whose aims are to lower entry level of
 complex FPGA IP cores by providing simple, elegant and efficient implementations
 ofcomponents used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller...
 
@@ -23,11 +23,11 @@ adapters to use standardized AXI or Avalon-ST streaming buses.
 Since Python is used to describe the HDL, the core is highly and easily
 configurable.
 
-LiteEthernet uses technologies developed in partnership with M-Labs Ltd:
+LiteEth uses technologies developed in partnership with M-Labs Ltd:
  - Migen enables generating HDL with Python in an efficient way.
  - MiSoC provides the basic blocks to build a powerful and small footprint SoC.
 
-LiteEthernet can be used as a Migen/MiSoC library (by simply installing  it
+LiteEth can be used as a Migen/MiSoC library (by simply installing  it
 with the provided setup.py) or can be integrated with your standard design flow
 by generating the verilog rtl that you will use as a standard core.
 
@@ -62,24 +62,24 @@ devel [AT] lists.m-labs.hk.
 
 [> License
 -----------
-LiteEthernet is released under the very permissive two-clause BSD license. Under
-the terms of this license, you are authorized to use LiteEthernet for closed-source
+LiteEth is released under the very permissive two-clause BSD license. Under
+the terms of this license, you are authorized to use LiteEth for closed-source
 proprietary designs.
 Even though we do not require you to do so, those things are awesome, so please
 do them if possible:
- - tell us that you are using LiteEthernet
- - cite LiteEthernet in publications related to research it has helped
+ - tell us that you are using LiteEth
+ - cite LiteEth in publications related to research it has helped
  - send us feedback and suggestions for improvements
  - send us bug reports when something goes wrong
- - send us the modifications and improvements you have done to LiteEthernet.
+ - send us the modifications and improvements you have done to LiteEth.
 
 [> Support and Consulting
 --------------------------
 We love open-source hardware and like sharing our designs with others.
 
-LiteEthernet is developed and maintained by EnjoyDigital.
+LiteEth is developed and maintained by EnjoyDigital.
 
-If you would like to know more about LiteEthernet or if you are already a happy
+If you would like to know more about LiteEth or if you are already a happy
 user and would like to extend it for your needs, EnjoyDigital can provide standard
 commercial support as well as consulting services.
 
diff --git a/liteeth/__init__.py b/liteeth/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/arp/__init__.py b/liteeth/arp/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/common.py b/liteeth/common.py
new file mode 100644 (file)
index 0000000..177943e
--- /dev/null
@@ -0,0 +1,14 @@
+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/liteeth/etherbone/__init__.py b/liteeth/etherbone/__init__.py
new file mode 100644 (file)
index 0000000..f84348a
--- /dev/null
@@ -0,0 +1,581 @@
+# This file is Copyright (c) 2014 Robert Jordens <jordens@gmail.com>
+# License: BSD
+
+import struct
+from collections import namedtuple
+
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.record import Record
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.fifo import SyncFIFO
+from migen.genlib.misc import optree
+from migen.actorlib.structuring import Cast, Pack, Unpack, pack_layout
+from migen.actorlib.sim import SimActor
+from migen.bus.transactions import TRead, TWrite
+from migen.flow.transactions import Token
+from migen.flow.actor import Source, Sink
+from migen.flow.network import DataFlowGraph, CompositeActor
+
+
+_eb_width = 32 # addr and data
+_eb_queue_len = 32
+_eb_magic = 0x4e6f
+_eb_ver = 1
+_eb_hdr = [
+               ("magic", 16),
+               ("ver", 4),
+               ("res1", 1),
+               ("no_response", 1),
+               ("probe_res", 1),
+               ("probe", 1),
+               ("addr_size", 4),
+               ("data_size", 4),
+       ][::-1] # big-endian
+
+_eb_rec_hdr = [
+               ("bca_cfg", 1),
+               ("rca_cfg", 1),
+               ("rd_fifo", 1),
+               ("res1", 1),
+               ("drop_cyc", 1),
+               ("wca_cfg", 1),
+               ("wr_fifo", 1),
+               ("res2", 1),
+               ("sel", 8),
+               ("wr_cnt", 8),
+               ("rd_cnt", 8),
+       ][::-1] # big-endian
+
+_eb_layout = [("data", _eb_width)]
+
+
+class Config(Module):
+       def __init__(self, sdb_addr):
+               self.errreg = Signal(8*8)
+               mach = Signal(4*8, reset=0xd15e)
+               macl = Signal(4*8, reset=0xa5edbeef)
+               self.mac = Signal(6*8)
+               self.comb += self.mac.eq(Cat(macl, mach))
+               self.ip = Signal(4*8, reset=0xc0a80064)
+               self.port = Signal(4*8, reset=0xebd0)
+
+               self.bus = bus = wishbone.Interface()
+               self.submodules.fifo = SyncFIFO(3, _eb_queue_len)
+
+               read_mux = Array([self.errreg[32:], self.errreg[:32], 0,
+                       sdb_addr, mach, macl, self.ip, self.port])
+               write_mux = Array([mach, macl, self.ip, self.port])[bus.adr - 4]
+
+               self.dout = read_mux[self.fifo.dout]
+               self.comb += [
+                               bus.ack.eq(bus.cyc & bus.stb),
+                               bus.dat_r.eq(read_mux[bus.adr[:3]]),
+                               ]
+               self.sync += [
+                               If(bus.cyc & bus.stb & bus.we & optree("|",
+                                               [bus.adr[:3] == i for i in (4, 5, 6, 7)]),
+                                       write_mux.eq(bus.dat_w),
+                               )]
+
+class WishboneMaster(Module):
+       def __init__(self, timeout):
+               self.bus = bus = wishbone.Interface()
+               self.submodules.fifo = SyncFIFO(_eb_width + 1, _eb_queue_len)
+
+               self.active = Signal()
+               inflight = Signal(max=_eb_queue_len)
+               queued = Signal(max=_eb_queue_len)
+               self.sync += [
+                               inflight.eq(inflight + self.active - self.fifo.we),
+                               queued.eq(queued + self.active - self.fifo.re),
+                               ]
+
+               self.busy = Signal()
+               self.full = Signal()
+               self.comb += [
+                               self.busy.eq(inflight != 0),
+                               self.full.eq(queued == _eb_queue_len - 1),
+                               ]
+
+               kill_ack = Signal()
+               time = Signal(max=timeout)
+               self.comb += kill_ack.eq(time == timeout - 1)
+               self.sync += [
+                               If(self.fifo.we | ~self.busy,
+                                       time.eq(0),
+                               ).Else(
+                                       time.eq(time + 1),
+                               )]
+
+               self.comb += [
+                               self.fifo.we.eq(bus.ack | bus.err | kill_ack),
+                               self.fifo.din.eq(Cat(bus.dat_r, ~bus.ack)),
+                               ]
+
+               self.errreg = Signal(64)
+               self.sync += [
+                               If(self.fifo.re,
+                                       self.errreg.eq(Cat(self.fifo.dout[-1], self.errreg)),
+                               )]
+
+class Transmit(Module):
+       def __init__(self, pas, cfg, wbm, tag, tags):
+               self.tx = Source(_eb_layout)
+
+               data = Signal(_eb_width)
+               re = Signal(4)
+               self.tx_cyc = Signal()
+               self.tx_skip = Signal()
+               last_tx_cyc = Signal()
+               last_tx_skip = Signal()
+               readable = Signal()
+
+               self.sync += [
+                               last_tx_cyc.eq(self.tx_cyc),
+                               last_tx_skip.eq(self.tx_skip),
+                               ]
+
+               self.comb += [
+                               readable.eq(Cat(tag.readable, pas.readable,
+                                       cfg.fifo.readable, wbm.readable) & re == re),
+                               self.tx.stb.eq(readable & (re[1:] != 0)),
+                               self.tx.payload.data.eq(data),
+                               Case(tag.dout, {
+                                       tags["PASS_TX"]: [re.eq(0b0011), data.eq(pas.dout)],
+                                       tags["PASS_ON"]: [re.eq(0b0011), data.eq(pas.dout)],
+                                       tags["CFG_REQ"]: [re.eq(0b0101), data.eq(cfg.dout)],
+                                       tags["CFG_IGN"]: [re.eq(0b0111), data.eq(pas.dout)],
+                                       tags["WBM_REQ"]: [re.eq(0b1001), data.eq(wbm.dout)],
+                                       tags["WBM_IGN"]: [re.eq(0b1011), data.eq(pas.dout)],
+                                       "default": [re.eq(0b0001)],
+                                       }),
+                               If(readable & (self.tx.ack | (re[1:] == 0)),
+                                       Cat(tag.re, pas.re, cfg.fifo.re, wbm.re).eq(re),
+                               ),
+                               If(tag.readable,
+                                       If(tag.dout == tags["PASS_TX"],
+                                               self.tx_cyc.eq(1),
+                                               self.tx_skip.eq(0),
+                                       ).Elif(tag.dout == tags["SKIP_TX"],
+                                               self.tx_cyc.eq(0),
+                                               self.tx_skip.eq(1),
+                                       ).Elif(tag.dout == tags["DROP_TX"],
+                                               self.tx_cyc.eq(0),
+                                               self.tx_skip.eq(0),
+                                       ).Else(
+                                               self.tx_cyc.eq(last_tx_cyc),
+                                               self.tx_skip.eq(last_tx_skip),
+                                       ),
+                               ).Else(
+                                       self.tx_cyc.eq(last_tx_cyc),
+                                       self.tx_skip.eq(last_tx_skip),
+                               ),
+                               ]
+
+class Receive(Module):
+       def __init__(self, pas, cfg, wbm, tag, tags):
+               self.rx = Sink(_eb_layout)
+
+               rx_rec_hdr = Record(_eb_rec_hdr)
+               tx_rec_hdr = Record(_eb_rec_hdr)
+               rx_eb_hdr = Record(_eb_hdr)
+               tx_eb_hdr = Record(_eb_hdr)
+               self.comb += [
+                               rx_eb_hdr.raw_bits().eq(self.rx.payload.data),
+                               tx_eb_hdr.magic.eq(rx_eb_hdr.magic),
+                               tx_eb_hdr.ver.eq(_eb_ver),
+                               tx_eb_hdr.no_response.eq(1),
+                               tx_eb_hdr.addr_size.eq(4),
+                               tx_eb_hdr.data_size.eq(4),
+                               tx_eb_hdr.probe_res.eq(rx_eb_hdr.probe),
+
+                               rx_rec_hdr.raw_bits().eq(self.rx.payload.data),
+                               tx_rec_hdr.wca_cfg.eq(rx_rec_hdr.bca_cfg),
+                               tx_rec_hdr.wr_fifo.eq(rx_rec_hdr.rd_fifo),
+                               tx_rec_hdr.wr_cnt.eq(rx_rec_hdr.rd_cnt),
+                               tx_rec_hdr.sel.eq(rx_rec_hdr.sel),
+                               tx_rec_hdr.drop_cyc.eq(rx_rec_hdr.drop_cyc),
+                               ]
+
+               do_rx = Signal()
+               self.rx_cyc = Signal()
+               self.comb += [
+                               wbm.bus.sel.eq(rx_rec_hdr.sel),
+                               do_rx.eq(tag.writable & # tag is always written/read
+                                       self.rx_cyc & self.rx.stb & # have data
+                                       (wbm.fifo.we | ~wbm.bus.stb) & # stb finished or idle
+                                       (wbm.bus.cyc | ~wbm.busy)), # in-cycle or idle
+                               self.rx.ack.eq(do_rx),
+                               cfg.fifo.din.eq(wbm.bus.adr),
+                               # no eb-cfg write support yet
+                               #cfg.dat_w.eq(wbm.bus.dat_w),
+                               #cfg.we.eq(wbm.bus.we),
+                               cfg.errreg.eq(wbm.errreg),
+                               ]
+
+               cur_rx_rec_hdr = Record(_eb_rec_hdr)
+               cur_tx_rec_hdr = Record(_eb_rec_hdr)
+               do_rec = Signal()
+               do_adr = Signal()
+               do_write = Signal()
+               do_read = Signal()
+               wr_adr = Signal(flen(wbm.bus.adr))
+               old_rx_cyc = Signal()
+               self.sync += [
+                               wbm.bus.stb.eq(wbm.bus.stb & ~wbm.fifo.we),
+                               wbm.bus.cyc.eq(wbm.bus.cyc & (
+                                       ~cur_rx_rec_hdr.drop_cyc |
+                                       (cur_rx_rec_hdr.wr_cnt > 0) |
+                                       (cur_rx_rec_hdr.rd_cnt > 0))),
+                               If(do_rec,
+                                       cur_rx_rec_hdr.eq(rx_rec_hdr),
+                                       cur_tx_rec_hdr.eq(tx_rec_hdr),
+                               ),
+                               If(do_adr,
+                                       wr_adr.eq(self.rx.payload.data[2:]),
+                               ),
+                               If(do_write,
+                                       If(cur_rx_rec_hdr.wca_cfg,
+                                               cfg.fifo.we.eq(1),
+                                       ).Else(
+                                               wbm.bus.cyc.eq(1),
+                                               wbm.bus.stb.eq(1),
+                                       ),
+                                       wbm.bus.we.eq(1),
+                                       wbm.bus.adr.eq(wr_adr),
+                                       wbm.bus.dat_w.eq(self.rx.payload.data),
+                                       If(~cur_rx_rec_hdr.wr_fifo,
+                                               wr_adr.eq(wr_adr + 1),
+                                       ),
+                                       cur_rx_rec_hdr.wr_cnt.eq(cur_rx_rec_hdr.wr_cnt - 1),
+                               ),
+                               If(do_read,
+                                       If(cur_rx_rec_hdr.rca_cfg,
+                                               cfg.fifo.we.eq(1),
+                                       ).Else(
+                                               wbm.bus.cyc.eq(1),
+                                               wbm.bus.stb.eq(1),
+                                       ),
+                                       wbm.bus.we.eq(0),
+                                       wbm.bus.adr.eq(self.rx.payload.data[2:]),
+                                       cur_rx_rec_hdr.rd_cnt.eq(cur_rx_rec_hdr.rd_cnt - 1),
+                               ),
+                               If(~self.rx_cyc,
+                                       wbm.bus.cyc.eq(0),
+                               ),
+                               old_rx_cyc.eq(self.rx_cyc),
+                               ]
+
+               fsm = self.submodules.fsm = FSM()
+               fsm.reset_state = "EB_HDR"
+               fsm.act("EB_HDR",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       If((rx_eb_hdr.magic != _eb_magic) |
+                                                       (rx_eb_hdr.ver !=_eb_ver),
+                                               tag.din.eq(tags["SKIP_TX"]),
+                                               NextState("DROP"),
+                                       ).Else(
+                                               If(rx_eb_hdr.no_response,
+                                                       tag.din.eq(tags["SKIP_TX"]),
+                                               ).Else(
+                                                       tag.din.eq(tags["PASS_TX"]),
+                                                       pas.we.eq(1),
+                                                       pas.din.eq(tx_eb_hdr.raw_bits()),
+                                               ),
+                                               If(rx_eb_hdr.probe,
+                                                       If(rx_eb_hdr.addr_size[2] &
+                                                                       rx_eb_hdr.data_size[2],
+                                                               NextState("PROBE_ID"),
+                                                       ).Else(
+                                                               NextState("PROBE_DROP"),
+                                                       ),
+                                               ).Else(
+                                                       If((rx_eb_hdr.addr_size == 4) &
+                                                                       (rx_eb_hdr.data_size == 4),
+                                                               NextState("CYC_HDR"),
+                                                       ).Else(
+                                                               NextState("DROP"),
+                                                       ),
+                                               ),
+                                       ),
+                               ))
+               fsm.act("PROBE_DROP",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       pas.din.eq(self.rx.payload.data),
+                                       NextState("DROP"),
+                               ))
+               fsm.act("PROBE_ID",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       pas.din.eq(self.rx.payload.data),
+                                       NextState("CYC_HDR"),
+                               ))
+               fsm.act("CYC_HDR",
+                               If(do_rx,
+                                       do_rec.eq(1),
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       If(rx_rec_hdr.wr_cnt != 0,
+                                               NextState("WR_ADR"),
+                                       ).Else(
+                                               pas.din.eq(tx_rec_hdr.raw_bits()),
+                                               If(rx_rec_hdr.rd_cnt != 0,
+                                                       NextState("RD_ADR"),
+                                               ).Else(
+                                                       NextState("CYC_HDR"),
+                                               ),
+                                       ),
+                               ))
+               fsm.act("WR_ADR",
+                               If(do_rx,
+                                       do_adr.eq(1),
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       NextState("WRITE"),
+                               ))
+               fsm.act("WRITE",
+                               If(do_rx,
+                                       do_write.eq(1),
+                                       tag.we.eq(1),
+                                       If(cur_rx_rec_hdr.wca_cfg,
+                                               tag.din.eq(tags["CFG_IGN"]),
+                                       ).Else(
+                                               wbm.active.eq(1),
+                                               tag.din.eq(tags["WBM_IGN"]),
+                                       ),
+                                       pas.we.eq(1),
+                                       If(cur_rx_rec_hdr.wr_cnt == 1,
+                                               pas.din.eq(cur_tx_rec_hdr.raw_bits()),
+                                               If(cur_rx_rec_hdr.rd_cnt != 0,
+                                                       NextState("RD_ADR"),
+                                               ).Else(
+                                                       NextState("CYC_HDR"),
+                                               ),
+                                       ),
+                               ))
+               fsm.act("RD_ADR",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       pas.din.eq(self.rx.payload.data),
+                                       NextState("READ"),
+                               ))
+               fsm.act("READ",
+                               If(do_rx,
+                                       do_read.eq(1),
+                                       tag.we.eq(1),
+                                       If(cur_rx_rec_hdr.rca_cfg,
+                                               tag.din.eq(tags["CFG_REQ"]),
+                                       ).Else(
+                                               wbm.active.eq(1),
+                                               tag.din.eq(tags["WBM_REQ"]),
+                                       ),
+                                       If(cur_rx_rec_hdr.rd_cnt == 1,
+                                               NextState("CYC_HDR"),
+                                       ),
+                               ))
+               fsm.act("DROP",
+                               #If(do_rx,
+                               #       tag.we.eq(1),
+                               #       tag.din.eq(tags["PASS_ON"]),
+                               #       pas.we.eq(1),
+                               #)
+                               )
+               for state in fsm.actions:
+                       fsm.act(state, If(~self.rx_cyc, NextState("EB_HDR")))
+               self.comb += [
+                               If(~self.rx_cyc,
+                                       Cat(do_rec, do_adr, do_write, do_read).eq(0),
+                                       Cat(wbm.active, pas.we).eq(0),
+                                       If(old_rx_cyc,
+                                               tag.we.eq(1),
+                                               tag.din.eq(tags["DROP_TX"]),
+                                       ),
+                               )]
+
+class Slave(Module):
+       def __init__(self, sdb_addr, timeout):
+               tags = dict((k, i) for i, k in enumerate(
+                       "DROP_TX SKIP_TX PASS_TX PASS_ON CFG_REQ "
+                       "CFG_IGN WBM_REQ WBM_IGN".split()))
+               tag_width = flen(Signal(max=len(tags)))
+
+               self.submodules.pas = SyncFIFO(_eb_width, _eb_queue_len)
+               self.submodules.cfg = Config(sdb_addr)
+               self.submodules.wbm = WishboneMaster(timeout)
+               self.submodules.tag = SyncFIFO(tag_width, _eb_queue_len)
+
+               self.submodules.rxfsm = Receive(self.pas, self.cfg,
+                               self.wbm, self.tag, tags)
+               self.rx = self.rxfsm.rx
+               self.rx_cyc = self.rxfsm.rx_cyc
+               self.submodules.txmux = Transmit(self.pas, self.cfg,
+                               self.wbm.fifo, self.tag, tags)
+               self.tx = self.txmux.tx
+               self.tx_skip = self.txmux.tx_skip
+               self.tx_cyc = self.txmux.tx_cyc
+               self.busy = self.wbm.busy
+
+class Converter(Module):
+       def __init__(self, raw_width, graph, **slave_kwargs):
+               raw_layout = [("data", raw_width)]
+               pack_factor = _eb_width//raw_width
+
+               self.rx = Sink(raw_layout)
+               rx_pack = Pack(raw_layout, pack_factor)
+               rx_cast = Cast(pack_layout(raw_layout, pack_factor), _eb_layout)
+               self.submodules.slave = Slave(**slave_kwargs)
+               tx_cast = Cast(_eb_layout, pack_layout(raw_layout, pack_factor))
+               tx_unpack = Unpack(pack_factor, raw_layout)
+               self.tx = Source(raw_layout)
+
+               graph.add_connection(self.rx, rx_pack)
+               graph.add_connection(rx_pack, rx_cast)
+               graph.add_connection(rx_cast, self.slave.rx)
+               graph.add_connection(self.slave.tx, tx_cast)
+               graph.add_connection(tx_cast, tx_unpack)
+               graph.add_connection(tx_unpack, self.tx)
+
+class SimTx(SimActor):
+       def __init__(self, data):
+               self.tx = Source(_eb_layout)
+               SimActor.__init__(self, self.gen(data))
+
+       def gen(self, data):
+               for i in data:
+                       yield Token("tx", {"data": i})
+                       print("eb tx", hex(i))
+
+class SimRx(SimActor):
+       def __init__(self):
+               self.rx = Sink(_eb_layout)
+               self.recv = []
+               SimActor.__init__(self, self.gen())
+
+       def gen(self):
+               while True:
+                       t = Token("rx")
+                       yield t
+                       print("eb rx", hex(t.value["data"]))
+                       self.recv.append(t.value["data"])
+
+class TB(Module):
+       def __init__(self, data):
+               ebm_tx = SimTx(data)
+               ebm_rx = SimRx()
+               self.slave = Slave(0x200, 10)
+               g = DataFlowGraph()
+               g.add_connection(ebm_tx, self.slave)
+               g.add_connection(self.slave, ebm_rx)
+               self.submodules.graph = CompositeActor(g)
+               self.submodules.cfg_master = wishbone.Initiator(self.gen_cfg_reads())
+               self.submodules.cfg_tap = wishbone.Tap(self.slave.cfg.bus,
+                               lambda l: print("cfg", l))
+               self.submodules.wbm_tap = wishbone.Tap(self.slave.wbm.bus,
+                               lambda l: print("wbm", l))
+               self.submodules.xbar = wishbone.Crossbar(
+                               [self.cfg_master.bus, self.slave.wbm.bus],
+                               [
+                                       (lambda a: a[6:] == 0x0, wishbone.Target(
+                                               wishbone.TargetModel()).bus),
+                                       (lambda a: a[6:] == 0x1, self.slave.cfg.bus),
+                               ])
+
+       def gen_cfg_reads(self):
+               for a in range(0x40, 0x40+4):
+                       t = TRead(a)
+                       yield t
+
+       def do_simulation(self, s):
+               #s.interrupt = self.cfg_master.done
+               s.wr(self.slave.rx_cyc, int(s.cycle_counter < 200))
+
+class MyStruct(object):
+       _data = None
+       _fmt = "!"
+
+       def __init__(self, **kwargs):
+               self.data = self._data(**kwargs)
+
+       def __bytes__(self):
+               return struct.pack(self._fmt, *self.data)
+
+class EbHeader(MyStruct):
+       _data = namedtuple("eb_hdr", "magic ver size")
+       _fmt = "!HBB"
+
+       def __init__(self, probe_id=None, addr_size=4, data_size=4, records=[]):
+               no_response = not any(r.read for r in records)
+               probe = probe_id is not None
+               probe_res = False
+               MyStruct.__init__(self, magic=_eb_magic, ver=(_eb_ver<<4) |
+                               (no_response<<2) | (probe_res<<1) | (probe<<0),
+                               size=(addr_size<<4) | (data_size<<0))
+               self.probe = struct.pack("!I", probe_id) if probe else b""
+               self.records = records
+
+       def __bytes__(self):
+               return (MyStruct.__bytes__(self) + self.probe +
+                               b"".join(map(bytes, self.records)))
+
+class EbRecord(MyStruct):
+       _data = namedtuple("eb_rec", "flags sel wr_cnt rd_cnt")
+       _fmt = "!BBBB"
+
+       def __init__(self, sel=0xf, wr_adr=0, rd_adr=0, write=[], read=[],
+                       bca_cfg=False, rca_cfg=False, rd_fifo=False, drop_cyc=False,
+                       wca_cfg=False, wr_fifo=False):
+               MyStruct.__init__(self, sel=sel, wr_cnt=len(write),
+                               rd_cnt=len(read), flags=(bca_cfg<<7) | (rca_cfg<<6) |
+                                       (rd_fifo<<5) | (drop_cyc<<3) | (wca_cfg<<2) |
+                                       (wr_fifo>>1))
+               self.wr_adr = wr_adr
+               self.write = write
+               self.rd_adr = rd_adr
+               self.read = read
+
+       def __bytes__(self):
+               b = MyStruct.__bytes__(self)
+               if self.write:
+                       b += struct.pack("!I" + "I"*len(self.write), self.wr_adr,
+                                       *self.write)
+               if self.read:
+                       b += struct.pack("!I" + "I"*len(self.read), self.rd_adr,
+                                       *self.read)
+               return b
+
+def main():
+       from migen.sim.generic import Simulator, TopLevel
+
+       #from migen.fhdl import verilog
+       #s = Slave(0, 10)
+       #print(verilog.convert(s, ios={s.rx.payload.data, s.tx.payload.data,
+       #       s.rx.stb, s.rx.ack, s.tx.stb, s.tx.ack}))
+
+       eb_pkt = EbHeader(records=[
+                               EbRecord(wr_adr=0x10, write=[0x20, 0x21],
+                                       rd_adr=0x30, read=range(0, 8, 4)),
+                               EbRecord(rd_adr=0x40, read=range(0x100, 0x100+32, 4),
+                                       drop_cyc=True),
+                               EbRecord(rca_cfg=True, bca_cfg=True, rd_adr=0x50,
+                                       read=range(0, 0+8, 4), drop_cyc=True),
+                               ])
+       eb_pkt = bytes(eb_pkt)
+       eb_pkt = struct.unpack("!" + "I"*(len(eb_pkt)//4), eb_pkt)
+       tb = TB(eb_pkt)
+       sim = Simulator(tb, TopLevel("etherbone.vcd"))
+       sim.run(500)
+
+
+if __name__ == "__main__":
+       main()
\ No newline at end of file
diff --git a/liteeth/ip/__init__.py b/liteeth/ip/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/mac/__init__.py b/liteeth/mac/__init__.py
new file mode 100644 (file)
index 0000000..e9b2ccf
--- /dev/null
@@ -0,0 +1,54 @@
+from liteethernet.common import *
+from liteethernet.mac import LiteEthernetMAC
+
+class LiteEthernetMAC(Module, AutoCSR):
+       def __init__(self, phy, frontend="wishbone", with_hw_preamble_crc=True, endianness="be"):
+               self.submodules.core = LiteEthernetMAC(phy, with_hw_preamble, endianness)
+
+               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/liteeth/mac/common.py b/liteeth/mac/common.py
new file mode 100644 (file)
index 0000000..177943e
--- /dev/null
@@ -0,0 +1,14 @@
+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/liteeth/mac/core/__init__.py b/liteeth/mac/core/__init__.py
new file mode 100644 (file)
index 0000000..a361d5d
--- /dev/null
@@ -0,0 +1,54 @@
+
+from liteethernet.common import *
+from liteethernet.mac.common import *
+from liteethernet.mac.preamble import PreambleInserter, PreambleChecker
+from liteethernet.mac.crc import CRC32Inserter, CRC32Checker
+from liteethernet.mac.last_be import TXLastBE, RXLastBE
+
+class LiteEthernetMACCore(Module, AutoCSR):
+       def __init__(self, phy, 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)
+
+               self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
diff --git a/liteeth/mac/core/crc.py b/liteeth/mac/core/crc.py
new file mode 100644 (file)
index 0000000..8a058fa
--- /dev/null
@@ -0,0 +1,284 @@
+from migen.fhdl.std import *
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.record import *
+from migen.genlib.misc import optree, chooser
+from migen.genlib.crc import *
+from migen.flow.actor import Sink, Source
+from migen.actorlib.fifo import SyncFIFO
+
+from collections import OrderedDict
+
+class CRCEngine(Module):
+       """Cyclic Redundancy Check Engine
+
+       Compute next CRC value from last CRC value and data input using
+       an optimized asynchronous LFSR.
+
+       Parameters
+       ----------
+       dat_width : int
+               Width of the data bus.
+       width : int
+               Width of the CRC.
+       polynom : int
+               Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
+
+       Attributes
+       ----------
+       d : in
+               Data input.
+       last : in
+               last CRC value.
+       next :
+               next CRC value.
+       """
+       def __init__(self, dat_width, width, polynom):
+               self.d = Signal(dat_width)
+               self.last = Signal(width)
+               self.next = Signal(width)
+
+               ###
+
+               def _optimize_eq(l):
+                       """
+                       Replace even numbers of XORs in the equation
+                       with an equivalent XOR
+                       """
+                       d = OrderedDict()
+                       for e in l:
+                               if e in d:
+                                       d[e] += 1
+                               else:
+                                       d[e] = 1
+                       r = []
+                       for key, value in d.items():
+                               if value%2 != 0:
+                                       r.append(key)
+                       return r
+
+               # compute and optimize CRC's LFSR
+               curval = [[("state", i)] for i in range(width)]
+               for i in range(dat_width):
+                       feedback = curval.pop() + [("din", i)]
+                       for j in range(width-1):
+                               if (polynom & (1<<(j+1))):
+                                       curval[j] += feedback
+                               curval[j] = _optimize_eq(curval[j])
+                       curval.insert(0, feedback)
+
+               # implement logic
+               for i in range(width):
+                       xors = []
+                       for t, n in curval[i]:
+                               if t == "state":
+                                       xors += [self.last[n]]
+                               elif t == "din":
+                                       xors += [self.d[n]]
+                       self.comb += self.next[i].eq(optree("^", xors))
+
+@DecorateModule(InsertReset)
+@DecorateModule(InsertCE)
+class CRC32(Module):
+       """IEEE 802.3 CRC
+
+       Implement an IEEE 802.3 CRC generator/checker.
+
+       Parameters
+       ----------
+       dat_width : int
+               Width of the data bus.
+
+       Attributes
+       ----------
+       d : in
+               Data input.
+       value : out
+               CRC value (used for generator).
+       error : out
+               CRC error (used for checker).
+       """
+       width = 32
+       polynom = 0x04C11DB7
+       init = 2**width-1
+       check = 0xC704DD7B
+       def __init__(self, dat_width):
+               self.d = Signal(dat_width)
+               self.value = Signal(self.width)
+               self.error = Signal()
+
+               ###
+
+               self.submodules.engine = CRCEngine(dat_width, self.width, self.polynom)
+               reg = Signal(self.width, reset=self.init)
+               self.sync += reg.eq(self.engine.next)
+               self.comb += [
+                       self.engine.d.eq(self.d),
+                       self.engine.last.eq(reg),
+
+                       self.value.eq(~reg[::-1]),
+                       self.error.eq(self.engine.next != self.check)
+               ]
+
+class CRCInserter(Module):
+       """CRC Inserter
+
+       Append a CRC at the end of each packet.
+
+       Parameters
+       ----------
+       layout : layout
+               Layout of the dataflow.
+
+       Attributes
+       ----------
+       sink : in
+               Packets input without CRC.
+       source : out
+               Packets output with CRC.
+       """
+       def __init__(self, crc_class, layout):
+               self.sink = sink = Sink(layout)
+               self.source = source = Source(layout)
+               self.busy = Signal()
+
+               ###
+
+               dw = flen(sink.d)
+               crc = crc_class(dw)
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += crc, fsm
+
+               fsm.act("IDLE",
+                       crc.reset.eq(1),
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("COPY"),
+                       )
+               )
+               fsm.act("COPY",
+                       crc.ce.eq(sink.stb & source.ack),
+                       crc.d.eq(sink.d),
+                       Record.connect(sink, source),
+                       source.eop.eq(0),
+                       If(sink.stb & sink.eop & source.ack,
+                               NextState("INSERT"),
+                       )
+               )
+               ratio = crc.width//dw
+               if ratio > 1:
+                       cnt = Signal(max=ratio, reset=ratio-1)
+                       cnt_done = Signal()
+                       fsm.act("INSERT",
+                               source.stb.eq(1),
+                               chooser(crc.value, cnt, source.d, reverse=True),
+                               If(cnt_done,
+                                       source.eop.eq(1),
+                                       If(source.ack, NextState("IDLE"))
+                               )
+                       )
+                       self.comb += cnt_done.eq(cnt == 0)
+                       self.sync += \
+                               If(fsm.ongoing("IDLE"),
+                                       cnt.eq(cnt.reset)
+                               ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
+                                       cnt.eq(cnt - source.ack)
+                               )
+               else:
+                       fsm.act("INSERT",
+                               source.stb.eq(1),
+                               source.eop.eq(1),
+                               source.d.eq(crc.value),
+                               If(source.ack, NextState("IDLE"))
+                       )
+               self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+
+class CRC32Inserter(CRCInserter):
+       def __init__(self, layout):
+               CRCInserter.__init__(self, CRC32, layout)
+
+class CRCChecker(Module):
+       """CRC Checker
+
+       Check CRC at the end of each packet.
+
+       Parameters
+       ----------
+       layout : layout
+               Layout of the dataflow.
+
+       Attributes
+       ----------
+       sink : in
+               Packets input with CRC.
+       source : out
+               Packets output without CRC and "error" set to 0
+               on eop when CRC OK / set to 1 when CRC KO.
+       """
+       def __init__(self, crc_class, layout):
+               self.sink = sink = Sink(layout)
+               self.source = source = Source(layout)
+               self.busy = Signal()
+
+               ###
+
+               dw = flen(sink.d)
+               crc = crc_class(dw)
+               self.submodules += crc
+               ratio = crc.width//dw
+
+               error = Signal()
+               fifo = InsertReset(SyncFIFO(layout, ratio + 1))
+               self.submodules += fifo
+
+               fsm = FSM(reset_state="RESET")
+               self.submodules += fsm
+
+               fifo_in = Signal()
+               fifo_out = Signal()
+               fifo_full = Signal()
+
+               self.comb += [
+                       fifo_full.eq(fifo.fifo.level == ratio),
+                       fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
+                       fifo_out.eq(source.stb & source.ack),
+
+                       Record.connect(sink, fifo.sink),
+                       fifo.sink.stb.eq(fifo_in),
+                       self.sink.ack.eq(fifo_in),
+
+                       source.stb.eq(sink.stb & fifo_full),
+                       source.sop.eq(fifo.source.sop),
+                       source.eop.eq(sink.eop),
+                       fifo.source.ack.eq(fifo_out),
+                       source.payload.eq(fifo.source.payload),
+
+                       source.error.eq(sink.error | crc.error),
+               ]
+
+               fsm.act("RESET",
+                       crc.reset.eq(1),
+                       fifo.reset.eq(1),
+                       NextState("IDLE"),
+               )
+               fsm.act("IDLE",
+                       crc.d.eq(sink.d),
+                       If(sink.stb & sink.sop & sink.ack,
+                               crc.ce.eq(1),
+                               NextState("COPY")
+                       )
+               )
+               fsm.act("COPY",
+                       crc.d.eq(sink.d),
+                       If(sink.stb & sink.ack,
+                               crc.ce.eq(1),
+                               If(sink.eop,
+                                       NextState("RESET")
+                               )
+                       )
+               )
+               self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+
+class CRC32Checker(CRCChecker):
+       def __init__(self, layout):
+               CRCChecker.__init__(self, CRC32, layout)
diff --git a/liteeth/mac/core/last_be.py b/liteeth/mac/core/last_be.py
new file mode 100644 (file)
index 0000000..555e523
--- /dev/null
@@ -0,0 +1,40 @@
+from migen.fhdl.std import *
+from migen.genlib.record import *
+from migen.flow.actor import Sink, Source
+
+from liteethernet.common import *
+from liteethernet.mac.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/liteeth/mac/core/preamble.py b/liteeth/mac/core/preamble.py
new file mode 100644 (file)
index 0000000..f1c7603
--- /dev/null
@@ -0,0 +1,146 @@
+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 liteethernet.common import *
+from liteethernet.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/liteeth/mac/frontend/__init__.py b/liteeth/mac/frontend/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/mac/frontend/sram.py b/liteeth/mac/frontend/sram.py
new file mode 100644 (file)
index 0000000..c51c0ec
--- /dev/null
@@ -0,0 +1,252 @@
+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 liteethernet.common import *
+from liteethernet.mac.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/liteeth/mac/frontend/wishbone.py b/liteeth/mac/frontend/wishbone.py
new file mode 100644 (file)
index 0000000..56601e1
--- /dev/null
@@ -0,0 +1,39 @@
+from liteethernet.common import *
+from liteethernet.mac import LiteEthernetMAC
+
+class LiteEthernetMACWishboneInterface(Module, AutoCSR):
+       def __init__(self, nrxslots=2, ntxslots=2):
+               self.sink = Sink(mac_description(dw))
+               self.source = Source(max_description(dw))
+               self.bus = wishbone.Interface()
+
+               ###
+
+               # SRAM Storage
+               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)
+               self.comb += [
+                       Record.connect(self.sink, self.sram_writer.sink),
+                       Record.connect(self.sram_reader.source, self.source)
+               ]
+
+               # 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
diff --git a/liteeth/mac/test/Makefile b/liteeth/mac/test/Makefile
new file mode 100644 (file)
index 0000000..55d28e1
--- /dev/null
@@ -0,0 +1,13 @@
+MSCDIR = ../../../
+PYTHON = python3
+
+CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
+
+crc_tb:
+       $(CMD) crc_tb.py
+
+preamble_tb:
+       $(CMD) preamble_tb.py
+
+ethmac_tb:
+       $(CMD) ethmac_tb.py
diff --git a/liteeth/mac/test/__init__.py b/liteeth/mac/test/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/mac/test/common.py b/liteeth/mac/test/common.py
new file mode 100644 (file)
index 0000000..1312370
--- /dev/null
@@ -0,0 +1,120 @@
+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/liteeth/mac/test/crc_tb.py b/liteeth/mac/test/crc_tb.py
new file mode 100644 (file)
index 0000000..5d185ac
--- /dev/null
@@ -0,0 +1,83 @@
+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/liteeth/mac/test/ethmac_tb.gtkw b/liteeth/mac/test/ethmac_tb.gtkw
new file mode 100644 (file)
index 0000000..350521a
--- /dev/null
@@ -0,0 +1,75 @@
+[*]
+[*] GTKWave Analyzer v3.3.46 (w)1999-2012 BSI
+[*] Fri Oct 31 11:20:55 2014
+[*]
+[dumpfile] "/home/florent/Dev/misoc/misoclib/ethmac/test/my.vcd"
+[dumpfile_mtime] "Fri Oct 31 11:20:07 2014"
+[dumpfile_size] 5152269
+[savefile] "/home/florent/Dev/misoc/misoclib/ethmac/test/ethmac_tb.gtkw"
+[timestart] 0
+[size] 1548 849
+[pos] 101 171
+*-25.000000 34300000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] top.
+[sst_width] 379
+[signals_width] 464
+[sst_expanded] 1
+[sst_vpaned_height] 485
+@200
+-WISHBONE
+@28
+top.dut.bus_ack
+@22
+top.dut.bus_adr[29:0]
+@28
+top.dut.bus_bte[1:0]
+top.dut.bus_cti[2:0]
+top.dut.bus_cyc
+@22
+top.dut.bus_dat_r[31:0]
+top.dut.bus_dat_w[31:0]
+@28
+top.dut.bus_err
+@22
+top.dut.bus_sel[3:0]
+@28
+top.dut.bus_stb
+top.dut.bus_we
+@200
+-SRAM_READER --> PHYTx
+@28
+top.dut.sram_reader_source_ack
+top.dut.sram_reader_source_eop
+@22
+top.dut.sram_reader_source_payload_d[31:0]
+top.dut.sram_reader_source_payload_error[3:0]
+top.dut.sram_reader_source_payload_last_be[3:0]
+@28
+top.dut.sram_reader_source_sop
+top.dut.sram_reader_source_stb
+@200
+-LOOPBACK
+@28
+top.dut.phy_source_ack
+top.dut.phy_source_eop
+@22
+top.dut.phy_source_payload_d[7:0]
+@28
+top.dut.phy_source_payload_error
+top.dut.phy_source_payload_last_be
+top.dut.phy_source_sop
+top.dut.phy_source_stb
+@200
+-PHYRx --> SRAM_WRITER
+@28
+top.dut.sram_writer_sink_ack
+top.dut.sram_writer_sink_eop
+@22
+top.dut.sram_writer_sink_payload_d[31:0]
+top.dut.sram_writer_sink_payload_error[3:0]
+top.dut.sram_writer_sink_payload_last_be[3:0]
+@28
+top.dut.sram_writer_sink_sop
+top.dut.sram_writer_sink_stb
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/liteeth/mac/test/ethmac_tb.py b/liteeth/mac/test/ethmac_tb.py
new file mode 100644 (file)
index 0000000..1e4dbf1
--- /dev/null
@@ -0,0 +1,123 @@
+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/liteeth/mac/test/preamble_tb.py b/liteeth/mac/test/preamble_tb.py
new file mode 100644 (file)
index 0000000..85bd7e6
--- /dev/null
@@ -0,0 +1,82 @@
+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/liteeth/phy/__init__.py b/liteeth/phy/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/phy/gmii.py b/liteeth/phy/gmii.py
new file mode 100644 (file)
index 0000000..c1b8243
--- /dev/null
@@ -0,0 +1,70 @@
+from migen.fhdl.std import *
+from migen.flow.actor import Sink, Source
+from migen.bank.description import *
+from migen.genlib.resetsync import AsyncResetSynchronizer
+
+from liteethernet.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/liteeth/phy/loopback.py b/liteeth/phy/loopback.py
new file mode 100644 (file)
index 0000000..04a51d0
--- /dev/null
@@ -0,0 +1,31 @@
+from migen.fhdl.std import *
+from migen.flow.actor import Sink, Source
+from migen.bank.description import *
+from migen.genlib.record import *
+
+from liteethernet.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/liteeth/phy/mii.py b/liteeth/phy/mii.py
new file mode 100644 (file)
index 0000000..a58b52b
--- /dev/null
@@ -0,0 +1,122 @@
+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 liteethernet.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/liteeth/udp/__init__.py b/liteeth/udp/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteethernet/__init__.py b/liteethernet/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/liteethernet/arp/__init__.py b/liteethernet/arp/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/liteethernet/common.py b/liteethernet/common.py
deleted file mode 100644 (file)
index 177943e..0000000
+++ /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/liteethernet/etherbone/__init__.py b/liteethernet/etherbone/__init__.py
deleted file mode 100644 (file)
index f84348a..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-# This file is Copyright (c) 2014 Robert Jordens <jordens@gmail.com>
-# License: BSD
-
-import struct
-from collections import namedtuple
-
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.record import Record
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.fifo import SyncFIFO
-from migen.genlib.misc import optree
-from migen.actorlib.structuring import Cast, Pack, Unpack, pack_layout
-from migen.actorlib.sim import SimActor
-from migen.bus.transactions import TRead, TWrite
-from migen.flow.transactions import Token
-from migen.flow.actor import Source, Sink
-from migen.flow.network import DataFlowGraph, CompositeActor
-
-
-_eb_width = 32 # addr and data
-_eb_queue_len = 32
-_eb_magic = 0x4e6f
-_eb_ver = 1
-_eb_hdr = [
-               ("magic", 16),
-               ("ver", 4),
-               ("res1", 1),
-               ("no_response", 1),
-               ("probe_res", 1),
-               ("probe", 1),
-               ("addr_size", 4),
-               ("data_size", 4),
-       ][::-1] # big-endian
-
-_eb_rec_hdr = [
-               ("bca_cfg", 1),
-               ("rca_cfg", 1),
-               ("rd_fifo", 1),
-               ("res1", 1),
-               ("drop_cyc", 1),
-               ("wca_cfg", 1),
-               ("wr_fifo", 1),
-               ("res2", 1),
-               ("sel", 8),
-               ("wr_cnt", 8),
-               ("rd_cnt", 8),
-       ][::-1] # big-endian
-
-_eb_layout = [("data", _eb_width)]
-
-
-class Config(Module):
-       def __init__(self, sdb_addr):
-               self.errreg = Signal(8*8)
-               mach = Signal(4*8, reset=0xd15e)
-               macl = Signal(4*8, reset=0xa5edbeef)
-               self.mac = Signal(6*8)
-               self.comb += self.mac.eq(Cat(macl, mach))
-               self.ip = Signal(4*8, reset=0xc0a80064)
-               self.port = Signal(4*8, reset=0xebd0)
-
-               self.bus = bus = wishbone.Interface()
-               self.submodules.fifo = SyncFIFO(3, _eb_queue_len)
-
-               read_mux = Array([self.errreg[32:], self.errreg[:32], 0,
-                       sdb_addr, mach, macl, self.ip, self.port])
-               write_mux = Array([mach, macl, self.ip, self.port])[bus.adr - 4]
-
-               self.dout = read_mux[self.fifo.dout]
-               self.comb += [
-                               bus.ack.eq(bus.cyc & bus.stb),
-                               bus.dat_r.eq(read_mux[bus.adr[:3]]),
-                               ]
-               self.sync += [
-                               If(bus.cyc & bus.stb & bus.we & optree("|",
-                                               [bus.adr[:3] == i for i in (4, 5, 6, 7)]),
-                                       write_mux.eq(bus.dat_w),
-                               )]
-
-class WishboneMaster(Module):
-       def __init__(self, timeout):
-               self.bus = bus = wishbone.Interface()
-               self.submodules.fifo = SyncFIFO(_eb_width + 1, _eb_queue_len)
-
-               self.active = Signal()
-               inflight = Signal(max=_eb_queue_len)
-               queued = Signal(max=_eb_queue_len)
-               self.sync += [
-                               inflight.eq(inflight + self.active - self.fifo.we),
-                               queued.eq(queued + self.active - self.fifo.re),
-                               ]
-
-               self.busy = Signal()
-               self.full = Signal()
-               self.comb += [
-                               self.busy.eq(inflight != 0),
-                               self.full.eq(queued == _eb_queue_len - 1),
-                               ]
-
-               kill_ack = Signal()
-               time = Signal(max=timeout)
-               self.comb += kill_ack.eq(time == timeout - 1)
-               self.sync += [
-                               If(self.fifo.we | ~self.busy,
-                                       time.eq(0),
-                               ).Else(
-                                       time.eq(time + 1),
-                               )]
-
-               self.comb += [
-                               self.fifo.we.eq(bus.ack | bus.err | kill_ack),
-                               self.fifo.din.eq(Cat(bus.dat_r, ~bus.ack)),
-                               ]
-
-               self.errreg = Signal(64)
-               self.sync += [
-                               If(self.fifo.re,
-                                       self.errreg.eq(Cat(self.fifo.dout[-1], self.errreg)),
-                               )]
-
-class Transmit(Module):
-       def __init__(self, pas, cfg, wbm, tag, tags):
-               self.tx = Source(_eb_layout)
-
-               data = Signal(_eb_width)
-               re = Signal(4)
-               self.tx_cyc = Signal()
-               self.tx_skip = Signal()
-               last_tx_cyc = Signal()
-               last_tx_skip = Signal()
-               readable = Signal()
-
-               self.sync += [
-                               last_tx_cyc.eq(self.tx_cyc),
-                               last_tx_skip.eq(self.tx_skip),
-                               ]
-
-               self.comb += [
-                               readable.eq(Cat(tag.readable, pas.readable,
-                                       cfg.fifo.readable, wbm.readable) & re == re),
-                               self.tx.stb.eq(readable & (re[1:] != 0)),
-                               self.tx.payload.data.eq(data),
-                               Case(tag.dout, {
-                                       tags["PASS_TX"]: [re.eq(0b0011), data.eq(pas.dout)],
-                                       tags["PASS_ON"]: [re.eq(0b0011), data.eq(pas.dout)],
-                                       tags["CFG_REQ"]: [re.eq(0b0101), data.eq(cfg.dout)],
-                                       tags["CFG_IGN"]: [re.eq(0b0111), data.eq(pas.dout)],
-                                       tags["WBM_REQ"]: [re.eq(0b1001), data.eq(wbm.dout)],
-                                       tags["WBM_IGN"]: [re.eq(0b1011), data.eq(pas.dout)],
-                                       "default": [re.eq(0b0001)],
-                                       }),
-                               If(readable & (self.tx.ack | (re[1:] == 0)),
-                                       Cat(tag.re, pas.re, cfg.fifo.re, wbm.re).eq(re),
-                               ),
-                               If(tag.readable,
-                                       If(tag.dout == tags["PASS_TX"],
-                                               self.tx_cyc.eq(1),
-                                               self.tx_skip.eq(0),
-                                       ).Elif(tag.dout == tags["SKIP_TX"],
-                                               self.tx_cyc.eq(0),
-                                               self.tx_skip.eq(1),
-                                       ).Elif(tag.dout == tags["DROP_TX"],
-                                               self.tx_cyc.eq(0),
-                                               self.tx_skip.eq(0),
-                                       ).Else(
-                                               self.tx_cyc.eq(last_tx_cyc),
-                                               self.tx_skip.eq(last_tx_skip),
-                                       ),
-                               ).Else(
-                                       self.tx_cyc.eq(last_tx_cyc),
-                                       self.tx_skip.eq(last_tx_skip),
-                               ),
-                               ]
-
-class Receive(Module):
-       def __init__(self, pas, cfg, wbm, tag, tags):
-               self.rx = Sink(_eb_layout)
-
-               rx_rec_hdr = Record(_eb_rec_hdr)
-               tx_rec_hdr = Record(_eb_rec_hdr)
-               rx_eb_hdr = Record(_eb_hdr)
-               tx_eb_hdr = Record(_eb_hdr)
-               self.comb += [
-                               rx_eb_hdr.raw_bits().eq(self.rx.payload.data),
-                               tx_eb_hdr.magic.eq(rx_eb_hdr.magic),
-                               tx_eb_hdr.ver.eq(_eb_ver),
-                               tx_eb_hdr.no_response.eq(1),
-                               tx_eb_hdr.addr_size.eq(4),
-                               tx_eb_hdr.data_size.eq(4),
-                               tx_eb_hdr.probe_res.eq(rx_eb_hdr.probe),
-
-                               rx_rec_hdr.raw_bits().eq(self.rx.payload.data),
-                               tx_rec_hdr.wca_cfg.eq(rx_rec_hdr.bca_cfg),
-                               tx_rec_hdr.wr_fifo.eq(rx_rec_hdr.rd_fifo),
-                               tx_rec_hdr.wr_cnt.eq(rx_rec_hdr.rd_cnt),
-                               tx_rec_hdr.sel.eq(rx_rec_hdr.sel),
-                               tx_rec_hdr.drop_cyc.eq(rx_rec_hdr.drop_cyc),
-                               ]
-
-               do_rx = Signal()
-               self.rx_cyc = Signal()
-               self.comb += [
-                               wbm.bus.sel.eq(rx_rec_hdr.sel),
-                               do_rx.eq(tag.writable & # tag is always written/read
-                                       self.rx_cyc & self.rx.stb & # have data
-                                       (wbm.fifo.we | ~wbm.bus.stb) & # stb finished or idle
-                                       (wbm.bus.cyc | ~wbm.busy)), # in-cycle or idle
-                               self.rx.ack.eq(do_rx),
-                               cfg.fifo.din.eq(wbm.bus.adr),
-                               # no eb-cfg write support yet
-                               #cfg.dat_w.eq(wbm.bus.dat_w),
-                               #cfg.we.eq(wbm.bus.we),
-                               cfg.errreg.eq(wbm.errreg),
-                               ]
-
-               cur_rx_rec_hdr = Record(_eb_rec_hdr)
-               cur_tx_rec_hdr = Record(_eb_rec_hdr)
-               do_rec = Signal()
-               do_adr = Signal()
-               do_write = Signal()
-               do_read = Signal()
-               wr_adr = Signal(flen(wbm.bus.adr))
-               old_rx_cyc = Signal()
-               self.sync += [
-                               wbm.bus.stb.eq(wbm.bus.stb & ~wbm.fifo.we),
-                               wbm.bus.cyc.eq(wbm.bus.cyc & (
-                                       ~cur_rx_rec_hdr.drop_cyc |
-                                       (cur_rx_rec_hdr.wr_cnt > 0) |
-                                       (cur_rx_rec_hdr.rd_cnt > 0))),
-                               If(do_rec,
-                                       cur_rx_rec_hdr.eq(rx_rec_hdr),
-                                       cur_tx_rec_hdr.eq(tx_rec_hdr),
-                               ),
-                               If(do_adr,
-                                       wr_adr.eq(self.rx.payload.data[2:]),
-                               ),
-                               If(do_write,
-                                       If(cur_rx_rec_hdr.wca_cfg,
-                                               cfg.fifo.we.eq(1),
-                                       ).Else(
-                                               wbm.bus.cyc.eq(1),
-                                               wbm.bus.stb.eq(1),
-                                       ),
-                                       wbm.bus.we.eq(1),
-                                       wbm.bus.adr.eq(wr_adr),
-                                       wbm.bus.dat_w.eq(self.rx.payload.data),
-                                       If(~cur_rx_rec_hdr.wr_fifo,
-                                               wr_adr.eq(wr_adr + 1),
-                                       ),
-                                       cur_rx_rec_hdr.wr_cnt.eq(cur_rx_rec_hdr.wr_cnt - 1),
-                               ),
-                               If(do_read,
-                                       If(cur_rx_rec_hdr.rca_cfg,
-                                               cfg.fifo.we.eq(1),
-                                       ).Else(
-                                               wbm.bus.cyc.eq(1),
-                                               wbm.bus.stb.eq(1),
-                                       ),
-                                       wbm.bus.we.eq(0),
-                                       wbm.bus.adr.eq(self.rx.payload.data[2:]),
-                                       cur_rx_rec_hdr.rd_cnt.eq(cur_rx_rec_hdr.rd_cnt - 1),
-                               ),
-                               If(~self.rx_cyc,
-                                       wbm.bus.cyc.eq(0),
-                               ),
-                               old_rx_cyc.eq(self.rx_cyc),
-                               ]
-
-               fsm = self.submodules.fsm = FSM()
-               fsm.reset_state = "EB_HDR"
-               fsm.act("EB_HDR",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       If((rx_eb_hdr.magic != _eb_magic) |
-                                                       (rx_eb_hdr.ver !=_eb_ver),
-                                               tag.din.eq(tags["SKIP_TX"]),
-                                               NextState("DROP"),
-                                       ).Else(
-                                               If(rx_eb_hdr.no_response,
-                                                       tag.din.eq(tags["SKIP_TX"]),
-                                               ).Else(
-                                                       tag.din.eq(tags["PASS_TX"]),
-                                                       pas.we.eq(1),
-                                                       pas.din.eq(tx_eb_hdr.raw_bits()),
-                                               ),
-                                               If(rx_eb_hdr.probe,
-                                                       If(rx_eb_hdr.addr_size[2] &
-                                                                       rx_eb_hdr.data_size[2],
-                                                               NextState("PROBE_ID"),
-                                                       ).Else(
-                                                               NextState("PROBE_DROP"),
-                                                       ),
-                                               ).Else(
-                                                       If((rx_eb_hdr.addr_size == 4) &
-                                                                       (rx_eb_hdr.data_size == 4),
-                                                               NextState("CYC_HDR"),
-                                                       ).Else(
-                                                               NextState("DROP"),
-                                                       ),
-                                               ),
-                                       ),
-                               ))
-               fsm.act("PROBE_DROP",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       pas.din.eq(self.rx.payload.data),
-                                       NextState("DROP"),
-                               ))
-               fsm.act("PROBE_ID",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       pas.din.eq(self.rx.payload.data),
-                                       NextState("CYC_HDR"),
-                               ))
-               fsm.act("CYC_HDR",
-                               If(do_rx,
-                                       do_rec.eq(1),
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       If(rx_rec_hdr.wr_cnt != 0,
-                                               NextState("WR_ADR"),
-                                       ).Else(
-                                               pas.din.eq(tx_rec_hdr.raw_bits()),
-                                               If(rx_rec_hdr.rd_cnt != 0,
-                                                       NextState("RD_ADR"),
-                                               ).Else(
-                                                       NextState("CYC_HDR"),
-                                               ),
-                                       ),
-                               ))
-               fsm.act("WR_ADR",
-                               If(do_rx,
-                                       do_adr.eq(1),
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       NextState("WRITE"),
-                               ))
-               fsm.act("WRITE",
-                               If(do_rx,
-                                       do_write.eq(1),
-                                       tag.we.eq(1),
-                                       If(cur_rx_rec_hdr.wca_cfg,
-                                               tag.din.eq(tags["CFG_IGN"]),
-                                       ).Else(
-                                               wbm.active.eq(1),
-                                               tag.din.eq(tags["WBM_IGN"]),
-                                       ),
-                                       pas.we.eq(1),
-                                       If(cur_rx_rec_hdr.wr_cnt == 1,
-                                               pas.din.eq(cur_tx_rec_hdr.raw_bits()),
-                                               If(cur_rx_rec_hdr.rd_cnt != 0,
-                                                       NextState("RD_ADR"),
-                                               ).Else(
-                                                       NextState("CYC_HDR"),
-                                               ),
-                                       ),
-                               ))
-               fsm.act("RD_ADR",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       pas.din.eq(self.rx.payload.data),
-                                       NextState("READ"),
-                               ))
-               fsm.act("READ",
-                               If(do_rx,
-                                       do_read.eq(1),
-                                       tag.we.eq(1),
-                                       If(cur_rx_rec_hdr.rca_cfg,
-                                               tag.din.eq(tags["CFG_REQ"]),
-                                       ).Else(
-                                               wbm.active.eq(1),
-                                               tag.din.eq(tags["WBM_REQ"]),
-                                       ),
-                                       If(cur_rx_rec_hdr.rd_cnt == 1,
-                                               NextState("CYC_HDR"),
-                                       ),
-                               ))
-               fsm.act("DROP",
-                               #If(do_rx,
-                               #       tag.we.eq(1),
-                               #       tag.din.eq(tags["PASS_ON"]),
-                               #       pas.we.eq(1),
-                               #)
-                               )
-               for state in fsm.actions:
-                       fsm.act(state, If(~self.rx_cyc, NextState("EB_HDR")))
-               self.comb += [
-                               If(~self.rx_cyc,
-                                       Cat(do_rec, do_adr, do_write, do_read).eq(0),
-                                       Cat(wbm.active, pas.we).eq(0),
-                                       If(old_rx_cyc,
-                                               tag.we.eq(1),
-                                               tag.din.eq(tags["DROP_TX"]),
-                                       ),
-                               )]
-
-class Slave(Module):
-       def __init__(self, sdb_addr, timeout):
-               tags = dict((k, i) for i, k in enumerate(
-                       "DROP_TX SKIP_TX PASS_TX PASS_ON CFG_REQ "
-                       "CFG_IGN WBM_REQ WBM_IGN".split()))
-               tag_width = flen(Signal(max=len(tags)))
-
-               self.submodules.pas = SyncFIFO(_eb_width, _eb_queue_len)
-               self.submodules.cfg = Config(sdb_addr)
-               self.submodules.wbm = WishboneMaster(timeout)
-               self.submodules.tag = SyncFIFO(tag_width, _eb_queue_len)
-
-               self.submodules.rxfsm = Receive(self.pas, self.cfg,
-                               self.wbm, self.tag, tags)
-               self.rx = self.rxfsm.rx
-               self.rx_cyc = self.rxfsm.rx_cyc
-               self.submodules.txmux = Transmit(self.pas, self.cfg,
-                               self.wbm.fifo, self.tag, tags)
-               self.tx = self.txmux.tx
-               self.tx_skip = self.txmux.tx_skip
-               self.tx_cyc = self.txmux.tx_cyc
-               self.busy = self.wbm.busy
-
-class Converter(Module):
-       def __init__(self, raw_width, graph, **slave_kwargs):
-               raw_layout = [("data", raw_width)]
-               pack_factor = _eb_width//raw_width
-
-               self.rx = Sink(raw_layout)
-               rx_pack = Pack(raw_layout, pack_factor)
-               rx_cast = Cast(pack_layout(raw_layout, pack_factor), _eb_layout)
-               self.submodules.slave = Slave(**slave_kwargs)
-               tx_cast = Cast(_eb_layout, pack_layout(raw_layout, pack_factor))
-               tx_unpack = Unpack(pack_factor, raw_layout)
-               self.tx = Source(raw_layout)
-
-               graph.add_connection(self.rx, rx_pack)
-               graph.add_connection(rx_pack, rx_cast)
-               graph.add_connection(rx_cast, self.slave.rx)
-               graph.add_connection(self.slave.tx, tx_cast)
-               graph.add_connection(tx_cast, tx_unpack)
-               graph.add_connection(tx_unpack, self.tx)
-
-class SimTx(SimActor):
-       def __init__(self, data):
-               self.tx = Source(_eb_layout)
-               SimActor.__init__(self, self.gen(data))
-
-       def gen(self, data):
-               for i in data:
-                       yield Token("tx", {"data": i})
-                       print("eb tx", hex(i))
-
-class SimRx(SimActor):
-       def __init__(self):
-               self.rx = Sink(_eb_layout)
-               self.recv = []
-               SimActor.__init__(self, self.gen())
-
-       def gen(self):
-               while True:
-                       t = Token("rx")
-                       yield t
-                       print("eb rx", hex(t.value["data"]))
-                       self.recv.append(t.value["data"])
-
-class TB(Module):
-       def __init__(self, data):
-               ebm_tx = SimTx(data)
-               ebm_rx = SimRx()
-               self.slave = Slave(0x200, 10)
-               g = DataFlowGraph()
-               g.add_connection(ebm_tx, self.slave)
-               g.add_connection(self.slave, ebm_rx)
-               self.submodules.graph = CompositeActor(g)
-               self.submodules.cfg_master = wishbone.Initiator(self.gen_cfg_reads())
-               self.submodules.cfg_tap = wishbone.Tap(self.slave.cfg.bus,
-                               lambda l: print("cfg", l))
-               self.submodules.wbm_tap = wishbone.Tap(self.slave.wbm.bus,
-                               lambda l: print("wbm", l))
-               self.submodules.xbar = wishbone.Crossbar(
-                               [self.cfg_master.bus, self.slave.wbm.bus],
-                               [
-                                       (lambda a: a[6:] == 0x0, wishbone.Target(
-                                               wishbone.TargetModel()).bus),
-                                       (lambda a: a[6:] == 0x1, self.slave.cfg.bus),
-                               ])
-
-       def gen_cfg_reads(self):
-               for a in range(0x40, 0x40+4):
-                       t = TRead(a)
-                       yield t
-
-       def do_simulation(self, s):
-               #s.interrupt = self.cfg_master.done
-               s.wr(self.slave.rx_cyc, int(s.cycle_counter < 200))
-
-class MyStruct(object):
-       _data = None
-       _fmt = "!"
-
-       def __init__(self, **kwargs):
-               self.data = self._data(**kwargs)
-
-       def __bytes__(self):
-               return struct.pack(self._fmt, *self.data)
-
-class EbHeader(MyStruct):
-       _data = namedtuple("eb_hdr", "magic ver size")
-       _fmt = "!HBB"
-
-       def __init__(self, probe_id=None, addr_size=4, data_size=4, records=[]):
-               no_response = not any(r.read for r in records)
-               probe = probe_id is not None
-               probe_res = False
-               MyStruct.__init__(self, magic=_eb_magic, ver=(_eb_ver<<4) |
-                               (no_response<<2) | (probe_res<<1) | (probe<<0),
-                               size=(addr_size<<4) | (data_size<<0))
-               self.probe = struct.pack("!I", probe_id) if probe else b""
-               self.records = records
-
-       def __bytes__(self):
-               return (MyStruct.__bytes__(self) + self.probe +
-                               b"".join(map(bytes, self.records)))
-
-class EbRecord(MyStruct):
-       _data = namedtuple("eb_rec", "flags sel wr_cnt rd_cnt")
-       _fmt = "!BBBB"
-
-       def __init__(self, sel=0xf, wr_adr=0, rd_adr=0, write=[], read=[],
-                       bca_cfg=False, rca_cfg=False, rd_fifo=False, drop_cyc=False,
-                       wca_cfg=False, wr_fifo=False):
-               MyStruct.__init__(self, sel=sel, wr_cnt=len(write),
-                               rd_cnt=len(read), flags=(bca_cfg<<7) | (rca_cfg<<6) |
-                                       (rd_fifo<<5) | (drop_cyc<<3) | (wca_cfg<<2) |
-                                       (wr_fifo>>1))
-               self.wr_adr = wr_adr
-               self.write = write
-               self.rd_adr = rd_adr
-               self.read = read
-
-       def __bytes__(self):
-               b = MyStruct.__bytes__(self)
-               if self.write:
-                       b += struct.pack("!I" + "I"*len(self.write), self.wr_adr,
-                                       *self.write)
-               if self.read:
-                       b += struct.pack("!I" + "I"*len(self.read), self.rd_adr,
-                                       *self.read)
-               return b
-
-def main():
-       from migen.sim.generic import Simulator, TopLevel
-
-       #from migen.fhdl import verilog
-       #s = Slave(0, 10)
-       #print(verilog.convert(s, ios={s.rx.payload.data, s.tx.payload.data,
-       #       s.rx.stb, s.rx.ack, s.tx.stb, s.tx.ack}))
-
-       eb_pkt = EbHeader(records=[
-                               EbRecord(wr_adr=0x10, write=[0x20, 0x21],
-                                       rd_adr=0x30, read=range(0, 8, 4)),
-                               EbRecord(rd_adr=0x40, read=range(0x100, 0x100+32, 4),
-                                       drop_cyc=True),
-                               EbRecord(rca_cfg=True, bca_cfg=True, rd_adr=0x50,
-                                       read=range(0, 0+8, 4), drop_cyc=True),
-                               ])
-       eb_pkt = bytes(eb_pkt)
-       eb_pkt = struct.unpack("!" + "I"*(len(eb_pkt)//4), eb_pkt)
-       tb = TB(eb_pkt)
-       sim = Simulator(tb, TopLevel("etherbone.vcd"))
-       sim.run(500)
-
-
-if __name__ == "__main__":
-       main()
\ No newline at end of file
diff --git a/liteethernet/ip/__init__.py b/liteethernet/ip/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/liteethernet/mac/__init__.py b/liteethernet/mac/__init__.py
deleted file mode 100644 (file)
index e9b2ccf..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-from liteethernet.common import *
-from liteethernet.mac import LiteEthernetMAC
-
-class LiteEthernetMAC(Module, AutoCSR):
-       def __init__(self, phy, frontend="wishbone", with_hw_preamble_crc=True, endianness="be"):
-               self.submodules.core = LiteEthernetMAC(phy, with_hw_preamble, endianness)
-
-               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/liteethernet/mac/common.py b/liteethernet/mac/common.py
deleted file mode 100644 (file)
index 177943e..0000000
+++ /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/liteethernet/mac/core/__init__.py b/liteethernet/mac/core/__init__.py
deleted file mode 100644 (file)
index a361d5d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-
-from liteethernet.common import *
-from liteethernet.mac.common import *
-from liteethernet.mac.preamble import PreambleInserter, PreambleChecker
-from liteethernet.mac.crc import CRC32Inserter, CRC32Checker
-from liteethernet.mac.last_be import TXLastBE, RXLastBE
-
-class LiteEthernetMACCore(Module, AutoCSR):
-       def __init__(self, phy, 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)
-
-               self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
diff --git a/liteethernet/mac/core/crc.py b/liteethernet/mac/core/crc.py
deleted file mode 100644 (file)
index 8a058fa..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.record import *
-from migen.genlib.misc import optree, chooser
-from migen.genlib.crc import *
-from migen.flow.actor import Sink, Source
-from migen.actorlib.fifo import SyncFIFO
-
-from collections import OrderedDict
-
-class CRCEngine(Module):
-       """Cyclic Redundancy Check Engine
-
-       Compute next CRC value from last CRC value and data input using
-       an optimized asynchronous LFSR.
-
-       Parameters
-       ----------
-       dat_width : int
-               Width of the data bus.
-       width : int
-               Width of the CRC.
-       polynom : int
-               Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
-
-       Attributes
-       ----------
-       d : in
-               Data input.
-       last : in
-               last CRC value.
-       next :
-               next CRC value.
-       """
-       def __init__(self, dat_width, width, polynom):
-               self.d = Signal(dat_width)
-               self.last = Signal(width)
-               self.next = Signal(width)
-
-               ###
-
-               def _optimize_eq(l):
-                       """
-                       Replace even numbers of XORs in the equation
-                       with an equivalent XOR
-                       """
-                       d = OrderedDict()
-                       for e in l:
-                               if e in d:
-                                       d[e] += 1
-                               else:
-                                       d[e] = 1
-                       r = []
-                       for key, value in d.items():
-                               if value%2 != 0:
-                                       r.append(key)
-                       return r
-
-               # compute and optimize CRC's LFSR
-               curval = [[("state", i)] for i in range(width)]
-               for i in range(dat_width):
-                       feedback = curval.pop() + [("din", i)]
-                       for j in range(width-1):
-                               if (polynom & (1<<(j+1))):
-                                       curval[j] += feedback
-                               curval[j] = _optimize_eq(curval[j])
-                       curval.insert(0, feedback)
-
-               # implement logic
-               for i in range(width):
-                       xors = []
-                       for t, n in curval[i]:
-                               if t == "state":
-                                       xors += [self.last[n]]
-                               elif t == "din":
-                                       xors += [self.d[n]]
-                       self.comb += self.next[i].eq(optree("^", xors))
-
-@DecorateModule(InsertReset)
-@DecorateModule(InsertCE)
-class CRC32(Module):
-       """IEEE 802.3 CRC
-
-       Implement an IEEE 802.3 CRC generator/checker.
-
-       Parameters
-       ----------
-       dat_width : int
-               Width of the data bus.
-
-       Attributes
-       ----------
-       d : in
-               Data input.
-       value : out
-               CRC value (used for generator).
-       error : out
-               CRC error (used for checker).
-       """
-       width = 32
-       polynom = 0x04C11DB7
-       init = 2**width-1
-       check = 0xC704DD7B
-       def __init__(self, dat_width):
-               self.d = Signal(dat_width)
-               self.value = Signal(self.width)
-               self.error = Signal()
-
-               ###
-
-               self.submodules.engine = CRCEngine(dat_width, self.width, self.polynom)
-               reg = Signal(self.width, reset=self.init)
-               self.sync += reg.eq(self.engine.next)
-               self.comb += [
-                       self.engine.d.eq(self.d),
-                       self.engine.last.eq(reg),
-
-                       self.value.eq(~reg[::-1]),
-                       self.error.eq(self.engine.next != self.check)
-               ]
-
-class CRCInserter(Module):
-       """CRC Inserter
-
-       Append a CRC at the end of each packet.
-
-       Parameters
-       ----------
-       layout : layout
-               Layout of the dataflow.
-
-       Attributes
-       ----------
-       sink : in
-               Packets input without CRC.
-       source : out
-               Packets output with CRC.
-       """
-       def __init__(self, crc_class, layout):
-               self.sink = sink = Sink(layout)
-               self.source = source = Source(layout)
-               self.busy = Signal()
-
-               ###
-
-               dw = flen(sink.d)
-               crc = crc_class(dw)
-               fsm = FSM(reset_state="IDLE")
-               self.submodules += crc, fsm
-
-               fsm.act("IDLE",
-                       crc.reset.eq(1),
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("COPY"),
-                       )
-               )
-               fsm.act("COPY",
-                       crc.ce.eq(sink.stb & source.ack),
-                       crc.d.eq(sink.d),
-                       Record.connect(sink, source),
-                       source.eop.eq(0),
-                       If(sink.stb & sink.eop & source.ack,
-                               NextState("INSERT"),
-                       )
-               )
-               ratio = crc.width//dw
-               if ratio > 1:
-                       cnt = Signal(max=ratio, reset=ratio-1)
-                       cnt_done = Signal()
-                       fsm.act("INSERT",
-                               source.stb.eq(1),
-                               chooser(crc.value, cnt, source.d, reverse=True),
-                               If(cnt_done,
-                                       source.eop.eq(1),
-                                       If(source.ack, NextState("IDLE"))
-                               )
-                       )
-                       self.comb += cnt_done.eq(cnt == 0)
-                       self.sync += \
-                               If(fsm.ongoing("IDLE"),
-                                       cnt.eq(cnt.reset)
-                               ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
-                                       cnt.eq(cnt - source.ack)
-                               )
-               else:
-                       fsm.act("INSERT",
-                               source.stb.eq(1),
-                               source.eop.eq(1),
-                               source.d.eq(crc.value),
-                               If(source.ack, NextState("IDLE"))
-                       )
-               self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
-
-class CRC32Inserter(CRCInserter):
-       def __init__(self, layout):
-               CRCInserter.__init__(self, CRC32, layout)
-
-class CRCChecker(Module):
-       """CRC Checker
-
-       Check CRC at the end of each packet.
-
-       Parameters
-       ----------
-       layout : layout
-               Layout of the dataflow.
-
-       Attributes
-       ----------
-       sink : in
-               Packets input with CRC.
-       source : out
-               Packets output without CRC and "error" set to 0
-               on eop when CRC OK / set to 1 when CRC KO.
-       """
-       def __init__(self, crc_class, layout):
-               self.sink = sink = Sink(layout)
-               self.source = source = Source(layout)
-               self.busy = Signal()
-
-               ###
-
-               dw = flen(sink.d)
-               crc = crc_class(dw)
-               self.submodules += crc
-               ratio = crc.width//dw
-
-               error = Signal()
-               fifo = InsertReset(SyncFIFO(layout, ratio + 1))
-               self.submodules += fifo
-
-               fsm = FSM(reset_state="RESET")
-               self.submodules += fsm
-
-               fifo_in = Signal()
-               fifo_out = Signal()
-               fifo_full = Signal()
-
-               self.comb += [
-                       fifo_full.eq(fifo.fifo.level == ratio),
-                       fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
-                       fifo_out.eq(source.stb & source.ack),
-
-                       Record.connect(sink, fifo.sink),
-                       fifo.sink.stb.eq(fifo_in),
-                       self.sink.ack.eq(fifo_in),
-
-                       source.stb.eq(sink.stb & fifo_full),
-                       source.sop.eq(fifo.source.sop),
-                       source.eop.eq(sink.eop),
-                       fifo.source.ack.eq(fifo_out),
-                       source.payload.eq(fifo.source.payload),
-
-                       source.error.eq(sink.error | crc.error),
-               ]
-
-               fsm.act("RESET",
-                       crc.reset.eq(1),
-                       fifo.reset.eq(1),
-                       NextState("IDLE"),
-               )
-               fsm.act("IDLE",
-                       crc.d.eq(sink.d),
-                       If(sink.stb & sink.sop & sink.ack,
-                               crc.ce.eq(1),
-                               NextState("COPY")
-                       )
-               )
-               fsm.act("COPY",
-                       crc.d.eq(sink.d),
-                       If(sink.stb & sink.ack,
-                               crc.ce.eq(1),
-                               If(sink.eop,
-                                       NextState("RESET")
-                               )
-                       )
-               )
-               self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
-
-class CRC32Checker(CRCChecker):
-       def __init__(self, layout):
-               CRCChecker.__init__(self, CRC32, layout)
diff --git a/liteethernet/mac/core/last_be.py b/liteethernet/mac/core/last_be.py
deleted file mode 100644 (file)
index 555e523..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.record import *
-from migen.flow.actor import Sink, Source
-
-from liteethernet.common import *
-from liteethernet.mac.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/liteethernet/mac/core/preamble.py b/liteethernet/mac/core/preamble.py
deleted file mode 100644 (file)
index f1c7603..0000000
+++ /dev/null
@@ -1,146 +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 liteethernet.common import *
-from liteethernet.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/liteethernet/mac/frontend/__init__.py b/liteethernet/mac/frontend/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/liteethernet/mac/frontend/sram.py b/liteethernet/mac/frontend/sram.py
deleted file mode 100644 (file)
index c51c0ec..0000000
+++ /dev/null
@@ -1,252 +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 liteethernet.common import *
-from liteethernet.mac.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/liteethernet/mac/frontend/wishbone.py b/liteethernet/mac/frontend/wishbone.py
deleted file mode 100644 (file)
index 56601e1..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-from liteethernet.common import *
-from liteethernet.mac import LiteEthernetMAC
-
-class LiteEthernetMACWishboneInterface(Module, AutoCSR):
-       def __init__(self, nrxslots=2, ntxslots=2):
-               self.sink = Sink(mac_description(dw))
-               self.source = Source(max_description(dw))
-               self.bus = wishbone.Interface()
-
-               ###
-
-               # SRAM Storage
-               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)
-               self.comb += [
-                       Record.connect(self.sink, self.sram_writer.sink),
-                       Record.connect(self.sram_reader.source, self.source)
-               ]
-
-               # 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
diff --git a/liteethernet/mac/test/Makefile b/liteethernet/mac/test/Makefile
deleted file mode 100644 (file)
index 55d28e1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-MSCDIR = ../../../
-PYTHON = python3
-
-CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
-
-crc_tb:
-       $(CMD) crc_tb.py
-
-preamble_tb:
-       $(CMD) preamble_tb.py
-
-ethmac_tb:
-       $(CMD) ethmac_tb.py
diff --git a/liteethernet/mac/test/__init__.py b/liteethernet/mac/test/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/liteethernet/mac/test/common.py b/liteethernet/mac/test/common.py
deleted file mode 100644 (file)
index 1312370..0000000
+++ /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/liteethernet/mac/test/crc_tb.py b/liteethernet/mac/test/crc_tb.py
deleted file mode 100644 (file)
index 5d185ac..0000000
+++ /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/liteethernet/mac/test/ethmac_tb.gtkw b/liteethernet/mac/test/ethmac_tb.gtkw
deleted file mode 100644 (file)
index 350521a..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-[*]
-[*] GTKWave Analyzer v3.3.46 (w)1999-2012 BSI
-[*] Fri Oct 31 11:20:55 2014
-[*]
-[dumpfile] "/home/florent/Dev/misoc/misoclib/ethmac/test/my.vcd"
-[dumpfile_mtime] "Fri Oct 31 11:20:07 2014"
-[dumpfile_size] 5152269
-[savefile] "/home/florent/Dev/misoc/misoclib/ethmac/test/ethmac_tb.gtkw"
-[timestart] 0
-[size] 1548 849
-[pos] 101 171
-*-25.000000 34300000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-[treeopen] top.
-[sst_width] 379
-[signals_width] 464
-[sst_expanded] 1
-[sst_vpaned_height] 485
-@200
--WISHBONE
-@28
-top.dut.bus_ack
-@22
-top.dut.bus_adr[29:0]
-@28
-top.dut.bus_bte[1:0]
-top.dut.bus_cti[2:0]
-top.dut.bus_cyc
-@22
-top.dut.bus_dat_r[31:0]
-top.dut.bus_dat_w[31:0]
-@28
-top.dut.bus_err
-@22
-top.dut.bus_sel[3:0]
-@28
-top.dut.bus_stb
-top.dut.bus_we
-@200
--SRAM_READER --> PHYTx
-@28
-top.dut.sram_reader_source_ack
-top.dut.sram_reader_source_eop
-@22
-top.dut.sram_reader_source_payload_d[31:0]
-top.dut.sram_reader_source_payload_error[3:0]
-top.dut.sram_reader_source_payload_last_be[3:0]
-@28
-top.dut.sram_reader_source_sop
-top.dut.sram_reader_source_stb
-@200
--LOOPBACK
-@28
-top.dut.phy_source_ack
-top.dut.phy_source_eop
-@22
-top.dut.phy_source_payload_d[7:0]
-@28
-top.dut.phy_source_payload_error
-top.dut.phy_source_payload_last_be
-top.dut.phy_source_sop
-top.dut.phy_source_stb
-@200
--PHYRx --> SRAM_WRITER
-@28
-top.dut.sram_writer_sink_ack
-top.dut.sram_writer_sink_eop
-@22
-top.dut.sram_writer_sink_payload_d[31:0]
-top.dut.sram_writer_sink_payload_error[3:0]
-top.dut.sram_writer_sink_payload_last_be[3:0]
-@28
-top.dut.sram_writer_sink_sop
-top.dut.sram_writer_sink_stb
-[pattern_trace] 1
-[pattern_trace] 0
diff --git a/liteethernet/mac/test/ethmac_tb.py b/liteethernet/mac/test/ethmac_tb.py
deleted file mode 100644 (file)
index 1e4dbf1..0000000
+++ /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/liteethernet/mac/test/preamble_tb.py b/liteethernet/mac/test/preamble_tb.py
deleted file mode 100644 (file)
index 85bd7e6..0000000
+++ /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/liteethernet/phy/__init__.py b/liteethernet/phy/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/liteethernet/phy/gmii.py b/liteethernet/phy/gmii.py
deleted file mode 100644 (file)
index c1b8243..0000000
+++ /dev/null
@@ -1,70 +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 liteethernet.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/liteethernet/phy/loopback.py b/liteethernet/phy/loopback.py
deleted file mode 100644 (file)
index 04a51d0..0000000
+++ /dev/null
@@ -1,31 +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 liteethernet.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/liteethernet/phy/mii.py b/liteethernet/phy/mii.py
deleted file mode 100644 (file)
index a58b52b..0000000
+++ /dev/null
@@ -1,122 +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 liteethernet.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/liteethernet/udp/__init__.py b/liteethernet/udp/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
index ca0e57d8aa7daa783677e18b09e7c44a7f35c300..933518416d096bf4f04736cdb2ebc4751926248a 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -9,18 +9,18 @@ README = open(os.path.join(here, "README")).read()
 
 required_version = (3, 3)
 if sys.version_info < required_version:
-       raise SystemExit("LiteEthernet requires python {0} or greater".format(
+       raise SystemExit("LiteEth requires python {0} or greater".format(
                ".".join(map(str, required_version))))
 
 setup(
        name="liteethernet",
        version="unknown",
-       description="small footprint and configurable embedded FPGA logic analyzer",
+       description="small footprint and configurable Ethernet core",
        long_description=README,
        author="Florent Kermarrec",
        author_email="florent@enjoy-digital.fr",
        url="http://enjoy-digital.fr",
-       download_url="https://github.com/enjoy-digital/liteethernet",
+       download_url="https://github.com/enjoy-digital/liteeth",
        packages=find_packages(here),
        license="GPL",
        platforms=["Any"],