mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
litex: reorganize things, first work working version
This commit is contained in:
parent
637634f312
commit
6a0f85dc42
476 changed files with 487 additions and 21805 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -1,7 +1,5 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
*.pyc
|
*.pyc
|
||||||
*.egg-info/
|
*.egg-info
|
||||||
vpi/*.o
|
*.vcd
|
||||||
vpi/migensim.vpi
|
outgoing
|
||||||
examples/*.vcd
|
|
||||||
doc/_build
|
|
||||||
|
|
12
.gitmodules
vendored
Normal file
12
.gitmodules
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[submodule "litex/soc/cores/cpu/lm32/verilog/submodule"]
|
||||||
|
path = litex/soc/cores/cpu/lm32/verilog/submodule
|
||||||
|
url = https://github.com/m-labs/lm32.git
|
||||||
|
[submodule "litex/soc/cores/cpu/mor1kx/verilog"]
|
||||||
|
path = litex/soc/cores/cpu/mor1kx/verilog
|
||||||
|
url = https://github.com/openrisc/mor1kx.git
|
||||||
|
[submodule "litex/soc/software/compiler_rt"]
|
||||||
|
path = litex/soc/software/compiler_rt
|
||||||
|
url = http://llvm.org/git/compiler-rt.git
|
||||||
|
[submodule "litex/soc/software/unwinder"]
|
||||||
|
path = litex/soc/software/unwinder
|
||||||
|
url = https://github.com/whitequark/libunwind
|
52
.travis.yml
52
.travis.yml
|
@ -1,52 +0,0 @@
|
||||||
language: python
|
|
||||||
python:
|
|
||||||
- "3.5"
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- PATH=$HOME/miniconda/bin:$PATH
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# Install Miniconda
|
|
||||||
- wget https://raw.githubusercontent.com/m-labs/artiq/master/.travis/get-anaconda.sh
|
|
||||||
- chmod +x get-anaconda.sh
|
|
||||||
- ./get-anaconda.sh
|
|
||||||
- source $HOME/miniconda/bin/activate py35
|
|
||||||
- conda install anaconda-client numpydoc
|
|
||||||
install:
|
|
||||||
# Install iverilog package.
|
|
||||||
# - "sudo add-apt-repository -y ppa:mithro/iverilog-backport"
|
|
||||||
# - "sudo apt-get update"
|
|
||||||
# - "sudo apt-get install iverilog"
|
|
||||||
# - "iverilog -v; true"
|
|
||||||
# Build the vpi module.
|
|
||||||
# - "(cd vpi; make; sudo make install)"
|
|
||||||
# Install verilator package
|
|
||||||
- "sudo apt-get install verilator"
|
|
||||||
- "verilator --version; true"
|
|
||||||
# Build and install Migen conda package
|
|
||||||
# workaround for https://github.com/conda/conda-build/issues/466
|
|
||||||
- "mkdir -p /home/travis/miniconda/conda-bld/linux-64"
|
|
||||||
- "conda index /home/travis/miniconda/conda-bld/linux-64"
|
|
||||||
- "conda build --python 3.5 conda/migen"
|
|
||||||
- "conda install $(conda build --output --python 3.5 conda/migen)"
|
|
||||||
|
|
||||||
script:
|
|
||||||
# Run tests
|
|
||||||
- "python setup.py test"
|
|
||||||
# Generate HTML documentation
|
|
||||||
- "make -C doc html"
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
# Upload Migen conda package to binstar
|
|
||||||
- if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then anaconda login --hostname $(hostname) --username $binstar_login --password $binstar_password; fi
|
|
||||||
- if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then anaconda upload --user $binstar_login --channel dev --force $HOME/miniconda/conda-bld/noarch/migen-*.tar.bz2; fi
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- chat.freenode.net#m-labs
|
|
||||||
template:
|
|
||||||
- "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}"
|
|
||||||
- "Build details : %{build_url}"
|
|
3
MANIFEST.in
Normal file
3
MANIFEST.in
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
graft litex/soc/software
|
||||||
|
graft litex/soc/cores/cpu/lm32/verilog
|
||||||
|
graft litex/soc/cores/cpu/mor1kx/verilog
|
42
README
Normal file
42
README
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
__ _ __ _ __
|
||||||
|
/ / (_) /____ | |/_/
|
||||||
|
/ /__/ / __/ -_)> <
|
||||||
|
/____/_/\__/\__/_/|_|
|
||||||
|
|
||||||
|
Build your hardware, easily!
|
||||||
|
Copyright 2015 Enjoy-Digital
|
||||||
|
(based on Migen/MiSoC technologies)
|
||||||
|
|
||||||
|
[> Intro
|
||||||
|
---------
|
||||||
|
LiteX is a fork of Migen/MiSoC for our own needs at Enjoy-Digital. It provides
|
||||||
|
a single python package and add some specific features to design our FPGA cores,
|
||||||
|
build a SoC with or or load/flash it to the hardware.
|
||||||
|
|
||||||
|
The structure of LiteX is kept close to Migen/MiSoC to enable collaboration
|
||||||
|
between projects.
|
||||||
|
|
||||||
|
[> License
|
||||||
|
-----------
|
||||||
|
LiteX is copyright (c) 2015 Enjoy-Digital.
|
||||||
|
Since it is based on Migen/MiSoC, see gen/MIGEN_LICENSE and soc/MISOC_LICENSE or
|
||||||
|
git history to get correct ownership of files.
|
||||||
|
|
||||||
|
[> Sub-packages
|
||||||
|
-----------
|
||||||
|
gen:
|
||||||
|
Provides tools and simple modules to generate HDL.
|
||||||
|
|
||||||
|
build:
|
||||||
|
Provides tools to build FPGA bitstreams (interface to vendor toolchains) and to
|
||||||
|
simulate HDL code or full SoCs.
|
||||||
|
|
||||||
|
soc:
|
||||||
|
Provides definitions/modules to build cores (bus, bank, flow), cores and tools
|
||||||
|
to build a SoC from such cores.
|
||||||
|
|
||||||
|
boards:
|
||||||
|
Provides platforms and targets for the supported boards.
|
||||||
|
|
||||||
|
[> Contact
|
||||||
|
E-mail: florent [AT] enjoy-digital.fr
|
82
README.rst
82
README.rst
|
@ -1,82 +0,0 @@
|
||||||
### Migen (Milkymist generator)
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/m-labs/migen.svg)](
|
|
||||||
https://travis-ci.org/m-labs/migen)
|
|
||||||
|
|
||||||
#### A Python toolbox for building complex digital hardware
|
|
||||||
|
|
||||||
Despite being faster than schematics entry, hardware design with Verilog and
|
|
||||||
VHDL remains tedious and inefficient for several reasons. The event-driven
|
|
||||||
model introduces issues and manual coding that are unnecessary for synchronous
|
|
||||||
circuits, which represent the lion's share of today's logic designs. Counter-
|
|
||||||
intuitive arithmetic rules result in steeper learning curves and provide a
|
|
||||||
fertile ground for subtle bugs in designs. Finally, support for procedural
|
|
||||||
generation of logic (metaprogramming) through "generate" statements is very
|
|
||||||
limited and restricts the ways code can be made generic, reused and organized.
|
|
||||||
|
|
||||||
To address those issues, we have developed the **Migen FHDL** library that
|
|
||||||
replaces the event-driven paradigm with the notions of combinatorial and
|
|
||||||
synchronous statements, has arithmetic rules that make integers always behave
|
|
||||||
like mathematical integers, and most importantly allows the design's logic to
|
|
||||||
be constructed by a Python program. This last point enables hardware designers
|
|
||||||
to take advantage of the richness of the Python language - object oriented
|
|
||||||
programming, function parameters, generators, operator overloading, libraries,
|
|
||||||
etc. - to build well organized, reusable and elegant designs.
|
|
||||||
|
|
||||||
Other Migen libraries are built on FHDL and provide various tools such as a
|
|
||||||
system-on-chip interconnect infrastructure, a dataflow programming system, a
|
|
||||||
more traditional high-level synthesizer that compiles Python routines into
|
|
||||||
state machines with datapaths, and a simulator that allows test benches to be
|
|
||||||
written in Python.
|
|
||||||
|
|
||||||
See the doc/ folder for more technical information.
|
|
||||||
|
|
||||||
Migen is designed for Python 3.3. Note that Migen is **not** spelled MiGen.
|
|
||||||
|
|
||||||
#### Quick Links
|
|
||||||
|
|
||||||
Code repository:
|
|
||||||
https://github.com/m-labs/migen
|
|
||||||
|
|
||||||
System-on-chip design based on Migen:
|
|
||||||
https://github.com/m-labs/misoc
|
|
||||||
|
|
||||||
Online documentation:
|
|
||||||
http://m-labs.hk/gateware.html
|
|
||||||
|
|
||||||
#### Quick intro
|
|
||||||
|
|
||||||
```python
|
|
||||||
from migen import *
|
|
||||||
from migen.build.platforms import m1
|
|
||||||
plat = m1.Platform()
|
|
||||||
led = plat.request("user_led")
|
|
||||||
m = Module()
|
|
||||||
counter = Signal(26)
|
|
||||||
m.comb += led.eq(counter[25])
|
|
||||||
m.sync += counter.eq(counter + 1)
|
|
||||||
plat.build_cmdline(m)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### License
|
|
||||||
|
|
||||||
Migen is released under the very permissive two-clause BSD license. Under the
|
|
||||||
terms of this license, you are authorized to use Migen 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 Migen
|
|
||||||
* put the Migen logo (doc/migen_logo.svg) on the page of a product using it,
|
|
||||||
with a link to http://m-labs.hk
|
|
||||||
* cite Migen 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 Migen. 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 it on
|
|
||||||
the mailing list or IRC (#m-labs on Freenode) beforehand.
|
|
||||||
|
|
||||||
See LICENSE file for full copyright and license info. You can contact us on the
|
|
||||||
public mailing list devel [AT] lists.m-labs.hk.
|
|
||||||
|
|
||||||
"Electricity! It's like magic!"
|
|
|
@ -1 +0,0 @@
|
||||||
%PYTHON% setup.py install
|
|
|
@ -1,28 +0,0 @@
|
||||||
package:
|
|
||||||
name: migen
|
|
||||||
version: {{ environ.get("GIT_DESCRIBE_TAG", "") }}
|
|
||||||
|
|
||||||
source:
|
|
||||||
git_url: https://github.com/m-labs/migen
|
|
||||||
git_tag: master
|
|
||||||
|
|
||||||
build:
|
|
||||||
noarch_python: true
|
|
||||||
number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}
|
|
||||||
string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_DESCRIBE_HASH", "")[1:] }}
|
|
||||||
script: $PYTHON setup.py install
|
|
||||||
|
|
||||||
requirements:
|
|
||||||
build:
|
|
||||||
- python 3.5.*
|
|
||||||
run:
|
|
||||||
- python 3.5.*
|
|
||||||
|
|
||||||
test:
|
|
||||||
imports:
|
|
||||||
- migen
|
|
||||||
|
|
||||||
about:
|
|
||||||
home: http://m-labs.hk/gateware.html
|
|
||||||
license: 3-clause BSD
|
|
||||||
summary: 'A Python toolbox for building complex digital hardware'
|
|
130
doc/Makefile
130
doc/Makefile
|
@ -1,130 +0,0 @@
|
||||||
# Makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
|
||||||
SPHINXOPTS =
|
|
||||||
SPHINXBUILD = sphinx-build
|
|
||||||
PAPER =
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Internal variables.
|
|
||||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
|
||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
|
||||||
|
|
||||||
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 " qthelp to make HTML files and a qthelp project"
|
|
||||||
@echo " devhelp to make HTML files and a Devhelp 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 " text to make text files"
|
|
||||||
@echo " man to make manual pages"
|
|
||||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
|
||||||
@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."
|
|
||||||
|
|
||||||
qthelp:
|
|
||||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Migen.qhcp"
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Migen.qhc"
|
|
||||||
|
|
||||||
devhelp:
|
|
||||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished."
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Migen"
|
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Migen"
|
|
||||||
@echo "# devhelp"
|
|
||||||
|
|
||||||
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."
|
|
||||||
|
|
||||||
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."
|
|
||||||
|
|
||||||
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."
|
|
0
doc/_build/.keep_me
vendored
0
doc/_build/.keep_me
vendored
0
doc/_static/.keep_me
vendored
0
doc/_static/.keep_me
vendored
0
doc/_templates/.keep_me
vendored
0
doc/_templates/.keep_me
vendored
223
doc/conf.py
223
doc/conf.py
|
@ -1,223 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Migen documentation build configuration file, created by
|
|
||||||
# sphinx-quickstart on Fri Mar 9 14:11:54 2012.
|
|
||||||
#
|
|
||||||
# This file is execfile()d with the current directory set to its containing dir.
|
|
||||||
#
|
|
||||||
# Note that not all possible configuration values are present in this
|
|
||||||
# autogenerated file.
|
|
||||||
#
|
|
||||||
# All configuration values have a default; values that are commented out
|
|
||||||
# serve to show the default.
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
#sys.path.insert(0, os.path.abspath('.'))
|
|
||||||
|
|
||||||
# -- General configuration -----------------------------------------------------
|
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
|
||||||
#needs_sphinx = '1.0'
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
|
||||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
|
||||||
extensions = [
|
|
||||||
'sphinx.ext.pngmath',
|
|
||||||
'sphinx.ext.autodoc',
|
|
||||||
'sphinx.ext.doctest',
|
|
||||||
'sphinx.ext.autosummary',
|
|
||||||
'numpydoc', # to preprocess docstrings
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix of source filenames.
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The encoding of source files.
|
|
||||||
#source_encoding = 'utf-8-sig'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = u'Migen'
|
|
||||||
copyright = u'2011-2015, M-Labs Limited'
|
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
|
||||||
# |version| and |release|, also used in various other places throughout the
|
|
||||||
# built documents.
|
|
||||||
#
|
|
||||||
# The short X.Y version.
|
|
||||||
version = '1.0'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = '1.0'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#language = None
|
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
|
||||||
# non-false value, then it is used:
|
|
||||||
#today = ''
|
|
||||||
# Else, today_fmt is used as the format for a strftime call.
|
|
||||||
#today_fmt = '%B %d, %Y'
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
exclude_patterns = ['_build']
|
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
|
||||||
#default_role = None
|
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
|
||||||
#add_function_parentheses = True
|
|
||||||
|
|
||||||
# If true, the current module name will be prepended to all description
|
|
||||||
# unit titles (such as .. function::).
|
|
||||||
#add_module_names = True
|
|
||||||
|
|
||||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
|
||||||
# output. They are ignored by default.
|
|
||||||
#show_authors = False
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
|
||||||
modindex_common_prefix = ['migen.']
|
|
||||||
|
|
||||||
numpydoc_show_class_members = False
|
|
||||||
|
|
||||||
# -- Options for HTML output ---------------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
html_theme = 'alabaster'
|
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
|
||||||
# further. For a list of options available for each theme, see the
|
|
||||||
# documentation.
|
|
||||||
#html_theme_options = {}
|
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
|
||||||
#html_theme_path = []
|
|
||||||
|
|
||||||
# The name for this set of Sphinx documents. If None, it defaults to
|
|
||||||
# "<project> v<release> documentation".
|
|
||||||
#html_title = None
|
|
||||||
|
|
||||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
|
||||||
#html_short_title = None
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top
|
|
||||||
# of the sidebar.
|
|
||||||
#html_logo = None
|
|
||||||
|
|
||||||
# The name of an image file (within the static path) to use as favicon of the
|
|
||||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
|
||||||
# pixels large.
|
|
||||||
#html_favicon = None
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
|
||||||
# using the given strftime format.
|
|
||||||
#html_last_updated_fmt = '%b %d, %Y'
|
|
||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
|
||||||
# typographically correct entities.
|
|
||||||
#html_use_smartypants = True
|
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
|
||||||
#html_sidebars = {}
|
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
|
||||||
# template names.
|
|
||||||
#html_additional_pages = {}
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#html_domain_indices = True
|
|
||||||
|
|
||||||
# If false, no index is generated.
|
|
||||||
#html_use_index = True
|
|
||||||
|
|
||||||
# If true, the index is split into individual pages for each letter.
|
|
||||||
#html_split_index = False
|
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
|
||||||
#html_show_sourcelink = True
|
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_sphinx = True
|
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_copyright = True
|
|
||||||
|
|
||||||
# If true, an OpenSearch description file will be output, and all pages will
|
|
||||||
# contain a <link> tag referring to it. The value of this option must be the
|
|
||||||
# base URL from which the finished HTML is served.
|
|
||||||
#html_use_opensearch = ''
|
|
||||||
|
|
||||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
|
||||||
#html_file_suffix = None
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = 'Migendoc'
|
|
||||||
|
|
||||||
html_use_modindex = False
|
|
||||||
|
|
||||||
# -- Options for LaTeX output --------------------------------------------------
|
|
||||||
|
|
||||||
# The paper size ('letter' or 'a4').
|
|
||||||
#latex_paper_size = 'letter'
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#latex_font_size = '10pt'
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
|
||||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
|
||||||
latex_documents = [
|
|
||||||
('index', 'Migen.tex', u'Migen manual',
|
|
||||||
u'Sebastien Bourdeauducq', 'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
|
||||||
# the title page.
|
|
||||||
latex_logo = "migen_logo.png"
|
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
|
||||||
# not chapters.
|
|
||||||
#latex_use_parts = False
|
|
||||||
|
|
||||||
# If true, show page references after internal links.
|
|
||||||
#latex_show_pagerefs = False
|
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
|
||||||
#latex_show_urls = False
|
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
latex_preamble = '\setcounter{tocdepth}{3}'
|
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
|
||||||
#latex_appendices = []
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#latex_domain_indices = True
|
|
||||||
|
|
||||||
latex_use_modindex = False
|
|
||||||
|
|
||||||
# -- Options for manual page output --------------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
('index', 'migen', u'Migen manual',
|
|
||||||
[u'Sebastien Bourdeauducq'], 1)
|
|
||||||
]
|
|
362
doc/fhdl.rst
362
doc/fhdl.rst
|
@ -1,362 +0,0 @@
|
||||||
The FHDL domain-specific language
|
|
||||||
#################################
|
|
||||||
|
|
||||||
The Fragmented Hardware Description Language (FHDL) is the basis of Migen. It consists of a formal system to describe signals, and combinatorial and synchronous statements operating on them. The formal system itself is low level and close to the synthesizable subset of Verilog, and we then rely on Python algorithms to build complex structures by combining FHDL elements.
|
|
||||||
The FHDL module also contains a back-end to produce synthesizable Verilog, and some structure analysis and manipulation functionality.
|
|
||||||
|
|
||||||
FHDL differs from MyHDL [myhdl]_ in fundamental ways. MyHDL follows the event-driven paradigm of traditional HDLs (see :ref:`background`) while FHDL separates the code into combinatorial statements, synchronous statements, and reset values. In MyHDL, the logic is described directly in the Python AST. The converter to Verilog or VHDL then examines the Python AST and recognizes a subset of Python that it translates into V*HDL statements. This seriously impedes the capability of MyHDL to generate logic procedurally. With FHDL, you manipulate a custom AST from Python, and you can more easily design algorithms that operate on it.
|
|
||||||
|
|
||||||
.. [myhdl] http://www.myhdl.org
|
|
||||||
|
|
||||||
FHDL is made of several elements, which are briefly explained below. They all can be imported directly from the ``migen`` module.
|
|
||||||
|
|
||||||
Expressions
|
|
||||||
***********
|
|
||||||
|
|
||||||
Constants
|
|
||||||
=========
|
|
||||||
|
|
||||||
The ``Constant`` object represents a constant, HDL-literal integer. It behaves like specifying integers and booleans but also supports slicing and can have a bit width or signedness different from what is implied by the value it represents.
|
|
||||||
|
|
||||||
``True`` and ``False`` are interpreted as 1 and 0, respectively.
|
|
||||||
|
|
||||||
Negative integers are explicitly supported. As with MyHDL [countin]_, arithmetic operations return the natural results.
|
|
||||||
|
|
||||||
To lighten the syntax, assignments and operators automatically wrap Python integers and booleans into ``Constant``. Additionally, ``Constant`` is aliased to ``C``. The following are valid Migen statements: ``a.eq(0)``, ``a.eq(a + 1)``, ``a.eq(C(42)[0:1])``.
|
|
||||||
|
|
||||||
.. [countin] http://www.jandecaluwe.com/hdldesign/counting.html
|
|
||||||
|
|
||||||
Signal
|
|
||||||
======
|
|
||||||
|
|
||||||
The signal object represents a value that is expected to change in the circuit. It does exactly what Verilog's "wire" and "reg" and VHDL's "signal" do.
|
|
||||||
|
|
||||||
The main point of the signal object is that it is identified by its Python ID (as returned by the :py:func:`id` function), and nothing else. It is the responsibility of the V*HDL back-end to establish an injective mapping between Python IDs and the V*HDL namespace. It should perform name mangling to ensure this. The consequence of this is that signal objects can safely become members of arbitrary Python classes, or be passed as parameters to functions or methods that generate logic involving them.
|
|
||||||
|
|
||||||
The properties of a signal object are:
|
|
||||||
|
|
||||||
* An integer or a (integer, boolean) pair that defines the number of bits and whether the bit of higher index of the signal is a sign bit (i.e. the signal is signed). The defaults are one bit and unsigned. Alternatively, the ``min`` and ``max`` parameters can be specified to define the range of the signal and determine its bit width and signedness. As with Python ranges, ``min`` is inclusive and defaults to 0, ``max`` is exclusive and defaults to 2.
|
|
||||||
* A name, used as a hint for the V*HDL back-end name mangler.
|
|
||||||
* The signal's reset value. It must be an integer, and defaults to 0. When the signal's value is modified with a synchronous statement, the reset value is the initialization value of the associated register. When the signal is assigned to in a conditional combinatorial statement (``If`` or ``Case``), the reset value is the value that the signal has when no condition that causes the signal to be driven is verified. This enforces the absence of latches in designs. If the signal is permanently driven using a combinatorial statement, the reset value has no effect.
|
|
||||||
|
|
||||||
The sole purpose of the name property is to make the generated V*HDL code easier to understand and debug. From a purely functional point of view, it is perfectly OK to have several signals with the same name property. The back-end will generate a unique name for each object. If no name property is specified, Migen will analyze the code that created the signal object, and try to extract the variable or member name from there. For example, the following statements will create one or several signals named "bar": ::
|
|
||||||
|
|
||||||
bar = Signal()
|
|
||||||
self.bar = Signal()
|
|
||||||
self.baz.bar = Signal()
|
|
||||||
bar = [Signal() for x in range(42)]
|
|
||||||
|
|
||||||
In case of conflicts, Migen tries first to resolve the situation by prefixing the identifiers with names from the class and module hierarchy that created them. If the conflict persists (which can be the case if two signal objects are created with the same name in the same context), it will ultimately add number suffixes.
|
|
||||||
|
|
||||||
Operators
|
|
||||||
=========
|
|
||||||
|
|
||||||
Operators are represented by the ``_Operator`` object, which generally should not be used directly. Instead, most FHDL objects overload the usual Python logic and arithmetic operators, which allows a much lighter syntax to be used. For example, the expression: ::
|
|
||||||
|
|
||||||
a * b + c
|
|
||||||
|
|
||||||
is equivalent to::
|
|
||||||
|
|
||||||
_Operator("+", [_Operator("*", [a, b]), c])
|
|
||||||
|
|
||||||
Slices
|
|
||||||
======
|
|
||||||
|
|
||||||
Likewise, slices are represented by the ``_Slice`` object, which often should not be used in favor of the Python slice operation [x:y]. Implicit indices using the forms [x], [x:] and [:y] are supported. Beware! Slices work like Python slices, not like VHDL or Verilog slices. The first bound is the index of the LSB and is inclusive. The second bound is the index of MSB and is exclusive. In V*HDL, bounds are MSB:LSB and both are inclusive.
|
|
||||||
|
|
||||||
Concatenations
|
|
||||||
==============
|
|
||||||
|
|
||||||
Concatenations are done using the ``Cat`` object. To make the syntax lighter, its constructor takes a variable number of arguments, which are the signals to be concatenated together (you can use the Python "*" operator to pass a list instead).
|
|
||||||
To be consistent with slices, the first signal is connected to the bits with the lowest indices in the result. This is the opposite of the way the "{}" construct works in Verilog.
|
|
||||||
|
|
||||||
Replications
|
|
||||||
============
|
|
||||||
|
|
||||||
The ``Replicate`` object represents the equivalent of {count{expression}} in Verilog.
|
|
||||||
|
|
||||||
Statements
|
|
||||||
**********
|
|
||||||
|
|
||||||
Assignment
|
|
||||||
==========
|
|
||||||
|
|
||||||
Assignments are represented with the ``_Assign`` object. Since using it directly would result in a cluttered syntax, the preferred technique for assignments is to use the ``eq()`` method provided by objects that can have a value assigned to them. They are signals, and their combinations with the slice and concatenation operators.
|
|
||||||
As an example, the statement: ::
|
|
||||||
|
|
||||||
a[0].eq(b)
|
|
||||||
|
|
||||||
is equivalent to: ::
|
|
||||||
|
|
||||||
_Assign(_Slice(a, 0, 1), b)
|
|
||||||
|
|
||||||
If
|
|
||||||
==
|
|
||||||
|
|
||||||
The ``If`` object takes a first parameter which must be an expression (combination of the ``Constant``, ``Signal``, ``_Operator``, ``_Slice``, etc. objects) representing the condition, then a variable number of parameters representing the statements (``_Assign``, ``If``, ``Case``, etc. objects) to be executed when the condition is verified.
|
|
||||||
|
|
||||||
The ``If`` object defines a ``Else()`` method, which when called defines the statements to be executed when the condition is not true. Those statements are passed as parameters to the variadic method.
|
|
||||||
|
|
||||||
For convenience, there is also a ``Elif()`` method.
|
|
||||||
|
|
||||||
Example: ::
|
|
||||||
|
|
||||||
If(tx_count16 == 0,
|
|
||||||
tx_bitcount.eq(tx_bitcount + 1),
|
|
||||||
If(tx_bitcount == 8,
|
|
||||||
self.tx.eq(1)
|
|
||||||
).Elif(tx_bitcount == 9,
|
|
||||||
self.tx.eq(1),
|
|
||||||
tx_busy.eq(0)
|
|
||||||
).Else(
|
|
||||||
self.tx.eq(tx_reg[0]),
|
|
||||||
tx_reg.eq(Cat(tx_reg[1:], 0))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
Case
|
|
||||||
====
|
|
||||||
|
|
||||||
The ``Case`` object constructor takes as first parameter the expression to be tested, and a dictionary whose keys are the values to be matched, and values the statements to be executed in the case of a match. The special value ``"default"`` can be used as match value, which means the statements should be executed whenever there is no other match.
|
|
||||||
|
|
||||||
Arrays
|
|
||||||
======
|
|
||||||
|
|
||||||
The ``Array`` object represents lists of other objects that can be indexed by FHDL expressions. It is explicitly possible to:
|
|
||||||
|
|
||||||
* nest ``Array`` objects to create multidimensional tables.
|
|
||||||
* list any Python object in a ``Array`` as long as every expression appearing in a module ultimately evaluates to a ``Signal`` for all possible values of the indices. This allows the creation of lists of structured data.
|
|
||||||
* use expressions involving ``Array`` objects in both directions (assignment and reading).
|
|
||||||
|
|
||||||
For example, this creates a 4x4 matrix of 1-bit signals: ::
|
|
||||||
|
|
||||||
my_2d_array = Array(Array(Signal() for a in range(4)) for b in range(4))
|
|
||||||
|
|
||||||
You can then read the matrix with (``x`` and ``y`` being 2-bit signals): ::
|
|
||||||
|
|
||||||
out.eq(my_2d_array[x][y])
|
|
||||||
|
|
||||||
and write it with: ::
|
|
||||||
|
|
||||||
my_2d_array[x][y].eq(inp)
|
|
||||||
|
|
||||||
Since they have no direct equivalent in Verilog, ``Array`` objects are lowered into multiplexers and conditional statements before the actual conversion takes place. Such lowering happens automatically without any user intervention.
|
|
||||||
|
|
||||||
Specials
|
|
||||||
********
|
|
||||||
|
|
||||||
Tri-state I/O
|
|
||||||
=============
|
|
||||||
|
|
||||||
A triplet (O, OE, I) of one-way signals defining a tri-state I/O port is represented by the ``TSTriple`` object. Such objects are only containers for signals that are intended to be later connected to a tri-state I/O buffer, and cannot be used as module specials. Such objects, however, should be kept in the design as long as possible as they allow the individual one-way signals to be manipulated in a non-ambiguous way.
|
|
||||||
|
|
||||||
The object that can be used in as a module special is ``Tristate``, and it behaves exactly like an instance of a tri-state I/O buffer that would be defined as follows: ::
|
|
||||||
|
|
||||||
Instance("Tristate",
|
|
||||||
io_target=target,
|
|
||||||
i_o=o,
|
|
||||||
i_oe=oe,
|
|
||||||
o_i=i
|
|
||||||
)
|
|
||||||
|
|
||||||
Signals ``target``, ``o`` and ``i`` can have any width, while ``oe`` is 1-bit wide. The ``target`` signal should go to a port and not be used elsewhere in the design. Like modern FPGA architectures, Migen does not support internal tri-states.
|
|
||||||
|
|
||||||
A ``Tristate`` object can be created from a ``TSTriple`` object by calling the ``get_tristate`` method.
|
|
||||||
|
|
||||||
By default, Migen emits technology-independent behavioral code for a tri-state buffer. If a specific code is needed, the tristate handler can be overriden using the appropriate parameter of the V*HDL conversion function.
|
|
||||||
|
|
||||||
Instances
|
|
||||||
=========
|
|
||||||
|
|
||||||
Instance objects represent the parametrized instantiation of a V*HDL module, and the connection of its ports to FHDL signals. They are useful in a number of cases:
|
|
||||||
|
|
||||||
* Reusing legacy or third-party V*HDL code.
|
|
||||||
* Using special FPGA features (DCM, ICAP, ...).
|
|
||||||
* Implementing logic that cannot be expressed with FHDL (e.g. latches).
|
|
||||||
* Breaking down a Migen system into multiple sub-systems.
|
|
||||||
|
|
||||||
The instance object constructor takes the type (i.e. name of the instantiated module) of the instance, then multiple parameters describing how to connect and parametrize the instance.
|
|
||||||
|
|
||||||
These parameters can be:
|
|
||||||
|
|
||||||
* ``Instance.Input``, ``Instance.Output`` or ``Instance.InOut`` to describe signal connections with the instance. The parameters are the name of the port at the instance, and the FHDL expression it should be connected to.
|
|
||||||
* ``Instance.Parameter`` sets a parameter (with a name and value) of the instance.
|
|
||||||
* ``Instance.ClockPort`` and ``Instance.ResetPort`` are used to connect clock and reset signals to the instance. The only mandatory parameter is the name of the port at the instance. Optionally, a clock domain name can be specified, and the ``invert`` option can be used to interface to those modules that require a 180-degree clock or a active-low reset.
|
|
||||||
|
|
||||||
Memories
|
|
||||||
========
|
|
||||||
|
|
||||||
Memories (on-chip SRAM) are supported using a mechanism similar to instances.
|
|
||||||
|
|
||||||
A memory object has the following parameters:
|
|
||||||
|
|
||||||
* The width, which is the number of bits in each word.
|
|
||||||
* The depth, which represents the number of words in the memory.
|
|
||||||
* An optional list of integers used to initialize the memory.
|
|
||||||
|
|
||||||
To access the memory in hardware, ports can be obtained by calling the ``get_port`` method. A port always has an address signal ``a`` and a data read signal ``dat_r``. Other signals may be available depending on the port's configuration.
|
|
||||||
|
|
||||||
Options to ``get_port`` are:
|
|
||||||
|
|
||||||
* ``write_capable`` (default: ``False``): if the port can be used to write to the memory. This creates an additional ``we`` signal.
|
|
||||||
* ``async_read`` (default: ``False``): whether reads are asychronous (combinatorial) or synchronous (registered).
|
|
||||||
* ``has_re`` (default: ``False``): adds a read clock-enable signal ``re`` (ignored for asychronous ports).
|
|
||||||
* ``we_granularity`` (default: ``0``): if non-zero, writes of less than a memory word can occur. The width of the ``we`` signal is increased to act as a selection signal for the sub-words.
|
|
||||||
* ``mode`` (default: ``WRITE_FIRST``, ignored for aynchronous ports). It can be:
|
|
||||||
|
|
||||||
* ``READ_FIRST``: during a write, the previous value is read.
|
|
||||||
* ``WRITE_FIRST``: the written value is returned.
|
|
||||||
* ``NO_CHANGE``: the data read signal keeps its previous value on a write.
|
|
||||||
|
|
||||||
* ``clock_domain`` (default: ``"sys"``): the clock domain used for reading and writing from this port.
|
|
||||||
|
|
||||||
Migen generates behavioural V*HDL code that should be compatible with all simulators and, if the number of ports is <= 2, most FPGA synthesizers. If a specific code is needed, the memory handler can be overriden using the appropriate parameter of the V*HDL conversion function.
|
|
||||||
|
|
||||||
Inline synthesis directives
|
|
||||||
===========================
|
|
||||||
|
|
||||||
Inline synthesis directives (pseudo-comments such as ``// synthesis attribute keep of clock_signal_name is true``) are supported using the ``SynthesisDirective`` object. Its constructor takes as parameters a string containing the body of the directive, and optional keyword parameters that are used to replace signal names similarly to the Python string method ``format``. The above example could be represented as follows: ::
|
|
||||||
|
|
||||||
SynthesisDirective("attribute keep of {clksig} is true", clksig=clock_domain.clk)
|
|
||||||
|
|
||||||
Modules
|
|
||||||
*******
|
|
||||||
|
|
||||||
Modules play the same role as Verilog modules and VHDL entities. Similarly, they are organized in a tree structure. A FHDL module is a Python object that derives from the ``Module`` class. This class defines special attributes to be used by derived classes to describe their logic. They are explained below.
|
|
||||||
|
|
||||||
Combinatorial statements
|
|
||||||
========================
|
|
||||||
|
|
||||||
A combinatorial statement is a statement that is executed whenever one of its inputs changes.
|
|
||||||
|
|
||||||
Combinatorial statements are added to a module by using the ``comb`` special attribute. Like most module special attributes, it must be accessed using the ``+=`` incrementation operator, and either a single statement, a tuple of statements or a list of statements can appear on the right hand side.
|
|
||||||
|
|
||||||
For example, the module below implements a OR gate: ::
|
|
||||||
|
|
||||||
class ORGate(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.a = Signal()
|
|
||||||
self.b = Signal()
|
|
||||||
self.x = Signal()
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
self.comb += x.eq(a | b)
|
|
||||||
|
|
||||||
To improve code readability, it is recommended to place the interface of the module at the beginning of the ``__init__`` function, and separate it from the implementation using three hash signs.
|
|
||||||
|
|
||||||
Synchronous statements
|
|
||||||
======================
|
|
||||||
|
|
||||||
A synchronous statements is a statement that is executed at each edge of some clock signal.
|
|
||||||
|
|
||||||
They are added to a module by using the ``sync`` special attribute, which has the same properties as the ``comb`` attribute.
|
|
||||||
|
|
||||||
The ``sync`` special attribute also has sub-attributes that correspond to abstract clock domains. For example, to add a statement to the clock domain named ``foo``, one would write ``self.sync.foo += statement``. The default clock domain is ``sys`` and writing ``self.sync += statement`` is equivalent to writing ``self.sync.sys += statement``.
|
|
||||||
|
|
||||||
Submodules and specials
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Submodules and specials can be added by using the ``submodules`` and ``specials`` attributes respectively. This can be done in two ways:
|
|
||||||
|
|
||||||
#. anonymously, by using the ``+=`` operator on the special attribute directly, e.g. ``self.submodules += some_other_module``. Like with the ``comb`` and ``sync`` attributes, a single module/special or a tuple or list can be specified.
|
|
||||||
#. by naming the submodule/special using a subattribute of the ``submodules`` or ``specials`` attribute, e.g. ``self.submodules.foo = module_foo``. The submodule/special is then accessible as an attribute of the object, e.g. ``self.foo`` (and not ``self.submodules.foo``). Only one submodule/special can be added at a time using this form.
|
|
||||||
|
|
||||||
Clock domains
|
|
||||||
=============
|
|
||||||
|
|
||||||
Specifying the implementation of a clock domain is done using the ``ClockDomain`` object. It contains the name of the clock domain, a clock signal that can be driven like any other signal in the design (for example, using a PLL instance), and optionally a reset signal. Clock domains without a reset signal are reset using e.g. ``initial`` statements in Verilog, which in many FPGA families initalize the registers during configuration.
|
|
||||||
|
|
||||||
The name can be omitted if it can be extracted from the variable name. When using this automatic naming feature, prefixes ``_``, ``cd_`` and ``_cd_`` are removed.
|
|
||||||
|
|
||||||
Clock domains are then added to a module using the ``clock_domains`` special attribute, which behaves exactly like ``submodules`` and ``specials``.
|
|
||||||
|
|
||||||
Summary of special attributes
|
|
||||||
=============================
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| Syntax | Action |
|
|
||||||
+============================================+==============================================================+
|
|
||||||
| self.comb += stmt | Add combinatorial statement to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.comb += stmtA, stmtB | Add combinatorial statements A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.comb += [stmtA, stmtB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.sync += stmt | Add synchronous statement to current module, in default |
|
|
||||||
| | clock domain sys. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.sync.foo += stmt | Add synchronous statement to current module, in clock domain |
|
|
||||||
| | foo. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.sync.foo += stmtA, stmtB | Add synchronous statements A and B to current module, in |
|
|
||||||
| | clock domain foo. |
|
|
||||||
| self.sync.foo += [stmtA, stmtB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.submodules += mod | Add anonymous submodule to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.submodules += modA, modB | Add anonymous submodules A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.submodules += [modA, modB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.submodules.bar = mod | Add submodule named bar to current module. The submodule can |
|
|
||||||
| | then be accessed using self.bar. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.specials += spe | Add anonymous special to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.specials += speA, speB | Add anonymous specials A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.specials += [speA, speB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.specials.bar = spe | Add special named bar to current module. The special can |
|
|
||||||
| | then be accessed using self.bar. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.clock_domains += cd | Add clock domain to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.clock_domains += cdA, cdB | Add clock domains A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.clock_domains += [cdA, cdB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.clock_domains.pix = ClockDomain() | Create and add clock domain pix to current module. The clock |
|
|
||||||
| | domain name is pix in all cases. It can be accessed using |
|
|
||||||
| self.clock_domains._pix = ClockDomain() | self.pix, self._pix, self.cd_pix and self._cd_pix, |
|
|
||||||
| | respectively. |
|
|
||||||
| self.clock_domains.cd_pix = ClockDomain() | |
|
|
||||||
| | |
|
|
||||||
| self.clock_domains._cd_pix = ClockDomain() | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
|
|
||||||
Clock domain management
|
|
||||||
=======================
|
|
||||||
|
|
||||||
When a module has named submodules that define one or several clock domains with the same name, those clock domain names are prefixed with the name of each submodule plus an underscore.
|
|
||||||
|
|
||||||
An example use case of this feature is a system with two independent video outputs. Each video output module is made of a clock generator module that defines a clock domain ``pix`` and drives the clock signal, plus a driver module that has synchronous statements and other elements in clock domain ``pix``. The designer of the video output module can simply use the clock domain name ``pix`` in that module. In the top-level system module, the video output submodules are named ``video0`` and ``video1``. Migen then automatically renames the ``pix`` clock domain of each module to ``video0_pix`` and ``video1_pix``. Note that happens only because the clock domain is defined (using ClockDomain objects), not simply referenced (using e.g. synchronous statements) in the video output modules.
|
|
||||||
|
|
||||||
Clock domain name overlap is an error condition when any of the submodules that defines the clock domains is anonymous.
|
|
||||||
|
|
||||||
Finalization mechanism
|
|
||||||
======================
|
|
||||||
|
|
||||||
Sometimes, it is desirable that some of a module logic be created only after the user has finished manipulating that module. For example, the FSM module supports that states be defined dynamically, and the width of the state signal can be known only after all states have been added. One solution is to declare the final number of states in the FSM constructor, but this is not user-friendly. A better solution is to automatically create the state signal just before the FSM module is converted to V*HDL. Migen supports this using the so-called finalization mechanism.
|
|
||||||
|
|
||||||
Modules can overload a ``do_finalize`` method that can create logic and is called using the algorithm below:
|
|
||||||
|
|
||||||
#. Finalization of the current module begins.
|
|
||||||
#. If the module has already been finalized (e.g. manually), the procedure stops here.
|
|
||||||
#. Submodules of the current module are recursively finalized.
|
|
||||||
#. ``do_finalize`` is called for the current module.
|
|
||||||
#. Any new submodules created by the current module's ``do_finalize`` are recursively finalized.
|
|
||||||
|
|
||||||
Finalization is automatically invoked at V*HDL conversion and at simulation. It can be manually invoked for any module by calling its ``finalize`` method.
|
|
||||||
|
|
||||||
The clock domain management mechanism explained above happens during finalization.
|
|
||||||
|
|
||||||
Conversion for synthesis
|
|
||||||
************************
|
|
||||||
|
|
||||||
Any FHDL module can be converted into synthesizable Verilog HDL. This is accomplished by using the ``convert`` function in the ``verilog`` module.
|
|
||||||
|
|
||||||
The ``migen.build`` component provides scripts to interface third-party FPGA tools (from Xilinx, Altera and Lattice) to Migen, and a database of boards for the easy deployment of designs.
|
|
|
@ -1,11 +0,0 @@
|
||||||
Migen manual
|
|
||||||
############
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
introduction
|
|
||||||
fhdl
|
|
||||||
simulation
|
|
||||||
synthesis
|
|
||||||
reference
|
|
|
@ -1,73 +0,0 @@
|
||||||
Introduction
|
|
||||||
############
|
|
||||||
|
|
||||||
Migen is a Python-based tool that aims at automating further the VLSI design process.
|
|
||||||
|
|
||||||
Migen makes it possible to apply modern software concepts such as object-oriented programming and metaprogramming to design hardware. This results in more elegant and easily maintained designs and reduces the incidence of human errors.
|
|
||||||
|
|
||||||
.. _background:
|
|
||||||
|
|
||||||
Background
|
|
||||||
**********
|
|
||||||
|
|
||||||
Even though the Milkymist system-on-chip [mm]_ had many successes, it suffers from several limitations stemming from its implementation in manually written Verilog HDL:
|
|
||||||
|
|
||||||
.. [mm] http://m-labs.hk
|
|
||||||
|
|
||||||
#. The "event-driven" paradigm of today's dominant hardware descriptions languages (Verilog and VHDL, collectively referred to as "V*HDL" in the rest of this document) is often too general. Today's FPGA architectures are optimized for the implementation of fully synchronous circuits. This means that the bulk of the code for an efficient FPGA design falls into three categories:
|
|
||||||
|
|
||||||
#. Combinatorial statements
|
|
||||||
#. Synchronous statements
|
|
||||||
#. Initialization of registers at reset
|
|
||||||
|
|
||||||
V*HDL do not follow this organization. This means that a lot of repetitive manual coding is needed, which brings sources of human errors, petty issues, and confusion for beginners:
|
|
||||||
|
|
||||||
#. wire vs. reg in Verilog
|
|
||||||
#. forgetting to initialize a register at reset
|
|
||||||
#. deciding whether a combinatorial statement must go into a process/always block or not
|
|
||||||
#. simulation mismatches with combinatorial processes/always blocks
|
|
||||||
#. and more...
|
|
||||||
|
|
||||||
A little-known fact about FPGAs is that many of them have the ability to initialize their registers from the bitstream contents. This can be done in a portable and standard way using an "initial" block in Verilog, and by affecting a value at the signal declaration in VHDL. This renders an explicit reset signal unnecessary in practice in some cases, which opens the way for further design optimization. However, this form of initialization is entirely not synthesizable for ASIC targets, and it is not easy to switch between the two forms of reset using V*HDL.
|
|
||||||
|
|
||||||
#. V*HDL support for composite types is very limited. Signals having a record type in VHDL are unidirectional, which makes them clumsy to use e.g. in bus interfaces. There is no record type support in Verilog, which means that a lot of copy-and-paste has to be done when forwarding grouped signals.
|
|
||||||
|
|
||||||
#. V*HDL support for procedurally generated logic is extremely limited. The most advanced forms of procedural generation of synthesizable logic that V*HDL offers are CPP-style directives in Verilog, combinatorial functions, and ``generate`` statements. Nothing really fancy, and it shows. To give a few examples:
|
|
||||||
|
|
||||||
#. Building highly flexible bus interconnect is not possible. Even arbitrating any given number of bus masters for commonplace protocols such as Wishbone is difficult with the tools that V*HDL puts at our disposal.
|
|
||||||
#. Building a memory infrastructure (including bus interconnect, bridges and caches) that can automatically adapt itself at compile-time to any word size of the SDRAM is clumsy and tedious.
|
|
||||||
#. Building register banks for control, status and interrupt management of cores can also largely benefit from automation.
|
|
||||||
#. Many hardware acceleration problems can fit into the dataflow programming model. Manual dataflow implementation in V*HDL has, again, a lot of redundancy and potential for human errors. See the Milkymist texture mapping unit [mthesis]_ [mxcell]_ for an example of this. The amount of detail to deal with manually also makes the design space exploration difficult, and therefore hinders the design of efficient architectures.
|
|
||||||
#. Pre-computation of values, such as filter coefficients for DSP or even simply trigonometric tables, must often be done using external tools whose results are copy-and-pasted (in the best case, automatically) into the V*HDL source.
|
|
||||||
|
|
||||||
.. [mthesis] http://m-labs.hk/thesis/thesis.pdf
|
|
||||||
.. [mxcell] http://www.xilinx.com/publications/archives/xcell/Xcell77.pdf p30-35
|
|
||||||
|
|
||||||
Enter Migen, a Python toolbox for building complex digital hardware. We could have designed a brand new programming language, but that would have been reinventing the wheel instead of being able to benefit from Python's rich features and immense library. The price to pay is a slightly cluttered syntax at times when writing descriptions in FHDL, but we believe this is totally acceptable, particularly when compared to VHDL ;-)
|
|
||||||
|
|
||||||
Migen is made up of several related components:
|
|
||||||
|
|
||||||
#. the base language, FHDL
|
|
||||||
#. a library of small generic cores
|
|
||||||
#. a simulator
|
|
||||||
#. a build system
|
|
||||||
|
|
||||||
Installing Migen
|
|
||||||
****************
|
|
||||||
|
|
||||||
Either run the ``setup.py`` installation script or simply set ``PYTHONPATH`` to the root of the source directory.
|
|
||||||
|
|
||||||
If you wish to contribute patches, the suggest way to install is;
|
|
||||||
#. Clone from the git repository at http://github.com/m-labs/migen
|
|
||||||
#. Install using ``python3 ./setup.py develop --user``
|
|
||||||
#. Edit the code in your git checkout.
|
|
||||||
|
|
||||||
Alternative install methods
|
|
||||||
===========================
|
|
||||||
|
|
||||||
* Migen is available for the Anaconda Python distribution. The package can be found at at https://anaconda.org/m-labs/migen
|
|
||||||
* Migen can be referenced in a requirements.txt file (used for ``pip install -r requirements.txt``) via ``-e git+http://github.com/m-labs/migen.git#egg=migen``. See the pip documentation for more information.
|
|
||||||
|
|
||||||
Feedback
|
|
||||||
********
|
|
||||||
Feedback concerning Migen or this manual should be sent to the M-Labs developers' mailing list ``devel`` on lists.m-labs.hk.
|
|
Binary file not shown.
Before Width: | Height: | Size: 73 KiB |
|
@ -1,224 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="159.05869"
|
|
||||||
height="106.55"
|
|
||||||
id="svg3245"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.1 r9760"
|
|
||||||
sodipodi:docname="migen.svg"
|
|
||||||
inkscape:export-filename="/home/lekernel/migen.png"
|
|
||||||
inkscape:export-xdpi="184.10001"
|
|
||||||
inkscape:export-ydpi="184.10001">
|
|
||||||
<defs
|
|
||||||
id="defs3247">
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient6093">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2ca22c;stop-opacity:0;"
|
|
||||||
offset="0"
|
|
||||||
id="stop6095" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2ca22c;stop-opacity:1;"
|
|
||||||
offset="1"
|
|
||||||
id="stop6097" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient6047">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop6049" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#ffffff;stop-opacity:0;"
|
|
||||||
offset="1"
|
|
||||||
id="stop6051" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#a"
|
|
||||||
id="linearGradient6176"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.24477,0,0,0.24477,203.271,213.559)"
|
|
||||||
x1="150.95"
|
|
||||||
y1="-22.384001"
|
|
||||||
x2="252.2"
|
|
||||||
y2="204.03999" />
|
|
||||||
<linearGradient
|
|
||||||
id="a"
|
|
||||||
y2="150.32001"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
y1="13.899"
|
|
||||||
x2="200.5"
|
|
||||||
x1="200.5">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#fff"
|
|
||||||
offset=".1374"
|
|
||||||
id="stop7" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#509e10;stop-opacity:1;"
|
|
||||||
offset="1"
|
|
||||||
id="stop9" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#a"
|
|
||||||
id="linearGradient3345"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.24477,0,0,0.24477,203.271,213.559)"
|
|
||||||
x1="150.95"
|
|
||||||
y1="-22.384001"
|
|
||||||
x2="252.2"
|
|
||||||
y2="204.03999" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#a"
|
|
||||||
id="linearGradient3349"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.24477,0,0,0.24477,280.71427,440.33237)"
|
|
||||||
x1="150.95"
|
|
||||||
y1="-22.384001"
|
|
||||||
x2="252.2"
|
|
||||||
y2="204.03999" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient6047"
|
|
||||||
id="linearGradient6053"
|
|
||||||
x1="178.04323"
|
|
||||||
y1="474.42865"
|
|
||||||
x2="235.87062"
|
|
||||||
y2="474.42865"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.78422775,0,0,1,105.91918,-2.4999996)" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient6093"
|
|
||||||
id="linearGradient6099"
|
|
||||||
x1="242.87946"
|
|
||||||
y1="471.54514"
|
|
||||||
x2="289.73526"
|
|
||||||
y2="471.54514"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(1,0,0,1.1424088,0,-67.150429)" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="2.8"
|
|
||||||
inkscape:cx="134.13698"
|
|
||||||
inkscape:cy="59.325232"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1916"
|
|
||||||
inkscape:window-height="1117"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:guide-bbox="true"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata3250">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-242.87946,-440.32929)">
|
|
||||||
<rect
|
|
||||||
style="fill:url(#linearGradient6099);fill-opacity:1;stroke:none"
|
|
||||||
id="rect6043"
|
|
||||||
width="66.843575"
|
|
||||||
height="23.704336"
|
|
||||||
x="242.87946"
|
|
||||||
y="459.6947" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path29"
|
|
||||||
d="m 366.02427,471.24237 c -22.519,36.716 -73.921,29.454 -73.921,29.454 32.229,-32.229 0.16326,-57.929 0.16326,-57.929 0,0 51.973,-7.996 73.758,28.475"
|
|
||||||
style="font-size:18px;fill:#00ad00;fill-opacity:1;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path31"
|
|
||||||
d="m 366.02427,471.24237 c -22.519,36.716 -73.921,29.454 -73.921,29.454 32.229,-32.229 0.16326,-57.929 0.16326,-57.929 0,0 51.973,-7.996 73.758,28.475"
|
|
||||||
style="font-size:18px;fill:none;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<path
|
|
||||||
style="font-size:18px;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path33"
|
|
||||||
d="m 364.64427,470.43237 c -5.3108,8.6038 -12.825,15.435 -21.719,20.199 -7.7214,4.1357 -16.268,6.5868 -24.897,7.9228 -6.0011,0.92916 -12.11,1.2491 -18.178,1.0907 -1.8804,-0.0489 -3.76,-0.15102 -5.6339,-0.31747 -0.51696,-0.046 -1.0334,-0.0977 -1.5489,-0.15739 -0.29226,-0.0338 -0.85842,-0.11431 -0.14808,-0.0144 0.234,0.88632 0.468,1.7726 0.702,2.6592 8.3771,-8.431 15.128,-19.206 14.819,-31.472 -0.20072,-7.9507 -3.4638,-15.551 -8.2374,-21.816 -1.8852,-2.4739 -3.9815,-4.9329 -6.418,-6.8911 -0.234,0.88633 -0.46801,1.7729 -0.70201,2.6592 0.61487,-0.0942 -0.31747,0.0377 0.24551,-0.0343 0.60361,-0.0769 1.2087,-0.14221 1.814,-0.20194 2.1765,-0.21442 4.3616,-0.33925 6.5477,-0.40461 7.0088,-0.20928 14.057,0.24796 20.959,1.4953 7.9781,1.442 15.783,3.9756 22.86,7.9654 8.0388,4.532 14.777,11.012 19.535,18.924 1.0557,1.756 3.8079,0.15739 2.7476,-1.606 -5.1914,-8.6336 -12.6,-15.613 -21.408,-20.474 -7.7483,-4.275 -16.361,-6.8644 -25.074,-8.2486 -9.4825,-1.5066 -19.54,-1.944 -29.073,-0.48367 -1.1345,0.17379 -1.5874,1.9477 -0.70201,2.6592 3.0624,2.4612 5.6283,5.6205 7.7454,8.8104 4.5202,6.8118 6.9303,14.977 5.6423,23.154 -1.4588,9.2607 -7.0781,17.201 -13.551,23.715 -0.75977,0.76492 -0.53067,2.4859 0.70201,2.6592 9.9738,1.4023 20.482,0.7025 30.334,-1.1362 8.4689,-1.5805 16.759,-4.3922 24.256,-8.6664 8.6297,-4.9199 15.91,-11.93 21.128,-20.383 1.0812,-1.7514 -1.6723,-3.3482 -2.7473,-1.606 z" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path35"
|
|
||||||
d="m 295.19427,443.74237 c 0,0 12.67,11.257 12.67,27.475 0,0 9.8236,-9.7551 23.069,0 0,0 15.098,13.305 33.229,0 0,0 -15.539,-32.087 -68.968,-27.475 z"
|
|
||||||
style="font-size:18px;fill:url(#linearGradient3349);fill-opacity:1;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<line
|
|
||||||
id="line39"
|
|
||||||
y2="471.03238"
|
|
||||||
x2="400.71429"
|
|
||||||
y1="471.03238"
|
|
||||||
x1="366.79425"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44770002;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path59"
|
|
||||||
d="m 344.15733,461.16448 4.84652,0"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44799995;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cc"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44799995;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
d="m 344.15733,481.90109 4.84652,0"
|
|
||||||
id="path6037"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Orbitron;-inkscape-font-specification:Orbitron Light"
|
|
||||||
x="257.14285"
|
|
||||||
y="537.7193"
|
|
||||||
id="text6055"
|
|
||||||
sodipodi:linespacing="125%"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan6057"
|
|
||||||
x="257.14285"
|
|
||||||
y="537.7193">migen</tspan></text>
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cc"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.61650872;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
d="m 289.42519,459.68794 14.57866,0"
|
|
||||||
id="path6105"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path6107"
|
|
||||||
d="m 289.42519,483.37763 14.57866,0"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.61650872;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 9 KiB |
|
@ -1,37 +0,0 @@
|
||||||
API reference
|
|
||||||
=============
|
|
||||||
|
|
||||||
:mod:`fhdl.structure` module
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.fhdl.structure
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`fhdl.bitcontainer` module
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.fhdl.bitcontainer
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`genlib.fifo` module
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.genlib.fifo
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`genlib.coding` module
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.genlib.coding
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`genlib.sort` module
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.genlib.sort
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
|
@ -1,6 +0,0 @@
|
||||||
Simulating a Migen design
|
|
||||||
#########################
|
|
||||||
|
|
||||||
Migen allows you to easily simulate your FHDL design and interface it with arbitrary Python code. The simulator is written in pure Python and interprets the FHDL structure directly without using an external Verilog simulator.
|
|
||||||
|
|
||||||
[To be rewritten]
|
|
|
@ -1,4 +0,0 @@
|
||||||
Synthesizing a Migen design
|
|
||||||
###########################
|
|
||||||
|
|
||||||
[To be written]
|
|
|
@ -1,28 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self):
|
|
||||||
dx = 2
|
|
||||||
dy = 2
|
|
||||||
|
|
||||||
x = Signal(max=dx)
|
|
||||||
y = Signal(max=dy)
|
|
||||||
out = Signal()
|
|
||||||
|
|
||||||
my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy))
|
|
||||||
self.comb += out.eq(my_2d_array[x][y])
|
|
||||||
|
|
||||||
we = Signal()
|
|
||||||
inp = Signal()
|
|
||||||
self.sync += If(we,
|
|
||||||
my_2d_array[x][y].eq(inp)
|
|
||||||
)
|
|
||||||
|
|
||||||
ina = Array(Signal() for a in range(dx))
|
|
||||||
outa = Array(Signal() for a in range(dy))
|
|
||||||
self.specials += Instance("test", o_O=outa[y], i_I=ina[x])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print(verilog.convert(Example()))
|
|
|
@ -1,31 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.s = Signal()
|
|
||||||
self.counter = Signal(8)
|
|
||||||
x = Array(Signal(name="a") for i in range(7))
|
|
||||||
|
|
||||||
myfsm = FSM()
|
|
||||||
self.submodules += myfsm
|
|
||||||
|
|
||||||
myfsm.act("FOO",
|
|
||||||
self.s.eq(1),
|
|
||||||
NextState("BAR")
|
|
||||||
)
|
|
||||||
myfsm.act("BAR",
|
|
||||||
self.s.eq(0),
|
|
||||||
NextValue(self.counter, self.counter + 1),
|
|
||||||
NextValue(x[self.counter], 89),
|
|
||||||
NextState("FOO")
|
|
||||||
)
|
|
||||||
|
|
||||||
self.be = myfsm.before_entering("FOO")
|
|
||||||
self.ae = myfsm.after_entering("FOO")
|
|
||||||
self.bl = myfsm.before_leaving("FOO")
|
|
||||||
self.al = myfsm.after_leaving("FOO")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
example = Example()
|
|
||||||
print(verilog.convert(example, {example.s, example.counter, example.be, example.ae, example.bl, example.al}))
|
|
|
@ -1,18 +0,0 @@
|
||||||
from random import Random
|
|
||||||
|
|
||||||
from migen import *
|
|
||||||
from migen.genlib.cdc import GrayCounter
|
|
||||||
|
|
||||||
|
|
||||||
def tb(dut):
|
|
||||||
prng = Random(7345)
|
|
||||||
for i in range(35):
|
|
||||||
print("{0:0{1}b} CE={2} bin={3}".format((yield dut.q),
|
|
||||||
len(dut.q), (yield dut.ce), (yield dut.q_binary)))
|
|
||||||
yield dut.ce.eq(prng.getrandbits(1))
|
|
||||||
yield
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
dut = GrayCounter(3)
|
|
||||||
run_simulation(dut, tb(dut), vcd_name="graycounter.vcd")
|
|
|
@ -1,68 +0,0 @@
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from migen import *
|
|
||||||
from migen.fhdl.verilog import convert
|
|
||||||
|
|
||||||
|
|
||||||
# Create a parent module with two instances of a child module.
|
|
||||||
# Bind input ports to first module and output ports to second,
|
|
||||||
# and create internal signals to connect the first module to the
|
|
||||||
# second.
|
|
||||||
class ParentModule(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.inputs = [Signal(x+1, name="input{}".format(x)) for x in range(4)]
|
|
||||||
self.trans = [Signal(x+1) for x in range(4)]
|
|
||||||
self.outputs = [Signal(x+1, name="output{}".format(x)) for x in range(4)]
|
|
||||||
self.io = set(self.inputs) | set(self.outputs)
|
|
||||||
i = Instance("ChildModule",
|
|
||||||
i_master_clk=ClockSignal(),
|
|
||||||
i_master_rst=ResetSignal(),
|
|
||||||
i_input0=self.inputs[0],
|
|
||||||
i_input1=self.inputs[1],
|
|
||||||
i_input2=self.inputs[2],
|
|
||||||
i_input3=self.inputs[3],
|
|
||||||
o_output0=self.trans[0],
|
|
||||||
o_output1=self.trans[1],
|
|
||||||
o_output2=self.trans[2],
|
|
||||||
o_output3=self.trans[3]
|
|
||||||
)
|
|
||||||
j = Instance("ChildModule",
|
|
||||||
i_master_clk=ClockSignal(),
|
|
||||||
i_master_rst=ResetSignal(),
|
|
||||||
i_input0=self.trans[0],
|
|
||||||
i_input1=self.trans[1],
|
|
||||||
i_input2=self.trans[2],
|
|
||||||
i_input3=self.trans[3],
|
|
||||||
o_output0=self.outputs[0],
|
|
||||||
o_output1=self.outputs[1],
|
|
||||||
o_output2=self.outputs[2],
|
|
||||||
o_output3=self.outputs[3]
|
|
||||||
)
|
|
||||||
self.specials += i, j
|
|
||||||
|
|
||||||
|
|
||||||
class ChildModule(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.inputs = [Signal(x+1, name_override="input{}".format(x)) for x in range(4)]
|
|
||||||
self.outputs = [Signal(x+1, name_override="output{}".format(x)) for x in range(4)]
|
|
||||||
self.io = set()
|
|
||||||
for x in range(4):
|
|
||||||
self.sync.master += self.outputs[x].eq(self.inputs[x])
|
|
||||||
self.io = self.io.union(self.inputs)
|
|
||||||
self.io = self.io.union(self.outputs)
|
|
||||||
|
|
||||||
|
|
||||||
# Generate RTL for the parent module and the submodule, run through
|
|
||||||
# icarus for a syntax check
|
|
||||||
def test_instance_module():
|
|
||||||
sub = ChildModule()
|
|
||||||
convert(sub, sub.io, name="ChildModule").write("ChildModule.v")
|
|
||||||
|
|
||||||
im = ParentModule()
|
|
||||||
convert(im, im.io, name="ParentModule").write("ParentModule.v")
|
|
||||||
|
|
||||||
subprocess.check_call(["iverilog", "-W", "all",
|
|
||||||
"ParentModule.v", "ChildModule.v"])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
test_instance_module()
|
|
|
@ -1,19 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
from migen.genlib.divider import Divider
|
|
||||||
|
|
||||||
|
|
||||||
class CDM(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.submodules.divider = Divider(5)
|
|
||||||
self.clock_domains.cd_sys = ClockDomain(reset_less=True)
|
|
||||||
|
|
||||||
|
|
||||||
class MultiMod(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.submodules.foo = CDM()
|
|
||||||
self.submodules.bar = CDM()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
mm = MultiMod()
|
|
||||||
print(verilog.convert(mm, {mm.foo.cd_sys.clk, mm.bar.cd_sys.clk}))
|
|
|
@ -1,17 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.specials.mem = Memory(32, 100, init=[5, 18, 32])
|
|
||||||
p1 = self.mem.get_port(write_capable=True, we_granularity=8)
|
|
||||||
p2 = self.mem.get_port(has_re=True, clock_domain="rd")
|
|
||||||
self.specials += p1, p2
|
|
||||||
self.ios = {p1.adr, p1.dat_r, p1.we, p1.dat_w,
|
|
||||||
p2.adr, p2.dat_r, p2.re}
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
example = Example()
|
|
||||||
print(verilog.convert(example, example.ios))
|
|
|
@ -1,44 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
from functools import reduce
|
|
||||||
from operator import or_
|
|
||||||
|
|
||||||
|
|
||||||
def gen_list(n):
|
|
||||||
s = [Signal() for i in range(n)]
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def gen_2list(n):
|
|
||||||
s = [Signal(2) for i in range(n)]
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
class Foo:
|
|
||||||
def __init__(self):
|
|
||||||
la = gen_list(3)
|
|
||||||
lb = gen_2list(2)
|
|
||||||
self.sigs = la + lb
|
|
||||||
|
|
||||||
|
|
||||||
class Bar:
|
|
||||||
def __init__(self):
|
|
||||||
self.sigs = gen_list(2)
|
|
||||||
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self):
|
|
||||||
a = [Bar() for x in range(3)]
|
|
||||||
b = [Foo() for x in range(3)]
|
|
||||||
c = b
|
|
||||||
b = [Bar() for x in range(2)]
|
|
||||||
|
|
||||||
output = Signal()
|
|
||||||
allsigs = []
|
|
||||||
for lst in [a, b, c]:
|
|
||||||
for obj in lst:
|
|
||||||
allsigs.extend(obj.sigs)
|
|
||||||
self.comb += output.eq(reduce(or_, allsigs))
|
|
||||||
|
|
||||||
print(verilog.convert(Example()))
|
|
|
@ -1,23 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl.specials import SynthesisDirective
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
from migen.genlib.cdc import *
|
|
||||||
|
|
||||||
|
|
||||||
class XilinxMultiRegImpl(MultiRegImpl):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
MultiRegImpl.__init__(self, *args, **kwargs)
|
|
||||||
self.specials += set(SynthesisDirective("attribute shreg_extract of {r} is no", r=r)
|
|
||||||
for r in self.regs)
|
|
||||||
|
|
||||||
|
|
||||||
class XilinxMultiReg:
|
|
||||||
@staticmethod
|
|
||||||
def lower(dr):
|
|
||||||
return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
ps = PulseSynchronizer("from", "to")
|
|
||||||
v = verilog.convert(ps, {ps.i, ps.o}, special_overrides={MultiReg: XilinxMultiReg})
|
|
||||||
print(v)
|
|
|
@ -1,26 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
|
|
||||||
L = [
|
|
||||||
("position", [
|
|
||||||
("x", 10, DIR_M_TO_S),
|
|
||||||
("y", 10, DIR_M_TO_S),
|
|
||||||
]),
|
|
||||||
("color", 32, DIR_M_TO_S),
|
|
||||||
("stb", 1, DIR_M_TO_S),
|
|
||||||
("ack", 1, DIR_S_TO_M)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Test(Module):
|
|
||||||
def __init__(self):
|
|
||||||
master = Record(L)
|
|
||||||
slave = Record(L)
|
|
||||||
self.comb += master.connect(slave)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print(verilog.convert(Test()))
|
|
||||||
print(layout_len(L))
|
|
||||||
print(layout_partial(L, "position/x", "color"))
|
|
|
@ -1,19 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self):
|
|
||||||
a = Signal(3)
|
|
||||||
b = Signal(4)
|
|
||||||
c = Signal(5)
|
|
||||||
d = Signal(7)
|
|
||||||
s1 = c[:3][:2]
|
|
||||||
s2 = Cat(a, b)[:6]
|
|
||||||
s3 = Cat(s1, s2)[-5:]
|
|
||||||
self.comb += s3.eq(0)
|
|
||||||
self.comb += d.eq(Cat(d[::-1], Cat(s1[:1], s3[-4:])[:3]))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print(verilog.convert(Example()))
|
|
|
@ -1,13 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self, n=6):
|
|
||||||
self.pad = Signal(n)
|
|
||||||
self.t = TSTriple(n)
|
|
||||||
self.specials += self.t.get_tristate(self.pad)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
e = Example()
|
|
||||||
print(verilog.convert(e, ios={e.pad, e.t.o, e.t.oe, e.t.i}))
|
|
|
@ -1,19 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
from migen.genlib import divider
|
|
||||||
|
|
||||||
|
|
||||||
@ResetInserter()
|
|
||||||
@CEInserter()
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self, width):
|
|
||||||
d1 = divider.Divider(width)
|
|
||||||
d2 = divider.Divider(width)
|
|
||||||
self.submodules += d1, d2
|
|
||||||
self.ios = {
|
|
||||||
d1.ready_o, d1.quotient_o, d1.remainder_o, d1.start_i, d1.dividend_i, d1.divisor_i,
|
|
||||||
d2.ready_o, d2.quotient_o, d2.remainder_o, d2.start_i, d2.dividend_i, d2.divisor_i}
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
example = Example(16)
|
|
||||||
print(verilog.convert(example, example.ios | {example.ce, example.reset}))
|
|
|
@ -1,29 +0,0 @@
|
||||||
from migen import *
|
|
||||||
|
|
||||||
|
|
||||||
# Our simple counter, which increments at every cycle.
|
|
||||||
class Counter(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.count = Signal(4)
|
|
||||||
|
|
||||||
# At each cycle, increase the value of the count signal.
|
|
||||||
# We do it with convertible/synthesizable FHDL code.
|
|
||||||
self.sync += self.count.eq(self.count + 1)
|
|
||||||
|
|
||||||
|
|
||||||
# Simply read the count signal and print it.
|
|
||||||
# The output is:
|
|
||||||
# Count: 0
|
|
||||||
# Count: 1
|
|
||||||
# Count: 2
|
|
||||||
# ...
|
|
||||||
def counter_test(dut):
|
|
||||||
for i in range(20):
|
|
||||||
print((yield dut.count)) # read and print
|
|
||||||
yield # next clock cycle
|
|
||||||
# simulation ends with this generator
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
dut = Counter()
|
|
||||||
run_simulation(dut, counter_test(dut), vcd_name="basic1.vcd")
|
|
|
@ -1,37 +0,0 @@
|
||||||
from migen import *
|
|
||||||
|
|
||||||
|
|
||||||
# A slightly more elaborate counter.
|
|
||||||
# Has a clock enable (CE) signal, counts on more bits
|
|
||||||
# and resets with a negative number.
|
|
||||||
class Counter(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.ce = Signal()
|
|
||||||
# Demonstrate negative numbers and signals larger than 32 bits.
|
|
||||||
self.count = Signal((37, True), reset=-5)
|
|
||||||
|
|
||||||
self.sync += If(self.ce, self.count.eq(self.count + 1))
|
|
||||||
|
|
||||||
|
|
||||||
def counter_test(dut):
|
|
||||||
for cycle in range(20):
|
|
||||||
# Only assert CE every second cycle.
|
|
||||||
# => each counter value is held for two cycles.
|
|
||||||
if cycle % 2:
|
|
||||||
yield dut.ce.eq(0) # This is how you write to a signal.
|
|
||||||
else:
|
|
||||||
yield dut.ce.eq(1)
|
|
||||||
print("Cycle: {} Count: {}".format(cycle, (yield dut.count)))
|
|
||||||
yield
|
|
||||||
|
|
||||||
# Output is:
|
|
||||||
# Cycle: 0 Count: -5
|
|
||||||
# Cycle: 1 Count: -5
|
|
||||||
# Cycle: 2 Count: -4
|
|
||||||
# Cycle: 3 Count: -4
|
|
||||||
# Cycle: 4 Count: -3
|
|
||||||
# ...
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
dut = Counter()
|
|
||||||
run_simulation(dut, counter_test(dut), vcd_name="basic2.vcd")
|
|
|
@ -1,67 +0,0 @@
|
||||||
from functools import reduce
|
|
||||||
from operator import add
|
|
||||||
|
|
||||||
from math import cos, pi
|
|
||||||
from scipy import signal
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
|
|
||||||
# A synthesizable FIR filter.
|
|
||||||
class FIR(Module):
|
|
||||||
def __init__(self, coef, wsize=16):
|
|
||||||
self.coef = coef
|
|
||||||
self.wsize = wsize
|
|
||||||
self.i = Signal((self.wsize, True))
|
|
||||||
self.o = Signal((self.wsize, True))
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
muls = []
|
|
||||||
src = self.i
|
|
||||||
for c in self.coef:
|
|
||||||
sreg = Signal((self.wsize, True))
|
|
||||||
self.sync += sreg.eq(src)
|
|
||||||
src = sreg
|
|
||||||
c_fp = int(c*2**(self.wsize - 1))
|
|
||||||
muls.append(c_fp*sreg)
|
|
||||||
sum_full = Signal((2*self.wsize-1, True))
|
|
||||||
self.sync += sum_full.eq(reduce(add, muls))
|
|
||||||
self.comb += self.o.eq(sum_full >> self.wsize-1)
|
|
||||||
|
|
||||||
|
|
||||||
# A test bench for our FIR filter.
|
|
||||||
# Generates a sine wave at the input and records the output.
|
|
||||||
def fir_tb(dut, frequency, inputs, outputs):
|
|
||||||
f = 2**(dut.wsize - 1)
|
|
||||||
for cycle in range(200):
|
|
||||||
v = 0.1*cos(2*pi*frequency*cycle)
|
|
||||||
yield dut.i.eq(int(f*v))
|
|
||||||
inputs.append(v)
|
|
||||||
outputs.append((yield dut.o)/f)
|
|
||||||
yield
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# Compute filter coefficients with SciPy.
|
|
||||||
coef = signal.remez(30, [0, 0.1, 0.2, 0.4, 0.45, 0.5], [0, 1, 0])
|
|
||||||
|
|
||||||
# Simulate for different frequencies and concatenate
|
|
||||||
# the results.
|
|
||||||
in_signals = []
|
|
||||||
out_signals = []
|
|
||||||
for frequency in [0.05, 0.1, 0.25]:
|
|
||||||
dut = FIR(coef)
|
|
||||||
tb = fir_tb(dut, frequency, in_signals, out_signals)
|
|
||||||
run_simulation(dut, tb)
|
|
||||||
|
|
||||||
# Plot data from the input and output waveforms.
|
|
||||||
plt.plot(in_signals)
|
|
||||||
plt.plot(out_signals)
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
# Print the Verilog source for the filter.
|
|
||||||
fir = FIR(coef)
|
|
||||||
print(verilog.convert(fir, ios={fir.i, fir.o}))
|
|
|
@ -1,26 +0,0 @@
|
||||||
from migen import *
|
|
||||||
|
|
||||||
|
|
||||||
class Mem(Module):
|
|
||||||
def __init__(self):
|
|
||||||
# Initialize the beginning of the memory with integers
|
|
||||||
# from 0 to 19.
|
|
||||||
self.specials.mem = Memory(16, 2**12, init=list(range(20)))
|
|
||||||
|
|
||||||
|
|
||||||
def memory_test(dut):
|
|
||||||
# write (only first 5 values)
|
|
||||||
for i in range(5):
|
|
||||||
yield dut.mem[i].eq(42 + i)
|
|
||||||
# remember: values are written after the tick, and read before the tick.
|
|
||||||
# wait one tick for the memory to update.
|
|
||||||
yield
|
|
||||||
# read what we have written, plus some initialization data
|
|
||||||
for i in range(10):
|
|
||||||
value = yield dut.mem[i]
|
|
||||||
print(value)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
dut = Mem()
|
|
||||||
run_simulation(dut, memory_test(dut))
|
|
|
@ -1,9 +1,9 @@
|
||||||
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
|
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build.altera import AlteraPlatform
|
from litex.build.altera import AlteraPlatform
|
||||||
from migen.build.altera.programmer import USBBlaster
|
from litex.build.altera.programmer import USBBlaster
|
||||||
|
|
||||||
|
|
||||||
_io = [
|
_io = [
|
|
@ -1,6 +1,6 @@
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build.xilinx import XilinxPlatform, XC3SProg, VivadoProgrammer, iMPACT
|
from litex.build.xilinx import XilinxPlatform, XC3SProg, VivadoProgrammer, iMPACT
|
||||||
from migen.build.xilinx.ise import XilinxISEToolchain
|
from litex.build.xilinx.ise import XilinxISEToolchain
|
||||||
|
|
||||||
|
|
||||||
_io = [
|
_io = [
|
|
@ -1,9 +1,9 @@
|
||||||
# This file is Copyright (c) 2015 Matt O'Gorman <mog@rldn.net>
|
# This file is Copyright (c) 2015 Matt O'Gorman <mog@rldn.net>
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build.xilinx import XilinxPlatform
|
from litex.build.xilinx import XilinxPlatform
|
||||||
from migen.build.xilinx.programmer import XC3SProg, FpgaProg
|
from litex.build.xilinx.programmer import XC3SProg, FpgaProg
|
||||||
|
|
||||||
|
|
||||||
_io = [
|
_io = [
|
|
@ -1,5 +1,5 @@
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build.sim import SimPlatform
|
from litex.build.sim import SimPlatform
|
||||||
|
|
||||||
|
|
||||||
class SimPins(Pins):
|
class SimPins(Pins):
|
|
@ -1,9 +1,9 @@
|
||||||
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
|
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build.lattice import LatticePlatform
|
from litex.build.lattice import LatticePlatform
|
||||||
from migen.build.lattice.programmer import LatticeProgrammer
|
from litex.build.lattice.programmer import LatticeProgrammer
|
||||||
|
|
||||||
|
|
||||||
_io = [
|
_io = [
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from migen import *
|
from litex.gen import *
|
||||||
from migen.build.platforms import de0nano
|
from litex.boards.platforms import de0nano
|
||||||
|
|
||||||
from misoc.cores.sdram_settings import IS42S16160
|
from litex.soc.cores.sdram.settings import IS42S16160
|
||||||
from misoc.cores.sdram_phy import GENSDRPHY
|
from litex.soc.cores.sdram.phy import GENSDRPHY
|
||||||
from misoc.integration.soc_sdram import *
|
from litex.soc.integration.soc_sdram import *
|
||||||
from misoc.integration.builder import *
|
from litex.soc.integration.builder import *
|
||||||
|
|
||||||
|
|
||||||
class _PLL(Module):
|
class _PLL(Module):
|
||||||
|
@ -101,7 +101,7 @@ class BaseSoC(SoCSDRAM):
|
||||||
sdram_module.geom_settings, sdram_module.timing_settings)
|
sdram_module.geom_settings, sdram_module.timing_settings)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="MiSoC port to the Altera DE0 Nano")
|
parser = argparse.ArgumentParser(description="LiteX SoC port to the Altera DE0 Nano")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
soc_sdram_args(parser)
|
soc_sdram_args(parser)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
|
@ -2,19 +2,19 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from migen import *
|
from litex.gen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.build.platforms import kc705
|
from litex.boards.platforms import kc705
|
||||||
|
|
||||||
from misoc.cores.sdram_settings import MT8JTF12864
|
from litex.soc.cores.sdram.settings import MT8JTF12864
|
||||||
from misoc.cores.sdram_phy import k7ddrphy
|
from litex.soc.cores.sdram.phy import k7ddrphy
|
||||||
from misoc.cores import spi_flash
|
from litex.soc.cores.flash import spi_flash
|
||||||
from misoc.cores.liteeth_mini.phy import LiteEthPHY
|
from litex.soc.integration.soc_core import mem_decoder
|
||||||
from misoc.cores.liteeth_mini.mac import LiteEthMAC
|
from litex.soc.integration.soc_sdram import *
|
||||||
from misoc.integration.soc_core import mem_decoder
|
from litex.soc.integration.builder import *
|
||||||
from misoc.integration.soc_sdram import *
|
|
||||||
from misoc.integration.builder import *
|
|
||||||
|
|
||||||
|
from liteeth.phy import LiteEthPHY
|
||||||
|
from liteeth.core.mac import LiteEthMAC
|
||||||
|
|
||||||
|
|
||||||
class _CRG(Module):
|
class _CRG(Module):
|
||||||
|
@ -150,7 +150,7 @@ def soc_kc705_argdict(args):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="MiSoC port to the KC705")
|
parser = argparse.ArgumentParser(description="LiteX SoC port to the KC705")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
soc_kc705_args(parser)
|
soc_kc705_args(parser)
|
||||||
parser.add_argument("--with-ethernet", action="store_true",
|
parser.add_argument("--with-ethernet", action="store_true",
|
|
@ -3,14 +3,14 @@
|
||||||
import argparse
|
import argparse
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
from migen import *
|
from litex.gen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.build.platforms import minispartan6
|
from litex.boards.platforms import minispartan6
|
||||||
|
|
||||||
from misoc.cores.sdram_settings import AS4C16M16
|
from litex.soc.cores.sdram.settings import AS4C16M16
|
||||||
from misoc.cores.sdram_phy import GENSDRPHY
|
from litex.soc.cores.sdram.phy import GENSDRPHY
|
||||||
from misoc.integration.soc_sdram import *
|
from litex.soc.integration.soc_sdram import *
|
||||||
from misoc.integration.builder import *
|
from litex.soc.integration.builder import *
|
||||||
|
|
||||||
|
|
||||||
class _CRG(Module):
|
class _CRG(Module):
|
||||||
|
@ -82,7 +82,7 @@ class BaseSoC(SoCSDRAM):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="MiSoC port to the MiniSpartan6")
|
parser = argparse.ArgumentParser(description="LiteX SoC port to the MiniSpartan6")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
soc_sdram_args(parser)
|
soc_sdram_args(parser)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
|
@ -3,15 +3,15 @@
|
||||||
import argparse
|
import argparse
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
from migen import *
|
from litex.gen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.build.platforms import papilio_pro
|
from litex.boards.platforms import papilio_pro
|
||||||
|
|
||||||
from misoc.cores.sdram_settings import MT48LC4M16
|
from litex.soc.cores.sdram.settings import MT48LC4M16
|
||||||
from misoc.cores.sdram_phy import GENSDRPHY
|
from litex.soc.cores.sdram.phy import GENSDRPHY
|
||||||
from misoc.cores import spi_flash
|
from litex.soc.cores.flash import spi_flash
|
||||||
from misoc.integration.soc_sdram import *
|
from litex.soc.integration.soc_sdram import *
|
||||||
from misoc.integration.builder import *
|
from litex.soc.integration.builder import *
|
||||||
|
|
||||||
|
|
||||||
class _CRG(Module):
|
class _CRG(Module):
|
||||||
|
@ -94,7 +94,7 @@ class BaseSoC(SoCSDRAM):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="MiSoC port to the Papilio Pro")
|
parser = argparse.ArgumentParser(description="LiteX SoC port to the Papilio Pro")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
soc_sdram_args(parser)
|
soc_sdram_args(parser)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
|
@ -3,15 +3,15 @@
|
||||||
import argparse
|
import argparse
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
from migen import *
|
from litex.gen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.build.platforms import pipistrello
|
from litex.boards.platforms import pipistrello
|
||||||
|
|
||||||
from misoc.cores.sdram_settings import MT46H32M16
|
from litex.soc.cores.sdram_settings import MT46H32M16
|
||||||
from misoc.cores.sdram_phy import S6HalfRateDDRPHY
|
from litex.soc.cores.sdram_phy import S6HalfRateDDRPHY
|
||||||
from misoc.cores import spi_flash
|
from litex.soc.cores.flash import spi_flash
|
||||||
from misoc.integration.soc_sdram import *
|
from litex.soc.integration.soc_sdram import *
|
||||||
from misoc.integration.builder import *
|
from litex.soc.integration.builder import *
|
||||||
|
|
||||||
|
|
||||||
class _CRG(Module):
|
class _CRG(Module):
|
||||||
|
@ -136,7 +136,7 @@ soc_pipistrello_argdict = soc_sdram_argdict
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="MiSoC port to the Pipistrello")
|
parser = argparse.ArgumentParser(description="LiteX SoC port to the Pipistrello")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
soc_pipistrello_args(parser)
|
soc_pipistrello_args(parser)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
|
@ -3,13 +3,14 @@
|
||||||
import argparse
|
import argparse
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
from migen import *
|
from litex.gen import *
|
||||||
from migen.genlib.io import CRG
|
from litex.gen.genlib.io import CRG
|
||||||
|
|
||||||
from misoc.cores.liteeth_mini.phy import LiteEthPHY
|
from litex.soc.integration.soc_core import *
|
||||||
from misoc.cores.liteeth_mini.mac import LiteEthMAC
|
from litex.soc.integration.builder import *
|
||||||
from misoc.integration.soc_core import *
|
|
||||||
from misoc.integration.builder import *
|
from liteeth.phy import LiteEthPHY
|
||||||
|
from liteeth.core.mac import LiteEthMAC
|
||||||
|
|
||||||
|
|
||||||
class BaseSoC(SoCCore):
|
class BaseSoC(SoCCore):
|
||||||
|
@ -52,13 +53,13 @@ class MiniSoC(BaseSoC):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Generic MiSoC port")
|
parser = argparse.ArgumentParser(description="Generic LiteX SoC")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
soc_core_args(parser)
|
soc_core_args(parser)
|
||||||
parser.add_argument("--with-ethernet", action="store_true",
|
parser.add_argument("--with-ethernet", action="store_true",
|
||||||
help="enable Ethernet support")
|
help="enable Ethernet support")
|
||||||
parser.add_argument("platform",
|
parser.add_argument("platform",
|
||||||
help="module name of the Migen platform to build for")
|
help="module name of the platform to build for")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
platform_module = importlib.import_module(args.platform)
|
platform_module = importlib.import_module(args.platform)
|
2
litex/build/altera/__init__.py
Normal file
2
litex/build/altera/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
from litex.build.altera.platform import AlteraPlatform
|
||||||
|
from litex.build.altera.programmer import USBBlaster
|
|
@ -1,6 +1,6 @@
|
||||||
from migen.fhdl.module import Module
|
from litex.gen.fhdl.module import Module
|
||||||
from migen.fhdl.specials import Instance
|
from litex.gen.fhdl.specials import Instance
|
||||||
from migen.genlib.io import DifferentialInput, DifferentialOutput
|
from litex.gen.genlib.io import DifferentialInput, DifferentialOutput
|
||||||
|
|
||||||
|
|
||||||
class AlteraDifferentialInputImpl(Module):
|
class AlteraDifferentialInputImpl(Module):
|
|
@ -1,5 +1,5 @@
|
||||||
from migen.build.generic_platform import GenericPlatform
|
from litex.build.generic_platform import GenericPlatform
|
||||||
from migen.build.altera import common, quartus
|
from litex.build.altera import common, quartus
|
||||||
|
|
||||||
|
|
||||||
class AlteraPlatform(GenericPlatform):
|
class AlteraPlatform(GenericPlatform):
|
|
@ -1,6 +1,6 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from migen.build.generic_programmer import GenericProgrammer
|
from litex.build.generic_programmer import GenericProgrammer
|
||||||
|
|
||||||
|
|
||||||
class USBBlaster(GenericProgrammer):
|
class USBBlaster(GenericProgrammer):
|
|
@ -4,10 +4,10 @@
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from migen.fhdl.structure import _Fragment
|
from litex.gen.fhdl.structure import _Fragment
|
||||||
|
|
||||||
from migen.build.generic_platform import Pins, IOStandard, Misc
|
from litex.build.generic_platform import Pins, IOStandard, Misc
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
|
|
||||||
|
|
||||||
def _format_constraint(c, signame, fmt_r):
|
def _format_constraint(c, signame, fmt_r):
|
||||||
|
@ -92,7 +92,7 @@ def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
|
||||||
|
|
||||||
|
|
||||||
def _run_quartus(build_name, quartus_path):
|
def _run_quartus(build_name, quartus_path):
|
||||||
build_script_contents = """# Autogenerated by Migen
|
build_script_contents = """# Autogenerated by LiteX
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from migen.fhdl.structure import Signal
|
from litex.gen.fhdl.structure import Signal
|
||||||
from migen.genlib.record import Record
|
from litex.gen.genlib.record import Record
|
||||||
from migen.genlib.io import CRG
|
from litex.gen.genlib.io import CRG
|
||||||
from migen.fhdl import verilog, edif
|
from litex.gen.fhdl import verilog, edif
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
|
|
||||||
|
|
||||||
class ConstraintError(Exception):
|
class ConstraintError(Exception):
|
|
@ -5,8 +5,7 @@ class GenericProgrammer:
|
||||||
def __init__(self, flash_proxy_basename=None):
|
def __init__(self, flash_proxy_basename=None):
|
||||||
self.flash_proxy_basename = flash_proxy_basename
|
self.flash_proxy_basename = flash_proxy_basename
|
||||||
self.flash_proxy_dirs = [
|
self.flash_proxy_dirs = [
|
||||||
"~/.migen", "/usr/local/share/migen", "/usr/share/migen",
|
"~/.litex", "/usr/local/share/litex", "/usr/share/litex"]
|
||||||
"~/.mlabs", "/usr/local/share/mlabs", "/usr/share/mlabs"]
|
|
||||||
|
|
||||||
def set_flash_proxy_dir(self, flash_proxy_dir):
|
def set_flash_proxy_dir(self, flash_proxy_dir):
|
||||||
if flash_proxy_dir is not None:
|
if flash_proxy_dir is not None:
|
2
litex/build/lattice/__init__.py
Normal file
2
litex/build/lattice/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
from litex.build.lattice.platform import LatticePlatform
|
||||||
|
from litex.build.lattice.programmer import LatticeProgrammer
|
|
@ -1,7 +1,7 @@
|
||||||
from migen.fhdl.module import Module
|
from litex.gen.fhdl.module import Module
|
||||||
from migen.fhdl.specials import Instance
|
from litex.gen.fhdl.specials import Instance
|
||||||
from migen.genlib.io import *
|
from litex.gen.genlib.io import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
|
||||||
|
|
||||||
class LatticeAsyncResetSynchronizerImpl(Module):
|
class LatticeAsyncResetSynchronizerImpl(Module):
|
|
@ -6,11 +6,11 @@ import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from migen.fhdl.structure import _Fragment
|
from litex.gen.fhdl.structure import _Fragment
|
||||||
|
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
from migen.build.lattice import common
|
from litex.build.lattice import common
|
||||||
|
|
||||||
|
|
||||||
def _format_constraint(c):
|
def _format_constraint(c):
|
||||||
|
@ -61,7 +61,7 @@ def _build_files(device, sources, vincpaths, build_name):
|
||||||
|
|
||||||
def _run_diamond(build_name, source, ver=None):
|
def _run_diamond(build_name, source, ver=None):
|
||||||
if sys.platform == "win32" or sys.platform == "cygwin":
|
if sys.platform == "win32" or sys.platform == "cygwin":
|
||||||
build_script_contents = "REM Autogenerated by Migen\n"
|
build_script_contents = "REM Autogenerated by LiteX\n"
|
||||||
build_script_contents = "pnmainc " + build_name + ".tcl\n"
|
build_script_contents = "pnmainc " + build_name + ".tcl\n"
|
||||||
build_script_file = "build_" + build_name + ".bat"
|
build_script_file = "build_" + build_name + ".bat"
|
||||||
tools.write_to_file(build_script_file, build_script_contents)
|
tools.write_to_file(build_script_file, build_script_contents)
|
|
@ -1,5 +1,5 @@
|
||||||
from migen.build.generic_platform import GenericPlatform
|
from litex.build.generic_platform import GenericPlatform
|
||||||
from migen.build.lattice import common, diamond
|
from litex.build.lattice import common, diamond
|
||||||
|
|
||||||
|
|
||||||
class LatticePlatform(GenericPlatform):
|
class LatticePlatform(GenericPlatform):
|
|
@ -1,8 +1,8 @@
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from migen.build.generic_programmer import GenericProgrammer
|
from litex.build.generic_programmer import GenericProgrammer
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
|
|
||||||
|
|
||||||
# XXX Lattice programmer need an .xcf file, will need clean up and support for more parameters
|
# XXX Lattice programmer need an .xcf file, will need clean up and support for more parameters
|
|
@ -1,6 +1,6 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from migen.build.generic_programmer import GenericProgrammer
|
from litex.build.generic_programmer import GenericProgrammer
|
||||||
|
|
||||||
|
|
||||||
class OpenOCD(GenericProgrammer):
|
class OpenOCD(GenericProgrammer):
|
1
litex/build/sim/__init__.py
Normal file
1
litex/build/sim/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from litex.build.sim.platform import SimPlatform
|
|
@ -1,5 +1,5 @@
|
||||||
from migen.build.generic_platform import GenericPlatform
|
from litex.build.generic_platform import GenericPlatform
|
||||||
from migen.build.sim import common, verilator
|
from litex.build.sim import common, verilator
|
||||||
|
|
||||||
|
|
||||||
class SimPlatform(GenericPlatform):
|
class SimPlatform(GenericPlatform):
|
|
@ -4,9 +4,9 @@
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from migen.fhdl.structure import _Fragment
|
from litex.gen.fhdl.structure import _Fragment
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
|
|
||||||
|
|
||||||
def _build_tb(platform, vns, serial, template):
|
def _build_tb(platform, vns, serial, template):
|
||||||
|
@ -86,7 +86,7 @@ def _build_sim(platform, vns, build_name, include_paths, sim_path, serial, verbo
|
||||||
for path in include_paths:
|
for path in include_paths:
|
||||||
include += "-I"+path+" "
|
include += "-I"+path+" "
|
||||||
|
|
||||||
build_script_contents = """# Autogenerated by Migen
|
build_script_contents = """# Autogenerated by LiteX
|
||||||
rm -rf obj_dir/
|
rm -rf obj_dir/
|
||||||
verilator {disable_warnings} -O3 --cc dut.v --exe dut_tb.cpp -LDFLAGS "-lpthread" -trace {include}
|
verilator {disable_warnings} -O3 --cc dut.v --exe dut_tb.cpp -LDFLAGS "-lpthread" -trace {include}
|
||||||
make -j -C obj_dir/ -f Vdut.mk Vdut
|
make -j -C obj_dir/ -f Vdut.mk Vdut
|
2
litex/build/xilinx/__init__.py
Normal file
2
litex/build/xilinx/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
from litex.build.xilinx.platform import XilinxPlatform
|
||||||
|
from litex.build.xilinx.programmer import UrJTAG, XC3SProg, FpgaProg, VivadoProgrammer, iMPACT, Adept
|
|
@ -2,15 +2,15 @@ import os
|
||||||
import sys
|
import sys
|
||||||
from distutils.version import StrictVersion
|
from distutils.version import StrictVersion
|
||||||
|
|
||||||
from migen.fhdl.structure import *
|
from litex.gen.fhdl.structure import *
|
||||||
from migen.fhdl.specials import Instance
|
from litex.gen.fhdl.specials import Instance
|
||||||
from migen.fhdl.module import Module
|
from litex.gen.fhdl.module import Module
|
||||||
from migen.fhdl.specials import SynthesisDirective
|
from litex.gen.fhdl.specials import SynthesisDirective
|
||||||
from migen.genlib.cdc import *
|
from litex.gen.genlib.cdc import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.genlib.io import *
|
from litex.gen.genlib.io import *
|
||||||
|
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
|
|
||||||
|
|
||||||
def settings(path, ver=None, sub=None):
|
def settings(path, ver=None, sub=None):
|
|
@ -2,10 +2,10 @@ import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from migen.fhdl.structure import _Fragment
|
from litex.gen.fhdl.structure import _Fragment
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
from migen.build.xilinx import common
|
from litex.build.xilinx import common
|
||||||
|
|
||||||
|
|
||||||
def _format_constraint(c):
|
def _format_constraint(c):
|
||||||
|
@ -87,12 +87,12 @@ def _run_ise(build_name, ise_path, source, mode, ngdbuild_opt,
|
||||||
source_cmd = "call "
|
source_cmd = "call "
|
||||||
script_ext = ".bat"
|
script_ext = ".bat"
|
||||||
shell = ["cmd", "/c"]
|
shell = ["cmd", "/c"]
|
||||||
build_script_contents = "@echo off\nrem Autogenerated by Migen\n"
|
build_script_contents = "@echo off\nrem Autogenerated by LiteX\n"
|
||||||
else:
|
else:
|
||||||
source_cmd = "source "
|
source_cmd = "source "
|
||||||
script_ext = ".sh"
|
script_ext = ".sh"
|
||||||
shell = ["bash"]
|
shell = ["bash"]
|
||||||
build_script_contents = "# Autogenerated by Migen\nset -e\n"
|
build_script_contents = "# Autogenerated by LiteX\nset -e\n"
|
||||||
if source:
|
if source:
|
||||||
settings = common.settings(ise_path, ver, "ISE_DS")
|
settings = common.settings(ise_path, ver, "ISE_DS")
|
||||||
build_script_contents += source_cmd + settings + "\n"
|
build_script_contents += source_cmd + settings + "\n"
|
|
@ -1,5 +1,5 @@
|
||||||
from migen.build.generic_platform import GenericPlatform
|
from litex.build.generic_platform import GenericPlatform
|
||||||
from migen.build.xilinx import common, vivado, ise
|
from litex.build.xilinx import common, vivado, ise
|
||||||
|
|
||||||
|
|
||||||
class XilinxPlatform(GenericPlatform):
|
class XilinxPlatform(GenericPlatform):
|
|
@ -2,8 +2,8 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from migen.build.generic_programmer import GenericProgrammer
|
from litex.build.generic_programmer import GenericProgrammer
|
||||||
from migen.build.xilinx import common
|
from litex.build.xilinx import common
|
||||||
|
|
||||||
|
|
||||||
def _run_urjtag(cmds):
|
def _run_urjtag(cmds):
|
|
@ -5,10 +5,10 @@ import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from migen.fhdl.structure import _Fragment
|
from litex.gen.fhdl.structure import _Fragment
|
||||||
from migen.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from migen.build import tools
|
from litex.build import tools
|
||||||
from migen.build.xilinx import common
|
from litex.build.xilinx import common
|
||||||
|
|
||||||
|
|
||||||
def _format_constraint(c):
|
def _format_constraint(c):
|
||||||
|
@ -52,13 +52,13 @@ def _build_xdc(named_sc, named_pc):
|
||||||
|
|
||||||
def _run_vivado(build_name, vivado_path, source, ver=None):
|
def _run_vivado(build_name, vivado_path, source, ver=None):
|
||||||
if sys.platform == "win32" or sys.platform == "cygwin":
|
if sys.platform == "win32" or sys.platform == "cygwin":
|
||||||
build_script_contents = "REM Autogenerated by Migen\n"
|
build_script_contents = "REM Autogenerated by LiteX\n"
|
||||||
build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n"
|
build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n"
|
||||||
build_script_file = "build_" + build_name + ".bat"
|
build_script_file = "build_" + build_name + ".bat"
|
||||||
tools.write_to_file(build_script_file, build_script_contents)
|
tools.write_to_file(build_script_file, build_script_contents)
|
||||||
r = subprocess.call([build_script_file])
|
r = subprocess.call([build_script_file])
|
||||||
else:
|
else:
|
||||||
build_script_contents = "# Autogenerated by Migen\nset -e\n"
|
build_script_contents = "# Autogenerated by LiteX\nset -e\n"
|
||||||
settings = common.settings(vivado_path, ver)
|
settings = common.settings(vivado_path, ver)
|
||||||
build_script_contents += "source " + settings + "\n"
|
build_script_contents += "source " + settings + "\n"
|
||||||
build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n"
|
build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n"
|
7
litex/gen/.gitignore
vendored
7
litex/gen/.gitignore
vendored
|
@ -1,7 +0,0 @@
|
||||||
__pycache__
|
|
||||||
*.pyc
|
|
||||||
*.egg-info/
|
|
||||||
vpi/*.o
|
|
||||||
vpi/migensim.vpi
|
|
||||||
examples/*.vcd
|
|
||||||
doc/_build
|
|
|
@ -1,52 +0,0 @@
|
||||||
language: python
|
|
||||||
python:
|
|
||||||
- "3.5"
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- PATH=$HOME/miniconda/bin:$PATH
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# Install Miniconda
|
|
||||||
- wget https://raw.githubusercontent.com/m-labs/artiq/master/.travis/get-anaconda.sh
|
|
||||||
- chmod +x get-anaconda.sh
|
|
||||||
- ./get-anaconda.sh
|
|
||||||
- source $HOME/miniconda/bin/activate py35
|
|
||||||
- conda install anaconda-client numpydoc
|
|
||||||
install:
|
|
||||||
# Install iverilog package.
|
|
||||||
# - "sudo add-apt-repository -y ppa:mithro/iverilog-backport"
|
|
||||||
# - "sudo apt-get update"
|
|
||||||
# - "sudo apt-get install iverilog"
|
|
||||||
# - "iverilog -v; true"
|
|
||||||
# Build the vpi module.
|
|
||||||
# - "(cd vpi; make; sudo make install)"
|
|
||||||
# Install verilator package
|
|
||||||
- "sudo apt-get install verilator"
|
|
||||||
- "verilator --version; true"
|
|
||||||
# Build and install Migen conda package
|
|
||||||
# workaround for https://github.com/conda/conda-build/issues/466
|
|
||||||
- "mkdir -p /home/travis/miniconda/conda-bld/linux-64"
|
|
||||||
- "conda index /home/travis/miniconda/conda-bld/linux-64"
|
|
||||||
- "conda build --python 3.5 conda/migen"
|
|
||||||
- "conda install $(conda build --output --python 3.5 conda/migen)"
|
|
||||||
|
|
||||||
script:
|
|
||||||
# Run tests
|
|
||||||
- "python setup.py test"
|
|
||||||
# Generate HTML documentation
|
|
||||||
- "make -C doc html"
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
# Upload Migen conda package to binstar
|
|
||||||
- if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then anaconda login --hostname $(hostname) --username $binstar_login --password $binstar_password; fi
|
|
||||||
- if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then anaconda upload --user $binstar_login --channel dev --force $HOME/miniconda/conda-bld/noarch/migen-*.tar.bz2; fi
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- chat.freenode.net#m-labs
|
|
||||||
template:
|
|
||||||
- "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}"
|
|
||||||
- "Build details : %{build_url}"
|
|
|
@ -1,31 +0,0 @@
|
||||||
Unless otherwise noted, Migen is copyright (C) 2011-2013 Sebastien Bourdeauducq.
|
|
||||||
The simulation extension (as mentioned in the comments at the beginning of the
|
|
||||||
corresponding source files) is copyright (C) 2012 Vermeer Manufacturing Co. All
|
|
||||||
rights reserved.
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,82 +0,0 @@
|
||||||
### Migen (Milkymist generator)
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/m-labs/migen.svg)](
|
|
||||||
https://travis-ci.org/m-labs/migen)
|
|
||||||
|
|
||||||
#### A Python toolbox for building complex digital hardware
|
|
||||||
|
|
||||||
Despite being faster than schematics entry, hardware design with Verilog and
|
|
||||||
VHDL remains tedious and inefficient for several reasons. The event-driven
|
|
||||||
model introduces issues and manual coding that are unnecessary for synchronous
|
|
||||||
circuits, which represent the lion's share of today's logic designs. Counter-
|
|
||||||
intuitive arithmetic rules result in steeper learning curves and provide a
|
|
||||||
fertile ground for subtle bugs in designs. Finally, support for procedural
|
|
||||||
generation of logic (metaprogramming) through "generate" statements is very
|
|
||||||
limited and restricts the ways code can be made generic, reused and organized.
|
|
||||||
|
|
||||||
To address those issues, we have developed the **Migen FHDL** library that
|
|
||||||
replaces the event-driven paradigm with the notions of combinatorial and
|
|
||||||
synchronous statements, has arithmetic rules that make integers always behave
|
|
||||||
like mathematical integers, and most importantly allows the design's logic to
|
|
||||||
be constructed by a Python program. This last point enables hardware designers
|
|
||||||
to take advantage of the richness of the Python language - object oriented
|
|
||||||
programming, function parameters, generators, operator overloading, libraries,
|
|
||||||
etc. - to build well organized, reusable and elegant designs.
|
|
||||||
|
|
||||||
Other Migen libraries are built on FHDL and provide various tools such as a
|
|
||||||
system-on-chip interconnect infrastructure, a dataflow programming system, a
|
|
||||||
more traditional high-level synthesizer that compiles Python routines into
|
|
||||||
state machines with datapaths, and a simulator that allows test benches to be
|
|
||||||
written in Python.
|
|
||||||
|
|
||||||
See the doc/ folder for more technical information.
|
|
||||||
|
|
||||||
Migen is designed for Python 3.3. Note that Migen is **not** spelled MiGen.
|
|
||||||
|
|
||||||
#### Quick Links
|
|
||||||
|
|
||||||
Code repository:
|
|
||||||
https://github.com/m-labs/migen
|
|
||||||
|
|
||||||
System-on-chip design based on Migen:
|
|
||||||
https://github.com/m-labs/misoc
|
|
||||||
|
|
||||||
Online documentation:
|
|
||||||
http://m-labs.hk/gateware.html
|
|
||||||
|
|
||||||
#### Quick intro
|
|
||||||
|
|
||||||
```python
|
|
||||||
from migen import *
|
|
||||||
from migen.build.platforms import m1
|
|
||||||
plat = m1.Platform()
|
|
||||||
led = plat.request("user_led")
|
|
||||||
m = Module()
|
|
||||||
counter = Signal(26)
|
|
||||||
m.comb += led.eq(counter[25])
|
|
||||||
m.sync += counter.eq(counter + 1)
|
|
||||||
plat.build_cmdline(m)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### License
|
|
||||||
|
|
||||||
Migen is released under the very permissive two-clause BSD license. Under the
|
|
||||||
terms of this license, you are authorized to use Migen 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 Migen
|
|
||||||
* put the Migen logo (doc/migen_logo.svg) on the page of a product using it,
|
|
||||||
with a link to http://m-labs.hk
|
|
||||||
* cite Migen 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 Migen. 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 it on
|
|
||||||
the mailing list or IRC (#m-labs on Freenode) beforehand.
|
|
||||||
|
|
||||||
See LICENSE file for full copyright and license info. You can contact us on the
|
|
||||||
public mailing list devel [AT] lists.m-labs.hk.
|
|
||||||
|
|
||||||
"Electricity! It's like magic!"
|
|
10
litex/gen/__init__.py
Normal file
10
litex/gen/__init__.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from litex.gen.fhdl.structure import *
|
||||||
|
from litex.gen.fhdl.module import *
|
||||||
|
from litex.gen.fhdl.specials import *
|
||||||
|
from litex.gen.fhdl.bitcontainer import *
|
||||||
|
from litex.gen.fhdl.decorators import *
|
||||||
|
|
||||||
|
from litex.gen.sim import *
|
||||||
|
|
||||||
|
from litex.gen.genlib.record import *
|
||||||
|
from litex.gen.genlib.fsm import *
|
|
@ -1 +0,0 @@
|
||||||
%PYTHON% setup.py install
|
|
|
@ -1,28 +0,0 @@
|
||||||
package:
|
|
||||||
name: migen
|
|
||||||
version: {{ environ.get("GIT_DESCRIBE_TAG", "") }}
|
|
||||||
|
|
||||||
source:
|
|
||||||
git_url: https://github.com/m-labs/migen
|
|
||||||
git_tag: master
|
|
||||||
|
|
||||||
build:
|
|
||||||
noarch_python: true
|
|
||||||
number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}
|
|
||||||
string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_DESCRIBE_HASH", "")[1:] }}
|
|
||||||
script: $PYTHON setup.py install
|
|
||||||
|
|
||||||
requirements:
|
|
||||||
build:
|
|
||||||
- python 3.5.*
|
|
||||||
run:
|
|
||||||
- python 3.5.*
|
|
||||||
|
|
||||||
test:
|
|
||||||
imports:
|
|
||||||
- migen
|
|
||||||
|
|
||||||
about:
|
|
||||||
home: http://m-labs.hk/gateware.html
|
|
||||||
license: 3-clause BSD
|
|
||||||
summary: 'A Python toolbox for building complex digital hardware'
|
|
|
@ -1,130 +0,0 @@
|
||||||
# Makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
|
||||||
SPHINXOPTS =
|
|
||||||
SPHINXBUILD = sphinx-build
|
|
||||||
PAPER =
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Internal variables.
|
|
||||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
|
||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
|
||||||
|
|
||||||
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 " qthelp to make HTML files and a qthelp project"
|
|
||||||
@echo " devhelp to make HTML files and a Devhelp 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 " text to make text files"
|
|
||||||
@echo " man to make manual pages"
|
|
||||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
|
||||||
@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."
|
|
||||||
|
|
||||||
qthelp:
|
|
||||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Migen.qhcp"
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Migen.qhc"
|
|
||||||
|
|
||||||
devhelp:
|
|
||||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished."
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Migen"
|
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Migen"
|
|
||||||
@echo "# devhelp"
|
|
||||||
|
|
||||||
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."
|
|
||||||
|
|
||||||
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."
|
|
||||||
|
|
||||||
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."
|
|
0
litex/gen/doc/_static/.keep_me
vendored
0
litex/gen/doc/_static/.keep_me
vendored
0
litex/gen/doc/_templates/.keep_me
vendored
0
litex/gen/doc/_templates/.keep_me
vendored
|
@ -1,223 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Migen documentation build configuration file, created by
|
|
||||||
# sphinx-quickstart on Fri Mar 9 14:11:54 2012.
|
|
||||||
#
|
|
||||||
# This file is execfile()d with the current directory set to its containing dir.
|
|
||||||
#
|
|
||||||
# Note that not all possible configuration values are present in this
|
|
||||||
# autogenerated file.
|
|
||||||
#
|
|
||||||
# All configuration values have a default; values that are commented out
|
|
||||||
# serve to show the default.
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
#sys.path.insert(0, os.path.abspath('.'))
|
|
||||||
|
|
||||||
# -- General configuration -----------------------------------------------------
|
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
|
||||||
#needs_sphinx = '1.0'
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
|
||||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
|
||||||
extensions = [
|
|
||||||
'sphinx.ext.pngmath',
|
|
||||||
'sphinx.ext.autodoc',
|
|
||||||
'sphinx.ext.doctest',
|
|
||||||
'sphinx.ext.autosummary',
|
|
||||||
'numpydoc', # to preprocess docstrings
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix of source filenames.
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The encoding of source files.
|
|
||||||
#source_encoding = 'utf-8-sig'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = u'Migen'
|
|
||||||
copyright = u'2011-2015, M-Labs Limited'
|
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
|
||||||
# |version| and |release|, also used in various other places throughout the
|
|
||||||
# built documents.
|
|
||||||
#
|
|
||||||
# The short X.Y version.
|
|
||||||
version = '1.0'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = '1.0'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#language = None
|
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
|
||||||
# non-false value, then it is used:
|
|
||||||
#today = ''
|
|
||||||
# Else, today_fmt is used as the format for a strftime call.
|
|
||||||
#today_fmt = '%B %d, %Y'
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
exclude_patterns = ['_build']
|
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
|
||||||
#default_role = None
|
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
|
||||||
#add_function_parentheses = True
|
|
||||||
|
|
||||||
# If true, the current module name will be prepended to all description
|
|
||||||
# unit titles (such as .. function::).
|
|
||||||
#add_module_names = True
|
|
||||||
|
|
||||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
|
||||||
# output. They are ignored by default.
|
|
||||||
#show_authors = False
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
|
||||||
modindex_common_prefix = ['migen.']
|
|
||||||
|
|
||||||
numpydoc_show_class_members = False
|
|
||||||
|
|
||||||
# -- Options for HTML output ---------------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
html_theme = 'alabaster'
|
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
|
||||||
# further. For a list of options available for each theme, see the
|
|
||||||
# documentation.
|
|
||||||
#html_theme_options = {}
|
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
|
||||||
#html_theme_path = []
|
|
||||||
|
|
||||||
# The name for this set of Sphinx documents. If None, it defaults to
|
|
||||||
# "<project> v<release> documentation".
|
|
||||||
#html_title = None
|
|
||||||
|
|
||||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
|
||||||
#html_short_title = None
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top
|
|
||||||
# of the sidebar.
|
|
||||||
#html_logo = None
|
|
||||||
|
|
||||||
# The name of an image file (within the static path) to use as favicon of the
|
|
||||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
|
||||||
# pixels large.
|
|
||||||
#html_favicon = None
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
|
||||||
# using the given strftime format.
|
|
||||||
#html_last_updated_fmt = '%b %d, %Y'
|
|
||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
|
||||||
# typographically correct entities.
|
|
||||||
#html_use_smartypants = True
|
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
|
||||||
#html_sidebars = {}
|
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
|
||||||
# template names.
|
|
||||||
#html_additional_pages = {}
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#html_domain_indices = True
|
|
||||||
|
|
||||||
# If false, no index is generated.
|
|
||||||
#html_use_index = True
|
|
||||||
|
|
||||||
# If true, the index is split into individual pages for each letter.
|
|
||||||
#html_split_index = False
|
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
|
||||||
#html_show_sourcelink = True
|
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_sphinx = True
|
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_copyright = True
|
|
||||||
|
|
||||||
# If true, an OpenSearch description file will be output, and all pages will
|
|
||||||
# contain a <link> tag referring to it. The value of this option must be the
|
|
||||||
# base URL from which the finished HTML is served.
|
|
||||||
#html_use_opensearch = ''
|
|
||||||
|
|
||||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
|
||||||
#html_file_suffix = None
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = 'Migendoc'
|
|
||||||
|
|
||||||
html_use_modindex = False
|
|
||||||
|
|
||||||
# -- Options for LaTeX output --------------------------------------------------
|
|
||||||
|
|
||||||
# The paper size ('letter' or 'a4').
|
|
||||||
#latex_paper_size = 'letter'
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#latex_font_size = '10pt'
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
|
||||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
|
||||||
latex_documents = [
|
|
||||||
('index', 'Migen.tex', u'Migen manual',
|
|
||||||
u'Sebastien Bourdeauducq', 'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
|
||||||
# the title page.
|
|
||||||
latex_logo = "migen_logo.png"
|
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
|
||||||
# not chapters.
|
|
||||||
#latex_use_parts = False
|
|
||||||
|
|
||||||
# If true, show page references after internal links.
|
|
||||||
#latex_show_pagerefs = False
|
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
|
||||||
#latex_show_urls = False
|
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
latex_preamble = '\setcounter{tocdepth}{3}'
|
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
|
||||||
#latex_appendices = []
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#latex_domain_indices = True
|
|
||||||
|
|
||||||
latex_use_modindex = False
|
|
||||||
|
|
||||||
# -- Options for manual page output --------------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
('index', 'migen', u'Migen manual',
|
|
||||||
[u'Sebastien Bourdeauducq'], 1)
|
|
||||||
]
|
|
|
@ -1,362 +0,0 @@
|
||||||
The FHDL domain-specific language
|
|
||||||
#################################
|
|
||||||
|
|
||||||
The Fragmented Hardware Description Language (FHDL) is the basis of Migen. It consists of a formal system to describe signals, and combinatorial and synchronous statements operating on them. The formal system itself is low level and close to the synthesizable subset of Verilog, and we then rely on Python algorithms to build complex structures by combining FHDL elements.
|
|
||||||
The FHDL module also contains a back-end to produce synthesizable Verilog, and some structure analysis and manipulation functionality.
|
|
||||||
|
|
||||||
FHDL differs from MyHDL [myhdl]_ in fundamental ways. MyHDL follows the event-driven paradigm of traditional HDLs (see :ref:`background`) while FHDL separates the code into combinatorial statements, synchronous statements, and reset values. In MyHDL, the logic is described directly in the Python AST. The converter to Verilog or VHDL then examines the Python AST and recognizes a subset of Python that it translates into V*HDL statements. This seriously impedes the capability of MyHDL to generate logic procedurally. With FHDL, you manipulate a custom AST from Python, and you can more easily design algorithms that operate on it.
|
|
||||||
|
|
||||||
.. [myhdl] http://www.myhdl.org
|
|
||||||
|
|
||||||
FHDL is made of several elements, which are briefly explained below. They all can be imported directly from the ``migen`` module.
|
|
||||||
|
|
||||||
Expressions
|
|
||||||
***********
|
|
||||||
|
|
||||||
Constants
|
|
||||||
=========
|
|
||||||
|
|
||||||
The ``Constant`` object represents a constant, HDL-literal integer. It behaves like specifying integers and booleans but also supports slicing and can have a bit width or signedness different from what is implied by the value it represents.
|
|
||||||
|
|
||||||
``True`` and ``False`` are interpreted as 1 and 0, respectively.
|
|
||||||
|
|
||||||
Negative integers are explicitly supported. As with MyHDL [countin]_, arithmetic operations return the natural results.
|
|
||||||
|
|
||||||
To lighten the syntax, assignments and operators automatically wrap Python integers and booleans into ``Constant``. Additionally, ``Constant`` is aliased to ``C``. The following are valid Migen statements: ``a.eq(0)``, ``a.eq(a + 1)``, ``a.eq(C(42)[0:1])``.
|
|
||||||
|
|
||||||
.. [countin] http://www.jandecaluwe.com/hdldesign/counting.html
|
|
||||||
|
|
||||||
Signal
|
|
||||||
======
|
|
||||||
|
|
||||||
The signal object represents a value that is expected to change in the circuit. It does exactly what Verilog's "wire" and "reg" and VHDL's "signal" do.
|
|
||||||
|
|
||||||
The main point of the signal object is that it is identified by its Python ID (as returned by the :py:func:`id` function), and nothing else. It is the responsibility of the V*HDL back-end to establish an injective mapping between Python IDs and the V*HDL namespace. It should perform name mangling to ensure this. The consequence of this is that signal objects can safely become members of arbitrary Python classes, or be passed as parameters to functions or methods that generate logic involving them.
|
|
||||||
|
|
||||||
The properties of a signal object are:
|
|
||||||
|
|
||||||
* An integer or a (integer, boolean) pair that defines the number of bits and whether the bit of higher index of the signal is a sign bit (i.e. the signal is signed). The defaults are one bit and unsigned. Alternatively, the ``min`` and ``max`` parameters can be specified to define the range of the signal and determine its bit width and signedness. As with Python ranges, ``min`` is inclusive and defaults to 0, ``max`` is exclusive and defaults to 2.
|
|
||||||
* A name, used as a hint for the V*HDL back-end name mangler.
|
|
||||||
* The signal's reset value. It must be an integer, and defaults to 0. When the signal's value is modified with a synchronous statement, the reset value is the initialization value of the associated register. When the signal is assigned to in a conditional combinatorial statement (``If`` or ``Case``), the reset value is the value that the signal has when no condition that causes the signal to be driven is verified. This enforces the absence of latches in designs. If the signal is permanently driven using a combinatorial statement, the reset value has no effect.
|
|
||||||
|
|
||||||
The sole purpose of the name property is to make the generated V*HDL code easier to understand and debug. From a purely functional point of view, it is perfectly OK to have several signals with the same name property. The back-end will generate a unique name for each object. If no name property is specified, Migen will analyze the code that created the signal object, and try to extract the variable or member name from there. For example, the following statements will create one or several signals named "bar": ::
|
|
||||||
|
|
||||||
bar = Signal()
|
|
||||||
self.bar = Signal()
|
|
||||||
self.baz.bar = Signal()
|
|
||||||
bar = [Signal() for x in range(42)]
|
|
||||||
|
|
||||||
In case of conflicts, Migen tries first to resolve the situation by prefixing the identifiers with names from the class and module hierarchy that created them. If the conflict persists (which can be the case if two signal objects are created with the same name in the same context), it will ultimately add number suffixes.
|
|
||||||
|
|
||||||
Operators
|
|
||||||
=========
|
|
||||||
|
|
||||||
Operators are represented by the ``_Operator`` object, which generally should not be used directly. Instead, most FHDL objects overload the usual Python logic and arithmetic operators, which allows a much lighter syntax to be used. For example, the expression: ::
|
|
||||||
|
|
||||||
a * b + c
|
|
||||||
|
|
||||||
is equivalent to::
|
|
||||||
|
|
||||||
_Operator("+", [_Operator("*", [a, b]), c])
|
|
||||||
|
|
||||||
Slices
|
|
||||||
======
|
|
||||||
|
|
||||||
Likewise, slices are represented by the ``_Slice`` object, which often should not be used in favor of the Python slice operation [x:y]. Implicit indices using the forms [x], [x:] and [:y] are supported. Beware! Slices work like Python slices, not like VHDL or Verilog slices. The first bound is the index of the LSB and is inclusive. The second bound is the index of MSB and is exclusive. In V*HDL, bounds are MSB:LSB and both are inclusive.
|
|
||||||
|
|
||||||
Concatenations
|
|
||||||
==============
|
|
||||||
|
|
||||||
Concatenations are done using the ``Cat`` object. To make the syntax lighter, its constructor takes a variable number of arguments, which are the signals to be concatenated together (you can use the Python "*" operator to pass a list instead).
|
|
||||||
To be consistent with slices, the first signal is connected to the bits with the lowest indices in the result. This is the opposite of the way the "{}" construct works in Verilog.
|
|
||||||
|
|
||||||
Replications
|
|
||||||
============
|
|
||||||
|
|
||||||
The ``Replicate`` object represents the equivalent of {count{expression}} in Verilog.
|
|
||||||
|
|
||||||
Statements
|
|
||||||
**********
|
|
||||||
|
|
||||||
Assignment
|
|
||||||
==========
|
|
||||||
|
|
||||||
Assignments are represented with the ``_Assign`` object. Since using it directly would result in a cluttered syntax, the preferred technique for assignments is to use the ``eq()`` method provided by objects that can have a value assigned to them. They are signals, and their combinations with the slice and concatenation operators.
|
|
||||||
As an example, the statement: ::
|
|
||||||
|
|
||||||
a[0].eq(b)
|
|
||||||
|
|
||||||
is equivalent to: ::
|
|
||||||
|
|
||||||
_Assign(_Slice(a, 0, 1), b)
|
|
||||||
|
|
||||||
If
|
|
||||||
==
|
|
||||||
|
|
||||||
The ``If`` object takes a first parameter which must be an expression (combination of the ``Constant``, ``Signal``, ``_Operator``, ``_Slice``, etc. objects) representing the condition, then a variable number of parameters representing the statements (``_Assign``, ``If``, ``Case``, etc. objects) to be executed when the condition is verified.
|
|
||||||
|
|
||||||
The ``If`` object defines a ``Else()`` method, which when called defines the statements to be executed when the condition is not true. Those statements are passed as parameters to the variadic method.
|
|
||||||
|
|
||||||
For convenience, there is also a ``Elif()`` method.
|
|
||||||
|
|
||||||
Example: ::
|
|
||||||
|
|
||||||
If(tx_count16 == 0,
|
|
||||||
tx_bitcount.eq(tx_bitcount + 1),
|
|
||||||
If(tx_bitcount == 8,
|
|
||||||
self.tx.eq(1)
|
|
||||||
).Elif(tx_bitcount == 9,
|
|
||||||
self.tx.eq(1),
|
|
||||||
tx_busy.eq(0)
|
|
||||||
).Else(
|
|
||||||
self.tx.eq(tx_reg[0]),
|
|
||||||
tx_reg.eq(Cat(tx_reg[1:], 0))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
Case
|
|
||||||
====
|
|
||||||
|
|
||||||
The ``Case`` object constructor takes as first parameter the expression to be tested, and a dictionary whose keys are the values to be matched, and values the statements to be executed in the case of a match. The special value ``"default"`` can be used as match value, which means the statements should be executed whenever there is no other match.
|
|
||||||
|
|
||||||
Arrays
|
|
||||||
======
|
|
||||||
|
|
||||||
The ``Array`` object represents lists of other objects that can be indexed by FHDL expressions. It is explicitly possible to:
|
|
||||||
|
|
||||||
* nest ``Array`` objects to create multidimensional tables.
|
|
||||||
* list any Python object in a ``Array`` as long as every expression appearing in a module ultimately evaluates to a ``Signal`` for all possible values of the indices. This allows the creation of lists of structured data.
|
|
||||||
* use expressions involving ``Array`` objects in both directions (assignment and reading).
|
|
||||||
|
|
||||||
For example, this creates a 4x4 matrix of 1-bit signals: ::
|
|
||||||
|
|
||||||
my_2d_array = Array(Array(Signal() for a in range(4)) for b in range(4))
|
|
||||||
|
|
||||||
You can then read the matrix with (``x`` and ``y`` being 2-bit signals): ::
|
|
||||||
|
|
||||||
out.eq(my_2d_array[x][y])
|
|
||||||
|
|
||||||
and write it with: ::
|
|
||||||
|
|
||||||
my_2d_array[x][y].eq(inp)
|
|
||||||
|
|
||||||
Since they have no direct equivalent in Verilog, ``Array`` objects are lowered into multiplexers and conditional statements before the actual conversion takes place. Such lowering happens automatically without any user intervention.
|
|
||||||
|
|
||||||
Specials
|
|
||||||
********
|
|
||||||
|
|
||||||
Tri-state I/O
|
|
||||||
=============
|
|
||||||
|
|
||||||
A triplet (O, OE, I) of one-way signals defining a tri-state I/O port is represented by the ``TSTriple`` object. Such objects are only containers for signals that are intended to be later connected to a tri-state I/O buffer, and cannot be used as module specials. Such objects, however, should be kept in the design as long as possible as they allow the individual one-way signals to be manipulated in a non-ambiguous way.
|
|
||||||
|
|
||||||
The object that can be used in as a module special is ``Tristate``, and it behaves exactly like an instance of a tri-state I/O buffer that would be defined as follows: ::
|
|
||||||
|
|
||||||
Instance("Tristate",
|
|
||||||
io_target=target,
|
|
||||||
i_o=o,
|
|
||||||
i_oe=oe,
|
|
||||||
o_i=i
|
|
||||||
)
|
|
||||||
|
|
||||||
Signals ``target``, ``o`` and ``i`` can have any width, while ``oe`` is 1-bit wide. The ``target`` signal should go to a port and not be used elsewhere in the design. Like modern FPGA architectures, Migen does not support internal tri-states.
|
|
||||||
|
|
||||||
A ``Tristate`` object can be created from a ``TSTriple`` object by calling the ``get_tristate`` method.
|
|
||||||
|
|
||||||
By default, Migen emits technology-independent behavioral code for a tri-state buffer. If a specific code is needed, the tristate handler can be overriden using the appropriate parameter of the V*HDL conversion function.
|
|
||||||
|
|
||||||
Instances
|
|
||||||
=========
|
|
||||||
|
|
||||||
Instance objects represent the parametrized instantiation of a V*HDL module, and the connection of its ports to FHDL signals. They are useful in a number of cases:
|
|
||||||
|
|
||||||
* Reusing legacy or third-party V*HDL code.
|
|
||||||
* Using special FPGA features (DCM, ICAP, ...).
|
|
||||||
* Implementing logic that cannot be expressed with FHDL (e.g. latches).
|
|
||||||
* Breaking down a Migen system into multiple sub-systems.
|
|
||||||
|
|
||||||
The instance object constructor takes the type (i.e. name of the instantiated module) of the instance, then multiple parameters describing how to connect and parametrize the instance.
|
|
||||||
|
|
||||||
These parameters can be:
|
|
||||||
|
|
||||||
* ``Instance.Input``, ``Instance.Output`` or ``Instance.InOut`` to describe signal connections with the instance. The parameters are the name of the port at the instance, and the FHDL expression it should be connected to.
|
|
||||||
* ``Instance.Parameter`` sets a parameter (with a name and value) of the instance.
|
|
||||||
* ``Instance.ClockPort`` and ``Instance.ResetPort`` are used to connect clock and reset signals to the instance. The only mandatory parameter is the name of the port at the instance. Optionally, a clock domain name can be specified, and the ``invert`` option can be used to interface to those modules that require a 180-degree clock or a active-low reset.
|
|
||||||
|
|
||||||
Memories
|
|
||||||
========
|
|
||||||
|
|
||||||
Memories (on-chip SRAM) are supported using a mechanism similar to instances.
|
|
||||||
|
|
||||||
A memory object has the following parameters:
|
|
||||||
|
|
||||||
* The width, which is the number of bits in each word.
|
|
||||||
* The depth, which represents the number of words in the memory.
|
|
||||||
* An optional list of integers used to initialize the memory.
|
|
||||||
|
|
||||||
To access the memory in hardware, ports can be obtained by calling the ``get_port`` method. A port always has an address signal ``a`` and a data read signal ``dat_r``. Other signals may be available depending on the port's configuration.
|
|
||||||
|
|
||||||
Options to ``get_port`` are:
|
|
||||||
|
|
||||||
* ``write_capable`` (default: ``False``): if the port can be used to write to the memory. This creates an additional ``we`` signal.
|
|
||||||
* ``async_read`` (default: ``False``): whether reads are asychronous (combinatorial) or synchronous (registered).
|
|
||||||
* ``has_re`` (default: ``False``): adds a read clock-enable signal ``re`` (ignored for asychronous ports).
|
|
||||||
* ``we_granularity`` (default: ``0``): if non-zero, writes of less than a memory word can occur. The width of the ``we`` signal is increased to act as a selection signal for the sub-words.
|
|
||||||
* ``mode`` (default: ``WRITE_FIRST``, ignored for aynchronous ports). It can be:
|
|
||||||
|
|
||||||
* ``READ_FIRST``: during a write, the previous value is read.
|
|
||||||
* ``WRITE_FIRST``: the written value is returned.
|
|
||||||
* ``NO_CHANGE``: the data read signal keeps its previous value on a write.
|
|
||||||
|
|
||||||
* ``clock_domain`` (default: ``"sys"``): the clock domain used for reading and writing from this port.
|
|
||||||
|
|
||||||
Migen generates behavioural V*HDL code that should be compatible with all simulators and, if the number of ports is <= 2, most FPGA synthesizers. If a specific code is needed, the memory handler can be overriden using the appropriate parameter of the V*HDL conversion function.
|
|
||||||
|
|
||||||
Inline synthesis directives
|
|
||||||
===========================
|
|
||||||
|
|
||||||
Inline synthesis directives (pseudo-comments such as ``// synthesis attribute keep of clock_signal_name is true``) are supported using the ``SynthesisDirective`` object. Its constructor takes as parameters a string containing the body of the directive, and optional keyword parameters that are used to replace signal names similarly to the Python string method ``format``. The above example could be represented as follows: ::
|
|
||||||
|
|
||||||
SynthesisDirective("attribute keep of {clksig} is true", clksig=clock_domain.clk)
|
|
||||||
|
|
||||||
Modules
|
|
||||||
*******
|
|
||||||
|
|
||||||
Modules play the same role as Verilog modules and VHDL entities. Similarly, they are organized in a tree structure. A FHDL module is a Python object that derives from the ``Module`` class. This class defines special attributes to be used by derived classes to describe their logic. They are explained below.
|
|
||||||
|
|
||||||
Combinatorial statements
|
|
||||||
========================
|
|
||||||
|
|
||||||
A combinatorial statement is a statement that is executed whenever one of its inputs changes.
|
|
||||||
|
|
||||||
Combinatorial statements are added to a module by using the ``comb`` special attribute. Like most module special attributes, it must be accessed using the ``+=`` incrementation operator, and either a single statement, a tuple of statements or a list of statements can appear on the right hand side.
|
|
||||||
|
|
||||||
For example, the module below implements a OR gate: ::
|
|
||||||
|
|
||||||
class ORGate(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.a = Signal()
|
|
||||||
self.b = Signal()
|
|
||||||
self.x = Signal()
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
self.comb += x.eq(a | b)
|
|
||||||
|
|
||||||
To improve code readability, it is recommended to place the interface of the module at the beginning of the ``__init__`` function, and separate it from the implementation using three hash signs.
|
|
||||||
|
|
||||||
Synchronous statements
|
|
||||||
======================
|
|
||||||
|
|
||||||
A synchronous statements is a statement that is executed at each edge of some clock signal.
|
|
||||||
|
|
||||||
They are added to a module by using the ``sync`` special attribute, which has the same properties as the ``comb`` attribute.
|
|
||||||
|
|
||||||
The ``sync`` special attribute also has sub-attributes that correspond to abstract clock domains. For example, to add a statement to the clock domain named ``foo``, one would write ``self.sync.foo += statement``. The default clock domain is ``sys`` and writing ``self.sync += statement`` is equivalent to writing ``self.sync.sys += statement``.
|
|
||||||
|
|
||||||
Submodules and specials
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Submodules and specials can be added by using the ``submodules`` and ``specials`` attributes respectively. This can be done in two ways:
|
|
||||||
|
|
||||||
#. anonymously, by using the ``+=`` operator on the special attribute directly, e.g. ``self.submodules += some_other_module``. Like with the ``comb`` and ``sync`` attributes, a single module/special or a tuple or list can be specified.
|
|
||||||
#. by naming the submodule/special using a subattribute of the ``submodules`` or ``specials`` attribute, e.g. ``self.submodules.foo = module_foo``. The submodule/special is then accessible as an attribute of the object, e.g. ``self.foo`` (and not ``self.submodules.foo``). Only one submodule/special can be added at a time using this form.
|
|
||||||
|
|
||||||
Clock domains
|
|
||||||
=============
|
|
||||||
|
|
||||||
Specifying the implementation of a clock domain is done using the ``ClockDomain`` object. It contains the name of the clock domain, a clock signal that can be driven like any other signal in the design (for example, using a PLL instance), and optionally a reset signal. Clock domains without a reset signal are reset using e.g. ``initial`` statements in Verilog, which in many FPGA families initalize the registers during configuration.
|
|
||||||
|
|
||||||
The name can be omitted if it can be extracted from the variable name. When using this automatic naming feature, prefixes ``_``, ``cd_`` and ``_cd_`` are removed.
|
|
||||||
|
|
||||||
Clock domains are then added to a module using the ``clock_domains`` special attribute, which behaves exactly like ``submodules`` and ``specials``.
|
|
||||||
|
|
||||||
Summary of special attributes
|
|
||||||
=============================
|
|
||||||
|
|
||||||
.. table::
|
|
||||||
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| Syntax | Action |
|
|
||||||
+============================================+==============================================================+
|
|
||||||
| self.comb += stmt | Add combinatorial statement to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.comb += stmtA, stmtB | Add combinatorial statements A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.comb += [stmtA, stmtB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.sync += stmt | Add synchronous statement to current module, in default |
|
|
||||||
| | clock domain sys. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.sync.foo += stmt | Add synchronous statement to current module, in clock domain |
|
|
||||||
| | foo. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.sync.foo += stmtA, stmtB | Add synchronous statements A and B to current module, in |
|
|
||||||
| | clock domain foo. |
|
|
||||||
| self.sync.foo += [stmtA, stmtB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.submodules += mod | Add anonymous submodule to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.submodules += modA, modB | Add anonymous submodules A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.submodules += [modA, modB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.submodules.bar = mod | Add submodule named bar to current module. The submodule can |
|
|
||||||
| | then be accessed using self.bar. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.specials += spe | Add anonymous special to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.specials += speA, speB | Add anonymous specials A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.specials += [speA, speB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.specials.bar = spe | Add special named bar to current module. The special can |
|
|
||||||
| | then be accessed using self.bar. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.clock_domains += cd | Add clock domain to current module. |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.clock_domains += cdA, cdB | Add clock domains A and B to current module. |
|
|
||||||
| | |
|
|
||||||
| self.clock_domains += [cdA, cdB] | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
| self.clock_domains.pix = ClockDomain() | Create and add clock domain pix to current module. The clock |
|
|
||||||
| | domain name is pix in all cases. It can be accessed using |
|
|
||||||
| self.clock_domains._pix = ClockDomain() | self.pix, self._pix, self.cd_pix and self._cd_pix, |
|
|
||||||
| | respectively. |
|
|
||||||
| self.clock_domains.cd_pix = ClockDomain() | |
|
|
||||||
| | |
|
|
||||||
| self.clock_domains._cd_pix = ClockDomain() | |
|
|
||||||
+--------------------------------------------+--------------------------------------------------------------+
|
|
||||||
|
|
||||||
Clock domain management
|
|
||||||
=======================
|
|
||||||
|
|
||||||
When a module has named submodules that define one or several clock domains with the same name, those clock domain names are prefixed with the name of each submodule plus an underscore.
|
|
||||||
|
|
||||||
An example use case of this feature is a system with two independent video outputs. Each video output module is made of a clock generator module that defines a clock domain ``pix`` and drives the clock signal, plus a driver module that has synchronous statements and other elements in clock domain ``pix``. The designer of the video output module can simply use the clock domain name ``pix`` in that module. In the top-level system module, the video output submodules are named ``video0`` and ``video1``. Migen then automatically renames the ``pix`` clock domain of each module to ``video0_pix`` and ``video1_pix``. Note that happens only because the clock domain is defined (using ClockDomain objects), not simply referenced (using e.g. synchronous statements) in the video output modules.
|
|
||||||
|
|
||||||
Clock domain name overlap is an error condition when any of the submodules that defines the clock domains is anonymous.
|
|
||||||
|
|
||||||
Finalization mechanism
|
|
||||||
======================
|
|
||||||
|
|
||||||
Sometimes, it is desirable that some of a module logic be created only after the user has finished manipulating that module. For example, the FSM module supports that states be defined dynamically, and the width of the state signal can be known only after all states have been added. One solution is to declare the final number of states in the FSM constructor, but this is not user-friendly. A better solution is to automatically create the state signal just before the FSM module is converted to V*HDL. Migen supports this using the so-called finalization mechanism.
|
|
||||||
|
|
||||||
Modules can overload a ``do_finalize`` method that can create logic and is called using the algorithm below:
|
|
||||||
|
|
||||||
#. Finalization of the current module begins.
|
|
||||||
#. If the module has already been finalized (e.g. manually), the procedure stops here.
|
|
||||||
#. Submodules of the current module are recursively finalized.
|
|
||||||
#. ``do_finalize`` is called for the current module.
|
|
||||||
#. Any new submodules created by the current module's ``do_finalize`` are recursively finalized.
|
|
||||||
|
|
||||||
Finalization is automatically invoked at V*HDL conversion and at simulation. It can be manually invoked for any module by calling its ``finalize`` method.
|
|
||||||
|
|
||||||
The clock domain management mechanism explained above happens during finalization.
|
|
||||||
|
|
||||||
Conversion for synthesis
|
|
||||||
************************
|
|
||||||
|
|
||||||
Any FHDL module can be converted into synthesizable Verilog HDL. This is accomplished by using the ``convert`` function in the ``verilog`` module.
|
|
||||||
|
|
||||||
The ``migen.build`` component provides scripts to interface third-party FPGA tools (from Xilinx, Altera and Lattice) to Migen, and a database of boards for the easy deployment of designs.
|
|
|
@ -1,11 +0,0 @@
|
||||||
Migen manual
|
|
||||||
############
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
introduction
|
|
||||||
fhdl
|
|
||||||
simulation
|
|
||||||
synthesis
|
|
||||||
reference
|
|
|
@ -1,73 +0,0 @@
|
||||||
Introduction
|
|
||||||
############
|
|
||||||
|
|
||||||
Migen is a Python-based tool that aims at automating further the VLSI design process.
|
|
||||||
|
|
||||||
Migen makes it possible to apply modern software concepts such as object-oriented programming and metaprogramming to design hardware. This results in more elegant and easily maintained designs and reduces the incidence of human errors.
|
|
||||||
|
|
||||||
.. _background:
|
|
||||||
|
|
||||||
Background
|
|
||||||
**********
|
|
||||||
|
|
||||||
Even though the Milkymist system-on-chip [mm]_ had many successes, it suffers from several limitations stemming from its implementation in manually written Verilog HDL:
|
|
||||||
|
|
||||||
.. [mm] http://m-labs.hk
|
|
||||||
|
|
||||||
#. The "event-driven" paradigm of today's dominant hardware descriptions languages (Verilog and VHDL, collectively referred to as "V*HDL" in the rest of this document) is often too general. Today's FPGA architectures are optimized for the implementation of fully synchronous circuits. This means that the bulk of the code for an efficient FPGA design falls into three categories:
|
|
||||||
|
|
||||||
#. Combinatorial statements
|
|
||||||
#. Synchronous statements
|
|
||||||
#. Initialization of registers at reset
|
|
||||||
|
|
||||||
V*HDL do not follow this organization. This means that a lot of repetitive manual coding is needed, which brings sources of human errors, petty issues, and confusion for beginners:
|
|
||||||
|
|
||||||
#. wire vs. reg in Verilog
|
|
||||||
#. forgetting to initialize a register at reset
|
|
||||||
#. deciding whether a combinatorial statement must go into a process/always block or not
|
|
||||||
#. simulation mismatches with combinatorial processes/always blocks
|
|
||||||
#. and more...
|
|
||||||
|
|
||||||
A little-known fact about FPGAs is that many of them have the ability to initialize their registers from the bitstream contents. This can be done in a portable and standard way using an "initial" block in Verilog, and by affecting a value at the signal declaration in VHDL. This renders an explicit reset signal unnecessary in practice in some cases, which opens the way for further design optimization. However, this form of initialization is entirely not synthesizable for ASIC targets, and it is not easy to switch between the two forms of reset using V*HDL.
|
|
||||||
|
|
||||||
#. V*HDL support for composite types is very limited. Signals having a record type in VHDL are unidirectional, which makes them clumsy to use e.g. in bus interfaces. There is no record type support in Verilog, which means that a lot of copy-and-paste has to be done when forwarding grouped signals.
|
|
||||||
|
|
||||||
#. V*HDL support for procedurally generated logic is extremely limited. The most advanced forms of procedural generation of synthesizable logic that V*HDL offers are CPP-style directives in Verilog, combinatorial functions, and ``generate`` statements. Nothing really fancy, and it shows. To give a few examples:
|
|
||||||
|
|
||||||
#. Building highly flexible bus interconnect is not possible. Even arbitrating any given number of bus masters for commonplace protocols such as Wishbone is difficult with the tools that V*HDL puts at our disposal.
|
|
||||||
#. Building a memory infrastructure (including bus interconnect, bridges and caches) that can automatically adapt itself at compile-time to any word size of the SDRAM is clumsy and tedious.
|
|
||||||
#. Building register banks for control, status and interrupt management of cores can also largely benefit from automation.
|
|
||||||
#. Many hardware acceleration problems can fit into the dataflow programming model. Manual dataflow implementation in V*HDL has, again, a lot of redundancy and potential for human errors. See the Milkymist texture mapping unit [mthesis]_ [mxcell]_ for an example of this. The amount of detail to deal with manually also makes the design space exploration difficult, and therefore hinders the design of efficient architectures.
|
|
||||||
#. Pre-computation of values, such as filter coefficients for DSP or even simply trigonometric tables, must often be done using external tools whose results are copy-and-pasted (in the best case, automatically) into the V*HDL source.
|
|
||||||
|
|
||||||
.. [mthesis] http://m-labs.hk/thesis/thesis.pdf
|
|
||||||
.. [mxcell] http://www.xilinx.com/publications/archives/xcell/Xcell77.pdf p30-35
|
|
||||||
|
|
||||||
Enter Migen, a Python toolbox for building complex digital hardware. We could have designed a brand new programming language, but that would have been reinventing the wheel instead of being able to benefit from Python's rich features and immense library. The price to pay is a slightly cluttered syntax at times when writing descriptions in FHDL, but we believe this is totally acceptable, particularly when compared to VHDL ;-)
|
|
||||||
|
|
||||||
Migen is made up of several related components:
|
|
||||||
|
|
||||||
#. the base language, FHDL
|
|
||||||
#. a library of small generic cores
|
|
||||||
#. a simulator
|
|
||||||
#. a build system
|
|
||||||
|
|
||||||
Installing Migen
|
|
||||||
****************
|
|
||||||
|
|
||||||
Either run the ``setup.py`` installation script or simply set ``PYTHONPATH`` to the root of the source directory.
|
|
||||||
|
|
||||||
If you wish to contribute patches, the suggest way to install is;
|
|
||||||
#. Clone from the git repository at http://github.com/m-labs/migen
|
|
||||||
#. Install using ``python3 ./setup.py develop --user``
|
|
||||||
#. Edit the code in your git checkout.
|
|
||||||
|
|
||||||
Alternative install methods
|
|
||||||
===========================
|
|
||||||
|
|
||||||
* Migen is available for the Anaconda Python distribution. The package can be found at at https://anaconda.org/m-labs/migen
|
|
||||||
* Migen can be referenced in a requirements.txt file (used for ``pip install -r requirements.txt``) via ``-e git+http://github.com/m-labs/migen.git#egg=migen``. See the pip documentation for more information.
|
|
||||||
|
|
||||||
Feedback
|
|
||||||
********
|
|
||||||
Feedback concerning Migen or this manual should be sent to the M-Labs developers' mailing list ``devel`` on lists.m-labs.hk.
|
|
Binary file not shown.
Before Width: | Height: | Size: 73 KiB |
|
@ -1,224 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="159.05869"
|
|
||||||
height="106.55"
|
|
||||||
id="svg3245"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.1 r9760"
|
|
||||||
sodipodi:docname="migen.svg"
|
|
||||||
inkscape:export-filename="/home/lekernel/migen.png"
|
|
||||||
inkscape:export-xdpi="184.10001"
|
|
||||||
inkscape:export-ydpi="184.10001">
|
|
||||||
<defs
|
|
||||||
id="defs3247">
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient6093">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2ca22c;stop-opacity:0;"
|
|
||||||
offset="0"
|
|
||||||
id="stop6095" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2ca22c;stop-opacity:1;"
|
|
||||||
offset="1"
|
|
||||||
id="stop6097" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient6047">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop6049" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#ffffff;stop-opacity:0;"
|
|
||||||
offset="1"
|
|
||||||
id="stop6051" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#a"
|
|
||||||
id="linearGradient6176"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.24477,0,0,0.24477,203.271,213.559)"
|
|
||||||
x1="150.95"
|
|
||||||
y1="-22.384001"
|
|
||||||
x2="252.2"
|
|
||||||
y2="204.03999" />
|
|
||||||
<linearGradient
|
|
||||||
id="a"
|
|
||||||
y2="150.32001"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
y1="13.899"
|
|
||||||
x2="200.5"
|
|
||||||
x1="200.5">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#fff"
|
|
||||||
offset=".1374"
|
|
||||||
id="stop7" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#509e10;stop-opacity:1;"
|
|
||||||
offset="1"
|
|
||||||
id="stop9" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#a"
|
|
||||||
id="linearGradient3345"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.24477,0,0,0.24477,203.271,213.559)"
|
|
||||||
x1="150.95"
|
|
||||||
y1="-22.384001"
|
|
||||||
x2="252.2"
|
|
||||||
y2="204.03999" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#a"
|
|
||||||
id="linearGradient3349"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.24477,0,0,0.24477,280.71427,440.33237)"
|
|
||||||
x1="150.95"
|
|
||||||
y1="-22.384001"
|
|
||||||
x2="252.2"
|
|
||||||
y2="204.03999" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient6047"
|
|
||||||
id="linearGradient6053"
|
|
||||||
x1="178.04323"
|
|
||||||
y1="474.42865"
|
|
||||||
x2="235.87062"
|
|
||||||
y2="474.42865"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.78422775,0,0,1,105.91918,-2.4999996)" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient6093"
|
|
||||||
id="linearGradient6099"
|
|
||||||
x1="242.87946"
|
|
||||||
y1="471.54514"
|
|
||||||
x2="289.73526"
|
|
||||||
y2="471.54514"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(1,0,0,1.1424088,0,-67.150429)" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="2.8"
|
|
||||||
inkscape:cx="134.13698"
|
|
||||||
inkscape:cy="59.325232"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1916"
|
|
||||||
inkscape:window-height="1117"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:guide-bbox="true"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata3250">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-242.87946,-440.32929)">
|
|
||||||
<rect
|
|
||||||
style="fill:url(#linearGradient6099);fill-opacity:1;stroke:none"
|
|
||||||
id="rect6043"
|
|
||||||
width="66.843575"
|
|
||||||
height="23.704336"
|
|
||||||
x="242.87946"
|
|
||||||
y="459.6947" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path29"
|
|
||||||
d="m 366.02427,471.24237 c -22.519,36.716 -73.921,29.454 -73.921,29.454 32.229,-32.229 0.16326,-57.929 0.16326,-57.929 0,0 51.973,-7.996 73.758,28.475"
|
|
||||||
style="font-size:18px;fill:#00ad00;fill-opacity:1;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path31"
|
|
||||||
d="m 366.02427,471.24237 c -22.519,36.716 -73.921,29.454 -73.921,29.454 32.229,-32.229 0.16326,-57.929 0.16326,-57.929 0,0 51.973,-7.996 73.758,28.475"
|
|
||||||
style="font-size:18px;fill:none;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<path
|
|
||||||
style="font-size:18px;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path33"
|
|
||||||
d="m 364.64427,470.43237 c -5.3108,8.6038 -12.825,15.435 -21.719,20.199 -7.7214,4.1357 -16.268,6.5868 -24.897,7.9228 -6.0011,0.92916 -12.11,1.2491 -18.178,1.0907 -1.8804,-0.0489 -3.76,-0.15102 -5.6339,-0.31747 -0.51696,-0.046 -1.0334,-0.0977 -1.5489,-0.15739 -0.29226,-0.0338 -0.85842,-0.11431 -0.14808,-0.0144 0.234,0.88632 0.468,1.7726 0.702,2.6592 8.3771,-8.431 15.128,-19.206 14.819,-31.472 -0.20072,-7.9507 -3.4638,-15.551 -8.2374,-21.816 -1.8852,-2.4739 -3.9815,-4.9329 -6.418,-6.8911 -0.234,0.88633 -0.46801,1.7729 -0.70201,2.6592 0.61487,-0.0942 -0.31747,0.0377 0.24551,-0.0343 0.60361,-0.0769 1.2087,-0.14221 1.814,-0.20194 2.1765,-0.21442 4.3616,-0.33925 6.5477,-0.40461 7.0088,-0.20928 14.057,0.24796 20.959,1.4953 7.9781,1.442 15.783,3.9756 22.86,7.9654 8.0388,4.532 14.777,11.012 19.535,18.924 1.0557,1.756 3.8079,0.15739 2.7476,-1.606 -5.1914,-8.6336 -12.6,-15.613 -21.408,-20.474 -7.7483,-4.275 -16.361,-6.8644 -25.074,-8.2486 -9.4825,-1.5066 -19.54,-1.944 -29.073,-0.48367 -1.1345,0.17379 -1.5874,1.9477 -0.70201,2.6592 3.0624,2.4612 5.6283,5.6205 7.7454,8.8104 4.5202,6.8118 6.9303,14.977 5.6423,23.154 -1.4588,9.2607 -7.0781,17.201 -13.551,23.715 -0.75977,0.76492 -0.53067,2.4859 0.70201,2.6592 9.9738,1.4023 20.482,0.7025 30.334,-1.1362 8.4689,-1.5805 16.759,-4.3922 24.256,-8.6664 8.6297,-4.9199 15.91,-11.93 21.128,-20.383 1.0812,-1.7514 -1.6723,-3.3482 -2.7473,-1.606 z" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path35"
|
|
||||||
d="m 295.19427,443.74237 c 0,0 12.67,11.257 12.67,27.475 0,0 9.8236,-9.7551 23.069,0 0,0 15.098,13.305 33.229,0 0,0 -15.539,-32.087 -68.968,-27.475 z"
|
|
||||||
style="font-size:18px;fill:url(#linearGradient3349);fill-opacity:1;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<line
|
|
||||||
id="line39"
|
|
||||||
y2="471.03238"
|
|
||||||
x2="400.71429"
|
|
||||||
y1="471.03238"
|
|
||||||
x1="366.79425"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44770002;font-family:'DejaVu Sans, Arial, Sans'" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path59"
|
|
||||||
d="m 344.15733,461.16448 4.84652,0"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44799995;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cc"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.44799995;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
d="m 344.15733,481.90109 4.84652,0"
|
|
||||||
id="path6037"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Orbitron;-inkscape-font-specification:Orbitron Light"
|
|
||||||
x="257.14285"
|
|
||||||
y="537.7193"
|
|
||||||
id="text6055"
|
|
||||||
sodipodi:linespacing="125%"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan6057"
|
|
||||||
x="257.14285"
|
|
||||||
y="537.7193">migen</tspan></text>
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cc"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.61650872;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
d="m 289.42519,459.68794 14.57866,0"
|
|
||||||
id="path6105"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path6107"
|
|
||||||
d="m 289.42519,483.37763 14.57866,0"
|
|
||||||
style="font-size:18px;fill:none;stroke:#000000;stroke-width:2.61650872;stroke-miterlimit:4;stroke-dasharray:none;font-family:'DejaVu Sans, Arial, Sans'"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 9 KiB |
|
@ -1,37 +0,0 @@
|
||||||
API reference
|
|
||||||
=============
|
|
||||||
|
|
||||||
:mod:`fhdl.structure` module
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.fhdl.structure
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`fhdl.bitcontainer` module
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.fhdl.bitcontainer
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`genlib.fifo` module
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.genlib.fifo
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`genlib.coding` module
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.genlib.coding
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
:mod:`genlib.sort` module
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. automodule:: migen.genlib.sort
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
|
@ -1,6 +0,0 @@
|
||||||
Simulating a Migen design
|
|
||||||
#########################
|
|
||||||
|
|
||||||
Migen allows you to easily simulate your FHDL design and interface it with arbitrary Python code. The simulator is written in pure Python and interprets the FHDL structure directly without using an external Verilog simulator.
|
|
||||||
|
|
||||||
[To be rewritten]
|
|
|
@ -1,4 +0,0 @@
|
||||||
Synthesizing a Migen design
|
|
||||||
###########################
|
|
||||||
|
|
||||||
[To be written]
|
|
|
@ -1,28 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self):
|
|
||||||
dx = 2
|
|
||||||
dy = 2
|
|
||||||
|
|
||||||
x = Signal(max=dx)
|
|
||||||
y = Signal(max=dy)
|
|
||||||
out = Signal()
|
|
||||||
|
|
||||||
my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy))
|
|
||||||
self.comb += out.eq(my_2d_array[x][y])
|
|
||||||
|
|
||||||
we = Signal()
|
|
||||||
inp = Signal()
|
|
||||||
self.sync += If(we,
|
|
||||||
my_2d_array[x][y].eq(inp)
|
|
||||||
)
|
|
||||||
|
|
||||||
ina = Array(Signal() for a in range(dx))
|
|
||||||
outa = Array(Signal() for a in range(dy))
|
|
||||||
self.specials += Instance("test", o_O=outa[y], i_I=ina[x])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print(verilog.convert(Example()))
|
|
|
@ -1,31 +0,0 @@
|
||||||
from migen import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
|
|
||||||
class Example(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.s = Signal()
|
|
||||||
self.counter = Signal(8)
|
|
||||||
x = Array(Signal(name="a") for i in range(7))
|
|
||||||
|
|
||||||
myfsm = FSM()
|
|
||||||
self.submodules += myfsm
|
|
||||||
|
|
||||||
myfsm.act("FOO",
|
|
||||||
self.s.eq(1),
|
|
||||||
NextState("BAR")
|
|
||||||
)
|
|
||||||
myfsm.act("BAR",
|
|
||||||
self.s.eq(0),
|
|
||||||
NextValue(self.counter, self.counter + 1),
|
|
||||||
NextValue(x[self.counter], 89),
|
|
||||||
NextState("FOO")
|
|
||||||
)
|
|
||||||
|
|
||||||
self.be = myfsm.before_entering("FOO")
|
|
||||||
self.ae = myfsm.after_entering("FOO")
|
|
||||||
self.bl = myfsm.before_leaving("FOO")
|
|
||||||
self.al = myfsm.after_leaving("FOO")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
example = Example()
|
|
||||||
print(verilog.convert(example, {example.s, example.counter, example.be, example.ae, example.bl, example.al}))
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue