+++ /dev/null
-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:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Other authors retain ownership of their contributions. If a submission can
-reasonably be considered independently copyrightable, it's yours and we
-encourage you to claim it with appropriate copyright notices. This submission
-then falls under the "otherwise noted" category. All submissions are strongly
-encouraged to use the two-clause BSD license reproduced above.
+++ /dev/null
- __ _ __ ______ __
- / / (_) /____ / __/ /_/ /
- / /__/ / __/ -_) _// __/ _ \
- /____/_/\__/\__/___/\__/_//_/
-
- Copyright 2012-2015 / EnjoyDigital
- florent@enjoy-digital.fr
-
- A small footprint and configurable Ethernet core
- with UDP/IP hw stack and Etherbone frontend
- powered by Migen
-
-[> Doc
----------
-HTML : www.enjoy-digital.fr/litex/liteeth/
-PDF : www.enjoy-digital.fr/litex/liteeth.pdf
-
-[> Intro
----------
-LiteEth provides a small footprint and configurable Ethernet core.
-
-LiteEth is part of LiteX libraries whose aims are to lower entry level of
-complex FPGA cores by providing simple, elegant and efficient implementations
-ofcomponents used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller...
-
-The core uses simple and specific streaming buses and will provides in the future
-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.
-
-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.
-
-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.
-
-[> Features
------------
-- Ethernet MAC with various interfaces and various PHYs (GMII, MII, Loopback)
-- Hardware UDP/IP stack with ARP and ICMP
-
-[> Possible improvements
--------------------------
-- add standardized interfaces (AXI, Avalon-ST)
-- add DMA interface to MAC
-- add RGMII/SGMII PHYs
-- ... See below Support and consulting :)
-
-If you want to support these features, please contact us at florent [AT]
-enjoy-digital.fr. You can also contact our partner on the public mailing list
-devel [AT] lists.m-labs.hk.
-
-
-[> Getting started
-------------------
-1. Install Python3 and your vendor's software
-
-2. Obtain Migen and install it:
- git clone https://github.com/m-labs/migen
- cd migen
- python3 setup.py install
- cd ..
-
-Note: in case you have issues with Migen, please retry
-with our fork at:
- https://github.com/enjoy-digital/misoc
-until new features are merged.
-
-3. Obtain LiteScope and install it:
- git clone https://github.com/enjoy-digital/litescope
- cd litescope
- python3 setup.py install
- cd ..
-
-4. Obtain LiteEth
- git clone https://github.com/enjoy-digital/liteeth
-
-5. Build and load UDP loopback design (only for KC705 for now):
- python3 make.py -t udp all
-
-6. Test design (only for KC705 for now):
- try to ping 192.168.1.40
- go to ./test directory:
- change com port in config.py to your com port
- run make test_udp
-
-7. Build and load Etherbone design (only for KC705 for now):
- python3 make.py -t etherbone all
-
-8. Test design (only for KC705 for now):
- try to ping 192.168.1.40
- go to ./test directory run:
- run make test_etherbone
-
-[> Simulations:
- Simulations are available in ./liteth/test/:
- - mac_core_tb
- - mac_wishbone_tb
- - arp_tb
- - ip_tb
- - icmp_tb
- - udp_tb
- All ethernet layers have their own model tested against real Ethernet dumps (dumps.py)
- To run a simulation, move to ./liteeth/test and run:
- make simulation_name
-
-[> Tests :
- An UDP loopback example is provided and be controlled with: ./test/test_udp.py
- An Etherbone example with Wishbone SRAM is provided and can be controlled with:
- ./test/test_etherbone.py
-
-[> License
------------
-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 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 LiteEth.
-
-[> Support and consulting
---------------------------
-We love open-source hardware and like sharing our designs with others.
-
-LiteEth is developed and maintained by EnjoyDigital.
-
-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.
-
-So feel free to contact us, we'd love to work with you! (and eventually shorten
-the list of the possible improvements :)
-
-[> Contact
-E-mail: florent [AT] enjoy-digital.fr
\ No newline at end of file
--- /dev/null
+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:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Other authors retain ownership of their contributions. If a submission can
+reasonably be considered independently copyrightable, it's yours and we
+encourage you to claim it with appropriate copyright notices. This submission
+then falls under the "otherwise noted" category. All submissions are strongly
+encouraged to use the two-clause BSD license reproduced above.
--- /dev/null
+ __ _ __ ______ __
+ / / (_) /____ / __/ /_/ /
+ / /__/ / __/ -_) _// __/ _ \
+ /____/_/\__/\__/___/\__/_//_/
+
+ Copyright 2012-2015 / EnjoyDigital
+ florent@enjoy-digital.fr
+
+ A small footprint and configurable Ethernet core
+ with UDP/IP hw stack and Etherbone frontend
+ powered by Migen
+
+[> Doc
+---------
+HTML : www.enjoy-digital.fr/litex/liteeth/
+PDF : www.enjoy-digital.fr/litex/liteeth.pdf
+
+[> Intro
+---------
+LiteEth provides a small footprint and configurable Ethernet core.
+
+LiteEth is part of LiteX libraries whose aims are to lower entry level of
+complex FPGA cores by providing simple, elegant and efficient implementations
+ofcomponents used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller...
+
+The core uses simple and specific streaming buses and will provides in the future
+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.
+
+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.
+
+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.
+
+[> Features
+-----------
+- Ethernet MAC with various interfaces and various PHYs (GMII, MII, Loopback)
+- Hardware UDP/IP stack with ARP and ICMP
+
+[> Possible improvements
+-------------------------
+- add standardized interfaces (AXI, Avalon-ST)
+- add DMA interface to MAC
+- add RGMII/SGMII PHYs
+- ... See below Support and consulting :)
+
+If you want to support these features, please contact us at florent [AT]
+enjoy-digital.fr. You can also contact our partner on the public mailing list
+devel [AT] lists.m-labs.hk.
+
+
+[> Getting started
+------------------
+1. Install Python3 and your vendor's software
+
+2. Obtain Migen and install it:
+ git clone https://github.com/m-labs/migen
+ cd migen
+ python3 setup.py install
+ cd ..
+
+Note: in case you have issues with Migen, please retry
+with our fork at:
+ https://github.com/enjoy-digital/misoc
+until new features are merged.
+
+3. Obtain LiteScope and install it:
+ git clone https://github.com/enjoy-digital/litescope
+ cd litescope
+ python3 setup.py install
+ cd ..
+
+4. Obtain LiteEth
+ git clone https://github.com/enjoy-digital/liteeth
+
+5. Build and load UDP loopback design (only for KC705 for now):
+ python3 make.py -t udp all
+
+6. Test design (only for KC705 for now):
+ try to ping 192.168.1.40
+ go to ./test directory:
+ change com port in config.py to your com port
+ run make test_udp
+
+7. Build and load Etherbone design (only for KC705 for now):
+ python3 make.py -t etherbone all
+
+8. Test design (only for KC705 for now):
+ try to ping 192.168.1.40
+ go to ./test directory run:
+ run make test_etherbone
+
+[> Simulations:
+ Simulations are available in ./liteth/test/:
+ - mac_core_tb
+ - mac_wishbone_tb
+ - arp_tb
+ - ip_tb
+ - icmp_tb
+ - udp_tb
+ All ethernet layers have their own model tested against real Ethernet dumps (dumps.py)
+ To run a simulation, move to ./liteeth/test and run:
+ make simulation_name
+
+[> Tests :
+ An UDP loopback example is provided and be controlled with: ./test/test_udp.py
+ An Etherbone example with Wishbone SRAM is provided and can be controlled with:
+ ./test/test_etherbone.py
+
+[> License
+-----------
+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 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 LiteEth.
+
+[> Support and consulting
+--------------------------
+We love open-source hardware and like sharing our designs with others.
+
+LiteEth is developed and maintained by EnjoyDigital.
+
+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.
+
+So feel free to contact us, we'd love to work with you! (and eventually shorten
+the list of the possible improvements :)
+
+[> Contact
+E-mail: florent [AT] enjoy-digital.fr
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python3
+
+import sys, os, argparse, subprocess, struct, importlib
+
+from mibuild.tools import write_to_file
+from migen.util.misc import autotype
+from migen.fhdl import verilog, edif
+from migen.fhdl.structure import _Fragment
+from migen.bank.description import CSRStatus
+from mibuild import tools
+from mibuild.xilinx_common import *
+
+from liteeth.common import *
+
+def get_csr_csv(regions):
+ r = ""
+ for name, origin, busword, obj in regions:
+ if not isinstance(obj, Memory):
+ for csr in obj:
+ nr = (csr.size + busword - 1)//busword
+ r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
+ origin += 4*nr
+ return r
+
+def _import(default, name):
+ return importlib.import_module(default + "." + name)
+
+def _get_args():
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""\
+LiteEth - based on Migen.
+
+This program builds and/or loads LiteEth components.
+One or several actions can be specified:
+
+clean delete previous build(s).
+build-rtl build verilog rtl.
+build-bitstream build-bitstream build FPGA bitstream.
+build-csr-csv save CSR map into CSV file.
+
+load-bitstream load bitstream into volatile storage.
+
+all clean, build-csr-csv, build-bitstream, load-bitstream.
+""")
+
+ parser.add_argument("-t", "--target", default="base", help="Core type to build")
+ parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build")
+ parser.add_argument("-p", "--platform", default=None, help="platform to build for")
+ parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option")
+ parser.add_argument("-Op", "--platform-option", default=[("programmer", "vivado")], nargs=2, action="append", help="set platform-specific option")
+ parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into")
+
+ parser.add_argument("action", nargs="+", help="specify an action")
+
+ return parser.parse_args()
+
+# Note: misoclib need to be installed as a python library
+
+if __name__ == "__main__":
+ args = _get_args()
+
+ # create top-level Core object
+ target_module = _import("targets", args.target)
+ if args.sub_target:
+ top_class = getattr(target_module, args.sub_target)
+ else:
+ top_class = target_module.default_subtarget
+
+ if args.platform is None:
+ platform_name = top_class.default_platform
+ else:
+ platform_name = args.platform
+ platform_module = _import("platforms", platform_name)
+ platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option)
+ platform = platform_module.Platform(**platform_kwargs)
+
+ build_name = top_class.__name__.lower() + "-" + platform_name
+ top_kwargs = dict((k, autotype(v)) for k, v in args.target_option)
+ soc = top_class(platform, **top_kwargs)
+ soc.finalize()
+
+ # decode actions
+ action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"]
+ actions = {k: False for k in action_list}
+ for action in args.action:
+ if action in actions:
+ actions[action] = True
+ else:
+ print("Unknown action: "+action+". Valid actions are:")
+ for a in action_list:
+ print(" "+a)
+ sys.exit(1)
+
+ print("""
+ __ _ __ ______ __
+ / / (_) /____ / __/ /_/ /
+ / /__/ / __/ -_) _// __/ _ \\
+ /____/_/\__/\__/___/\__/_//_/
+
+ A small footprint and configurable Ethernet
+ core powered by Migen
+====== Building options: ======
+Platform: {}
+Target: {}
+Subtarget: {}
+System Clk: {} MHz
+===============================""".format(
+ platform_name,
+ args.target,
+ top_class.__name__,
+ soc.clk_freq/1000000
+ )
+)
+
+ # dependencies
+ if actions["all"]:
+ actions["build-csr-csv"] = True
+ actions["build-bitstream"] = True
+ actions["load-bitstream"] = True
+
+ if actions["build-bitstream"]:
+ actions["build-csr-csv"] = True
+ actions["build-bitstream"] = True
+ actions["load-bitstream"] = True
+
+ if actions["clean"]:
+ subprocess.call(["rm", "-rf", "build/*"])
+
+ if actions["build-csr-csv"]:
+ csr_csv = get_csr_csv(soc.cpu_csr_regions)
+ write_to_file(args.csr_csv, csr_csv)
+
+ if actions["build-bitstream"]:
+ vns = platform.build(soc, build_name=build_name)
+ if hasattr(soc, "do_exit") and vns is not None:
+ if hasattr(soc.do_exit, '__call__'):
+ soc.do_exit(vns)
+
+ if actions["load-bitstream"]:
+ prog = platform.create_programmer()
+ prog.load_bitstream("build/" + build_name + platform.bitstream_ext)
--- /dev/null
+from mibuild.generic_platform import *
+from mibuild.crg import SimpleCRG
+from mibuild.xilinx_common import CRG_DS
+from mibuild.xilinx_ise import XilinxISEPlatform
+from mibuild.xilinx_vivado import XilinxVivadoPlatform
+from mibuild.programmer import *
+
+def _run_vivado(cmds):
+ with subprocess.Popen("vivado -mode tcl", stdin=subprocess.PIPE, shell=True) as process:
+ process.stdin.write(cmds.encode("ASCII"))
+ process.communicate()
+
+class VivadoProgrammer(Programmer):
+ needs_bitreverse = False
+
+ def load_bitstream(self, bitstream_file):
+ cmds = """open_hw
+connect_hw_server
+open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost]] 0]
+
+set_property PROBES.FILE {{}} [lindex [get_hw_devices] 0]
+set_property PROGRAM.FILE {{{bitstream}}} [lindex [get_hw_devices] 0]
+
+program_hw_devices [lindex [get_hw_devices] 0]
+refresh_hw_device [lindex [get_hw_devices] 0]
+
+quit
+""".format(bitstream=bitstream_file)
+ _run_vivado(cmds)
+
+ def flash(self, address, data_file):
+ raise NotImplementedError
+
+_io = [
+ ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")),
+ ("user_led", 1, Pins("AA8"), IOStandard("LVCMOS15")),
+ ("user_led", 2, Pins("AC9"), IOStandard("LVCMOS15")),
+ ("user_led", 3, Pins("AB9"), IOStandard("LVCMOS15")),
+ ("user_led", 4, Pins("AE26"), IOStandard("LVCMOS25")),
+ ("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")),
+ ("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")),
+ ("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")),
+
+ ("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")),
+
+ ("clk200", 0,
+ Subsignal("p", Pins("AD12"), IOStandard("LVDS")),
+ Subsignal("n", Pins("AD11"), IOStandard("LVDS"))
+ ),
+
+ ("clk156", 0,
+ Subsignal("p", Pins("K28"), IOStandard("LVDS_25")),
+ Subsignal("n", Pins("K29"), IOStandard("LVDS_25"))
+ ),
+
+
+ ("serial", 0,
+ Subsignal("cts", Pins("L27")),
+ Subsignal("rts", Pins("K23")),
+ Subsignal("tx", Pins("K24")),
+ Subsignal("rx", Pins("M19")),
+ IOStandard("LVCMOS25")
+ ),
+
+ ("eth_clocks", 0,
+ Subsignal("tx", Pins("M28")),
+ Subsignal("gtx", Pins("K30")),
+ Subsignal("rx", Pins("U27")),
+ IOStandard("LVCMOS25")
+ ),
+ ("eth", 0,
+ Subsignal("rst_n", Pins("L20")),
+ Subsignal("int_n", Pins("N30")),
+ Subsignal("mdio", Pins("J21")),
+ Subsignal("mdc", Pins("R23")),
+ Subsignal("dv", Pins("R28")),
+ Subsignal("rx_er", Pins("V26")),
+ Subsignal("rx_data", Pins("U30 U25 T25 U28 R19 T27 T26 T28")),
+ Subsignal("tx_en", Pins("M27")),
+ Subsignal("tx_er", Pins("N29")),
+ Subsignal("tx_data", Pins("N27 N25 M29 L28 J26 K26 L30 J28")),
+ Subsignal("col", Pins("W19")),
+ Subsignal("crs", Pins("R30")),
+ IOStandard("LVCMOS25")
+ ),
+
+]
+
+def Platform(*args, toolchain="vivado", programmer="xc3sprog", **kwargs):
+ if toolchain == "ise":
+ xilinx_platform = XilinxISEPlatform
+ elif toolchain == "vivado":
+ xilinx_platform = XilinxVivadoPlatform
+ else:
+ raise ValueError
+
+ class RealPlatform(xilinx_platform):
+ bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g ConfigRate:12 -g SPI_buswidth:4"
+
+ def __init__(self, crg_factory=lambda p: CRG_DS(p, "clk200", "cpu_reset")):
+ xilinx_platform.__init__(self, "xc7k325t-ffg900-2", _io, crg_factory)
+
+ def create_programmer(self):
+ if programmer == "xc3sprog":
+ return XC3SProg("jtaghs1_fast", "bscan_spi_kc705.bit")
+ elif programmer == "vivado":
+ return VivadoProgrammer()
+ else:
+ raise ValueError
+
+ def do_finalize(self, fragment):
+ try:
+ self.add_period_constraint(self.lookup_request("clk156").p, 6.4)
+ except ConstraintError:
+ pass
+ try:
+ self.add_period_constraint(self.lookup_request("clk200").p, 5.0)
+ except ConstraintError:
+ pass
+ try:
+ self.add_period_constraint(self.lookup_request("eth_clocks").rx, 8.0)
+ except ConstraintError:
+ pass
+ self.add_platform_command("""
+create_clock -name sys_clk -period 6 [get_nets sys_clk]
+create_clock -name eth_rx_clk -period 8 [get_nets eth_rx_clk]
+create_clock -name eth_tx_clk -period 8 [get_nets eth_tx_clk]
+
+set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_rx_clk]
+set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_tx_clk]
+set_false_path -from [get_clocks eth_rx_clk] -to [get_clocks sys_clk]
+set_false_path -from [get_clocks eth_tx_clk] -to [get_clocks sys_clk]
+
+set_property CFGBVS VCCO [current_design]
+set_property CONFIG_VOLTAGE 2.5 [current_design]
+""")
+
+ return RealPlatform(*args, **kwargs)
--- /dev/null
+import subprocess
+
+from migen.fhdl.std import *
+from migen.bank.description import *
+
+def get_id():
+ output = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii")
+ return int(output[:8], 16)
+
+class Identifier(Module, AutoCSR):
+ def __init__(self, sysid, frequency, revision=None):
+ self._r_sysid = CSRStatus(16)
+ self._r_revision = CSRStatus(32)
+ self._r_frequency = CSRStatus(32)
+
+ ###
+
+ if revision is None:
+ revision = get_id()
+
+ self.comb += [
+ self._r_sysid.status.eq(sysid),
+ self._r_revision.status.eq(revision),
+ self._r_frequency.status.eq(frequency),
+ ]
+
--- /dev/null
+import os
+
+from migen.bank import csrgen
+from migen.bus import wishbone, csr
+from migen.bus import wishbone2csr
+from migen.genlib.cdc import *
+from migen.genlib.resetsync import AsyncResetSynchronizer
+from migen.bank.description import *
+
+from targets import *
+
+from litescope.common import *
+from litescope.bridge.uart2wb import LiteScopeUART2WB
+from litescope.frontend.la import LiteScopeLA
+from litescope.core.port import LiteScopeTerm
+
+from liteeth.common import *
+from liteeth.generic import *
+from liteeth.phy.gmii import LiteEthPHYGMII
+from liteeth.core import LiteEthUDPIPCore
+
+class _CRG(Module):
+ def __init__(self, platform):
+ self.clock_domains.cd_sys = ClockDomain()
+ self.reset = Signal()
+
+ clk200 = platform.request("clk200")
+ clk200_se = Signal()
+ self.specials += Instance("IBUFDS", i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se)
+
+ pll_locked = Signal()
+ pll_fb = Signal()
+ pll_sys = Signal()
+ self.specials += [
+ Instance("PLLE2_BASE",
+ p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
+
+ # VCO @ 1GHz
+ p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0,
+ p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1,
+ i_CLKIN1=clk200_se, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,
+
+ # 166MHz
+ p_CLKOUT0_DIVIDE=6, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys,
+
+ p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, #o_CLKOUT1=,
+
+ p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=,
+
+ p_CLKOUT3_DIVIDE=2, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=,
+
+ p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4=
+ ),
+ Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
+ AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset),
+ ]
+
+class GenSoC(Module):
+ csr_base = 0x00000000
+ csr_data_width = 32
+ csr_map = {
+ "bridge": 0,
+ "identifier": 1,
+ }
+ interrupt_map = {}
+ cpu_type = None
+ def __init__(self, platform, clk_freq):
+ self.clk_freq = clk_freq
+ # UART <--> Wishbone bridge
+ self.submodules.bridge = LiteScopeUART2WB(platform.request("serial"), clk_freq, baud=921600)
+
+ # CSR bridge 0x00000000 (shadow @0x00000000)
+ self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(self.csr_data_width))
+ self._wb_masters = [self.bridge.wishbone]
+ self._wb_slaves = [(lambda a: a[23:25] == 0, self.wishbone2csr.wishbone)]
+ self.cpu_csr_regions = [] # list of (name, origin, busword, csr_list/Memory)
+
+ # CSR
+ self.submodules.identifier = Identifier(0, int(clk_freq), 0)
+
+ def add_wb_master(self, wbm):
+ if self.finalized:
+ raise FinalizeError
+ self._wb_masters.append(wbm)
+
+ def add_wb_slave(self, address_decoder, interface):
+ if self.finalized:
+ raise FinalizeError
+ self._wb_slaves.append((address_decoder, interface))
+
+ def add_cpu_memory_region(self, name, origin, length):
+ self.cpu_memory_regions.append((name, origin, length))
+
+ def add_cpu_csr_region(self, name, origin, busword, obj):
+ self.cpu_csr_regions.append((name, origin, busword, obj))
+
+ def do_finalize(self):
+ # Wishbone
+ self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
+ self._wb_slaves, register=True)
+
+ # CSR
+ self.submodules.csrbankarray = csrgen.BankArray(self,
+ lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override],
+ data_width=self.csr_data_width)
+ self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses())
+ for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
+ self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), csrs)
+ for name, memory, mapaddr, mmap in self.csrbankarray.srams:
+ self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), memory)
+
+class BaseSoC(GenSoC, AutoCSR):
+ default_platform = "kc705"
+ csr_map = {
+ "phy": 11,
+ "core": 12
+ }
+ csr_map.update(GenSoC.csr_map)
+ def __init__(self, platform, clk_freq=166*1000000,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.1.40"):
+ GenSoC.__init__(self, platform, clk_freq)
+ self.submodules.crg = _CRG(platform)
+
+ # wishbone SRAM (to test Wishbone over UART and Etherbone)
+ self.submodules.sram = wishbone.SRAM(1024)
+ self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus)
+
+ # ethernet PHY and UDP/IP stack
+ self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth"))
+ self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq)
+
+class BaseSoCDevel(BaseSoC, AutoCSR):
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(BaseSoC.csr_map)
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform)
+
+ self.core_icmp_rx_fsm_state = Signal(4)
+ self.core_icmp_tx_fsm_state = Signal(4)
+ self.core_udp_rx_fsm_state = Signal(4)
+ self.core_udp_tx_fsm_state = Signal(4)
+ self.core_ip_rx_fsm_state = Signal(4)
+ self.core_ip_tx_fsm_state = Signal(4)
+ self.core_arp_rx_fsm_state = Signal(4)
+ self.core_arp_tx_fsm_state = Signal(4)
+ self.core_arp_table_fsm_state = Signal(4)
+
+ debug = (
+ # MAC interface
+ self.core.mac.core.sink.stb,
+ self.core.mac.core.sink.sop,
+ self.core.mac.core.sink.eop,
+ self.core.mac.core.sink.ack,
+ self.core.mac.core.sink.data,
+
+ self.core.mac.core.source.stb,
+ self.core.mac.core.source.sop,
+ self.core.mac.core.source.eop,
+ self.core.mac.core.source.ack,
+ self.core.mac.core.source.data,
+
+ # ICMP interface
+ self.core.icmp.echo.sink.stb,
+ self.core.icmp.echo.sink.sop,
+ self.core.icmp.echo.sink.eop,
+ self.core.icmp.echo.sink.ack,
+ self.core.icmp.echo.sink.data,
+
+ self.core.icmp.echo.source.stb,
+ self.core.icmp.echo.source.sop,
+ self.core.icmp.echo.source.eop,
+ self.core.icmp.echo.source.ack,
+ self.core.icmp.echo.source.data,
+
+ # IP interface
+ self.core.ip.crossbar.master.sink.stb,
+ self.core.ip.crossbar.master.sink.sop,
+ self.core.ip.crossbar.master.sink.eop,
+ self.core.ip.crossbar.master.sink.ack,
+ self.core.ip.crossbar.master.sink.data,
+ self.core.ip.crossbar.master.sink.ip_address,
+ self.core.ip.crossbar.master.sink.protocol,
+
+ # State machines
+ self.core_icmp_rx_fsm_state,
+ self.core_icmp_tx_fsm_state,
+
+ self.core_arp_rx_fsm_state,
+ self.core_arp_tx_fsm_state,
+ self.core_arp_table_fsm_state,
+
+ self.core_ip_rx_fsm_state,
+ self.core_ip_tx_fsm_state,
+
+ self.core_udp_rx_fsm_state,
+ self.core_udp_tx_fsm_state
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+
+ def do_finalize(self):
+ BaseSoC.do_finalize(self)
+ self.comb += [
+ self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state),
+ self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state),
+
+ self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state),
+ self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state),
+ self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state),
+
+ self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state),
+ self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state),
+
+ self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state),
+ self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state)
+ ]
+
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
+
+default_subtarget = BaseSoC
--- /dev/null
+from litescope.common import *
+from litescope.frontend.la import LiteScopeLA
+from litescope.core.port import LiteScopeTerm
+
+from liteeth.common import *
+from liteeth.generic import *
+
+from targets.base import BaseSoC
+from liteeth.core.etherbone import LiteEthEtherbone
+
+class EtherboneSoC(BaseSoC):
+ default_platform = "kc705"
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.1.40")
+ self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000)
+ self.add_wb_master(self.etherbone.master.bus)
+
+class EtherboneSoCDevel(EtherboneSoC):
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(EtherboneSoC.csr_map)
+ def __init__(self, platform):
+ EtherboneSoC.__init__(self, platform)
+ debug = (
+ # mmap stream from HOST
+ self.etherbone.master.sink.stb,
+ self.etherbone.master.sink.sop,
+ self.etherbone.master.sink.eop,
+ self.etherbone.master.sink.ack,
+ self.etherbone.master.sink.we,
+ self.etherbone.master.sink.count,
+ self.etherbone.master.sink.base_addr,
+ self.etherbone.master.sink.be,
+ self.etherbone.master.sink.addr,
+ self.etherbone.master.sink.data,
+
+ # mmap stream to HOST
+ self.etherbone.master.source.stb,
+ self.etherbone.master.source.sop,
+ self.etherbone.master.source.eop,
+ self.etherbone.master.source.ack,
+ self.etherbone.master.source.we,
+ self.etherbone.master.source.count,
+ self.etherbone.master.source.base_addr,
+ self.etherbone.master.source.be,
+ self.etherbone.master.source.addr,
+ self.etherbone.master.source.data,
+
+ # etherbone wishbone master
+ self.etherbone.master.bus.dat_w,
+ self.etherbone.master.bus.dat_r,
+ self.etherbone.master.bus.adr,
+ self.etherbone.master.bus.sel,
+ self.etherbone.master.bus.cyc,
+ self.etherbone.master.bus.stb,
+ self.etherbone.master.bus.ack,
+ self.etherbone.master.bus.we,
+ self.etherbone.master.bus.cti,
+ self.etherbone.master.bus.bte,
+ self.etherbone.master.bus.err
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
+
+default_subtarget = EtherboneSoC
--- /dev/null
+from litescope.common import *
+from litescope.frontend.la import LiteScopeLA
+from litescope.core.port import LiteScopeTerm
+
+from liteeth.common import *
+from liteeth.generic import *
+
+from targets.base import BaseSoC
+from liteeth.core.tty import LiteEthTTY
+
+class TTYSoC(BaseSoC):
+ default_platform = "kc705"
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.1.40")
+ self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.1.12"), 10000)
+ self.comb += Record.connect(self.tty.source, self.tty.sink)
+
+class TTYSoCDevel(TTYSoC):
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(TTYSoC.csr_map)
+ def __init__(self, platform):
+ TTYSoC.__init__(self, platform)
+ debug = (
+ self.tty.sink.stb,
+ self.tty.sink.ack,
+ self.tty.sink.data,
+
+ self.tty.source.stb,
+ self.tty.source.ack,
+ self.tty.source.data
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
+
+default_subtarget = TTYSoC
--- /dev/null
+from litescope.common import *
+from litescope.frontend.la import LiteScopeLA
+from litescope.core.port import LiteScopeTerm
+
+from liteeth.common import *
+from liteeth.generic import *
+
+from targets.base import BaseSoC
+
+class UDPSoC(BaseSoC):
+ default_platform = "kc705"
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.1.40")
+
+ # add udp loopback on port 6000 with dw=8
+ self.add_udp_loopback(6000, 8, 8192, "loopback_8")
+ # add udp loopback on port 8000 with dw=32
+ self.add_udp_loopback(8000, 32, 8192, "loopback_32")
+
+ def add_udp_loopback(self, port, dw, depth, name=None):
+ port = self.core.udp.crossbar.get_port(port, dw)
+ buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8)
+ if name is None:
+ self.submodules += buf
+ else:
+ setattr(self.submodules, name, buf)
+ self.comb += Port.connect(port, buf)
+
+class UDPSoCDevel(UDPSoC):
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(UDPSoC.csr_map)
+ def __init__(self, platform):
+ UDPSoC.__init__(self, platform)
+ debug = (
+ self.loopback_8.sink.stb,
+ self.loopback_8.sink.sop,
+ self.loopback_8.sink.eop,
+ self.loopback_8.sink.ack,
+ self.loopback_8.sink.data,
+
+ self.loopback_8.source.stb,
+ self.loopback_8.source.sop,
+ self.loopback_8.source.eop,
+ self.loopback_8.source.ack,
+ self.loopback_8.source.data,
+
+ self.loopback_32.sink.stb,
+ self.loopback_32.sink.sop,
+ self.loopback_32.sink.eop,
+ self.loopback_32.sink.ack,
+ self.loopback_32.sink.data,
+
+ self.loopback_32.source.stb,
+ self.loopback_32.source.sop,
+ self.loopback_32.source.eop,
+ self.loopback_32.source.ack,
+ self.loopback_32.source.data
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
+
+default_subtarget = UDPSoC
--- /dev/null
+#!/usr/bin/env python3
+import argparse, importlib
+
+def _get_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use")
+ parser.add_argument("--port", default=2, help="UART port")
+ parser.add_argument("--baudrate", default=921600, help="UART baudrate")
+ parser.add_argument("--ip_address", default="192.168.1.40", help="Etherbone IP address")
+ parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port")
+ parser.add_argument("--busword", default=32, help="CSR busword")
+
+ parser.add_argument("test", nargs="+", help="specify a test")
+
+ return parser.parse_args()
+
+if __name__ == "__main__":
+ args = _get_args()
+ if args.bridge == "uart":
+ from litescope.host.driver.uart import LiteScopeUARTDriver
+ wb = LiteScopeUARTDriver(args.port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
+ elif args.bridge == "etherbone":
+ from litescope.host.driver.etherbone import LiteScopeEtherboneDriver
+ wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False)
+ else:
+ ValueError("Invalid bridge {}".format(args.bridge))
+
+ def _import(name):
+ return importlib.import_module(name)
+
+ for test in args.test:
+ t = _import("test_"+test)
+ t.main(wb)
--- /dev/null
+import socket, time
+from liteeth.test.model.etherbone import *
+
+SRAM_BASE = 0x02000000
+
+import socket
+
+def main(wb):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+ # test probe
+ packet = EtherbonePacket()
+ packet.pf = 1
+ packet.encode()
+ sock.sendto(bytes(packet), ("192.168.1.40", 20000))
+ time.sleep(0.01)
+
+ # test writes
+ writes_datas = [j for j in range(16)]
+ writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas)
+ record = EtherboneRecord()
+ record.writes = writes
+ record.reads = None
+ record.bca = 0
+ record.rca = 0
+ record.rff = 0
+ record.cyc = 0
+ record.wca = 0
+ record.wff = 0
+ record.byte_enable = 0xf
+ record.wcount = len(writes_datas)
+ record.rcount = 0
+
+ packet = EtherbonePacket()
+ packet.records = [record]
+ packet.encode()
+ sock.sendto(bytes(packet), ("192.168.1.40", 20000))
+ time.sleep(0.01)
+
+ # test reads
+ reads_addrs = [SRAM_BASE+4*j for j in range(16)]
+ reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
+ record = EtherboneRecord()
+ record.writes = None
+ record.reads = reads
+ record.bca = 0
+ record.rca = 0
+ record.rff = 0
+ record.cyc = 0
+ record.wca = 0
+ record.wff = 0
+ record.byte_enable = 0xf
+ record.wcount = 0
+ record.rcount = len(reads_addrs)
+
+ packet = EtherbonePacket()
+ packet.records = [record]
+ packet.encode()
+ sock.sendto(bytes(packet), ("192.168.1.40", 20000))
+ time.sleep(0.01)
--- /dev/null
+import time
+from litescope.host.driver.la import LiteScopeLADriver
+
+def main(wb):
+ la = LiteScopeLADriver(wb.regs, "la", debug=True)
+
+ wb.open()
+ regs = wb.regs
+ ###
+
+ conditions = {}
+ la.configure_term(port=0, cond=conditions)
+ la.configure_sum("term")
+ # Run Logic Analyzer
+ la.run(offset=2048, length=4000)
+
+ while not la.done():
+ pass
+
+ la.upload()
+ la.save("dump.vcd")
+
+ ###
+ wb.close()
--- /dev/null
+def main(wb):
+ wb.open()
+ regs = wb.regs
+ ###
+ print("sysid : 0x%04x" %regs.identifier_sysid.read())
+ print("revision : 0x%04x" %regs.identifier_revision.read())
+ print("frequency : %d MHz" %(regs.identifier_frequency.read()/1000000))
+ SRAM_BASE = 0x02000000
+ wb.write(SRAM_BASE, [i for i in range(64)])
+ print(wb.read(SRAM_BASE, 64))
+ ###
+ wb.close()
--- /dev/null
+import socket
+import threading
+
+def test(fpga_ip, udp_port, test_message):
+ tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock.bind(("", udp_port))
+ rx_sock.settimeout(0.5)
+
+ def receive():
+ while True:
+ try:
+ msg = rx_sock.recv(8192)
+ for byte in msg:
+ print(chr(byte), end="")
+ except:
+ break
+
+ def send():
+ tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port))
+
+ receive_thread = threading.Thread(target=receive)
+ receive_thread.start()
+
+ send_thread = threading.Thread(target=send)
+ send_thread.start()
+
+ try:
+ send_thread.join(5)
+ send_thread.join(5)
+ except KeyboardInterrupt:
+ pass
+
+def main(wb):
+ test_message = "LiteEth virtual TTY Hello world\n"
+ test("192.168.1.40", 10000, test_message)
--- /dev/null
+import socket
+import time
+import threading
+import copy
+
+KB = 1024
+MB = 1024*KB
+GB = 1024*MB
+
+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 generate_packet(seed, length):
+ r = []
+ for i in range(length):
+ r.append(seed_to_data(seed, True)%0xff) # XXX FIXME
+ seed += 1
+ return r, seed
+
+def test(fpga_ip, udp_port, test_size):
+ tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock.bind(("", udp_port))
+
+ def receive():
+ rx_seed = 0
+ while rx_seed < test_size:
+ data, addr = rx_sock.recvfrom(8192)
+ rx_packet = []
+ for byte in data:
+ rx_packet.append(int(byte))
+ rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024)
+ s, l, e = check(rx_reference_packet, rx_packet)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+
+ def send():
+ tx_seed = 0
+ while tx_seed < test_size:
+ tx_packet, tx_seed = generate_packet(tx_seed, 1024)
+ tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port))
+ time.sleep(0.001) # XXX: FIXME, Python limitation?
+
+ receive_thread = threading.Thread(target=receive)
+ receive_thread.start()
+
+ send_thread = threading.Thread(target=send)
+ send_thread.start()
+
+ try:
+ send_thread.join(10)
+ receive_thread.join(0.1)
+ except KeyboardInterrupt:
+ pass
+
+def main(wb):
+ test("192.168.1.40", 6000, 128*KB)
+ test("192.168.1.40", 8000, 128*KB)
--- /dev/null
+#!/usr/bin/env python3
+
+import sys, os
+from setuptools import setup
+from setuptools import find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+README = open(os.path.join(here, "README")).read()
+
+required_version = (3, 3)
+if sys.version_info < required_version:
+ raise SystemExit("LiteEth requires python {0} or greater".format(
+ ".".join(map(str, required_version))))
+
+setup(
+ name="liteeth",
+ version="unknown",
+ 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/liteeth",
+ packages=find_packages(here),
+ license="GPL",
+ platforms=["Any"],
+ keywords="HDL ASIC FPGA hardware design",
+ classifiers=[
+ "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
+ "Environment :: Console",
+ "Development Status :: Alpha",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: GNU General Public License (GPL)",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ ],
+)
+++ /dev/null
-#!/usr/bin/env python3
-
-import sys, os, argparse, subprocess, struct, importlib
-
-from mibuild.tools import write_to_file
-from migen.util.misc import autotype
-from migen.fhdl import verilog, edif
-from migen.fhdl.structure import _Fragment
-from migen.bank.description import CSRStatus
-from mibuild import tools
-from mibuild.xilinx_common import *
-
-from liteeth.common import *
-
-def get_csr_csv(regions):
- r = ""
- for name, origin, busword, obj in regions:
- if not isinstance(obj, Memory):
- for csr in obj:
- nr = (csr.size + busword - 1)//busword
- r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
- origin += 4*nr
- return r
-
-def _import(default, name):
- return importlib.import_module(default + "." + name)
-
-def _get_args():
- parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
- description="""\
-LiteEth - based on Migen.
-
-This program builds and/or loads LiteEth components.
-One or several actions can be specified:
-
-clean delete previous build(s).
-build-rtl build verilog rtl.
-build-bitstream build-bitstream build FPGA bitstream.
-build-csr-csv save CSR map into CSV file.
-
-load-bitstream load bitstream into volatile storage.
-
-all clean, build-csr-csv, build-bitstream, load-bitstream.
-""")
-
- parser.add_argument("-t", "--target", default="base", help="Core type to build")
- parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build")
- parser.add_argument("-p", "--platform", default=None, help="platform to build for")
- parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option")
- parser.add_argument("-Op", "--platform-option", default=[("programmer", "vivado")], nargs=2, action="append", help="set platform-specific option")
- parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into")
-
- parser.add_argument("action", nargs="+", help="specify an action")
-
- return parser.parse_args()
-
-# Note: misoclib need to be installed as a python library
-
-if __name__ == "__main__":
- args = _get_args()
-
- # create top-level Core object
- target_module = _import("targets", args.target)
- if args.sub_target:
- top_class = getattr(target_module, args.sub_target)
- else:
- top_class = target_module.default_subtarget
-
- if args.platform is None:
- platform_name = top_class.default_platform
- else:
- platform_name = args.platform
- platform_module = _import("platforms", platform_name)
- platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option)
- platform = platform_module.Platform(**platform_kwargs)
-
- build_name = top_class.__name__.lower() + "-" + platform_name
- top_kwargs = dict((k, autotype(v)) for k, v in args.target_option)
- soc = top_class(platform, **top_kwargs)
- soc.finalize()
-
- # decode actions
- action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"]
- actions = {k: False for k in action_list}
- for action in args.action:
- if action in actions:
- actions[action] = True
- else:
- print("Unknown action: "+action+". Valid actions are:")
- for a in action_list:
- print(" "+a)
- sys.exit(1)
-
- print("""
- __ _ __ ______ __
- / / (_) /____ / __/ /_/ /
- / /__/ / __/ -_) _// __/ _ \\
- /____/_/\__/\__/___/\__/_//_/
-
- A small footprint and configurable Ethernet
- core powered by Migen
-====== Building options: ======
-Platform: {}
-Target: {}
-Subtarget: {}
-System Clk: {} MHz
-===============================""".format(
- platform_name,
- args.target,
- top_class.__name__,
- soc.clk_freq/1000000
- )
-)
-
- # dependencies
- if actions["all"]:
- actions["build-csr-csv"] = True
- actions["build-bitstream"] = True
- actions["load-bitstream"] = True
-
- if actions["build-bitstream"]:
- actions["build-csr-csv"] = True
- actions["build-bitstream"] = True
- actions["load-bitstream"] = True
-
- if actions["clean"]:
- subprocess.call(["rm", "-rf", "build/*"])
-
- if actions["build-csr-csv"]:
- csr_csv = get_csr_csv(soc.cpu_csr_regions)
- write_to_file(args.csr_csv, csr_csv)
-
- if actions["build-bitstream"]:
- vns = platform.build(soc, build_name=build_name)
- if hasattr(soc, "do_exit") and vns is not None:
- if hasattr(soc.do_exit, '__call__'):
- soc.do_exit(vns)
-
- if actions["load-bitstream"]:
- prog = platform.create_programmer()
- prog.load_bitstream("build/" + build_name + platform.bitstream_ext)
+++ /dev/null
-from mibuild.generic_platform import *
-from mibuild.crg import SimpleCRG
-from mibuild.xilinx_common import CRG_DS
-from mibuild.xilinx_ise import XilinxISEPlatform
-from mibuild.xilinx_vivado import XilinxVivadoPlatform
-from mibuild.programmer import *
-
-def _run_vivado(cmds):
- with subprocess.Popen("vivado -mode tcl", stdin=subprocess.PIPE, shell=True) as process:
- process.stdin.write(cmds.encode("ASCII"))
- process.communicate()
-
-class VivadoProgrammer(Programmer):
- needs_bitreverse = False
-
- def load_bitstream(self, bitstream_file):
- cmds = """open_hw
-connect_hw_server
-open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost]] 0]
-
-set_property PROBES.FILE {{}} [lindex [get_hw_devices] 0]
-set_property PROGRAM.FILE {{{bitstream}}} [lindex [get_hw_devices] 0]
-
-program_hw_devices [lindex [get_hw_devices] 0]
-refresh_hw_device [lindex [get_hw_devices] 0]
-
-quit
-""".format(bitstream=bitstream_file)
- _run_vivado(cmds)
-
- def flash(self, address, data_file):
- raise NotImplementedError
-
-_io = [
- ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")),
- ("user_led", 1, Pins("AA8"), IOStandard("LVCMOS15")),
- ("user_led", 2, Pins("AC9"), IOStandard("LVCMOS15")),
- ("user_led", 3, Pins("AB9"), IOStandard("LVCMOS15")),
- ("user_led", 4, Pins("AE26"), IOStandard("LVCMOS25")),
- ("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")),
- ("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")),
- ("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")),
-
- ("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")),
-
- ("clk200", 0,
- Subsignal("p", Pins("AD12"), IOStandard("LVDS")),
- Subsignal("n", Pins("AD11"), IOStandard("LVDS"))
- ),
-
- ("clk156", 0,
- Subsignal("p", Pins("K28"), IOStandard("LVDS_25")),
- Subsignal("n", Pins("K29"), IOStandard("LVDS_25"))
- ),
-
-
- ("serial", 0,
- Subsignal("cts", Pins("L27")),
- Subsignal("rts", Pins("K23")),
- Subsignal("tx", Pins("K24")),
- Subsignal("rx", Pins("M19")),
- IOStandard("LVCMOS25")
- ),
-
- ("eth_clocks", 0,
- Subsignal("tx", Pins("M28")),
- Subsignal("gtx", Pins("K30")),
- Subsignal("rx", Pins("U27")),
- IOStandard("LVCMOS25")
- ),
- ("eth", 0,
- Subsignal("rst_n", Pins("L20")),
- Subsignal("int_n", Pins("N30")),
- Subsignal("mdio", Pins("J21")),
- Subsignal("mdc", Pins("R23")),
- Subsignal("dv", Pins("R28")),
- Subsignal("rx_er", Pins("V26")),
- Subsignal("rx_data", Pins("U30 U25 T25 U28 R19 T27 T26 T28")),
- Subsignal("tx_en", Pins("M27")),
- Subsignal("tx_er", Pins("N29")),
- Subsignal("tx_data", Pins("N27 N25 M29 L28 J26 K26 L30 J28")),
- Subsignal("col", Pins("W19")),
- Subsignal("crs", Pins("R30")),
- IOStandard("LVCMOS25")
- ),
-
-]
-
-def Platform(*args, toolchain="vivado", programmer="xc3sprog", **kwargs):
- if toolchain == "ise":
- xilinx_platform = XilinxISEPlatform
- elif toolchain == "vivado":
- xilinx_platform = XilinxVivadoPlatform
- else:
- raise ValueError
-
- class RealPlatform(xilinx_platform):
- bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w -g ConfigRate:12 -g SPI_buswidth:4"
-
- def __init__(self, crg_factory=lambda p: CRG_DS(p, "clk200", "cpu_reset")):
- xilinx_platform.__init__(self, "xc7k325t-ffg900-2", _io, crg_factory)
-
- def create_programmer(self):
- if programmer == "xc3sprog":
- return XC3SProg("jtaghs1_fast", "bscan_spi_kc705.bit")
- elif programmer == "vivado":
- return VivadoProgrammer()
- else:
- raise ValueError
-
- def do_finalize(self, fragment):
- try:
- self.add_period_constraint(self.lookup_request("clk156").p, 6.4)
- except ConstraintError:
- pass
- try:
- self.add_period_constraint(self.lookup_request("clk200").p, 5.0)
- except ConstraintError:
- pass
- try:
- self.add_period_constraint(self.lookup_request("eth_clocks").rx, 8.0)
- except ConstraintError:
- pass
- self.add_platform_command("""
-create_clock -name sys_clk -period 6 [get_nets sys_clk]
-create_clock -name eth_rx_clk -period 8 [get_nets eth_rx_clk]
-create_clock -name eth_tx_clk -period 8 [get_nets eth_tx_clk]
-
-set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_rx_clk]
-set_false_path -from [get_clocks sys_clk] -to [get_clocks eth_tx_clk]
-set_false_path -from [get_clocks eth_rx_clk] -to [get_clocks sys_clk]
-set_false_path -from [get_clocks eth_tx_clk] -to [get_clocks sys_clk]
-
-set_property CFGBVS VCCO [current_design]
-set_property CONFIG_VOLTAGE 2.5 [current_design]
-""")
-
- return RealPlatform(*args, **kwargs)
+++ /dev/null
-#!/usr/bin/env python3
-
-import sys, os
-from setuptools import setup
-from setuptools import find_packages
-
-here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, "README")).read()
-
-required_version = (3, 3)
-if sys.version_info < required_version:
- raise SystemExit("LiteEth requires python {0} or greater".format(
- ".".join(map(str, required_version))))
-
-setup(
- name="liteeth",
- version="unknown",
- 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/liteeth",
- packages=find_packages(here),
- license="GPL",
- platforms=["Any"],
- keywords="HDL ASIC FPGA hardware design",
- classifiers=[
- "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
- "Environment :: Console",
- "Development Status :: Alpha",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: GNU General Public License (GPL)",
- "Operating System :: OS Independent",
- "Programming Language :: Python",
- ],
-)
+++ /dev/null
-import subprocess
-
-from migen.fhdl.std import *
-from migen.bank.description import *
-
-def get_id():
- output = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii")
- return int(output[:8], 16)
-
-class Identifier(Module, AutoCSR):
- def __init__(self, sysid, frequency, revision=None):
- self._r_sysid = CSRStatus(16)
- self._r_revision = CSRStatus(32)
- self._r_frequency = CSRStatus(32)
-
- ###
-
- if revision is None:
- revision = get_id()
-
- self.comb += [
- self._r_sysid.status.eq(sysid),
- self._r_revision.status.eq(revision),
- self._r_frequency.status.eq(frequency),
- ]
-
+++ /dev/null
-import os
-
-from migen.bank import csrgen
-from migen.bus import wishbone, csr
-from migen.bus import wishbone2csr
-from migen.genlib.cdc import *
-from migen.genlib.resetsync import AsyncResetSynchronizer
-from migen.bank.description import *
-
-from targets import *
-
-from litescope.common import *
-from litescope.bridge.uart2wb import LiteScopeUART2WB
-from litescope.frontend.la import LiteScopeLA
-from litescope.core.port import LiteScopeTerm
-
-from liteeth.common import *
-from liteeth.generic import *
-from liteeth.phy.gmii import LiteEthPHYGMII
-from liteeth.core import LiteEthUDPIPCore
-
-class _CRG(Module):
- def __init__(self, platform):
- self.clock_domains.cd_sys = ClockDomain()
- self.reset = Signal()
-
- clk200 = platform.request("clk200")
- clk200_se = Signal()
- self.specials += Instance("IBUFDS", i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se)
-
- pll_locked = Signal()
- pll_fb = Signal()
- pll_sys = Signal()
- self.specials += [
- Instance("PLLE2_BASE",
- p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
-
- # VCO @ 1GHz
- p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0,
- p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1,
- i_CLKIN1=clk200_se, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,
-
- # 166MHz
- p_CLKOUT0_DIVIDE=6, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys,
-
- p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, #o_CLKOUT1=,
-
- p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=,
-
- p_CLKOUT3_DIVIDE=2, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=,
-
- p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4=
- ),
- Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
- AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset),
- ]
-
-class GenSoC(Module):
- csr_base = 0x00000000
- csr_data_width = 32
- csr_map = {
- "bridge": 0,
- "identifier": 1,
- }
- interrupt_map = {}
- cpu_type = None
- def __init__(self, platform, clk_freq):
- self.clk_freq = clk_freq
- # UART <--> Wishbone bridge
- self.submodules.bridge = LiteScopeUART2WB(platform.request("serial"), clk_freq, baud=921600)
-
- # CSR bridge 0x00000000 (shadow @0x00000000)
- self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(self.csr_data_width))
- self._wb_masters = [self.bridge.wishbone]
- self._wb_slaves = [(lambda a: a[23:25] == 0, self.wishbone2csr.wishbone)]
- self.cpu_csr_regions = [] # list of (name, origin, busword, csr_list/Memory)
-
- # CSR
- self.submodules.identifier = Identifier(0, int(clk_freq), 0)
-
- def add_wb_master(self, wbm):
- if self.finalized:
- raise FinalizeError
- self._wb_masters.append(wbm)
-
- def add_wb_slave(self, address_decoder, interface):
- if self.finalized:
- raise FinalizeError
- self._wb_slaves.append((address_decoder, interface))
-
- def add_cpu_memory_region(self, name, origin, length):
- self.cpu_memory_regions.append((name, origin, length))
-
- def add_cpu_csr_region(self, name, origin, busword, obj):
- self.cpu_csr_regions.append((name, origin, busword, obj))
-
- def do_finalize(self):
- # Wishbone
- self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
- self._wb_slaves, register=True)
-
- # CSR
- self.submodules.csrbankarray = csrgen.BankArray(self,
- lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override],
- data_width=self.csr_data_width)
- self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses())
- for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
- self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), csrs)
- for name, memory, mapaddr, mmap in self.csrbankarray.srams:
- self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), memory)
-
-class BaseSoC(GenSoC, AutoCSR):
- default_platform = "kc705"
- csr_map = {
- "phy": 11,
- "core": 12
- }
- csr_map.update(GenSoC.csr_map)
- def __init__(self, platform, clk_freq=166*1000000,
- mac_address=0x10e2d5000000,
- ip_address="192.168.1.40"):
- GenSoC.__init__(self, platform, clk_freq)
- self.submodules.crg = _CRG(platform)
-
- # wishbone SRAM (to test Wishbone over UART and Etherbone)
- self.submodules.sram = wishbone.SRAM(1024)
- self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus)
-
- # ethernet PHY and UDP/IP stack
- self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth"))
- self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq)
-
-class BaseSoCDevel(BaseSoC, AutoCSR):
- csr_map = {
- "la": 20
- }
- csr_map.update(BaseSoC.csr_map)
- def __init__(self, platform):
- BaseSoC.__init__(self, platform)
-
- self.core_icmp_rx_fsm_state = Signal(4)
- self.core_icmp_tx_fsm_state = Signal(4)
- self.core_udp_rx_fsm_state = Signal(4)
- self.core_udp_tx_fsm_state = Signal(4)
- self.core_ip_rx_fsm_state = Signal(4)
- self.core_ip_tx_fsm_state = Signal(4)
- self.core_arp_rx_fsm_state = Signal(4)
- self.core_arp_tx_fsm_state = Signal(4)
- self.core_arp_table_fsm_state = Signal(4)
-
- debug = (
- # MAC interface
- self.core.mac.core.sink.stb,
- self.core.mac.core.sink.sop,
- self.core.mac.core.sink.eop,
- self.core.mac.core.sink.ack,
- self.core.mac.core.sink.data,
-
- self.core.mac.core.source.stb,
- self.core.mac.core.source.sop,
- self.core.mac.core.source.eop,
- self.core.mac.core.source.ack,
- self.core.mac.core.source.data,
-
- # ICMP interface
- self.core.icmp.echo.sink.stb,
- self.core.icmp.echo.sink.sop,
- self.core.icmp.echo.sink.eop,
- self.core.icmp.echo.sink.ack,
- self.core.icmp.echo.sink.data,
-
- self.core.icmp.echo.source.stb,
- self.core.icmp.echo.source.sop,
- self.core.icmp.echo.source.eop,
- self.core.icmp.echo.source.ack,
- self.core.icmp.echo.source.data,
-
- # IP interface
- self.core.ip.crossbar.master.sink.stb,
- self.core.ip.crossbar.master.sink.sop,
- self.core.ip.crossbar.master.sink.eop,
- self.core.ip.crossbar.master.sink.ack,
- self.core.ip.crossbar.master.sink.data,
- self.core.ip.crossbar.master.sink.ip_address,
- self.core.ip.crossbar.master.sink.protocol,
-
- # State machines
- self.core_icmp_rx_fsm_state,
- self.core_icmp_tx_fsm_state,
-
- self.core_arp_rx_fsm_state,
- self.core_arp_tx_fsm_state,
- self.core_arp_table_fsm_state,
-
- self.core_ip_rx_fsm_state,
- self.core_ip_tx_fsm_state,
-
- self.core_udp_rx_fsm_state,
- self.core_udp_tx_fsm_state
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
-
- def do_finalize(self):
- BaseSoC.do_finalize(self)
- self.comb += [
- self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state),
- self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state),
-
- self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state),
- self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state),
- self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state),
-
- self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state),
- self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state),
-
- self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state),
- self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state)
- ]
-
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
-
-default_subtarget = BaseSoC
+++ /dev/null
-from litescope.common import *
-from litescope.frontend.la import LiteScopeLA
-from litescope.core.port import LiteScopeTerm
-
-from liteeth.common import *
-from liteeth.generic import *
-
-from targets.base import BaseSoC
-from liteeth.core.etherbone import LiteEthEtherbone
-
-class EtherboneSoC(BaseSoC):
- default_platform = "kc705"
- def __init__(self, platform):
- BaseSoC.__init__(self, platform,
- mac_address=0x10e2d5000000,
- ip_address="192.168.1.40")
- self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000)
- self.add_wb_master(self.etherbone.master.bus)
-
-class EtherboneSoCDevel(EtherboneSoC):
- csr_map = {
- "la": 20
- }
- csr_map.update(EtherboneSoC.csr_map)
- def __init__(self, platform):
- EtherboneSoC.__init__(self, platform)
- debug = (
- # mmap stream from HOST
- self.etherbone.master.sink.stb,
- self.etherbone.master.sink.sop,
- self.etherbone.master.sink.eop,
- self.etherbone.master.sink.ack,
- self.etherbone.master.sink.we,
- self.etherbone.master.sink.count,
- self.etherbone.master.sink.base_addr,
- self.etherbone.master.sink.be,
- self.etherbone.master.sink.addr,
- self.etherbone.master.sink.data,
-
- # mmap stream to HOST
- self.etherbone.master.source.stb,
- self.etherbone.master.source.sop,
- self.etherbone.master.source.eop,
- self.etherbone.master.source.ack,
- self.etherbone.master.source.we,
- self.etherbone.master.source.count,
- self.etherbone.master.source.base_addr,
- self.etherbone.master.source.be,
- self.etherbone.master.source.addr,
- self.etherbone.master.source.data,
-
- # etherbone wishbone master
- self.etherbone.master.bus.dat_w,
- self.etherbone.master.bus.dat_r,
- self.etherbone.master.bus.adr,
- self.etherbone.master.bus.sel,
- self.etherbone.master.bus.cyc,
- self.etherbone.master.bus.stb,
- self.etherbone.master.bus.ack,
- self.etherbone.master.bus.we,
- self.etherbone.master.bus.cti,
- self.etherbone.master.bus.bte,
- self.etherbone.master.bus.err
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
-
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
-
-default_subtarget = EtherboneSoC
+++ /dev/null
-from litescope.common import *
-from litescope.frontend.la import LiteScopeLA
-from litescope.core.port import LiteScopeTerm
-
-from liteeth.common import *
-from liteeth.generic import *
-
-from targets.base import BaseSoC
-from liteeth.core.tty import LiteEthTTY
-
-class TTYSoC(BaseSoC):
- default_platform = "kc705"
- def __init__(self, platform):
- BaseSoC.__init__(self, platform,
- mac_address=0x10e2d5000000,
- ip_address="192.168.1.40")
- self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.1.12"), 10000)
- self.comb += Record.connect(self.tty.source, self.tty.sink)
-
-class TTYSoCDevel(TTYSoC):
- csr_map = {
- "la": 20
- }
- csr_map.update(TTYSoC.csr_map)
- def __init__(self, platform):
- TTYSoC.__init__(self, platform)
- debug = (
- self.tty.sink.stb,
- self.tty.sink.ack,
- self.tty.sink.data,
-
- self.tty.source.stb,
- self.tty.source.ack,
- self.tty.source.data
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
-
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
-
-default_subtarget = TTYSoC
+++ /dev/null
-from litescope.common import *
-from litescope.frontend.la import LiteScopeLA
-from litescope.core.port import LiteScopeTerm
-
-from liteeth.common import *
-from liteeth.generic import *
-
-from targets.base import BaseSoC
-
-class UDPSoC(BaseSoC):
- default_platform = "kc705"
- def __init__(self, platform):
- BaseSoC.__init__(self, platform,
- mac_address=0x10e2d5000000,
- ip_address="192.168.1.40")
-
- # add udp loopback on port 6000 with dw=8
- self.add_udp_loopback(6000, 8, 8192, "loopback_8")
- # add udp loopback on port 8000 with dw=32
- self.add_udp_loopback(8000, 32, 8192, "loopback_32")
-
- def add_udp_loopback(self, port, dw, depth, name=None):
- port = self.core.udp.crossbar.get_port(port, dw)
- buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8)
- if name is None:
- self.submodules += buf
- else:
- setattr(self.submodules, name, buf)
- self.comb += Port.connect(port, buf)
-
-class UDPSoCDevel(UDPSoC):
- csr_map = {
- "la": 20
- }
- csr_map.update(UDPSoC.csr_map)
- def __init__(self, platform):
- UDPSoC.__init__(self, platform)
- debug = (
- self.loopback_8.sink.stb,
- self.loopback_8.sink.sop,
- self.loopback_8.sink.eop,
- self.loopback_8.sink.ack,
- self.loopback_8.sink.data,
-
- self.loopback_8.source.stb,
- self.loopback_8.source.sop,
- self.loopback_8.source.eop,
- self.loopback_8.source.ack,
- self.loopback_8.source.data,
-
- self.loopback_32.sink.stb,
- self.loopback_32.sink.sop,
- self.loopback_32.sink.eop,
- self.loopback_32.sink.ack,
- self.loopback_32.sink.data,
-
- self.loopback_32.source.stb,
- self.loopback_32.source.sop,
- self.loopback_32.source.eop,
- self.loopback_32.source.ack,
- self.loopback_32.source.data
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
-
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
-
-default_subtarget = UDPSoC
+++ /dev/null
-#!/usr/bin/env python3
-import argparse, importlib
-
-def _get_args():
- parser = argparse.ArgumentParser()
- parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use")
- parser.add_argument("--port", default=2, help="UART port")
- parser.add_argument("--baudrate", default=921600, help="UART baudrate")
- parser.add_argument("--ip_address", default="192.168.1.40", help="Etherbone IP address")
- parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port")
- parser.add_argument("--busword", default=32, help="CSR busword")
-
- parser.add_argument("test", nargs="+", help="specify a test")
-
- return parser.parse_args()
-
-if __name__ == "__main__":
- args = _get_args()
- if args.bridge == "uart":
- from litescope.host.driver.uart import LiteScopeUARTDriver
- wb = LiteScopeUARTDriver(args.port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
- elif args.bridge == "etherbone":
- from litescope.host.driver.etherbone import LiteScopeEtherboneDriver
- wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False)
- else:
- ValueError("Invalid bridge {}".format(args.bridge))
-
- def _import(name):
- return importlib.import_module(name)
-
- for test in args.test:
- t = _import("test_"+test)
- t.main(wb)
+++ /dev/null
-import socket, time
-from liteeth.test.model.etherbone import *
-
-SRAM_BASE = 0x02000000
-
-import socket
-
-def main(wb):
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
- # test probe
- packet = EtherbonePacket()
- packet.pf = 1
- packet.encode()
- sock.sendto(bytes(packet), ("192.168.1.40", 20000))
- time.sleep(0.01)
-
- # test writes
- writes_datas = [j for j in range(16)]
- writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas)
- record = EtherboneRecord()
- record.writes = writes
- record.reads = None
- record.bca = 0
- record.rca = 0
- record.rff = 0
- record.cyc = 0
- record.wca = 0
- record.wff = 0
- record.byte_enable = 0xf
- record.wcount = len(writes_datas)
- record.rcount = 0
-
- packet = EtherbonePacket()
- packet.records = [record]
- packet.encode()
- sock.sendto(bytes(packet), ("192.168.1.40", 20000))
- time.sleep(0.01)
-
- # test reads
- reads_addrs = [SRAM_BASE+4*j for j in range(16)]
- reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
- record = EtherboneRecord()
- record.writes = None
- record.reads = reads
- record.bca = 0
- record.rca = 0
- record.rff = 0
- record.cyc = 0
- record.wca = 0
- record.wff = 0
- record.byte_enable = 0xf
- record.wcount = 0
- record.rcount = len(reads_addrs)
-
- packet = EtherbonePacket()
- packet.records = [record]
- packet.encode()
- sock.sendto(bytes(packet), ("192.168.1.40", 20000))
- time.sleep(0.01)
+++ /dev/null
-import time
-from litescope.host.driver.la import LiteScopeLADriver
-
-def main(wb):
- la = LiteScopeLADriver(wb.regs, "la", debug=True)
-
- wb.open()
- regs = wb.regs
- ###
-
- conditions = {}
- la.configure_term(port=0, cond=conditions)
- la.configure_sum("term")
- # Run Logic Analyzer
- la.run(offset=2048, length=4000)
-
- while not la.done():
- pass
-
- la.upload()
- la.save("dump.vcd")
-
- ###
- wb.close()
+++ /dev/null
-def main(wb):
- wb.open()
- regs = wb.regs
- ###
- print("sysid : 0x%04x" %regs.identifier_sysid.read())
- print("revision : 0x%04x" %regs.identifier_revision.read())
- print("frequency : %d MHz" %(regs.identifier_frequency.read()/1000000))
- SRAM_BASE = 0x02000000
- wb.write(SRAM_BASE, [i for i in range(64)])
- print(wb.read(SRAM_BASE, 64))
- ###
- wb.close()
+++ /dev/null
-import socket
-import threading
-
-def test(fpga_ip, udp_port, test_message):
- tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock.bind(("", udp_port))
- rx_sock.settimeout(0.5)
-
- def receive():
- while True:
- try:
- msg = rx_sock.recv(8192)
- for byte in msg:
- print(chr(byte), end="")
- except:
- break
-
- def send():
- tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port))
-
- receive_thread = threading.Thread(target=receive)
- receive_thread.start()
-
- send_thread = threading.Thread(target=send)
- send_thread.start()
-
- try:
- send_thread.join(5)
- send_thread.join(5)
- except KeyboardInterrupt:
- pass
-
-def main(wb):
- test_message = "LiteEth virtual TTY Hello world\n"
- test("192.168.1.40", 10000, test_message)
+++ /dev/null
-import socket
-import time
-import threading
-import copy
-
-KB = 1024
-MB = 1024*KB
-GB = 1024*MB
-
-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 generate_packet(seed, length):
- r = []
- for i in range(length):
- r.append(seed_to_data(seed, True)%0xff) # XXX FIXME
- seed += 1
- return r, seed
-
-def test(fpga_ip, udp_port, test_size):
- tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock.bind(("", udp_port))
-
- def receive():
- rx_seed = 0
- while rx_seed < test_size:
- data, addr = rx_sock.recvfrom(8192)
- rx_packet = []
- for byte in data:
- rx_packet.append(int(byte))
- rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024)
- s, l, e = check(rx_reference_packet, rx_packet)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
- def send():
- tx_seed = 0
- while tx_seed < test_size:
- tx_packet, tx_seed = generate_packet(tx_seed, 1024)
- tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port))
- time.sleep(0.001) # XXX: FIXME, Python limitation?
-
- receive_thread = threading.Thread(target=receive)
- receive_thread.start()
-
- send_thread = threading.Thread(target=send)
- send_thread.start()
-
- try:
- send_thread.join(10)
- receive_thread.join(0.1)
- except KeyboardInterrupt:
- pass
-
-def main(wb):
- test("192.168.1.40", 6000, 128*KB)
- test("192.168.1.40", 8000, 128*KB)