Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6db831e5a830
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0267868cbe87
Choose a head ref

Commits on Jan 27, 2015

  1. init repo

    enjoy-digital committed Jan 27, 2015
    Copy the full SHA
    a160b04 View commit details
  2. Copy the full SHA
    46c4841 View commit details
  3. Copy the full SHA
    0826811 View commit details
  4. start code adaptation

    enjoy-digital committed Jan 27, 2015
    Copy the full SHA
    8477974 View commit details

Commits on Jan 28, 2015

  1. Copy the full SHA
    4cd73fc View commit details
  2. Copy the full SHA
    8a2b65f View commit details
  3. Copy the full SHA
    0953752 View commit details
  4. Copy the full SHA
    e42fdb4 View commit details
  5. setup.py: fix

    enjoy-digital committed Jan 28, 2015
    Copy the full SHA
    8a42d74 View commit details
  6. Copy the full SHA
    33edf11 View commit details
  7. test: mac_core_tb OK

    enjoy-digital committed Jan 28, 2015
    Copy the full SHA
    fb00202 View commit details
  8. Copy the full SHA
    44113d7 View commit details
  9. Copy the full SHA
    ddf0579 View commit details
  10. Copy the full SHA
    98b8234 View commit details
  11. Copy the full SHA
    6249209 View commit details
  12. Copy the full SHA
    dc5e1aa View commit details
  13. Copy the full SHA
    5b37068 View commit details

Commits on Jan 29, 2015

  1. Copy the full SHA
    51c9f84 View commit details
  2. Copy the full SHA
    cb9ec51 View commit details
  3. Copy the full SHA
    96b08a0 View commit details
  4. model: add arp skeleton

    enjoy-digital committed Jan 29, 2015
    Copy the full SHA
    dcbfdca View commit details
  5. arp: add skeleton

    enjoy-digital committed Jan 29, 2015
    Copy the full SHA
    8d9357d View commit details
  6. Copy the full SHA
    08e83af View commit details
  7. Copy the full SHA
    18a7d66 View commit details

Commits on Jan 30, 2015

  1. arp: rx and decoding OK

    enjoy-digital committed Jan 30, 2015
    Copy the full SHA
    a7d4427 View commit details
  2. Copy the full SHA
    fa48346 View commit details
  3. arp: little clean up

    enjoy-digital committed Jan 30, 2015
    Copy the full SHA
    41ead49 View commit details
  4. ip: add skeleton

    enjoy-digital committed Jan 30, 2015
    Copy the full SHA
    1d447f2 View commit details
  5. Copy the full SHA
    124a041 View commit details
  6. Copy the full SHA
    d066497 View commit details
  7. add ip model skeleton

    enjoy-digital committed Jan 30, 2015
    Copy the full SHA
    328295c View commit details
  8. use ip model in ip_tb

    enjoy-digital committed Jan 30, 2015
    Copy the full SHA
    1c2030d View commit details
  9. Copy the full SHA
    6e966be View commit details
  10. clean up

    enjoy-digital committed Jan 30, 2015
    Copy the full SHA
    d7c7fd3 View commit details

Commits on Feb 4, 2015

  1. ip: small clean up

    enjoy-digital committed Feb 4, 2015
    Copy the full SHA
    df2f283 View commit details
  2. Copy the full SHA
    99323b4 View commit details
  3. Copy the full SHA
    34dad82 View commit details
  4. Copy the full SHA
    97daf9b View commit details
  5. reorganize core files

    enjoy-digital committed Feb 4, 2015
    Copy the full SHA
    957c162 View commit details
  6. udp: add model

    enjoy-digital committed Feb 4, 2015
    Copy the full SHA
    7a4713b View commit details
  7. udp: add skeleton

    enjoy-digital committed Feb 4, 2015
    Copy the full SHA
    90abd19 View commit details
  8. add udpip_tb skeleton

    enjoy-digital committed Feb 4, 2015
    Copy the full SHA
    4e5bd46 View commit details
  9. Copy the full SHA
    a9da9dc View commit details
  10. Copy the full SHA
    ca1e028 View commit details
  11. Copy the full SHA
    fa5ee3b View commit details

Commits on Feb 5, 2015

  1. Copy the full SHA
    afae3f0 View commit details
  2. Copy the full SHA
    b860e0b View commit details
  3. Copy the full SHA
    06a738f View commit details
  4. Copy the full SHA
    dbca377 View commit details
  5. Copy the full SHA
    8cf9883 View commit details
Showing with 10,220 additions and 8 deletions.
  1. +1 −0 .gitignore
  2. +0 −3 .gitmodules
  3. +0 −4 extcores/__init__.py
  4. +0 −1 extcores/litex
  5. +28 −0 misoclib/LICENSE
  6. +142 −0 misoclib/README
  7. +8 −0 misoclib/doc/.gitignore
  8. +157 −0 misoclib/doc/Makefile
  9. +220 −0 misoclib/doc/make.bat
  10. BIN misoclib/doc/source/_static/LiteEth_logo_full.png
  11. +246 −0 misoclib/doc/source/_static/LiteEth_logo_full.svg
  12. +17 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/__init__.py
  13. +11 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/breadcrumbs.html
  14. +100 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/footer.html
  15. +208 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/layout.html
  16. +205 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/layout_old.html
  17. +50 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/search.html
  18. +7 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/searchbox.html
  19. +1 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/css/badge_only.css
  20. +331 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/css/theme - prior to centering.css
  21. +512 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/css/theme.css
  22. BIN misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot
  23. +414 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg
  24. BIN misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf
  25. BIN misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff
  26. +47 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/static/js/theme.js
  27. +9 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/theme.conf
  28. +37 −0 misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/versions.html
  29. +402 −0 misoclib/doc/source/conf.py
  30. +7 −0 misoclib/doc/source/docs/core/index.rst
  31. +7 −0 misoclib/doc/source/docs/frontend/index.rst
  32. +7 −0 misoclib/doc/source/docs/getting_started/FAQ.rst
  33. +11 −0 misoclib/doc/source/docs/getting_started/bug_reports.rst
  34. +43 −0 misoclib/doc/source/docs/getting_started/downloads.rst
  35. +17 −0 misoclib/doc/source/docs/getting_started/index.rst
  36. +27 −0 misoclib/doc/source/docs/index.rst
  37. +59 −0 misoclib/doc/source/docs/intro/about.rst
  38. +5 −0 misoclib/doc/source/docs/intro/community.rst
  39. +15 −0 misoclib/doc/source/docs/intro/index.rst
  40. +47 −0 misoclib/doc/source/docs/intro/license.rst
  41. +13 −0 misoclib/doc/source/docs/intro/release_notes.rst
  42. +14 −0 misoclib/doc/source/docs/intro/talks_and_publications.rst
  43. +26 −0 misoclib/doc/source/home_page_layout.html
  44. +24 −0 misoclib/doc/source/index.rst
  45. +2 −0 misoclib/liteeth-version.txt
  46. 0 misoclib/liteeth/__init__.py
  47. +284 −0 misoclib/liteeth/common.py
  48. +19 −0 misoclib/liteeth/core/__init__.py
  49. +263 −0 misoclib/liteeth/core/arp/__init__.py
  50. +31 −0 misoclib/liteeth/core/etherbone/__init__.py
  51. +260 −0 misoclib/liteeth/core/etherbone/dissector/bit.lua
  52. +223 −0 misoclib/liteeth/core/etherbone/dissector/etherbone.lua
  53. +129 −0 misoclib/liteeth/core/etherbone/packet.py
  54. +24 −0 misoclib/liteeth/core/etherbone/probe.py
  55. +176 −0 misoclib/liteeth/core/etherbone/record.py
  56. +69 −0 misoclib/liteeth/core/etherbone/wishbone.py
  57. +138 −0 misoclib/liteeth/core/icmp/__init__.py
  58. +180 −0 misoclib/liteeth/core/ip/__init__.py
  59. +43 −0 misoclib/liteeth/core/ip/checksum.py
  60. +30 −0 misoclib/liteeth/core/ip/crossbar.py
  61. +97 −0 misoclib/liteeth/core/tty/__init__.py
  62. +125 −0 misoclib/liteeth/core/udp/__init__.py
  63. +47 −0 misoclib/liteeth/core/udp/crossbar.py
  64. +151 −0 misoclib/liteeth/generic/__init__.py
  65. +27 −0 misoclib/liteeth/generic/arbiter.py
  66. +31 −0 misoclib/liteeth/generic/crossbar.py
  67. +84 −0 misoclib/liteeth/generic/depacketizer.py
  68. +39 −0 misoclib/liteeth/generic/dispatcher.py
  69. +92 −0 misoclib/liteeth/generic/packetizer.py
  70. +33 −0 misoclib/liteeth/mac/__init__.py
  71. +46 −0 misoclib/liteeth/mac/common.py
  72. +83 −0 misoclib/liteeth/mac/core/__init__.py
  73. +277 −0 misoclib/liteeth/mac/core/crc.py
  74. +26 −0 misoclib/liteeth/mac/core/gap.py
  75. +38 −0 misoclib/liteeth/mac/core/last_be.py
  76. +47 −0 misoclib/liteeth/mac/core/padding.py
  77. +140 −0 misoclib/liteeth/mac/core/preamble.py
  78. 0 misoclib/liteeth/mac/frontend/__init__.py
  79. +254 −0 misoclib/liteeth/mac/frontend/sram.py
  80. +39 −0 misoclib/liteeth/mac/frontend/wishbone.py
  81. 0 misoclib/liteeth/phy/__init__.py
  82. +76 −0 misoclib/liteeth/phy/gmii.py
  83. +27 −0 misoclib/liteeth/phy/loopback.py
  84. +127 −0 misoclib/liteeth/phy/mii.py
  85. +43 −0 misoclib/liteeth/phy/sim.py
  86. +33 −0 misoclib/liteeth/test/Makefile
  87. 0 misoclib/liteeth/test/__init__.py
  88. +57 −0 misoclib/liteeth/test/arp_tb.py
  89. +162 −0 misoclib/liteeth/test/common.py
  90. +116 −0 misoclib/liteeth/test/etherbone_tb.py
  91. +58 −0 misoclib/liteeth/test/icmp_tb.py
  92. +59 −0 misoclib/liteeth/test/ip_tb.py
  93. +62 −0 misoclib/liteeth/test/mac_core_tb.py
  94. +145 −0 misoclib/liteeth/test/mac_wishbone_tb.py
  95. 0 misoclib/liteeth/test/model/__init__.py
  96. +152 −0 misoclib/liteeth/test/model/arp.py
  97. +90 −0 misoclib/liteeth/test/model/dumps.py
  98. +354 −0 misoclib/liteeth/test/model/etherbone.py
  99. +102 −0 misoclib/liteeth/test/model/icmp.py
  100. +148 −0 misoclib/liteeth/test/model/ip.py
  101. +150 −0 misoclib/liteeth/test/model/mac.py
  102. +56 −0 misoclib/liteeth/test/model/phy.py
  103. +117 −0 misoclib/liteeth/test/model/udp.py
  104. +70 −0 misoclib/liteeth/test/udp_tb.py
  105. +141 −0 misoclib/make.py
  106. +138 −0 misoclib/platforms/kc705.py
  107. +37 −0 misoclib/setup.py
  108. +26 −0 misoclib/targets/__init__.py
  109. +224 −0 misoclib/targets/base.py
  110. +71 −0 misoclib/targets/etherbone.py
  111. +42 −0 misoclib/targets/tty.py
  112. +69 −0 misoclib/targets/udp.py
  113. +33 −0 misoclib/test/make.py
  114. +60 −0 misoclib/test/test_etherbone.py
  115. +24 −0 misoclib/test/test_la.py
  116. +12 −0 misoclib/test/test_regs.py
  117. +36 −0 misoclib/test/test_tty.py
  118. +81 −0 misoclib/test/test_udp.py
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -11,3 +11,4 @@ tools/byteswap
software/include/generated/*.h
software/include/generated/*.ld
software/include/generated/*.mak
*.vcd
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -7,6 +7,3 @@
[submodule "software/compiler-rt"]
path = software/compiler-rt
url = http://llvm.org/git/compiler-rt.git
[submodule "extcores/litex"]
path = extcores/litex
url = https://github.com/enjoy-digital/litex
4 changes: 0 additions & 4 deletions extcores/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
import os, sys
sys.path.append(os.path.join("extcores", "litex", "litescope"))
sys.path.append(os.path.join("extcores", "litex", "liteeth"))
sys.path.append(os.path.join("extcores", "litex", "litesata"))
1 change: 0 additions & 1 deletion extcores/litex
Submodule litex deleted from 0dc0b6
28 changes: 28 additions & 0 deletions misoclib/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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.
142 changes: 142 additions & 0 deletions misoclib/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
__ _ __ ______ __
/ / (_) /____ / __/ /_/ /
/ /__/ / __/ -_) _// __/ _ \
/____/_/\__/\__/___/\__/_//_/

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
8 changes: 8 additions & 0 deletions misoclib/doc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.diff
*.pyc
*~
*.bc
*.md

# Ignore generated files
build/
157 changes: 157 additions & 0 deletions misoclib/doc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build

# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif

# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source

.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext

help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"

clean:
rm -rf $(BUILDDIR)/*

html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."

singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."

pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."

json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."

htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."

epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."

latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."

latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."

latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."

text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."

man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."

texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."

info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."

gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."

changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."

linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."

doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."

pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
220 changes: 220 additions & 0 deletions misoclib/doc/make.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
@ECHO OFF

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
set I18NSPHINXOPTS=%SPHINXOPTS% source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)

if "%1" == "" goto help

if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)

if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)


%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)

if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)

if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)

if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)

if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)

if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)

if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)

if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)

if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)

if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)

if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)

if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)

if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)

if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)

if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)

if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)

if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)

if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)

if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)

if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)

:end
Binary file added misoclib/doc/source/_static/LiteEth_logo_full.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
246 changes: 246 additions & 0 deletions misoclib/doc/source/_static/LiteEth_logo_full.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Sphinx ReadTheDocs theme.
From https://github.com/ryan-roemer/sphinx-bootstrap-theme.
"""
import os

VERSION = (0, 1, 6)

__version__ = ".".join(str(v) for v in VERSION)
__version_full__ = __version__


def get_html_theme_path():
"""Return list of HTML theme paths."""
cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
return cur_dir
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div role="navigation" aria-label="breadcrumbs navigation">

<div class="breadcrumb-box">
<a class="breadcrumb-box-item" href="{{ pathto(master_doc) }}">Home</a>
{% for doc in parents %}
<a class="breadcrumb-box-item" href="{{ doc.link|e }}">&raquo;&nbsp;{{ doc.title }}</a>
{% endfor %}
<div class="breadcrumb-box-item">&raquo;&nbsp;{{ title }}</div>
</div>

</div>
100 changes: 100 additions & 0 deletions misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/footer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<footer>
{% if next or prev %}
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
{% if next %}
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}"/>Next <span class="fa fa-arrow-circle-right"></span></a>
{% endif %}
{% if prev %}
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}"><span class="fa fa-arrow-circle-left"></span> Previous</a>
{% endif %}
</div>
{% endif %}


<!--begin hamishw addition -->



<!-- -->

<!--Footer important links
If no such page exists then nav item is not created. CSS defines which of the long or short version is
displayed. -->


{% set footer_links = [
('docs/getting_started/bug_reports', 'Report Bug', 'Report Bug'),
('docs/introducing_liteeth/license', 'Licensing', 'Licensing'),
('docs/contributing/contributing', 'Contributing', 'Contributing'),
('docs/introducing_liteeth/release_notes', 'Release notes', 'Release notes'),
('docs/introducing_liteeth/community', 'Help', 'Contact'),
] -%}

<div class="footer-nav-bar" style="">
<div class="footer-options">

{% for document, shorttext, longtext in footer_links %}
{%- if hasdoc(document) %}
<a class="footer-navlink-short" title="{{ shorttext }}" href="{{ pathto(document) }}">{{ shorttext }}</a><a class="footer-navlink-long" title="{{ longtext }}" href="{{ pathto(document) }}">{{ longtext }}</a>
{%- elif document | truncate(4, True, end='') == 'http' %}
<a class="footer-navlink-short external" href="{{ document }}">{{ shorttext }}</a><a class="footer-navlink-long external" href="{{ document }}">{{ longtext }}</a>
{%- else %}
{{ shorttext }}
{%- endif %}
{% endfor %}

</div>



</div>

<!-- {% include "breadcrumbs.html" %} -->

<!-- {% trans %}<a href="https://github.com/snide/sphinx_rtd_theme">Sphinx theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>{% endtrans %} --.
<!--end hamishw addition -->



<!-- end section moved here by hamishw -->
<div role="contentinfo" class="copyright-box">
<!-- section moved here by hamishw - needs tidying, which is why it is still in breadcrumbs mode -->
<ul class="wy-breadcrumbs">
<li class="wy-breadcrumbs-aside">
{% if display_github %}
<a href="https://github.com/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}.rst" class="fa fa-github"> Edit on GitHub</a>
{% elif display_bitbucket %}
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}.rst" class="fa fa-bitbucket"> Edit on Bitbucket</a>
{% elif show_source and has_source and sourcename %}
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a>
{% endif %}
</li>

<li class="wy-breadcrumbs-aside">
{%- if hasdoc('docs/site/about') %}
<a href="{{pathto('docs/site/about')}}">About site</a>
{%- endif %}
</li>

</ul>

<p>
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
{%- else %}
<!-- {% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %} -->
&copy; Copyright {{ copyright }} <a href="{{ pathto("docs\contributing\AUTHORS") }}">EnjoyDigital and M-Labs Contributors</a>.
<!-- update theme to remove the translation stuff here - it was breaking due to link to AUTHORS file. This is a cludge to allow specific link to my authors file -->
{%- endif %}
{%- endif %}

{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %}
</p>

</div>


</footer>
208 changes: 208 additions & 0 deletions misoclib/doc/source/_themes/enjoydigital_sphinx_rtd_theme/layout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
{# TEMPLATE VAR SETTINGS #}
{%- set url_root = pathto('', 1) %}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}

<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{% endblock %}

{# FAVICON #}
{% if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{% endif %}

{# CSS #}
<link href='https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700' rel='stylesheet' type='text/css'>

{# OPENSEARCH #}
{% if not embedded %}
{% if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{% endif %}

{% endif %}

{# RTD hosts this file, so just load on non RTD builds #}
{% if not READTHEDOCS %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
{% endif %}

{% for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}

{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}"
href="{{ pathto('about') }}"/>
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}"
href="{{ pathto('genindex') }}"/>
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}"/>
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}"/>
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}"/>
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"/>
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"/>
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"/>
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}

{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>

</head>

<body class="wy-body-for-nav" role="document">


<div class="grid-to-center-rtd-theme">

<div class="wy-grid-for-nav">



{# SIDE NAV, TOGGLES ON MOBILE #}
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search">
<!-- <a href="{{ pathto(master_doc) }}" class="fa fa-home"> {{ project }}</a> -->
<a href="{{ pathto(master_doc) }}"> <img src="{{ url_root }}/_static/{{ logo }}" alt="Logo" /> </a>

{% include "searchbox.html" %}
</div>

<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">

{% set toctree = toctree(maxdepth=4, collapse=False, includehidden=True) %}
{% if toctree %}
{{ toctree }}
<a class="toctree-l1" title="Index" href="{{ pathto('genindex') }}">Index</a>
{% else %}
<!-- Local TOC -->
<div class="local-toc">{{ toc }}</div>
{% endif %}
</div>
&nbsp;
</nav>

<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

{# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<!-- <a href="{{ pathto(master_doc) }}">{{ project }}</a> -->
<a href="{{ pathto(master_doc) }}"> <img src="{{ url_root }}/_static/{{ logo }}" alt="Logo" /> </a>
</nav>



{# PAGE CONTENT #}
<div class="wy-nav-content">
<div class="rst-content">

<!--begin hamishw addition -->

<!--Nav bar defined as a document followed by short version of nav text and long version
If no such page exists then nav item is not created. CSS defines which of the long or short version is
displayed. -->
{% set navigation_bar = [
('docs/index', 'Docs', 'Documentation'),
('docs/getting_started/downloads', 'SDK', 'Downloads'),
('docs/introducing_liteeth/community', 'Help', 'Community'),
('https://github.com/enjoy-digital/liteeth', 'Github', 'Github Project')
] -%}


<div class="main-nav-bar" style="">

<!-- the layout of the menu options - centered with left and right alignment of the first and last loop items respectively.
This is VERY UGLY as I'm adding to the CSS in the code to force the alignment. Would be better just to have the elements here and have the CSS in the CSS file. This could be done with a CSS selector, but not worked out how yet. -->

<ul id="menu-options">
{% for document, shorttext, longtext in navigation_bar %}
{%- if hasdoc(document) %}
<li{%- if loop.first %} style="text-align:left;" {%- endif %}{%- if loop.last %} style="text-align:right;" {%- endif %}><a class="navlink-short" title="{{ shorttext }}" href="{{ pathto(document) }}">{{ shorttext }}</a><a class="navlink-long" title="{{ longtext }}" href="{{ pathto(document) }}">{{ longtext }}</a></li>
{%- elif document | truncate(4, True, end='') == 'http' %}
<li{%- if loop.first %} style="text-align:left;" {%- endif %}{%- if loop.last %} style="text-align:right;" {%- endif %}><a class="navlink-short external" href="{{ document }}">{{ shorttext }}</a><a class="navlink-long external" href="{{ document }}">{{ longtext }}</a></li>
{%- endif %}
{% endfor %}
</ul>
<!-- <div style="clear:both;"></div> -->
{% include "breadcrumbs.html" %}

</div>



<!--end hamishw addition -->

<!--HamishW move {% include "breadcrumbs.html" %} -->
<div role="main">
{% block body %}{% endblock %}
</div>
{% include "footer.html" %}
</div>
</div>

</section>

</div>
{% include "versions.html" %}

{% if not embedded %}

<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'{{ url_root }}',
VERSION:'{{ release|e }}',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}

{% endif %}

{# RTD hosts this file, so just load on non RTD builds #}
{% if not READTHEDOCS %}
<script type="text/javascript" src="{{ pathto('_static/js/theme.js', 1) }}"></script>
{% endif %}

{# STICKY NAVIGATION #}
{% if theme_sticky_navigation %}
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
{% endif %}

{%- block footer %} {% endblock %}
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
{#
basic/layout.html
~~~~~~~~~~~~~~~~~

Master layout template for Sphinx themes.

:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block doctype -%}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
{%- endblock %}
{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
(sidebars != []) %}
{%- set url_root = pathto('', 1) %}
{# XXX necessary? #}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}

{%- macro relbar() %}
<div class="related">
<h3>{{ _('Navigation') }}</h3>
<ul>
{%- for rellink in rellinks %}
<li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
{%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
{%- endfor %}
{%- block rootrellink %}
<li><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
{%- endblock %}
{%- for parent in parents %}
<li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
{%- endfor %}
{%- block relbaritems %} {% endblock %}
</ul>
</div>
{%- endmacro %}

{%- macro sidebar() %}
{%- if render_sidebar %}
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
</a></p>
{%- endif %}
{%- endblock %}
{%- if sidebars != None %}
{#- new style sidebar: explicitly include/exclude templates #}
{%- for sidebartemplate in sidebars %}
{%- include sidebartemplate %}
{%- endfor %}
{%- else %}
{#- old style sidebars: using blocks -- should be deprecated #}
{%- block sidebartoc %}
{%- include "localtoc.html" %}
{%- endblock %}
{%- block sidebarrel %}
{%- include "relations.html" %}
{%- endblock %}
{%- block sidebarsourcelink %}
{%- include "sourcelink.html" %}
{%- endblock %}
{%- if customsidebar %}
{%- include customsidebar %}
{%- endif %}
{%- block sidebarsearch %}
{%- include "searchbox.html" %}
{%- endblock %}
{%- endif %}
</div>
</div>
{%- endif %}
{%- endmacro %}

{%- macro script() %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ url_root }}',
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{%- endmacro %}

{%- macro css() %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
{%- for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{%- endfor %}
{%- endmacro %}

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
{{ metatags }}
{%- block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{%- endblock %}
{{ css() }}
{%- if not embedded %}
{{ script() }}
{%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{%- endif %}
{%- if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{%- endif %}
{%- endif %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
<body>
{%- block header %}{% endblock %}

{%- block relbar1 %}{{ relbar() }}{% endblock %}

{%- block content %}
{%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}

<div class="document">
{%- block document %}
<div class="documentwrapper">
{%- if render_sidebar %}
<div class="bodywrapper">
{%- endif %}
<div class="body">
{% block body %} {% endblock %}
</div>
{%- if render_sidebar %}
</div>
{%- endif %}
</div>
{%- endblock %}

{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
<div class="clearer"></div>
</div>
{%- endblock %}

{%- block relbar2 %}{{ relbar() }}{% endblock %}

{%- block footer %}
<div class="footer">
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
{%- else %}
{% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
{%- endif %}
{%- endif %}
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %}
{%- if show_sphinx %}
{% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
{%- endif %}
</div>
<p>asdf asdf asdf asdf 22</p>
{%- endblock %}
</body>
</html>

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{#
basic/search.html
~~~~~~~~~~~~~~~~~

Template for the search page.

:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- extends "layout.html" %}
{% set title = _('Search') %}
{% set script_files = script_files + ['_static/searchtools.js'] %}
{% block footer %}
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
</script>
{# this is used when loading the search index using $.ajax fails,
such as on Chrome for documents on localhost #}
<script type="text/javascript" id="searchindexloader"></script>
{{ super() }}
{% endblock %}
{% block body %}
<noscript>
<div id="fallback" class="admonition warning">
<p class="last">
{% trans %}Please activate JavaScript to enable the search
functionality.{% endtrans %}
</p>
</div>
</noscript>

{% if search_performed %}
<h2>{{ _('Search Results') }}</h2>
{% if not search_results %}
<p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
{% endif %}
{% endif %}
<div id="search-results">
{% if search_results %}
<ul>
{% for href, caption, context in search_results %}
<li>
<a href="{{ pathto(item.href) }}">{{ caption }}</a>
<p class="context">{{ context|e }}</p>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
$( document ).ready(function() {
// Shift nav in mobile when clicking the menu.
$(document).on('click', "[data-toggle='wy-nav-top']", function() {
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
});
// Close menu when you click a link.
$(document).on('click', ".wy-menu-vertical .current ul li a", function() {
$("[data-toggle='wy-nav-shift']").removeClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
});
$(document).on('click', "[data-toggle='rst-current-version']", function() {
$("[data-toggle='rst-versions']").toggleClass("shift-up");
});
// Make tables responsive
$("table.docutils:not(.field-list)").wrap("<div class='wy-table-responsive'></div>");
});

window.SphinxRtdTheme = (function (jquery) {
var stickyNav = (function () {
var navBar,
win,
stickyNavCssClass = 'stickynav',
applyStickNav = function () {
if (navBar.height() <= win.height()) {
navBar.addClass(stickyNavCssClass);
} else {
navBar.removeClass(stickyNavCssClass);
}
},
enable = function () {
applyStickNav();
win.on('resize', applyStickNav);
},
init = function () {
navBar = jquery('nav.wy-nav-side:first');
win = jquery(window);
};
jquery(init);
return {
enable : enable
};
}());
return {
StickyNav : stickyNav
};
}($));
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[theme]
inherit = basic
stylesheet = css/theme.css

[options]
typekit_id = hiw1hhg
analytics_id =
sticky_navigation = True

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{% if READTHEDOCS %}
{# Add rst-badge after rst-versions for small badge style. #}
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span class="fa fa-book"> Read the Docs</span>
v: {{ current_version }}
<span class="fa fa-caret-down"></span>
</span>
<div class="rst-other-versions">
<dl>
<dt>Versions</dt>
{% for slug, url in versions %}
<dd><a href="{{ url }}">{{ slug }}</a></dd>
{% endfor %}
</dl>
<dl>
<dt>Downloads</dt>
{% for type, url in downloads %}
<dd><a href="{{ url }}">{{ type }}</a></dd>
{% endfor %}
</dl>
<dl>
<dt>On Read the Docs</dt>
<dd>
<a href="//{{ PRODUCTION_DOMAIN }}/projects/{{ slug }}/?fromdocs={{ slug }}">Project Home</a>
</dd>
<dd>
<a href="//{{ PRODUCTION_DOMAIN }}/builds/{{ slug }}/?fromdocs={{ slug }}">Builds</a>
</dd>
</dl>
<hr/>
Free document hosting provided by <a href="http://www.readthedocs.org">Read the Docs</a>.

</div>
</div>
{% endif %}

402 changes: 402 additions & 0 deletions misoclib/doc/source/conf.py

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions misoclib/doc/source/docs/core/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. _core-index:

========================
Core
========================
.. note::
Please contribute to this document, or support us financially to write it.
7 changes: 7 additions & 0 deletions misoclib/doc/source/docs/frontend/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. _frontend-index:

========================
Frontend
========================
.. note::
Please contribute to this document, or support us financially to write it.
7 changes: 7 additions & 0 deletions misoclib/doc/source/docs/getting_started/FAQ.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. _FAQ:

===
FAQ
===
.. note::
Please contribute to this document.
11 changes: 11 additions & 0 deletions misoclib/doc/source/docs/getting_started/bug_reports.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.. _bug-reports:

=============
Bug Reporting
=============
- 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.
The use of "git format-patch" is recommended. If your submission is large and
complex and/or you are not sure how to proceed, feel free to discuss with us
about it.
43 changes: 43 additions & 0 deletions misoclib/doc/source/docs/getting_started/downloads.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.. _sdk-download-and-install:

====================
Download and install
====================
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 forks at:
https://github.com/enjoy-digital/migen
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
17 changes: 17 additions & 0 deletions misoclib/doc/source/docs/getting_started/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.. _getting-started-index:

===============
Getting Started
===============

Now you know why LiteEth is :ref:`core for you <about>`, it's time to *get started*.

This section provides a walk-through of :ref:`downloading and installing the tools`.

.. toctree::
:maxdepth: 1

downloads
FAQ
bug_reports

27 changes: 27 additions & 0 deletions misoclib/doc/source/docs/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.. _documentation-home:

========================
LiteEth Documentation
========================

This comprehensive documentation set contains everything you need to know to use LiteEth and integrate it in your design.

**Getting started:**

- :ref:`intro-index` explains what LiteEth does, why it is needed, its limitations and its licensing. It will help you understand whether LiteEth is the right core for you.
- :ref:`getting-started-index` walks you through downloading, installing and using the LiteEth core.

**LiteEth Internals:**

- :ref:`core-index` describes core building blocks.
- :ref:`frontend-index` describes core building blocks.

The full hierarchy of articles, opened to the second level, is shown below.

.. toctree::
:maxdepth: 2

intro/index
getting_started/index
core/index
frontend/index
59 changes: 59 additions & 0 deletions misoclib/doc/source/docs/intro/about.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.. _about:

================
About LiteEth
================

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.

.. _about-toolchain:

Features
========
- Ethernet MAC with various interfaces and various PHYs (GMII, MII, Loopback)
- Hardware UDP/IP stack with ARP and ICMP

Possibles improvements
======================
- add standardized interfaces (AXI, Avalon-ST)
- add DMA interface to MAC
- add hardware Etherbone support
- add RGMII/SGMII PHYs
- ... See below Support and Consulting :)

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


5 changes: 5 additions & 0 deletions misoclib/doc/source/docs/intro/community.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.. _community:

=========
Community
=========
15 changes: 15 additions & 0 deletions misoclib/doc/source/docs/intro/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.. _intro-index:

======================
Introducing LiteEth
======================

This section explains what LiteEth does, why it is needed, its limitations and its licensing. After reading, you will understand whether LiteEth is the right core for you, and where to go if you have :ref:`further questions <community>`.

.. toctree::
:maxdepth: 1

about
license
release_notes
talks_and_publications
47 changes: 47 additions & 0 deletions misoclib/doc/source/docs/intro/license.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.. _license:

===================
Open Source 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.

::

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.
13 changes: 13 additions & 0 deletions misoclib/doc/source/docs/intro/release_notes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. _release-notes:

=============
Release Notes
=============

.. _ChangeLog:

ChangeLog
=========
0.9.0:
- First 0.9.0 release supporting hardware UDP/IP stack with ICMP and ARP.

14 changes: 14 additions & 0 deletions misoclib/doc/source/docs/intro/talks_and_publications.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.. _talks-and-publications:

======================
Talks and Publications
======================

- Migen / MiSoC documentation:
- `User guide <http://m-labs.hk/migen.pdf>`_ (`m-labs <https://github.com/m-labs>`_)
- `Tutorial: An introduction to Migen <http://m-labs.hk/migen-tutorial.pdf>`_ (`m-labs <https://github.com/m-labs>`_)

- Migen / MiSoC presentations:
- `Lecture slides <http://m-labs.hk/migen-slides.pdf>`_ (`sbourdeauducq <https://github.com/sbourdeauducq>`_)
- `EHSM 2012 presentation <https://www.youtube.com/watch?v=yxKMsAi_WEA>`_ (`sbourdeauducq <https://github.com/sbourdeauducq>`_)
- `ORCONF2014 <https://www.youtube.com/watch?v=AfEPbw4nREo>`_ (`fallen <https://github.com/fallen>`_)
26 changes: 26 additions & 0 deletions misoclib/doc/source/home_page_layout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<img alt="./_static/LiteEth_logo_full.png" src="_static/LiteEth_logo_full.png">

<h3>A small footprint and configurable Ethernet core with UDP/IP hw stack and Etherbone frontend</b>.</h3>

<div class="container" style="width:100%;margin-bottom:10px;">

<div class="one-third-container" style="width:32%; display:inline-block;">
<div class="signpost" style="display:inline-block; vertical-align:text-top; margin-left:5px;margin-right:5px;">
<div class="signpost-heading" style="font-size:2em; font-style:bold; margin-bottom:10px;">Small footprint</div>
<div class="signpost-body" style=""><p>Thanks to simple and efficient Migen's building blocks and the KISS principe used to develop this core, LiteEth footprint is really small!</p></div>
</div>
</div>
<div class="one-third-container" style="width:32%; display:inline-block; font-style:bold;">
<div class="signpost" style="display:inline-block; vertical-align:text-top; margin-left:5px;margin-right:5px;">
<div class="signpost-heading" style="font-size:2em; font-style:bold; margin-bottom:10px;">Configurable</div>
<div class="signpost-body" style=""><p>LiteEth generates HDL using Migen as a Python meta-language. The core is then easily configurable to fit user's needs! (Implement only the layers you need, store data in RAM or DMA, use full-hardware UDP/IP stack and so on...)</p></div>
</div>
</div>
<div class="one-third-container" style="width:32%; display:inline-block; font-style:bold;">
<div class="signpost" style="display:inline-block; vertical-align:text-top; margin-left:5px; margin-right:5px;">
<div class="signpost-heading" style="font-size:2em; font-style:bold; margin-bottom:10px;">Portable</div>
<div class="signpost-body" style=""><p>LiteEth can target all FPGAs regardless of the vendor, you only have to ensure that your PHY is available!</p></div>
</div>
</div>
</div>

24 changes: 24 additions & 0 deletions misoclib/doc/source/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.. title:: Main

.. _home-page:

.. raw:: html
:file: home_page_layout.html


-----

News
====

- First 0.9.0 release supporting hardware UDP/IP stack with ICMP and ARP.

.. toctree::
:hidden:

docs/intro/index
docs/getting_started/index
docs/core/index
docs/frontend/index
docs/site/about

2 changes: 2 additions & 0 deletions misoclib/liteeth-version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
0.9.0

Empty file added misoclib/liteeth/__init__.py
Empty file.
284 changes: 284 additions & 0 deletions misoclib/liteeth/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
import math
from collections import OrderedDict

from migen.fhdl.std import *
from migen.fhdl.decorators import ModuleDecorator
from migen.genlib.resetsync import AsyncResetSynchronizer
from migen.genlib.record import *
from migen.genlib.fsm import FSM, NextState
from migen.genlib.misc import chooser
from migen.flow.actor import *
from migen.flow.plumbing import Buffer
from migen.actorlib.structuring import Converter, Pipeline
from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
from migen.bank.description import *

eth_mtu = 1532
eth_min_len = 46
eth_interpacket_gap = 12
eth_preamble = 0xD555555555555555
buffer_depth = 2**log2_int(eth_mtu, need_pow2=False)

class HField():
def __init__(self, byte, offset, width):
self.byte = byte
self.offset = offset
self.width = width

ethernet_type_ip = 0x800
ethernet_type_arp = 0x806

mac_header_len = 14
mac_header = {
"target_mac": HField(0, 0, 48),
"sender_mac": HField(6, 0, 48),
"ethernet_type": HField(12, 0, 16)
}

arp_hwtype_ethernet = 0x0001
arp_proto_ip = 0x0800
arp_opcode_request = 0x0001
arp_opcode_reply = 0x0002

arp_header_len = 28
arp_header = {
"hwtype": HField( 0, 0, 16),
"proto": HField( 2, 0, 16),
"hwsize": HField( 4, 0, 8),
"protosize": HField( 5, 0, 8),
"opcode": HField( 6, 0, 16),
"sender_mac": HField( 8, 0, 48),
"sender_ip": HField(14, 0, 32),
"target_mac": HField(18, 0, 48),
"target_ip": HField(24, 0, 32)
}

ipv4_header_len = 20
ipv4_header = {
"ihl": HField(0, 0, 4),
"version": HField(0, 4, 4),
"total_length": HField(2, 0, 16),
"identification": HField(4, 0, 16),
"ttl": HField(8, 0, 8),
"protocol": HField(9, 0, 8),
"checksum": HField(10, 0, 16),
"sender_ip": HField(12, 0, 32),
"target_ip": HField(16, 0, 32)
}

icmp_header_len = 8
icmp_header = {
"msgtype": HField( 0, 0, 8),
"code": HField( 1, 0, 8),
"checksum": HField( 2, 0, 16),
"quench": HField( 4, 0, 32)
}
icmp_protocol = 0x01

udp_header_len = 8
udp_header = {
"src_port": HField( 0, 0, 16),
"dst_port": HField( 2, 0, 16),
"length": HField( 4, 0, 16),
"checksum": HField( 6, 0, 16)
}

udp_protocol = 0x11

etherbone_magic = 0x4e6f
etherbone_version = 1
etherbone_packet_header_len = 8
etherbone_packet_header = {
"magic": HField( 0, 0, 16),

"version": HField( 2, 4, 4),
"nr": HField( 2, 2, 1),
"pr": HField( 2, 1, 1),
"pf": HField( 2, 0, 1),

"addr_size": HField( 3, 4, 4),
"port_size": HField( 3, 0, 4)
}

etherbone_record_header_len = 4
etherbone_record_header = {
"bca": HField( 0, 0, 1),
"rca": HField( 0, 1, 1),
"rff": HField( 0, 2, 1),
"cyc": HField( 0, 4, 1),
"wca": HField( 0, 5, 1),
"wff": HField( 0, 6, 1),

"byte_enable": HField( 1, 0, 8),

"wcount": HField( 2, 0, 8),

"rcount": HField( 3, 0, 8)
}

def reverse_bytes(v):
n = math.ceil(flen(v)/8)
r = []
for i in reversed(range(n)):
r.append(v[i*8:min((i+1)*8, flen(v))])
return Cat(iter(r))

# layouts
def _layout_from_header(header):
_layout = []
for k, v in sorted(header.items()):
_layout.append((k, v.width))
return _layout

def _remove_from_layout(layout, *args):
r = []
for f in layout:
remove = False
for arg in args:
if f[0] == arg:
remove = True
if not remove:
r.append(f)
return r
def eth_phy_description(dw):
payload_layout = [
("data", dw),
("last_be", dw//8),
("error", dw//8)
]
return EndpointDescription(payload_layout, packetized=True)

def eth_mac_description(dw):
payload_layout = _layout_from_header(mac_header) + [
("data", dw),
("last_be", dw//8),
("error", dw//8)
]
return EndpointDescription(payload_layout, packetized=True)

def eth_arp_description(dw):
param_layout = _layout_from_header(arp_header)
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

arp_table_request_layout = [
("ip_address", 32)
]

arp_table_response_layout = [
("failed", 1),
("mac_address", 48)
]

def eth_ipv4_description(dw):
param_layout = _layout_from_header(ipv4_header)
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_ipv4_user_description(dw):
param_layout = [
("length", 16),
("protocol", 8),
("ip_address", 32)
]
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def convert_ip(s):
ip = 0
for e in s.split("."):
ip = ip << 8
ip += int(e)
return ip

def eth_icmp_description(dw):
param_layout = _layout_from_header(icmp_header)
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_icmp_user_description(dw):
param_layout = _layout_from_header(icmp_header) + [
("ip_address", 32),
("length", 16)
]
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_udp_description(dw):
param_layout = _layout_from_header(udp_header)
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_udp_user_description(dw):
param_layout = [
("src_port", 16),
("dst_port", 16),
("ip_address", 32),
("length", 16)
]
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_etherbone_packet_description(dw):
param_layout = _layout_from_header(etherbone_packet_header)
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_etherbone_packet_user_description(dw):
param_layout = _layout_from_header(etherbone_packet_header)
param_layout = _remove_from_layout(param_layout, "magic", "portsize", "addrsize", "version")
param_layout += eth_udp_user_description(dw).param_layout
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_etherbone_record_description(dw):
param_layout = _layout_from_header(etherbone_record_header)
payload_layout = [
("data", dw),
("error", dw//8)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_etherbone_mmap_description(dw):
param_layout = [
("we", 1),
("count", 8),
("base_addr", 32),
("be", dw//8)
]
payload_layout = [
("addr", 32),
("data", dw)
]
return EndpointDescription(payload_layout, param_layout, packetized=True)

def eth_tty_description(dw):
payload_layout = [("data", dw)]
return EndpointDescription(payload_layout, packetized=False)
19 changes: 19 additions & 0 deletions misoclib/liteeth/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from liteeth.common import *
from liteeth.generic import *
from liteeth.mac import LiteEthMAC
from liteeth.core.arp import LiteEthARP
from liteeth.core.ip import LiteEthIP
from liteeth.core.udp import LiteEthUDP
from liteeth.core.icmp import LiteEthICMP

class LiteEthIPCore(Module, AutoCSR):
def __init__(self, phy, mac_address, ip_address, clk_freq):
self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq)
self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table)
self.submodules.icmp = LiteEthICMP(self.ip, ip_address)

class LiteEthUDPIPCore(LiteEthIPCore):
def __init__(self, phy, mac_address, ip_address, clk_freq):
LiteEthIPCore.__init__(self, phy, mac_address, ip_address, clk_freq)
self.submodules.udp = LiteEthUDP(self.ip, ip_address)
263 changes: 263 additions & 0 deletions misoclib/liteeth/core/arp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
from liteeth.common import *
from liteeth.generic import *
from liteeth.generic.depacketizer import LiteEthDepacketizer
from liteeth.generic.packetizer import LiteEthPacketizer

_arp_table_layout = [
("reply", 1),
("request", 1),
("ip_address", 32),
("mac_address", 48)
]

class LiteEthARPPacketizer(LiteEthPacketizer):
def __init__(self):
LiteEthPacketizer.__init__(self,
eth_arp_description(8),
eth_mac_description(8),
arp_header,
arp_header_len)

class LiteEthARPTX(Module):
def __init__(self, mac_address, ip_address):
self.sink = sink = Sink(_arp_table_layout)
self.source = source = Source(eth_mac_description(8))
###
self.submodules.packetizer = packetizer = LiteEthARPPacketizer()

counter = Counter(max=max(arp_header_len, eth_min_len))
self.submodules += counter

self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
sink.ack.eq(1),
counter.reset.eq(1),
If(sink.stb,
sink.ack.eq(0),
NextState("SEND")
)
)
self.comb += [
packetizer.sink.sop.eq(counter.value == 0),
packetizer.sink.eop.eq(counter.value == max(arp_header_len, eth_min_len)-1),
packetizer.sink.hwtype.eq(arp_hwtype_ethernet),
packetizer.sink.proto.eq(arp_proto_ip),
packetizer.sink.hwsize.eq(6),
packetizer.sink.protosize.eq(4),
packetizer.sink.sender_mac.eq(mac_address),
packetizer.sink.sender_ip.eq(ip_address),
If(sink.reply,
packetizer.sink.opcode.eq(arp_opcode_reply),
packetizer.sink.target_mac.eq(sink.mac_address),
packetizer.sink.target_ip.eq(sink.ip_address)
).Elif(sink.request,

packetizer.sink.opcode.eq(arp_opcode_request),
packetizer.sink.target_mac.eq(0xffffffffffff),
packetizer.sink.target_ip.eq(sink.ip_address)
)
]
fsm.act("SEND",
packetizer.sink.stb.eq(1),
Record.connect(packetizer.source, source),
source.target_mac.eq(packetizer.sink.target_mac),
source.sender_mac.eq(mac_address),
source.ethernet_type.eq(ethernet_type_arp),
If(source.stb & source.ack,
counter.ce.eq(1),
If(source.eop,
sink.ack.eq(1),
NextState("IDLE")
)
)
)

class LiteEthARPDepacketizer(LiteEthDepacketizer):
def __init__(self):
LiteEthDepacketizer.__init__(self,
eth_mac_description(8),
eth_arp_description(8),
arp_header,
arp_header_len)

class LiteEthARPRX(Module):
def __init__(self, mac_address, ip_address):
self.sink = sink = Sink(eth_mac_description(8))
self.source = source = Source(_arp_table_layout)
###
self.submodules.depacketizer = depacketizer = LiteEthARPDepacketizer()
self.comb += Record.connect(sink, depacketizer.sink)

self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
depacketizer.source.ack.eq(1),
If(depacketizer.source.stb & depacketizer.source.sop,
depacketizer.source.ack.eq(0),
NextState("CHECK")
)
)
valid = Signal()
self.sync += valid.eq(
depacketizer.source.stb &
(depacketizer.source.hwtype == arp_hwtype_ethernet) &
(depacketizer.source.proto == arp_proto_ip) &
(depacketizer.source.hwsize == 6) &
(depacketizer.source.protosize == 4) &
(depacketizer.source.target_ip == ip_address)
)
reply = Signal()
request = Signal()
self.comb += Case(depacketizer.source.opcode, {
arp_opcode_request : [request.eq(1)],
arp_opcode_reply : [reply.eq(1)],
"default" : []
})
self.comb += [
source.ip_address.eq(depacketizer.source.sender_ip),
source.mac_address.eq(depacketizer.source.sender_mac)
]
fsm.act("CHECK",
If(valid,
source.stb.eq(1),
source.reply.eq(reply),
source.request.eq(request)
),
NextState("TERMINATE")
),
fsm.act("TERMINATE",
depacketizer.source.ack.eq(1),
If(depacketizer.source.stb & depacketizer.source.eop,
NextState("IDLE")
)
)

class LiteEthARPTable(Module):
def __init__(self, clk_freq, max_requests=8):
self.sink = sink = Sink(_arp_table_layout) # from arp_rx
self.source = source = Source(_arp_table_layout) # to arp_tx

# Request/Response interface
self.request = request = Sink(arp_table_request_layout)
self.response = response = Source(arp_table_response_layout)
###
request_timeout = Timeout(clk_freq//10)
request_counter = Counter(max=max_requests)
request_pending = FlipFlop()
request_ip_address = FlipFlop(32)
self.submodules += request_timeout, request_counter, request_pending, request_ip_address
self.comb += [
request_timeout.ce.eq(request_pending.q),
request_pending.d.eq(1),
request_ip_address.d.eq(request.ip_address)
]

# Note: Store only 1 IP/MAC couple, can be improved with a real
# table in the future to improve performance when packets are
# targeting multiple destinations.
update = Signal()
cached_valid = Signal()
cached_ip_address = Signal(32)
cached_mac_address = Signal(48)
cached_timeout = Timeout(clk_freq*10)
self.submodules += cached_timeout

self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
# Note: for simplicicy, if APR table is busy response from arp_rx
# is lost. This is compensated by the protocol (retries)
If(sink.stb & sink.request,
NextState("SEND_REPLY")
).Elif(sink.stb & sink.reply & request_pending.q,
NextState("UPDATE_TABLE"),
).Elif(request_counter.value == max_requests-1,
NextState("PRESENT_RESPONSE")
).Elif(request.stb | (request_pending.q & request_timeout.reached),
NextState("CHECK_TABLE")
)
)
fsm.act("SEND_REPLY",
source.stb.eq(1),
source.reply.eq(1),
source.ip_address.eq(sink.ip_address),
If(source.ack,
NextState("IDLE")
)
)
fsm.act("UPDATE_TABLE",
request_pending.reset.eq(1),
update.eq(1),
NextState("CHECK_TABLE")
)
self.sync += [
If(update,
cached_valid.eq(1),
cached_ip_address.eq(sink.ip_address),
cached_mac_address.eq(sink.mac_address),
cached_timeout.reset.eq(1)
).Else(
cached_timeout.ce.eq(1),
If(cached_timeout.reached,
cached_valid.eq(0)
)
)
]
found = Signal()
fsm.act("CHECK_TABLE",
If(cached_valid,
If(request_ip_address.q == cached_ip_address,
request_ip_address.reset.eq(1),
NextState("PRESENT_RESPONSE"),
).Elif(request.ip_address == cached_ip_address,
request.ack.eq(request.stb),
NextState("PRESENT_RESPONSE"),
).Else(
request_ip_address.ce.eq(request.stb),
NextState("SEND_REQUEST")
)
).Else(
request_ip_address.ce.eq(request.stb),
NextState("SEND_REQUEST")
)
)
fsm.act("SEND_REQUEST",
source.stb.eq(1),
source.request.eq(1),
source.ip_address.eq(request_ip_address.q),
If(source.ack,
request_timeout.reset.eq(1),
request_counter.reset.eq(request.stb),
request_counter.ce.eq(1),
request_pending.ce.eq(1),
request.ack.eq(1),
NextState("IDLE")
)
)
self.comb += [
If(request_counter == max_requests-1,
response.failed.eq(1),
request_counter.reset.eq(1),
request_pending.reset.eq(1)
),
response.mac_address.eq(cached_mac_address)
]
fsm.act("PRESENT_RESPONSE",
response.stb.eq(1),
If(response.ack,
NextState("IDLE")
)
)

class LiteEthARP(Module):
def __init__(self, mac, mac_address, ip_address, clk_freq):
self.submodules.tx = tx = LiteEthARPTX(mac_address, ip_address)
self.submodules.rx = rx = LiteEthARPRX(mac_address, ip_address)
self.submodules.table = table = LiteEthARPTable(clk_freq)
self.comb += [
Record.connect(rx.source, table.sink),
Record.connect(table.source, tx.sink)
]
mac_port = mac.crossbar.get_port(ethernet_type_arp)
self.comb += [
Record.connect(tx.source, mac_port.sink),
Record.connect(mac_port.source, rx.sink)
]
31 changes: 31 additions & 0 deletions misoclib/liteeth/core/etherbone/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from liteeth.common import *
from liteeth.generic import *
from liteeth.generic.arbiter import Arbiter
from liteeth.generic.dispatcher import Dispatcher
from liteeth.core.etherbone.packet import *
from liteeth.core.etherbone.probe import *
from liteeth.core.etherbone.record import *
from liteeth.core.etherbone.wishbone import *

class LiteEthEtherbone(Module):
def __init__(self, udp, udp_port):
# decode/encode etherbone packets
self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port)

# packets can be probe (etherbone discovering) or records with
# writes and reads
self.submodules.probe = probe = LiteEthEtherboneProbe()
self.submodules.record = record = LiteEthEtherboneRecord()

# arbitrate/dispatch probe/records packets
dispatcher = Dispatcher(packet.source, [probe.sink, record.sink])
self.comb += dispatcher.sel.eq(~packet.source.pf)
arbiter = Arbiter([probe.source, record.source], packet.sink)
self.submodules += dispatcher, arbiter

# create mmap ŵishbone master
self.submodules.master = master = LiteEthEtherboneWishboneMaster()
self.comb += [
Record.connect(record.receiver.source, master.sink),
Record.connect(master.source, record.sender.sink)
]
260 changes: 260 additions & 0 deletions misoclib/liteeth/core/etherbone/dissector/bit.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
--[[---------------
LuaBit v0.4
-------------------
a bitwise operation lib for lua.
http://luaforge.net/projects/bit/
How to use:
-------------------
bit.bnot(n) -- bitwise not (~n)
bit.band(m, n) -- bitwise and (m & n)
bit.bor(m, n) -- bitwise or (m | n)
bit.bxor(m, n) -- bitwise xor (m ^ n)
bit.brshift(n, bits) -- right shift (n >> bits)
bit.blshift(n, bits) -- left shift (n << bits)
bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
Please note that bit.brshift and bit.blshift only support number within
32 bits.
2 utility functions are provided too:
bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence)
-- high bits first
bit.tonumb(bit_tbl) -- convert a bit table into a number
-------------------
Under the MIT license.
copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
--]]---------------

do

------------------------
-- bit lib implementions

local function check_int(n)
-- checking not float
if(n - math.floor(n) > 0) then
error("trying to use bitwise operation on non-integer!")
end
end

local function to_bits(n)
check_int(n)
if(n < 0) then
-- negative
return to_bits(bit.bnot(math.abs(n)) + 1)
end
-- to bits table
local tbl = {}
local cnt = 1
while (n > 0) do
local last = math.mod(n,2)
if(last == 1) then
tbl[cnt] = 1
else
tbl[cnt] = 0
end
n = (n-last)/2
cnt = cnt + 1
end

return tbl
end

local function tbl_to_number(tbl)
local n = table.getn(tbl)

local rslt = 0
local power = 1
for i = 1, n do
rslt = rslt + tbl[i]*power
power = power*2
end

return rslt
end

local function expand(tbl_m, tbl_n)
local big = {}
local small = {}
if(table.getn(tbl_m) > table.getn(tbl_n)) then
big = tbl_m
small = tbl_n
else
big = tbl_n
small = tbl_m
end
-- expand small
for i = table.getn(small) + 1, table.getn(big) do
small[i] = 0
end

end

local function bit_or(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)

local tbl = {}
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
for i = 1, rslt do
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end

return tbl_to_number(tbl)
end

local function bit_and(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)

local tbl = {}
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
for i = 1, rslt do
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end

return tbl_to_number(tbl)
end

local function bit_not(n)

local tbl = to_bits(n)
local size = math.max(table.getn(tbl), 32)
for i = 1, size do
if(tbl[i] == 1) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl_to_number(tbl)
end

local function bit_xor(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)

local tbl = {}
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
for i = 1, rslt do
if(tbl_m[i] ~= tbl_n[i]) then
tbl[i] = 1
else
tbl[i] = 0
end
end

--table.foreach(tbl, print)

return tbl_to_number(tbl)
end

local function bit_rshift(n, bits)
check_int(n)

local high_bit = 0
if(n < 0) then
-- negative
n = bit_not(math.abs(n)) + 1
high_bit = 2147483648 -- 0x80000000
end

for i=1, bits do
n = n/2
n = bit_or(math.floor(n), high_bit)
end
return math.floor(n)
end

-- logic rightshift assures zero filling shift
local function bit_logic_rshift(n, bits)
check_int(n)
if(n < 0) then
-- negative
n = bit_not(math.abs(n)) + 1
end
for i=1, bits do
n = n/2
end
return math.floor(n)
end

local function bit_lshift(n, bits)
check_int(n)

if(n < 0) then
-- negative
n = bit_not(math.abs(n)) + 1
end

for i=1, bits do
n = n*2
end
return bit_and(n, 4294967295) -- 0xFFFFFFFF
end

local function bit_xor2(m, n)
local rhs = bit_or(bit_not(m), bit_not(n))
local lhs = bit_or(m, n)
local rslt = bit_and(lhs, rhs)
return rslt
end

--------------------
-- bit lib interface

bit = {
-- bit operations
bnot = bit_not,
band = bit_and,
bor = bit_or,
bxor = bit_xor,
brshift = bit_rshift,
blshift = bit_lshift,
bxor2 = bit_xor2,
blogic_rshift = bit_logic_rshift,

-- utility func
tobits = to_bits,
tonumb = tbl_to_number,
}

end

--[[
for i = 1, 100 do
for j = 1, 100 do
if(bit.bxor(i, j) ~= bit.bxor2(i, j)) then
error("bit.xor failed.")
end
end
end
--]]













223 changes: 223 additions & 0 deletions misoclib/liteeth/core/etherbone/dissector/etherbone.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
-- Etherbone Dissector
-- Copyright 2013 OHWR.org
-- Copyright 2015 EnjoyDigital (global clean up)

local bit = require("bit")

local VALS_BOOL = {[0] = "False", [1] = "True"}
local VALS_RES = {[0] = "not set", [1] = "set, bad data?"}
local VALS_SIZE = {
[0x00] = "Bad Value",
[0x01] = "8 bit",
[0x02] = "16 bit",
[0x03] = "16,8 bit",
[0x04] = "32 bit",
[0x05] = "32,8 bit",
[0x06] = "32,16 bit",
[0x07] = "32,16,8 bit",
[0x08] = "64 bit",
[0x09] = "64,8 bit",
[0x0A] = "64,16 bit",
[0x0B] = "64,16,8 bit",
[0x0C] = "64,32 bit",
[0x0D] = "64,32,8 bit",
[0x0E] = "64,32,16 bit",
[0x0F] = "64,32,16,8 bit",
}

function num2hex(num)
local hexstr = '0123456789abcdef'
local s = ''
while num > 0 do
local mod = math.fmod(num, 16)
s = string.sub(hexstr, mod+1, mod+1) .. s
num = math.floor(num / 16)
end
if s == '' then s = '0' end
return s
end

function max(a, b)
if a > b then
return a
else
return b
end
end

-- declare protocol
proto_eb = Proto("eb", "Etherbone")

-- declare fields
local eb = proto_eb.fields
eb.hdr = ProtoField.uint32("eb.hdr", "Header", base.HEX)
eb.rec = ProtoField.bytes("eb.rec", "Record ", base.HEX)

eb.hdr_magic = ProtoField.uint16("eb.hdr.magic", "Magic ", base.HEX, nil, 0xFFFF)
eb.hdr_ver = ProtoField.uint16("eb.hdr.ver", "Version ", base.DEC, nil, 0xF000)
eb.hdr_noreads = ProtoField.uint16("eb.hdr.noreads", "No Reads ", base.DEC, VALS_BOOL, 0x0400)
eb.hdr_proberep = ProtoField.uint16("eb.hdr.proberes", "Probe Reply ", base.DEC, VALS_BOOL, 0x0200)
eb.hdr_probereq = ProtoField.uint16("eb.hdr.probereq", "Probe Flag ", base.DEC, VALS_BOOL, 0x0100)
eb.hdr_adrs = ProtoField.uint16("eb.hdr.adrw", "Address Width ", base.DEC, VALS_SIZE , 0x00F0)
eb.hdr_ports = ProtoField.uint16("eb.hdr.portw", "Port Width ", base.DEC, VALS_SIZE , 0x000F)

eb.rec_hdr = ProtoField.uint32("eb.rec.hdr", "Header ", base.HEX)
eb.rec_writes = ProtoField.bytes("eb.rec.writes", "Writes ", base.HEX)
eb.rec_reads = ProtoField.bytes("eb.rec.reads", "Reads ", base.HEX)

eb.rec_hdr_flags = ProtoField.uint8("eb.rec.hdr.flags", "Flags ", base.HEX)
eb.rec_hdr_select = ProtoField.uint8("eb.rec.hdr.select", "Select ", base.HEX)
eb.rec_hdr_wr = ProtoField.uint8("eb.rec.hdr.wr", "Writes ", base.DEC)
eb.rec_hdr_rd = ProtoField.uint8("eb.rec.hdr.rd", "Reads ", base.DEC)

eb.rec_hdr_flags_adrcfg = ProtoField.uint8("eb.rec.hdr.flags.adrcfg", "ReplyToCfgSpace ", base.DEC, VALS_BOOL, 0x80)
eb.rec_hdr_flags_rbacfg = ProtoField.uint8("eb.rec.hdr.adrcfg", "ReadFromCfgSpace ", base.DEC, VALS_BOOL, 0x40)
eb.rec_hdr_flags_rdfifo = ProtoField.uint8("eb.rec.hdr.adrcfg", "ReadFIFO ", base.DEC, VALS_BOOL, 0x20)
eb.rec_hdr_flags_dropcyc= ProtoField.uint8("eb.rec.hdr.adrcfg", "DropCycle ", base.DEC, VALS_BOOL, 0x08)
eb.rec_hdr_flags_wbacfg = ProtoField.uint8("eb.rec.hdr.adrcfg", "WriteToCfgSpace ", base.DEC, VALS_BOOL, 0x04)
eb.rec_hdr_flags_wrfifo = ProtoField.uint8("eb.rec.hdr.adrcfg", "WriteFIFO ", base.DEC, VALS_BOOL, 0x02)

eb.rec_wrsadr8 = ProtoField.uint8("eb.rec.wrsadr8", "BaseAddr8 ", base.HEX)
eb.rec_wrsadr16 = ProtoField.uint16("eb.rec.wrsadr16", "BaseAddr16 ", base.HEX)
eb.rec_wrsadr32 = ProtoField.uint32("eb.rec.wrsadr32", "BaseAddr32 ", base.HEX)
eb.rec_wrsadr64 = ProtoField.uint64("eb.rec.wrsadr64", "BaseAddr64 ", base.HEX)
eb.rec_wrdata8 = ProtoField.uint8("eb.rec.wrdata8", "Value8 ", base.HEX)
eb.rec_wrdata16 = ProtoField.uint16("eb.rec.wrdata16", "Value16 ", base.HEX)
eb.rec_wrdata32 = ProtoField.uint32("eb.rec.wrdata32", "Value32 ", base.HEX)
eb.rec_wrdata64 = ProtoField.uint64("eb.rec.wrdata64", "Value64 ", base.HEX)

eb.rec_rdbadr8 = ProtoField.uint8("eb.rec.rdbadr8", "ReplyAddr8 ", base.HEX)
eb.rec_rdbadr16 = ProtoField.uint16("eb.rec.rdbadr16", "ReplyAddr16 ", base.HEX)
eb.rec_rdbadr32 = ProtoField.uint32("eb.rec.rdbadr32", "ReplyAddr32 ", base.HEX)
eb.rec_rdbadr64 = ProtoField.uint64("eb.rec.rdbadr64", "ReplyAddr64 ", base.HEX)
eb.rec_rddata8 = ProtoField.uint8("eb.rec.rddata8", "Address8 ", base.HEX)
eb.rec_rddata16 = ProtoField.uint16("eb.rec.rddata16", "Address16 ", base.HEX)
eb.rec_rddata32 = ProtoField.uint32("eb.rec.rddata32", "Address32 ", base.HEX)
eb.rec_rddata64 = ProtoField.uint64("eb.rec.rddata64", "Address64 ", base.HEX)

-- define the dissector
function proto_eb.dissector(buf, pinfo, tree)
if (buf:len() < 4) then
return 0 -- too short, go to default protocol
end

local mylen = buf:len()
pinfo.cols.protocol = "eb"

-- add packet to the tree root, fields will be added to subtree
local t = tree:add( proto_eb, buf(0, mylen) )
local t_hdr = t:add( eb.hdr, buf(0,4) )

local magic = num2hex(tonumber(buf(0,2):uint()))
if(magic == "4e6f") then

t_hdr:add( eb.hdr_magic, buf(0,2)) -- magic
t_hdr:add( eb.hdr_ver, buf(2,2)) -- version
t_hdr:add( eb.hdr_noreads, buf(2,2)) -- no reads
t_hdr:add( eb.hdr_proberep, buf(2,2)) -- probe response
t_hdr:add( eb.hdr_probereq, buf(2,2)) -- probe request

t_hdr:add( eb.hdr_adrs, buf(2,2)) -- supported addr size
t_hdr:add( eb.hdr_ports, buf(2,2)) -- supported port size

local probe = tonumber(buf(2,1):uint()) % 4
if (probe == 0) then
local widths = tonumber(buf(3,1):uint())
local data_width = widths % 16
local addr_width = (widths - data_width) / 16
local alignment = max(max(addr_width, data_width), 2)

local record_alignment = max(alignment, 4)
local offset = max(alignment, 4)

local recordcnt = 0
while (offset < buf:len()) do
local wr = tonumber(buf(offset+2,1):uint())
local rd = tonumber(buf(offset+3,1):uint())

local rdadr = 0
local wradr = 0
if(rd > 0) then
rdadr = 1
end
if(wr > 0) then
wradr = 1
end

if((wr == 0) and (rd == 0)) then
offset = offset + record_alignment
else
local t_rec = t:add( "Record "..tostring(recordcnt).." (W"..tostring(wr).." R"..tostring(rd)..")", buf(offset, (record_alignment+(rd+wr+rdadr+wradr)*alignment)))
recordcnt = recordcnt + 1

local t_rec_hdr = t_rec:add( eb.rec_hdr, buf(offset,4))
local t_rec_hdr_flags = t_rec_hdr:add( eb.rec_hdr_flags, buf(offset,1))
t_rec_hdr_flags:add( eb.rec_hdr_flags_adrcfg, buf(offset,1))
t_rec_hdr_flags:add( eb.rec_hdr_flags_rbacfg, buf(offset,1))
t_rec_hdr_flags:add( eb.rec_hdr_flags_rdfifo, buf(offset,1))
t_rec_hdr_flags:add( eb.rec_hdr_flags_dropcyc , buf(offset,1))
t_rec_hdr_flags:add( eb.rec_hdr_flags_wbacfg , buf(offset,1))
t_rec_hdr_flags:add( eb.rec_hdr_flags_wrfifo, buf(offset,1))
t_rec_hdr:add( eb.rec_hdr_select, buf(offset+1,1))
t_rec_hdr:add( eb.rec_hdr_wr, buf(offset+2,1))
t_rec_hdr:add( eb.rec_hdr_rd, buf(offset+3,1))
offset = offset + record_alignment
local tmp_offset

if(wr > 0) then
local t_writes = t_rec:add( eb.rec_writes, buf(offset,(1+wr)*alignment))

if addr_width==1 then t_writes:add(eb.rec_wrsadr8, buf(offset+alignment-1, 1))
elseif addr_width==2 then t_writes:add(eb.rec_wrsadr16, buf(offset+alignment-2, 2))
elseif addr_width==4 then t_writes:add(eb.rec_wrsadr32, buf(offset+alignment-4, 4))
elseif addr_width==8 then t_writes:add(eb.rec_wrsadr64, buf(offset+alignment-8, 8))
end
offset = offset + alignment

tmp_offset = offset
while (tmp_offset < offset+wr*alignment) do
if data_width==1 then t_writes:add( eb.rec_wrdata8, buf(tmp_offset+alignment-1, 1))
elseif data_width==2 then t_writes:add( eb.rec_wrdata16, buf(tmp_offset+alignment-2, 2))
elseif data_width==4 then t_writes:add( eb.rec_wrdata32, buf(tmp_offset+alignment-4, 4))
elseif data_width==8 then t_writes:add( eb.rec_wrdata64, buf(tmp_offset+alignment-8, 8))
end
tmp_offset = tmp_offset + alignment
end
offset = tmp_offset
end

if(rd > 0) then
local t_reads = t_rec:add( eb.rec_reads, buf(offset,(1+rd)*alignment))

if addr_width==1 then t_reads:add( eb.rec_rdbadr8, buf(offset+alignment-1, 1))
elseif addr_width==2 then t_reads:add( eb.rec_rdbadr16, buf(offset+alignment-2, 2))
elseif addr_width==4 then t_reads:add( eb.rec_rdbadr32, buf(offset+alignment-4, 4))
elseif addr_width==8 then t_reads:add( eb.rec_rdbadr64, buf(offset+alignment-8, 8))
end
offset = offset + alignment

tmp_offset = offset
while (tmp_offset < offset+rd*alignment) do
if addr_width==1 then t_reads:add( eb.rec_rddata8, buf(tmp_offset+alignment-1, 1))
elseif addr_width==2 then t_reads:add( eb.rec_rddata16, buf(tmp_offset+alignment-2, 2))
elseif addr_width==4 then t_reads:add( eb.rec_rddata32, buf(tmp_offset+alignment-4, 4))
elseif addr_width==8 then t_reads:add( eb.rec_rddata64, buf(tmp_offset+alignment-8, 8))
end
tmp_offset = tmp_offset + alignment
end
offset = tmp_offset
end
end
end

end

else
return 0
end

end

-- register eb protocol on UDP port 20000
local tab = DissectorTable.get("udp.port")
tab:add(20000, proto_eb)
129 changes: 129 additions & 0 deletions misoclib/liteeth/core/etherbone/packet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
from liteeth.common import *
from liteeth.generic import *
from liteeth.generic.depacketizer import LiteEthDepacketizer
from liteeth.generic.packetizer import LiteEthPacketizer

class LiteEthEtherbonePacketPacketizer(LiteEthPacketizer):
def __init__(self):
LiteEthPacketizer.__init__(self,
eth_etherbone_packet_description(32),
eth_udp_user_description(32),
etherbone_packet_header,
etherbone_packet_header_len)

class LiteEthEtherbonePacketTX(Module):
def __init__(self, udp_port):
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
self.source = source = Source(eth_udp_user_description(32))
###
self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer()
self.comb += [
packetizer.sink.stb.eq(sink.stb),
packetizer.sink.sop.eq(sink.sop),
packetizer.sink.eop.eq(sink.eop),
sink.ack.eq(packetizer.sink.ack),

packetizer.sink.magic.eq(etherbone_magic),
packetizer.sink.port_size.eq(32//8),
packetizer.sink.addr_size.eq(32//8),
packetizer.sink.pf.eq(sink.pf),
packetizer.sink.pr.eq(sink.pr),
packetizer.sink.nr.eq(sink.nr),
packetizer.sink.version.eq(etherbone_version),

packetizer.sink.data.eq(sink.data)
]
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
packetizer.source.ack.eq(1),
If(packetizer.source.stb & packetizer.source.sop,
packetizer.source.ack.eq(0),
NextState("SEND")
)
)
fsm.act("SEND",
Record.connect(packetizer.source, source),
source.src_port.eq(udp_port),
source.dst_port.eq(udp_port),
source.ip_address.eq(sink.ip_address),
source.length.eq(sink.length + etherbone_packet_header_len),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)

class LiteEthEtherbonePacketDepacketizer(LiteEthDepacketizer):
def __init__(self):
LiteEthDepacketizer.__init__(self,
eth_udp_user_description(32),
eth_etherbone_packet_description(32),
etherbone_packet_header,
etherbone_packet_header_len)

class LiteEthEtherbonePacketRX(Module):
def __init__(self):
self.sink = sink = Sink(eth_udp_user_description(32))
self.source = source = Source(eth_etherbone_packet_user_description(32))
###
self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer()
self.comb += Record.connect(sink, depacketizer.sink)

self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
depacketizer.source.ack.eq(1),
If(depacketizer.source.stb & depacketizer.source.sop,
depacketizer.source.ack.eq(0),
NextState("CHECK")
)
)
valid = Signal()
self.sync += valid.eq(
depacketizer.source.stb &
(depacketizer.source.magic == etherbone_magic)
)
fsm.act("CHECK",
If(valid,
NextState("PRESENT")
).Else(
NextState("DROP")
)
)
self.comb += [
source.sop.eq(depacketizer.source.sop),
source.eop.eq(depacketizer.source.eop),

source.pf.eq(depacketizer.source.pf),
source.pr.eq(depacketizer.source.pr),
source.nr.eq(depacketizer.source.nr),

source.data.eq(depacketizer.source.data),

source.src_port.eq(sink.src_port),
source.dst_port.eq(sink.dst_port),
source.ip_address.eq(sink.ip_address),
source.length.eq(sink.length - etherbone_packet_header_len)
]
fsm.act("PRESENT",
source.stb.eq(depacketizer.source.stb),
depacketizer.source.ack.eq(source.ack),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)
fsm.act("DROP",
depacketizer.source.ack.eq(1),
If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack,
NextState("IDLE")
)
)

class LiteEthEtherbonePacket(Module):
def __init__(self, udp, udp_port):
self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port)
self.submodules.rx = rx = LiteEthEtherbonePacketRX()
udp_port = udp.crossbar.get_port(udp_port, dw=32)
self.comb += [
Record.connect(tx.source, udp_port.sink),
Record.connect(udp_port.source, rx.sink)
]
self.sink, self.source = self.tx.sink, self.rx.source
24 changes: 24 additions & 0 deletions misoclib/liteeth/core/etherbone/probe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from liteeth.common import *
from liteeth.generic import *

class LiteEthEtherboneProbe(Module):
def __init__(self):
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
self.source = source = Source(eth_etherbone_packet_user_description(32))
###
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
sink.ack.eq(1),
If(sink.stb & sink.sop,
sink.ack.eq(0),
NextState("PROBE_RESPONSE")
)
)
fsm.act("PROBE_RESPONSE",
Record.connect(sink, source),
source.pf.eq(0),
source.pr.eq(1),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)
176 changes: 176 additions & 0 deletions misoclib/liteeth/core/etherbone/record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
from liteeth.common import *
from liteeth.generic import *
from liteeth.generic.depacketizer import LiteEthDepacketizer
from liteeth.generic.packetizer import LiteEthPacketizer

class LiteEthEtherboneRecordPacketizer(LiteEthPacketizer):
def __init__(self):
LiteEthPacketizer.__init__(self,
eth_etherbone_record_description(32),
eth_etherbone_packet_user_description(32),
etherbone_record_header,
etherbone_record_header_len)

class LiteEthEtherboneRecordDepacketizer(LiteEthDepacketizer):
def __init__(self):
LiteEthDepacketizer.__init__(self,
eth_etherbone_packet_user_description(32),
eth_etherbone_record_description(32),
etherbone_record_header,
etherbone_record_header_len)

class LiteEthEtherboneRecordReceiver(Module):
def __init__(self, buffer_depth=256):
self.sink = sink = Sink(eth_etherbone_record_description(32))
self.source = source = Source(eth_etherbone_mmap_description(32))
###
fifo = SyncFIFO(eth_etherbone_record_description(32), buffer_depth, buffered=True)
self.submodules += fifo
self.comb += Record.connect(sink, fifo.sink)

self.submodules.base_addr = base_addr = FlipFlop(32)
self.comb += base_addr.d.eq(fifo.source.data)

self.submodules.counter = counter = Counter(max=512)

self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
fifo.source.ack.eq(1),
counter.reset.eq(1),
If(fifo.source.stb & fifo.source.sop,
base_addr.ce.eq(1),
If(fifo.source.wcount,
NextState("RECEIVE_WRITES")
).Elif(fifo.source.rcount,
NextState("RECEIVE_READS")
)
)
)
fsm.act("RECEIVE_WRITES",
source.stb.eq(fifo.source.stb),
source.sop.eq(counter.value == 0),
source.eop.eq(counter.value == fifo.source.wcount-1),
source.count.eq(fifo.source.wcount),
source.be.eq(fifo.source.byte_enable),
source.addr.eq(base_addr.q[2:] + counter.value),
source.we.eq(1),
source.data.eq(fifo.source.data),
fifo.source.ack.eq(source.ack),
If(source.stb & source.ack,
counter.ce.eq(1),
If(source.eop,
If(fifo.source.rcount,
NextState("RECEIVE_BASE_RET_ADDR")
).Else(
NextState("IDLE")
)
)
)
)
fsm.act("RECEIVE_BASE_RET_ADDR",
counter.reset.eq(1),
If(fifo.source.stb & fifo.source.sop,
base_addr.ce.eq(1),
NextState("RECEIVE_READS")
)
)
fsm.act("RECEIVE_READS",
source.stb.eq(fifo.source.stb),
source.sop.eq(counter.value == 0),
source.eop.eq(counter.value == fifo.source.rcount-1),
source.count.eq(fifo.source.rcount),
source.base_addr.eq(base_addr.q),
source.addr.eq(fifo.source.data[2:]),
fifo.source.ack.eq(source.ack),
If(source.stb & source.ack,
counter.ce.eq(1),
If(source.eop,
NextState("IDLE")
)
)
)

class LiteEthEtherboneRecordSender(Module):
def __init__(self, buffer_depth=256):
self.sink = sink = Sink(eth_etherbone_mmap_description(32))
self.source = source = Source(eth_etherbone_record_description(32))
###
pbuffer = PacketBuffer(eth_etherbone_mmap_description(32), buffer_depth)
self.submodules += pbuffer
self.comb += Record.connect(sink, pbuffer.sink)

self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
pbuffer.source.ack.eq(1),
If(pbuffer.source.stb & pbuffer.source.sop,
pbuffer.source.ack.eq(0),
NextState("SEND_BASE_ADDRESS")
)
)
self.comb += [
source.byte_enable.eq(pbuffer.source.be),
If(pbuffer.source.we,
source.wcount.eq(pbuffer.source.count)
).Else(
source.rcount.eq(pbuffer.source.count)
)
]

fsm.act("SEND_BASE_ADDRESS",
source.stb.eq(pbuffer.source.stb),
source.sop.eq(1),
source.eop.eq(0),
source.data.eq(pbuffer.source.base_addr),
If(source.ack,
NextState("SEND_DATA")
)
)
fsm.act("SEND_DATA",
source.stb.eq(pbuffer.source.stb),
source.sop.eq(0),
source.eop.eq(pbuffer.source.eop),
source.data.eq(pbuffer.source.data),
If(source.stb & source.ack,
pbuffer.source.ack.eq(1),
If(source.eop,
NextState("IDLE")
)
)
)

# Limitation: For simplicity we only support 1 record per packet
class LiteEthEtherboneRecord(Module):
def __init__(self, endianness="big"):
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
self.source = source = Sink(eth_etherbone_packet_user_description(32))
###

# receive record, decode it and generate mmap stream
self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer()
self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver()
self.comb += [
Record.connect(sink, depacketizer.sink),
Record.connect(depacketizer.source, receiver.sink)
]
if endianness is "big":
self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data))

# save last ip address
last_ip_address = Signal(32)
self.sync += [
If(sink.stb & sink.sop & sink.ack,
last_ip_address.eq(sink.ip_address)
)
]

# receive mmap stream, encode it and send records
self.submodules.sender = sender = LiteEthEtherboneRecordSender()
self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer()
self.comb += [
Record.connect(sender.source, packetizer.sink),
Record.connect(packetizer.source, source),
source.length.eq(sender.source.wcount*4 + 4 +etherbone_record_header_len), # XXX improve this
source.ip_address.eq(last_ip_address)
]
if endianness is "big":
self.comb += packetizer.sink.data.eq(reverse_bytes(sender.source.data))
Loading