├── .gitignore ├── .travis.yml ├── COPYING ├── COPYING.LESSER ├── README.md ├── docs ├── Makefile └── source │ ├── conf.py │ ├── cores.rst │ ├── cores │ ├── fifo.rst │ ├── gemac.rst │ ├── hdmi.rst │ ├── index.rst │ ├── sdram.rst │ ├── spi.rst │ └── usb.rst │ ├── examples.rst │ ├── index.rst │ ├── intro.rst │ ├── models.rst │ ├── models │ └── eeprom.rst │ ├── system.rst │ └── system │ └── register_file.rst ├── examples ├── README.md ├── boards │ ├── README.md │ ├── nexys │ │ └── fpgalink │ │ │ ├── compile_fpgalink.py │ │ │ ├── fpgalink.py │ │ │ └── fpgalink_nexys.v │ └── xula │ │ └── vga │ │ ├── convert_color_bars.py │ │ ├── convert_xula_vga.py │ │ └── xula_vga.py ├── cores │ ├── fifo36 │ │ └── ex_fifo36.py │ ├── fpgalink │ │ └── led │ │ │ ├── fpgalink_led.py │ │ │ ├── fpgalink_led.v │ │ │ ├── fpgalink_led_top.v │ │ │ ├── fpgalink_led_tri.py │ │ │ ├── ise_flled │ │ │ └── ise_flled.xise │ │ │ └── test_fpgalink_led.py │ └── serio │ │ └── convert_serio.py └── designs │ └── btn_led_mm │ ├── README.md │ ├── btn_led_mm.py │ └── test_btn_led.py ├── mn ├── __init__.py ├── cores │ ├── __init__.py │ ├── common │ │ └── __init__.py │ ├── eth │ │ ├── __init__.py │ │ └── gemac_lite │ │ │ └── _gemac_lite.py │ ├── fifo │ │ ├── __init__.py │ │ ├── _fifo_async.py │ │ ├── _fifo_fast.py │ │ ├── _fifo_intf.py │ │ ├── _fifo_mem.py │ │ ├── _fifo_srl.py │ │ ├── _fifo_sync.py │ │ ├── _fifo_syncers.py │ │ └── ramp │ │ │ ├── __init__.py │ │ │ ├── _fifo_ramp.py │ │ │ └── _regfile_def.py │ ├── misc │ │ ├── __init__.py │ │ ├── _assign.py │ │ ├── _btn_debounce.py │ │ ├── _btn_mm_ctl.py │ │ ├── _led_count.py │ │ ├── _led_dance.py │ │ ├── _led_mm_per.py │ │ ├── _led_stroby.py │ │ └── _serio.py │ ├── sdram │ │ ├── __init__.py │ │ ├── _intf.py │ │ ├── _memories.py │ │ ├── _sdram_sdr.py │ │ └── _sdram_self_test.py │ ├── spi │ │ ├── __init__.py │ │ ├── _regfile_def.py │ │ ├── _spi.py │ │ └── _spibus.py │ ├── usbext │ │ ├── __init__.py │ │ ├── fpgalink │ │ │ ├── __init__.py │ │ │ ├── _fl_convert.py │ │ │ ├── _fpgalink_fx2.py │ │ │ ├── comm_fpga_fx2_v1.v │ │ │ ├── comm_fpga_fx2_v1_stub.v │ │ │ ├── comm_fpga_fx2_v2.v │ │ │ ├── comm_fpga_fx2_v2.vhd │ │ │ ├── pck_myhdl_08.vhd │ │ │ ├── tb_comm_fpga_fx2_m.v │ │ │ ├── tb_comm_fpga_fx2_v1_stub.v │ │ │ └── tb_comm_fpga_fx2_v2.v │ │ └── usbp │ │ │ ├── __init__.py │ │ │ ├── _fx2_arb.py │ │ │ ├── _fx2_iobuf.py │ │ │ ├── _fx2_sfifo.py │ │ │ ├── _usbp_wb.py │ │ │ ├── _wb_master.py │ │ │ └── _wb_master_cmd.py │ └── video │ │ ├── __init__.py │ │ ├── _color_bars.py │ │ ├── _vidmem.py │ │ ├── hdmi │ │ ├── __init__.py │ │ ├── _hdmi.py │ │ └── _hdmi_intf.py │ │ └── vga │ │ ├── __init__.py │ │ ├── _timing_params.py │ │ ├── _vga_intf.py │ │ └── _vga_sync.py ├── models │ ├── __init__.py │ ├── spi │ │ ├── __init__.py │ │ └── _spi_eeprom.py │ ├── usbext │ │ ├── __init__.py │ │ └── fx2 │ │ │ ├── __init__.py │ │ │ ├── _fpgalink_host.py │ │ │ ├── _fx2_model.py │ │ │ └── _usbp_host.py │ └── video │ │ ├── __init__.py │ │ └── _video_display.py ├── system │ ├── __init__.py │ ├── _clock.py │ ├── _glbl.py │ ├── _reset.py │ ├── fifobus │ │ ├── __init__.py │ │ └── _fifobus.py │ ├── memmap │ │ ├── __init__.py │ │ ├── _avalonmm.py │ │ ├── _axi4.py │ │ ├── _barebone.py │ │ ├── _bbus.py │ │ ├── _memmap.py │ │ └── _wishbone.py │ └── regfile │ │ ├── __init__.py │ │ └── _regfile.py └── utils │ ├── __init__.py │ ├── _extract.py │ └── test │ ├── __init__.py │ └── _test_utils.py ├── scripts └── ci │ └── install_myhdl.sh ├── setup.py └── test ├── README.md ├── test_cores ├── test_eth │ ├── README.md │ └── test_gemac_lite.py ├── test_fifo │ ├── test_afifo.py │ ├── test_ffifo.py │ ├── test_fifo_ramp.py │ └── test_sfifo.py ├── test_hdmi │ ├── README.md │ └── test_hdmi.py ├── test_sdram │ ├── README.md │ └── test_sdram.py ├── test_serio.py ├── test_spi.py ├── test_vga │ ├── mm_vgasys.py │ ├── test_vgasys.py │ ├── test_vgasys_frame_1.png │ └── test_vgasys_frame_2.png └── vcd │ └── vcdfiles.txt ├── test_cosim ├── test_fpgalink │ ├── _fpgalink_logic_ex1.py │ ├── _test_utils.py │ └── test_fpgalink.py └── test_hdmi │ ├── _hdmi_prep_cosim.py │ └── tb_hdmi.v ├── test_models └── test_fx2_model.py └── test_system └── test_regfile.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | .backups 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "pypy" 5 | 6 | # get some stuff to install 7 | before_install: 8 | - sudo apt-get install iverilog 9 | 10 | # command to install dependencies 11 | install: 12 | - chmod +x ./scripts/ci/install_myhdl.sh 13 | - ./scripts/ci/install_myhdl.sh 14 | - pip install git+https://github.com/cfelton/gizflo 15 | - pip install coverage 16 | - pip install coveralls 17 | - pip install Pillow 18 | - pip install . 19 | 20 | # run the test, nosetests can be used 21 | script: 22 | - cd examples 23 | - py.test -s 24 | - cd ../test 25 | - py.test -s 26 | 27 | notifications: 28 | email: true 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project has been merged into [rhea](https://github.com/cfelton/rhea). 2 | This project will not be updated or developed further. 3 | 4 | The repository will be deleted in the near future. 5 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/minnesota.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/minnesota.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/minnesota" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/minnesota" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /docs/source/cores.rst: -------------------------------------------------------------------------------- 1 | 2 | Cores 3 | ===== 4 | The following is a list of currently implemented cores. 5 | 6 | FIFO 7 | ---- 8 | Various synchronous and asynchronous FIFO implementations. 9 | 10 | .. @todo mixed size FIFOs, need to infer 1-bit primitives 11 | .. and use these to be the mixed-size FIFO. 12 | 13 | 14 | fpgalink 15 | -------- 16 | 17 | This is a MyHDL implementation of the HDL for the *fpgalink* 18 | project. The fpgalink HDL core can be instantiated into 19 | a design: 20 | 21 | .. code-block::python 22 | 23 | from mn.cores.usbext import m_fpgalink_fx2 24 | 25 | # ... 26 | # fpgalink interface 27 | g_fli = m_fpgalink_fx2(clock,reset,fx2bus,flbus) 28 | 29 | # ... 30 | 31 | For simulation and verification the *fpgalink* interface can be 32 | stimulated using the FX2 model and high-level access functions: 33 | 34 | .. code-block::python 35 | 36 | from mn.models.usbext import fpgalink_host 37 | from mn.cores.usbext import fpgalink 38 | from mn.cores.usbext import m_fpgalink_fx2 39 | 40 | # instantiate the components, etc (see examples in example dir) 41 | # ... 42 | # use high-level accessors to 43 | fh.WriteAddress(1, [0xC3]) # write 0xCE to address 1 44 | fh.WriteAddress(0, [1,2,3,4]) # write 1,2,3,4 to address 0 45 | rb = fh.ReadAddress(1) # read address 1 46 | 47 | 48 | The following is a pictorial of the verification environment . 49 | 50 | 51 | For more information on the [fpgalink]() software, firmware, and 52 | general design information see [makestuff](). 53 | 54 | 55 | usbp 56 | ---- 57 | 58 | USB Peripheral, this is another Cypress FX2 controller interface, 59 | this has two interfaces a "control" interface and a "streaming" 60 | interface. This FX2 interface is intended to work with the 61 | [fx2 firmware]() that configures the controller as a USB CDC/ACM 62 | device (virtual serial port). The [fx2 firmware]() also has a 63 | couple vendor unique commands that can be sent using the pyusb 64 | (or other low-level USB interfaces like libusb). The Python 65 | version of the host software (including firmware) can be retrieved 66 | via pip :: 67 | 68 | >> pip install usbp 69 | >>> import usbp 70 | >>> import serial 71 | 72 | One of the tricky items with USB devices is setting the permissions 73 | correctly. On a linux system to set the … 74 | 75 | 76 | spi 77 | --- 78 | This is a generic SPI controller. 79 | 80 | .. @todo: need more verbage and examples 81 | 82 | 83 | vga 84 | --- 85 | VGA controller. 86 | 87 | .. @todo: need more verbage and examples 88 | -------------------------------------------------------------------------------- /docs/source/cores/fifo.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/cores/fifo.rst -------------------------------------------------------------------------------- /docs/source/cores/gemac.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/cores/gemac.rst -------------------------------------------------------------------------------- /docs/source/cores/hdmi.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/cores/hdmi.rst -------------------------------------------------------------------------------- /docs/source/cores/index.rst: -------------------------------------------------------------------------------- 1 | 2 | 3 | Cores 4 | ====== 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | 9 | fifo 10 | spi 11 | usb 12 | sdram (TBC) 13 | gemac (TBC) 14 | hdmi (TBC) 15 | -------------------------------------------------------------------------------- /docs/source/cores/sdram.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/cores/sdram.rst -------------------------------------------------------------------------------- /docs/source/cores/spi.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/cores/spi.rst -------------------------------------------------------------------------------- /docs/source/cores/usb.rst: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/source/examples.rst: -------------------------------------------------------------------------------- 1 | 2 | The following are the examples available in the examples 3 | directory. 4 | 5 | Xess Xula(2) 6 | ============ 7 | 8 | * binary hello (blinky) 9 | * VGA (TBC) 10 | 11 | 12 | Digilent Nexys 13 | ============== 14 | 15 | * binary hello (blinky) 16 | * fpgalink 17 | * usbp 18 | 19 | 20 | Digilent Atlys 21 | ============== 22 | 23 | * binary hello (blinky) 24 | * fpgalink (TBC) 25 | * usbp (TBC) 26 | 27 | 28 | Digilent Zybo 29 | ============= 30 | 31 | * binary hello (blinky) 32 | 33 | 34 | Open-Source UFO-400 35 | =================== 36 | 37 | * binary hello (blinky) 38 | * usbp 39 | 40 | 41 | DSPtronics Signa-X1 (sx1) 42 | ========================= 43 | 44 | * binary hello (blinky) 45 | * fpgalink 46 | * usbp 47 | * audio examples 48 | * audio echo (TBC) 49 | * audio streaming (TBC) 50 | 51 | 52 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. minnesota documentation master file, created by 2 | sphinx-quickstart on Sat Feb 28 07:32:25 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to minnesota's documentation! 7 | ===================================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | intro 15 | system 16 | cores 17 | models 18 | examples 19 | 20 | 21 | Indices and tables 22 | ================== 23 | 24 | * :ref:`genindex` 25 | * :ref:`modindex` 26 | * :ref:`search` 27 | 28 | -------------------------------------------------------------------------------- /docs/source/intro.rst: -------------------------------------------------------------------------------- 1 | 2 | ############## 3 | Introduction 4 | ############## 5 | 6 | The ``mn`` package is a collection of HDL cores written in 7 | `myhdl`_. The ``mn`` package is more than just a collection of 8 | cores it is also a framework for creating complex digital 9 | circuits. The ``mn`` package also includes a complete test 10 | suite. 11 | 12 | .. _myhdl : http://www.myhdl.org 13 | 14 | The ``mn`` package is divided into three main subpackages: 15 | 16 | * system 17 | * models 18 | * cores 19 | 20 | 21 | System 22 | ====== 23 | The system subpackage contains the [interfaces]() and other 24 | useful tools to assist in building complex digital designs. 25 | 26 | regfile 27 | ------- 28 | The register file objects provide simple methods to define 29 | registers and collections of registers. The registers files 30 | can be easily be connected to memory-mapped bus (e.g 31 | wishbone, avalon, etc.). 32 | 33 | Defining a Register File 34 | ^^^^^^^^^^^^^^^^^^^^^^^^ 35 | The following is a example defining a couple registers: 36 | 37 | .. code-block::python 38 | 39 | regfile = RegisterFile(width=8) 40 | reg0 = Register('status', 0x0020, 8, 'ro', 0) 41 | regfile.add_register(reg0) 42 | reg1 = Register('control', 0x0024, 8, 'rw', 0) 43 | regfile.add_register(reg1) 44 | 45 | .. regfile needs to be enhanced to automatically determine 46 | .. the best list-of-signal organization. The register definitions 47 | .. should be able to be defined logically and randomly and the 48 | .. RegisterFile will organize the list-of-signals as needed ... 49 | .. Future enhancement that can occur under the hood 50 | 51 | 52 | Models 53 | ====== 54 | This subpackage contains various models used for development 55 | and verification. 56 | 57 | .. To facilitate development and verification models are created of external 58 | .. devices or "golden" models of an internal peripheral or processing block. 59 | 60 | 61 | Cores 62 | ===== 63 | This subpackage contains the core implementations. 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/source/models.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/models.rst -------------------------------------------------------------------------------- /docs/source/models/eeprom.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/models/eeprom.rst -------------------------------------------------------------------------------- /docs/source/system.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/system.rst -------------------------------------------------------------------------------- /docs/source/system/register_file.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/docs/source/system/register_file.rst -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Examples 3 | This directory contains examples for certain FPGA development 4 | boards and conversion examples. The FPGA examples build a system 5 | with the `mn` cores and execute the FPGA toolflow. 6 | 7 | Most of the conversion examples are *core builders*, 8 | the conversion scipts will accept a handful of command-line arguments 9 | that determine configuration of the converted core. These can 10 | be used to create Verilog of VHDL version of the cores. 11 | 12 | 15 | 16 | 19 | -------------------------------------------------------------------------------- /examples/boards/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/examples/boards/README.md -------------------------------------------------------------------------------- /examples/boards/nexys/fpgalink/compile_fpgalink.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/examples/boards/nexys/fpgalink/compile_fpgalink.py -------------------------------------------------------------------------------- /examples/boards/nexys/fpgalink/fpgalink.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from mn.cores.usbext import fpgalink 4 | from mn.cores.usbext import m_fpgalink_fx2 5 | 6 | 7 | def fpgalink_nexys( 8 | # ~~ FX2 interface signals ~~ 9 | IFCLK, # 48 MHz clock from FX2 10 | RST, # active low async reset 11 | SLWR, # active low write strobe 12 | SLRD, # active low read strobe 13 | SLOE, # active low output enable 14 | FDI, # input data bus 15 | FDO, # output data bus 16 | FDS, # data select 17 | ADDR, # 2bit address (fifo select) 18 | FLAGA, # not used 19 | FLAGB, # gotroom 20 | FLAGC, # gotdata 21 | FLAGD, # not used 22 | PKTEND, # submit partial (less than 512) 23 | # ~~ peripherals interfaces ~~ 24 | LEDS # external LEDs 25 | ): 26 | """ 27 | """ 28 | 29 | # get the local references for the top-level 30 | clock,reset,fx2_bus,fl_bus = fpgalink.get_interfaces() 31 | clock = IFCLK 32 | reset = RST 33 | fx2_bus.data_i = FDI 34 | fx2_bus.data_o = FDO 35 | fx2_bus.data_t = FDS 36 | fx2_bus.gotdata = FLAGC 37 | fx2_bus.gotroom = FLAGB 38 | fx2_bus.write = SLWR 39 | fx2_bus.read = SLRD 40 | #SLOE = SLRD now shadowed signals for conversion 41 | fx2_bus.pktend = PKTEND 42 | 43 | # instantiate the fpgalink interface 44 | g_fli = m_fpgalink_fx2(clock, reset, fx2_bus, fl_bus) 45 | 46 | # ~~~~~~ 47 | lreg = Signal(intbv(0)[7:]) 48 | treg = Signal(intbv(0)[1:]) 49 | tcnt = Signal(modbv(0, min=0, max=2**24)) 50 | 51 | # aliases 52 | f2hValid_in = fl_bus.valid_i 53 | h2fReady_in = fl_bus.ready_i 54 | h2fValid_out = fl_bus.valid_o 55 | chanAddr_out = fl_bus.chan_addr 56 | f2hData_in = fl_bus.data_i 57 | h2fData_out = fl_bus.data_o 58 | 59 | fifosel = fx2_bus.fifosel 60 | @always_comb 61 | def hdl_assigns(): 62 | ADDR.next[0] = False 63 | ADDR.next[1] = fifosel 64 | SLOE.next = SLRD 65 | f2hValid_in.next = True 66 | h2fReady_in.next = True 67 | 68 | LEDS.next[7:] = lreg 69 | LEDS.next[7] = treg 70 | 71 | if chanAddr_out == 0: 72 | f2hData_in.next = 0xCE 73 | elif chanAddr_out == 1: 74 | f2hData_in.next = lreg 75 | else: 76 | f2hData_in.next = 0x55 77 | 78 | 79 | @always_seq(clock.posedge, reset=reset) 80 | def hdl_fl(): 81 | if h2fValid_out and chanAddr_out == 1: 82 | lreg.next = h2fData_out 83 | 84 | tcnt.next = tcnt + 1 85 | if tcnt[23]: 86 | treg.next = not treg 87 | 88 | return g_fli, hdl_fl, hdl_assigns 89 | 90 | 91 | def convert(): 92 | FDO = Signal(intbv(0)[8:]) 93 | FDI = Signal(intbv(0)[8:]) 94 | FDS = Signal(bool(0)) 95 | SLWR,SLRD,SLOE = [Signal(bool(0)) for ii in range(3)] 96 | FLAGA,FLAGB,FLAGC,FLAGD = [Signal(bool(0)) for ii in range(4)] 97 | ADDR = Signal(intbv(0)[2:]) 98 | IFCLK = Signal(bool(0)) 99 | RST = ResetSignal(bool(1), active=0, async=True) 100 | LEDS = Signal(intbv(0)[8:]) 101 | PKTEND = Signal(bool(0)) 102 | 103 | toVerilog(fpgalink_nexys, IFCLK, RST, SLWR, SLRD, SLOE, 104 | FDI, FDO, FDS, ADDR, FLAGA, FLAGB, FLAGC, FLAGD, PKTEND, 105 | LEDS) 106 | 107 | if __name__ == '__main__': 108 | convert() 109 | 110 | -------------------------------------------------------------------------------- /examples/boards/xula/vga/convert_color_bars.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import argparse 4 | 5 | from myhdl import * 6 | from vga_intf import * 7 | from vga_color_bars import m_color_bars 8 | 9 | def convert(args): 10 | dsys = System(frequency=50e6) 11 | vmem = VideoMemory() 12 | 13 | toVerilog(m_color_bars, dsys, vmem, 14 | resolution=args.res, width=args.width) 15 | 16 | #toVHDL(m_color_bars, dsys, vmem, 17 | # resolution=args.res, width=args.width) 18 | 19 | def get_cli_args(): 20 | parser = argparse.ArgumentParser(description="Convert colobar generator") 21 | parser.add_argument('--resolution', default="640,480", type=str, 22 | help="define the resolution, x, e.g. 1280x720") 23 | parser.add_argument('--width', default=8, type=int, 24 | help="define the pixel width in bits") 25 | 26 | args = parser.parse_args() 27 | 28 | res = args.resolution.replace(' ', '') 29 | res = res.lower() 30 | args.res = tuple(map(int, res.split('x'))) 31 | 32 | return args 33 | 34 | if __name__ == '__main__': 35 | args = get_cli_args() 36 | convert(args) 37 | -------------------------------------------------------------------------------- /examples/boards/xula/vga/convert_xula_vga.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import argparse 4 | 5 | from myhdl import * 6 | from mn.system import Global 7 | from mn.cores.video import VideoMemory 8 | from mn.cores.video impirt m_color_bars 9 | 10 | def convert(args): 11 | glbl = Global(frequency=50e6) 12 | vmem = VideoMemory() 13 | 14 | toVerilog(m_color_bars, glbl, vmem, 15 | resolution=args.res, width=args.width) 16 | 17 | toVHDL(m_color_bars, glbl, vmem, 18 | resolution=args.res, width=args.width) 19 | 20 | def get_cli_args(): 21 | parser = argparse.ArgumentParser(description="Convert colobar generator") 22 | parser.add_argument('--resolution', default="640,480", type=str, 23 | help="define the resolution, x, e.g. 1280x720") 24 | parser.add_argument('--width', default=8, type=int, 25 | help="define the pixel width in bits") 26 | 27 | args = parser.parse_args() 28 | 29 | res = args.resolution.replace(' ', '') 30 | res = res.lower() 31 | args.res = tuple(map(int, res.split('x'))) 32 | 33 | return args 34 | 35 | if __name__ == '__main__': 36 | args = get_cli_args() 37 | convert(args) 38 | -------------------------------------------------------------------------------- /examples/boards/xula/vga/xula_vga.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | import mn 5 | from mn.system import Clock 6 | from mn.system import Reset 7 | from mn.system import Global 8 | 9 | from mn.cores.video import VGA 10 | from mn.cores.video import VideoMemory 11 | from mn.cores.video import m_vga_sync 12 | from mn.cores.video import m_color_bars 13 | 14 | def mm_vgasys( 15 | 16 | # ~~~[PORTS]~~~ 17 | clock, reset, vselect, 18 | hsync, vsync, 19 | red, green, blue, 20 | pxlen, active, 21 | 22 | # ~~~~[PARAMETERS]~~~~ 23 | resolution=(640,480,), 24 | color_depth=(10,10,10,), 25 | refresh_rate=60, 26 | line_rate=31250 27 | ): 28 | 29 | # create the system-level signals, overwrite clock, reset 30 | glbl = Global(clock=clock, reset=reset) 31 | # VGA inteface 32 | vga = VGA(hsync=hsync, vsync=vsync, 33 | red=red, green=green, blue=blue, 34 | pxlen=pxlen, active=active) 35 | # video memory interface 36 | vmem = VideoMemory() 37 | 38 | # instances of modules 39 | gbar = m_color_bars(glbl, vmem, 40 | resolution=resolution) 41 | 42 | gvga = m_vga_sync(glbl, vga, vmem, 43 | resolution=resolution) 44 | 45 | 46 | return gvga, gbar 47 | 48 | 49 | def convert(color_depth=(10,10,10,)): 50 | """ convert the vgasys to verilog 51 | """ 52 | clock = Clock(0, frequency=50e6) 53 | reset = Reset(0, active=0, async=False) 54 | vselect = Signal(bool(0)) 55 | 56 | hsync = Signal(bool(0)) 57 | vsync = Signal(bool(0)) 58 | cd = color_depth 59 | red = Signal(intbv(0)[cd[0]:]) 60 | green = Signal(intbv(0)[cd[1]:]) 61 | blue = Signal(intbv(0)[cd[2]:]) 62 | pxlen = Signal(bool(0)) 63 | active = Signal(bool(0)) 64 | 65 | toVerilog.timescale = '1ns/1ns' 66 | toVerilog(mm_vgasys, clock, reset, vselect, 67 | hsync, vsync, red, green, blue, 68 | pxlen, active) 69 | 70 | toVHDL(mm_vgasys, clock, reset, vselect, 71 | hsync, vsync, red, green, blue, 72 | pxlen, active) 73 | 74 | 75 | if __name__ == '__main__': 76 | convert() 77 | -------------------------------------------------------------------------------- /examples/cores/fifo36/ex_fifo36.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | This example takes a different 4 | """ 5 | 6 | from argparse import Namespace 7 | 8 | from myhdl import * 9 | import myhdl_tools as tlz 10 | 11 | from mn.system import FIFOBus 12 | from mn.cores.fifo import m_fifo_async 13 | from mn.cores.fifo import m_fifo_fast 14 | 15 | def m_fifo_2clock_cascade( 16 | wclk, # in: write side clock 17 | datain, # in: write data 18 | src_rdy_i, # in: 19 | dst_rdy_o, # out: 20 | space, # out: how many can be written 21 | 22 | rclk, # in: read side clock 23 | dataout, # out: read data 24 | src_rdy_o, # out: 25 | dst_rdy_i, # in: 26 | occupied, # out: number in the fifo 27 | 28 | reset, # in: system reset 29 | ): 30 | 31 | 32 | wr = Signal(bool(0)) 33 | rd = Signal(bool(0)) 34 | dataout_d = Signal(intbv(0, min=dataout.min, max=dataout.max)) 35 | 36 | args = Namespace(width=36, size=128, name='fifo_2clock_cascade') 37 | fbus = FIFOBus(args=args) 38 | # need to update the fbus refernces to reference the Signals in 39 | # the moudule port list (function arguments). 40 | fbus.wr = wr 41 | fbus.wdata = datain 42 | fbus.rd = rd 43 | fbus.rdata = dataout_d 44 | 45 | @always_comb 46 | def rtl_assign1(): 47 | wr.next = src_rdy_i & dst_rdy_o 48 | rd.next = dst_rdy_i & src_rdy_o 49 | 50 | @always_comb 51 | def rtl_assign2(): 52 | dst_rdy_o.next = not fbus.full 53 | src_rdy_o.next = not fbus.empty 54 | 55 | # the original was a chain: 56 | # m_fifo_fast (16) 57 | # m_fifo_async (??) 58 | # m_fifo_fast (16) 59 | # not sure why the chain was needed 60 | gfifo = m_fifo_async(reset, wclk, rclk, fbus) 61 | # @todo: calculate space and occupied based on fbus.count 62 | 63 | # @todo: the output is delayed two clock from the "read" strobe 64 | # the m_fifo_async only has a delta of one (read valid strobe 65 | # aligns with valid data). Need to delay the data one more 66 | # clock cycle??? 67 | 68 | @always(rclk.posedge) 69 | def rtl_delay(): 70 | dataout.next = dataout_d 71 | 72 | return rtl_assign1, rtl_assign2, gfifo, rtl_delay 73 | 74 | 75 | def m_fifo_short(clock, reset, clear, 76 | datain, src_rdy_i, dst_rdy_o, 77 | dataout, src_rdy_o, dst_rdy_i): 78 | 79 | wr = Signal(bool(0)) 80 | rd = Signal(bool(0)) 81 | 82 | args = Namespace(width=36, size=16, name='fifo_2clock_cascade') 83 | fbus = FIFOBus(args=args) 84 | # need to update the fbus refernces to reference the Signals in 85 | # the moudule port list (function arguments). 86 | fbus.wr = wr 87 | fbus.wdata = datain 88 | fbus.rd = rd 89 | fbus.rdata = dataout 90 | 91 | @always_comb 92 | def rtl_assign1(): 93 | wr.next = src_rdy_i & dst_rdy_o 94 | rd.next = dst_rdy_i & src_rdy_o 95 | 96 | @always_comb 97 | def rtl_assign2(): 98 | dst_rdy_o.next = not fbus.full 99 | src_rdy_o.next = not fbus.empty 100 | 101 | gfifo = m_fifo_fast(clock, reset, fbus) 102 | 103 | return rtl_assign1, rtl_assign2, gfifo 104 | 105 | 106 | def convert(args=None): 107 | wclk = Signal(bool(0)) 108 | datain = Signal(intbv(0)[36:]) 109 | src_rdy_i = Signal(bool(0)) 110 | dst_rdy_o = Signal(bool(0)) 111 | space = Signal(intbv(0)[16:]) 112 | 113 | rclk = Signal(bool(0)) 114 | dataout = Signal(intbv(0)[36:]) 115 | src_rdy_o = Signal(bool(0)) 116 | dst_rdy_i = Signal(bool(0)) 117 | occupied = Signal(intbv(0)[16:]) 118 | 119 | reset = ResetSignal(0, active=1, async=True) 120 | 121 | toVerilog(m_fifo_2clock_cascade, 122 | wclk, datain, src_rdy_i, dst_rdy_o, space, 123 | rclk, dataout, src_rdy_o, dst_rdy_i, occupied, 124 | reset) 125 | 126 | clock = Signal(bool(0)) 127 | clear = Signal(bool(0)) 128 | toVerilog(m_fifo_short, 129 | clock, reset, clear, 130 | datain, src_rdy_i, dst_rdy_o, 131 | dataout, src_rdy_o, dst_rdy_i) 132 | 133 | if __name__ == '__main__': 134 | convert() -------------------------------------------------------------------------------- /examples/cores/fpgalink/led/fpgalink_led.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from mn.cores.usb_ext import fl_fx2 4 | from mn.cores.usb_ext import fpgalink_fx2 5 | 6 | 7 | def fpgalink_led( 8 | # ~~ FX2 interface signals ~~ 9 | IFCLK, # 48 MHz clock from FX2 10 | RST, # active low async reset 11 | SLWR, # active low write strobe 12 | SLRD, # active low read strobe 13 | SLOE, # active low output enable 14 | FDI, # input data bus 15 | FDO, # output data bus 16 | FDS, # data select 17 | ADDR, # 2bit address (fifo select) 18 | FLAGA, # not used 19 | FLAGB, # gotroom 20 | FLAGC, # gotdata 21 | FLAGD, # not used 22 | PKTEND, # submit partial (less than 512) 23 | # ~~ peripherals interfaces ~~ 24 | LEDS # external LEDs 25 | ): 26 | """ 27 | """ 28 | 29 | # get the local references for the top-level 30 | clock,reset,fx2_bus,fl_bus = fl_fx2.get_interfaces() 31 | clock = IFCLK 32 | reset = RST 33 | fx2_bus.data_i = FDI 34 | fx2_bus.data_o = FDO 35 | fx2_bus.data_t = FDS 36 | fx2_bus.gotdata = FLAGC 37 | fx2_bus.gotroom = FLAGB 38 | fx2_bus.write = SLWR 39 | fx2_bus.read = SLRD 40 | #SLOE = SLRD now shadowed signals for conversion 41 | fx2_bus.pktend = PKTEND 42 | 43 | # instantiate the fpgalink interface 44 | g_fli = fpgalink_fx2(clock, reset, fx2_bus, fl_bus) 45 | 46 | # ~~~~~~ 47 | lreg = Signal(intbv(0)[8:]) 48 | f2hValid_in = fl_bus.valid_i 49 | h2fReady_in = fl_bus.ready_i 50 | h2fValid_out = fl_bus.valid_o 51 | chanAddr_out = fl_bus.chan_addr 52 | f2hData_in = fl_bus.data_i 53 | h2fData_out = fl_bus.data_o 54 | 55 | fifosel = fx2_bus.fifosel 56 | @always_comb 57 | def hdl_assigns(): 58 | ADDR.next[0] = False 59 | ADDR.next[1] = fifosel 60 | SLOE.next = SLRD 61 | f2hValid_in.next = True 62 | h2fReady_in.next = True 63 | 64 | LEDS.next = lreg 65 | 66 | if chanAddr_out == 0: 67 | f2hData_in.next = 0xCE 68 | elif chanAddr_out == 1: 69 | f2hData_in.next = lreg 70 | else: 71 | f2hData_in.next = 0x55 72 | 73 | 74 | @always_seq(clock.posedge, reset=reset) 75 | def hdl_fl(): 76 | if h2fValid_out and chanAddr_out == 1: 77 | lreg.next = h2fData_out 78 | 79 | 80 | return g_fli, hdl_fl, hdl_assigns 81 | 82 | 83 | def convert(): 84 | FDO = Signal(intbv(0)[8:]) 85 | FDI = Signal(intbv(0)[8:]) 86 | FDS = Signal(bool(0)) 87 | SLWR,SLRD,SLOE = [Signal(bool(0)) for ii in range(3)] 88 | FLAGA,FLAGB,FLAGC,FLAGD = [Signal(bool(0)) for ii in range(4)] 89 | ADDR = Signal(intbv(0)[2:]) 90 | IFCLK = Signal(bool(0)) 91 | RST = ResetSignal(bool(1), active=0, async=True) 92 | LEDS = Signal(intbv(0)[8:]) 93 | PKTEND = Signal(bool(0)) 94 | 95 | toVerilog(fpgalink_led, IFCLK, RST, SLWR, SLRD, SLOE, 96 | FDI, FDO, FDS, ADDR, FLAGA, FLAGB, FLAGC, FLAGD, PKTEND, 97 | LEDS) 98 | 99 | if __name__ == '__main__': 100 | convert() 101 | 102 | -------------------------------------------------------------------------------- /examples/cores/fpgalink/led/fpgalink_led_top.v: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * small wrapper for the MyHDL module 5 | */ 6 | 7 | module fpgalink_led_top 8 | ( 9 | input wire IFCLK, 10 | input wire RST, 11 | output wire SLWR, 12 | output wire SLRD, 13 | output wire SLOE, 14 | inout wire [7:0] FDIO, 15 | output wire [1:0] ADDR, 16 | input wire FLAGA, 17 | input wire FLAGB, 18 | input wire FLAGC, 19 | input wire FLAGD, 20 | output wire PKTEND, 21 | output wire [7:0] LEDS 22 | ); 23 | 24 | wire [7:0] fdi, fdo; 25 | wire fds; 26 | assign fdi = FDIO; 27 | assign FDIO = (fds) ? fdo : 8'bz; 28 | 29 | fpgalink_led 30 | U1 31 | ( 32 | .IFCLK(IFCLK), 33 | .RST(RST), 34 | .SLWR(SLWR), 35 | .SLRD(SLRD), 36 | .SLOE(SLOE), 37 | .FDI(fdi), 38 | .FDO(fdo), 39 | .FDS(fds), 40 | .ADDR(ADDR), 41 | .FLAGA(FLAGA), 42 | .FLAGB(FLAGB), 43 | .FLAGC(FLAGC), 44 | .FLAGD(FLAGD), 45 | .PKTEND(PKTEND), 46 | .LEDS(LEDS) ); 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /examples/cores/fpgalink/led/fpgalink_led_tri.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from mn.cores.usb_ext import fl_fx2 4 | from mn.cores.usb_ext import fpgalink_fx2 5 | 6 | def tristate(dio, din, dout, dsel): 7 | dout = dio.driver() 8 | @always(dsel) 9 | def hdl(): 10 | pass 11 | dio.driven = "wire" 12 | din.driven = "wire" 13 | return hdl 14 | tristate.verilog_code = """ 15 | //module tristate( 16 | // inout [7:0] dio, 17 | // input [7:0] din, 18 | // output [7:0] dout, 19 | // input [7:0] dsel): 20 | assign din = dio; 21 | assign dio = dsel ? dout : 8'bz; 22 | //endmodule 23 | """ 24 | 25 | def fpgalink_led( 26 | 27 | # ~~ FX2 interface signals ~~ 28 | IFCLK, # 48 MHz clock from FX2 29 | RST, # active low async reset 30 | SLWR, # active low write strobe 31 | SLRD, # active low read strobe 32 | SLOE, # active low output enable 33 | FDIO, # bi-directional data bus 34 | ADDR, # 2bit address (fifo select) 35 | FLAGA, # not used 36 | FLAGB, # gotroom 37 | FLAGC, # gotdata 38 | FLAGD, # not used 39 | PKTEND, # submit partial (less than 512) 40 | 41 | # ~~ peripherals interfaces ~~ 42 | leds # external LEDs 43 | ): 44 | """ 45 | """ 46 | 47 | 48 | clock,reset,fx2_bus,fl_bus = fl_fx2.get_interfaces() 49 | clock = IFCLK 50 | reset = RST 51 | din = fx2_bus.data_i 52 | dout = fx2_bus.data_o 53 | dsel = fx2_bus.data_t 54 | fx2_bus.gotdata = FLAGC 55 | fx2_bus.gotroom = FLAGB 56 | fx2_bus.write = SLWR 57 | fx2_bus.read = SLRD 58 | #SLOE = SLRD now shadowed signals for conversion 59 | fx2_bus.pktend = PKTEND 60 | 61 | # instantiate the fpgalink interface 62 | g_fli = fpgalink_fx2(clock, reset, fx2_bus, fl_bus) 63 | g_tri = tristate(FDIO, din, dout, dsel) 64 | 65 | # ~~~~~~ 66 | lreg = Signal(intbv(0)[8:]) 67 | f2hValid_in = fl_bus.valid_i 68 | h2fReady_in = fl_bus.ready_i 69 | h2fValid_out = fl_bus.valid_o 70 | chanAddr_out = fl_bus.chan_addr 71 | f2hData_in = fl_bus.data_i 72 | h2fData_out = fl_bus.data_o 73 | 74 | fifosel = fx2_bus.fifosel 75 | @always_comb 76 | def hdl_assigns(): 77 | ADDR.next[0] = fifosel 78 | ADDR.next[1] = True 79 | SLOE.next = SLRD 80 | f2hValid_in.next = True 81 | h2fReady_in.next = True 82 | 83 | leds.next = lreg 84 | 85 | if chanAddr_out == 0: 86 | f2hData_in.next = 0xCE 87 | elif chanAddr_out == 1: 88 | f2hData_in.next = lreg 89 | else: 90 | f2hData_in.next = 0x55 91 | 92 | 93 | @always_seq(clock.posedge, reset=reset) 94 | def hdl_fl(): 95 | if h2fValid_out and chanAddr_out == 1: 96 | lreg.next = h2fData_out 97 | 98 | 99 | 100 | return g_fli, g_tri, hdl_fl, hdl_assigns 101 | 102 | 103 | def convert(): 104 | FDIO = TristateSignal(intbv(0)[8:]) 105 | SLWR,SLRD,SLOE = [Signal(bool(0)) for ii in range(3)] 106 | FLAGA,FLAGB,FLAGC,FLAGD = [Signal(bool(0)) for ii in range(4)] 107 | ADDR = Signal(intbv(0)[2:]) 108 | IFCLK = Signal(bool(0)) 109 | RST = ResetSignal(bool(1), active=0, async=True) 110 | leds = Signal(intbv(0)[8:]) 111 | PKTEND = Signal(bool(0)) 112 | 113 | toVerilog(fpgalink_led, IFCLK, RST, SLWR, SLRD, SLOE, 114 | FDIO, ADDR, FLAGA, FLAGB, FLAGC, FLAGD, PKTEND, 115 | leds) 116 | 117 | if __name__ == '__main__': 118 | convert() 119 | 120 | -------------------------------------------------------------------------------- /examples/cores/fpgalink/led/test_fpgalink_led.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/examples/cores/fpgalink/led/test_fpgalink_led.py -------------------------------------------------------------------------------- /examples/cores/serio/convert_serio.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | from mn.cores.misc import m_serio 5 | 6 | def m_serio_ex(clock, reset, sdi, sdo, Np=8): 7 | 8 | pin = [Signal(intbv(0)[8:]) for _ in range(Np)] 9 | pout = [Signal(intbv(0)[8:]) for _ in range(Np)] 10 | 11 | gserio = m_serio(clock, reset, sdi, sdo, pin, pout) 12 | 13 | @always_seq(clock.posedge, reset=reset) 14 | def rtl(): 15 | for ii in range(Np): 16 | pout[ii].next = pin[ii] 17 | 18 | return gserio, rtl 19 | 20 | clock = Signal(bool(0)) 21 | reset = ResetSignal(0, 0, False) 22 | sdi = Signal(bool(0)) 23 | sdo = Signal(bool(0)) 24 | 25 | 26 | toVerilog(m_serio_ex, clock, reset, sdi, sdo) 27 | toVHDL(m_serio_ex, clock, reset, sdi, sdo) 28 | 29 | -------------------------------------------------------------------------------- /examples/designs/btn_led_mm/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/examples/designs/btn_led_mm/README.md -------------------------------------------------------------------------------- /examples/designs/btn_led_mm/btn_led_mm.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import print_function 3 | 4 | import argparse 5 | 6 | from myhdl import * 7 | 8 | import gizflo as flo 9 | 10 | from mn.cores.misc import m_btn_mm_ctl # memmap controller 11 | from mn.cores.misc import m_led_mm_per # memmap peripheral 12 | 13 | from mn.system import Barebone 14 | from mn.system import Wishbone 15 | from mn.system import AvalonMM 16 | #from mn.system import AXI4 17 | from mn.system import Global 18 | 19 | 20 | def m_btn_led_mm(clock, reset, leds, btns, bus_type='W'): 21 | """ A toy example to demostrate bus agnosticism 22 | This example instantiates a memory-map controller and a 23 | memory-map peripheral. This example shows how the 24 | controllers and peripherals can be passed the memmap 25 | interface. The passing of the interface allows the 26 | modules (components) to be bus agnostic. 27 | 28 | This example solves a simple task in a complicated manner 29 | to show the point. When a button press is detected a 30 | bus cycle is generated to write the "flash" pattern to 31 | the LED peripheral. 32 | 33 | Note: for easy FPGA bit-stream generation the port names 34 | match the board names defined in the *gizflo* board definitions. 35 | """ 36 | glbl = Global(clock=clock, reset=reset) 37 | 38 | if bus_type == 'B': 39 | regbus = Barebone(glbl, data_width=8, address_width=16) 40 | elif bus_type == 'W': 41 | regbus = Wishbone(glbl, data_width=8, address_width=16) 42 | elif bus_type == 'A': 43 | regbus = AvalonMM(glbl, data_width=8, address_width=16) 44 | #elif bus_type == 'X': 45 | # regbus = AXI4(glbl, data_wdith=8, address_width=16) 46 | 47 | gbtn = m_btn_mm_ctl(glbl, regbus, btns) # memmap controller 48 | gled = m_led_mm_per(glbl, regbus, leds) # memmap peripheral 49 | gmap = regbus.m_per_outputs() # bus combiner 50 | 51 | print(vars(regbus.regfiles['LED_000'])) 52 | 53 | return gbtn, gled, gmap 54 | 55 | 56 | def build(args): 57 | """ Run the FPGA tools 58 | """ 59 | pass 60 | 61 | 62 | def getargs(): 63 | """ get CLI arguments 64 | """ 65 | pass 66 | 67 | 68 | if __name__ == '__main__': 69 | args = getargs() 70 | build(args) 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/designs/btn_led_mm/test_btn_led.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import print_function 3 | 4 | from myhdl import * 5 | 6 | from btn_led_mm import m_btn_led_mm 7 | 8 | from mn.system import Clock 9 | from mn.system import Reset 10 | from mn.utils.test import tb_clean_vcd 11 | 12 | def test_btn_led(): 13 | 14 | clock = Clock(0, frequency=500e3) 15 | reset = Reset(0, active=0, async=False) 16 | leds = Signal(intbv(0)[8:]) 17 | btns = Signal(intbv(0)[4:]) 18 | 19 | def _test(): 20 | 21 | # bus_type = ('A', 'B', 'W', 'X') # avalon, barebone, wishbon, AXI 22 | tbdut = m_btn_led_mm(clock, reset, leds, btns, bus_type='A') 23 | 24 | def dumpg(glist): 25 | for gg in glist: 26 | if isinstance(gg, (list,tuple)): 27 | dumpg(gg) 28 | elif gg is not None: 29 | print("{:16}: {}".format(gg.func.func_name, 30 | gg.func.func_code.co_filename)) 31 | dumpg(tbdut) 32 | 33 | tbclk = clock.gen() 34 | 35 | @instance 36 | def tbstim(): 37 | reset.next = reset.active 38 | yield delay(10) 39 | reset.next = not reset.active 40 | yield clock.posedge 41 | 42 | #assert leds == 0 43 | 44 | for ii in range(3): 45 | # simulate a button press 46 | btns.next = 1 << ii 47 | yield delay(12) 48 | btns.next = 0 49 | 50 | for cc in range(8): 51 | yield clock.posedge 52 | 53 | # @todo: a more interesting check 54 | #assert leds != 0 55 | yield delay(100) 56 | 57 | raise StopSimulation 58 | 59 | return tbdut, tbclk, tbstim 60 | 61 | tb_clean_vcd(_test.func_name) 62 | Simulation(traceSignals(_test)).run() 63 | #Simulation(_test()).run() 64 | # currently an error when converting to both at once, 65 | # only convert to one at a time. 66 | toVerilog(m_btn_led_mm, clock, reset, leds, btns) 67 | #toVHDL(m_btn_led_mm, clock, reset, leds, btns) 68 | 69 | 70 | if __name__ == '__main__': 71 | test_btn_led() 72 | -------------------------------------------------------------------------------- /mn/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/__init__.py -------------------------------------------------------------------------------- /mn/cores/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/cores/__init__.py -------------------------------------------------------------------------------- /mn/cores/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/cores/common/__init__.py -------------------------------------------------------------------------------- /mn/cores/eth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/cores/eth/__init__.py -------------------------------------------------------------------------------- /mn/cores/eth/gemac_lite/_gemac_lite.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | 5 | 6 | def m_simple_gemac( 7 | 8 | # ~~[ports]~~ 9 | clock, # 125 MHz 10 | reset, # system reset 11 | 12 | gmii, # GMII interface 13 | flow, # flow control 14 | 15 | rxst, # rx stream 16 | txst, # tx stream 17 | 18 | settings, # settings 19 | 20 | #~~[parameters]~~ 21 | config=None 22 | ): 23 | """ 24 | """ 25 | 26 | SGE_IFG = 12 # 12 should be the absolute minimum 27 | 28 | 29 | grst1 = m_reset_sync(rxst.clk, reset, reset_rxclk) 30 | grst2 = m_reset_sync(txst.clk, reset, reset_txclk) 31 | 32 | # @todo: break out the gmii into gmii_tx and gmii_rx 33 | gtx = m_simple_gemac_tx(clock, reset, 34 | gmii_tx, 35 | txst) 36 | 37 | grx = m_simple_gemax_rx(clock, reset, 38 | gmii_rx, 39 | rxst) 40 | 41 | gfl = m_flow_control() 42 | 43 | 44 | return grst1, grst2, gtx, grx, gfl -------------------------------------------------------------------------------- /mn/cores/fifo/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | from _fifo_async import m_fifo_async 4 | from _fifo_sync import m_fifo_sync 5 | from _fifo_fast import m_fifo_fast 6 | from ramp._fifo_ramp import m_fifo_ramp 7 | 8 | #from fifo_sync import fifo_two_port_sync 9 | #from _fifo_mem import m_fifo_mem_generic 10 | #from fifo_sync import fifo_sync 11 | #from fifo_fast import fifo_fast 12 | 13 | -------------------------------------------------------------------------------- /mn/cores/fifo/_fifo_async.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2006-2014 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from math import log, ceil 18 | 19 | from myhdl import * 20 | 21 | from _fifo_mem import m_fifo_mem_generic 22 | from _fifo_syncers import * 23 | from _fifo_intf import check_fifo_intf 24 | from _fifo_intf import _fifobus 25 | 26 | def m_fifo_async(reset, wclk, rclk, fbus): 27 | """ 28 | The following is a general purpose, platform independent 29 | asynchronous FIFO (dual clock domains). 30 | 31 | Cross-clock boundrary FIFO, based on: 32 | "Simulation and Synthesis Techniques for Asynchronous FIFO Design" 33 | 34 | Typically in the "mn" package the FIFOBus interface is used to 35 | describe 36 | Timing: 37 | """ 38 | 39 | # verify that the "interface" passed has the required Signals 40 | # (attributes). 41 | check_fifo_intf(fbus) 42 | 43 | # for simplification the memory size is forced to a power of 44 | # two - full address range, ptr (mem indexes) will wrap 45 | Asz = int(ceil(log(fbus.size, 2))) 46 | 47 | # an extra bit is used to determine full vs. empty (see paper) 48 | waddr = Signal(modbv(0)[Asz:]) 49 | raddr = Signal(modbv(0)[Asz:]) 50 | wptr = Signal(modbv(0)[Asz+1:]) 51 | rptr = Signal(modbv(0)[Asz+1:]) 52 | wq2_rptr = Signal(intbv(0)[Asz+1:]) 53 | rq2_wptr = Signal(intbv(0)[Asz+1:]) 54 | 55 | wfull = Signal(bool(0)) 56 | rempty = Signal(bool(1)) 57 | 58 | # sync'd resets, the input reset is more than likely sync'd to one 59 | # of the clock domains, sync both regardless ... 60 | wrst = ResetSignal(reset.active, active=reset.active, async=reset.async) 61 | rrst = ResetSignal(reset.active, active=reset.active, async=reset.async) 62 | 63 | # @todo: if ResetSignal use the active attribute to determine 64 | # if 'not reset' or 'reset'. If the active==0 then 65 | # set invert=False 66 | gs1 = m_sync_rst(wclk, reset, wrst) 67 | gs2 = m_sync_rst(rclk, reset, rrst) 68 | 69 | gs3 = m_sync_mbits(wclk, wrst, rptr, wq2_rptr) 70 | gs4 = m_sync_mbits(rclk, rrst, wptr, rq2_wptr) 71 | 72 | @always_comb 73 | def rtl_assigns(): 74 | fbus.empty.next = rempty 75 | fbus.full.next = wfull 76 | 77 | _we = Signal(bool(0)) 78 | @always_comb 79 | def rtl_wr(): 80 | _we.next = fbus.wr and not fbus.full 81 | 82 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 | # Memory for the FIFO 84 | g_fifomem = m_fifo_mem_generic(wclk, _we, fbus.wdata, waddr, 85 | rclk, fbus.rdata, raddr, 86 | mem_size=fbus.size) 87 | 88 | 89 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 90 | # --Text from the paper-- 91 | # The read pointer is a dual nbit Gray code counter. The nbit 92 | # pointer (rptr) is passed to the write clock domain through the 93 | # syncs. The (n-1)bit pointer (raddr) is used to address the FIFO 94 | # buffer. The FIFO empty output is registered and is asserted on 95 | # the next rising rclk edge when the next rptr value equals the 96 | # sync wptr value. 97 | rbin = Signal(modbv(0)[Asz+1:]) 98 | #raddr.assign(rbin[Asz:0] 99 | 100 | @always_seq(rclk.posedge, reset=rrst) 101 | def rtl_rptrs(): 102 | # increment when read and not empty 103 | rbn = rbin + (fbus.rd and not rempty) 104 | rbin.next = rbn 105 | rpn = (rbn >> 1) ^ rbn # gray counter 106 | rptr.next = rpn 107 | 108 | # FIFO empty when the next rptr == sync'd wptr or on reset 109 | rempty.next = (rpn == rq2_wptr) 110 | 111 | # the data is register from the memory, the data is delayed 112 | fbus.rvld.next = fbus.rd and not rempty 113 | 114 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 115 | # --Text from the paper-- 116 | # The write pointer is a dual nbit gray code conter. The nbit 117 | # pointer (wptr) is passed to the read clock domain through the 118 | # sync'ers. The (n-1)-bit pointer (waddr) is used ot address the 119 | # FIFO buffer. The FIFO full asserted when the next modified 120 | # value equals the sync'd and modified wrptr2 value (except MSBs). 121 | wbin = Signal(modbv(0)[Asz+1:]) 122 | #waddr.assign(wbin[Asz:0]) 123 | 124 | @always_seq(wclk.posedge, reset=wrst) 125 | def rtl_wptrs(): 126 | # increment when write and not full 127 | wbn = wbin + (fbus.wr and not wfull) 128 | wbin.next = wbn 129 | wpn = (wbn >> 1) ^ wbn 130 | wptr.next = wpn 131 | 132 | # the dillio with the full determination ... 133 | wfull.next = (wpn == concat(~wq2_rptr[Asz+1:Asz-1], 134 | wq2_rptr[Asz-1:0])) 135 | 136 | 137 | @always_comb 138 | def rtl_addrs(): 139 | waddr.next = wbin[Asz:0] 140 | raddr.next = rbin[Asz:0] 141 | 142 | 143 | return instances() 144 | 145 | m_fifo_async.fbus_intf = _fifobus -------------------------------------------------------------------------------- /mn/cores/fifo/_fifo_fast.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2014 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from myhdl import * 18 | 19 | from _fifo_intf import check_fifo_intf 20 | from _fifo_intf import _fifobus 21 | 22 | def m_fifo_fast(clock, reset, fbus, use_srl_prim=False): 23 | """ 24 | Often small simple, synchronous, FIFOs can be implemented with 25 | specialized hardware in an FPGA (e.g. vertically chaining LUTs). 26 | 27 | This FIFO is intended to be used for small fast FIFOs. But when 28 | used for large 29 | 30 | This FIFO is a small FIFO (currently fixed to 16) that is implemented 31 | to take advantage of some hardware implementations. 32 | 33 | Typical FPGA synthesis will infer shift-register-LUT (SRL) for small 34 | synchronous FIFOs. This FIFO is implemented generically, consult the 35 | synthesis and map reports. 36 | 37 | PORTS 38 | ===== 39 | 40 | PARAMETERS 41 | ========== 42 | use_slr_prim: this parameter indicates to use the SRL primitive 43 | (inferrable primitive). If SRL are not inferred from the generic 44 | description this option can be used. Note, srl_prim will only 45 | use a size (FIFO depth) of 16. 46 | """ 47 | 48 | # @todo: this is intended to be used for small fast fifo's but it 49 | # can be used for large synchronous fifo as well 50 | 51 | N = 32 # default and max size 52 | if use_srl_prim: 53 | N = 16 54 | elif fbus.size > N: 55 | print("@W: m_fifo_fast only supports size < %d, for fast" % (N)) 56 | print(" forcing size (depth) to %d" % (N)) 57 | else: 58 | N = fbus.size 59 | 60 | mem = [Signal(intbv(0)[fbus.width:]) for _ in range(N)] 61 | addr = Signal(intbv(0, min=0, max=N)) 62 | 63 | # aliases to the FIFO bus interface 64 | srlce = fbus.wr # single cycle write 65 | write = fbus.wr 66 | read = fbus.rd 67 | full = fbus.full 68 | empty = fbus.empty 69 | 70 | # note: use_srl_prim has not been tested! 71 | # note: signal slices wdata() will need to be used instead of 72 | # bit slices wsdata[]. Have add 73 | if use_srl_prim: 74 | gsrl = [None for _ in range(N)] 75 | for ii in range(N): 76 | gsrl[ii] = m_fifo_srl(clock, fbus.wdata(ii), fbus.wr, 77 | addr, fbus.rdata(ii)) 78 | else: 79 | # the SRL based FIFO always writes to address 0 and shifts 80 | # the FIFO, only a read address is accounted. 81 | @always(clock.posedge) 82 | def rtl_srl_in(): 83 | if srlce: 84 | mem[0].next = fbus.wdata 85 | for ii in range(1,N): 86 | mem[ii].next = mem[ii-1] 87 | 88 | @always_comb 89 | def rtl_srl_out(): 90 | fbus.rdata.next = mem[addr] 91 | 92 | @always_comb 93 | def rtl_vld(): 94 | fbus.rvld.next = fbus.rd # no delay on reads 95 | 96 | # the address is the read address, the write address is always 97 | # zero but on a write all values are shifted up one index, only 98 | # the read address is accounted in the following. 99 | @always_seq(clock.posedge, reset=reset) 100 | def rtl_fifo(): 101 | if fbus.clear: 102 | addr.next = 0 103 | fbus.empty.next = True 104 | fbus.full.next = False 105 | 106 | elif fbus.rd and not fbus.wr: 107 | fbus.full.next = False 108 | if addr == 0: 109 | fbus.empty.next = True 110 | else: 111 | addr.next = addr - 1 112 | 113 | elif fbus.wr and not fbus.rd: 114 | fbus.empty.next = False 115 | if not fbus.empty: 116 | addr.next = addr + 1 117 | if addr == N-2: 118 | fbus.full.next = True 119 | 120 | # nothing happens if read and write at the same time 121 | 122 | # note: failures occur if write/read when full/empty respectively 123 | 124 | nvacant = Signal(intbv(N, min=0, max=N+1)) # # empty slots 125 | ntenant = Signal(intbv(0, min=0, max=N+1)) # # filled slots 126 | 127 | @always_seq(clock.posedge, reset=reset) 128 | def dbg_occupancy(): 129 | if fbus.clear: 130 | nvacant.next = N 131 | ntenant.next = 0 132 | elif fbus.rd and not fbus.wr: 133 | nvacant.next = nvacant + 1 134 | ntenant.next = ntenant - 1 135 | elif fbus.wr and not fbus.rd: 136 | nvacant.next = nvacant - 1 137 | ntenant.next = ntenant + 1 138 | 139 | return rtl_srl_in, rtl_srl_out, rtl_vld, rtl_fifo, dbg_occupancy 140 | 141 | # attached a generic fifo bus object to the module 142 | m_fifo_fast.fbus_intf = _fifobus -------------------------------------------------------------------------------- /mn/cores/fifo/_fifo_intf.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | # this is the fifo interfaces 5 | 6 | class _fifobus(object): 7 | """ 8 | This object defines the signals needed to interface with the 9 | FIFO cores. If used in the "mn" pakcage use the FIFOBus defined 10 | in "system" 11 | """ 12 | def __init__(self, width=8, size=128): 13 | self.clear = Signal(bool(0)) # fifo clear 14 | self.wclk = None # write side clock 15 | self.wr = Signal(bool(0)) # write strobe to fifo 16 | self.wdata = Signal(intbv(0)[width:]) # fifo data in 17 | 18 | self.rclk = None # read side clock 19 | self.rd = Signal(bool(0)) # fifo read strobe 20 | self.rdata = Signal(intbv(0)[width:]) # fifo data out 21 | self.empty = Signal(bool(0)) # fifo empty 22 | self.full = Signal(bool(0)) # fifo full 23 | self.count = Signal(intbv(0, min=0, max=size)) 24 | 25 | 26 | def _fifo_intf_dump(): 27 | """ 28 | dump a ton of information about the expected bus interface 29 | """ 30 | pass 31 | 32 | def check_fifo_intf(fbus): 33 | """ 34 | In the MN project, typically the FIFOBus is used to created 35 | a FIFO. It is plausible for a separate interface to be 36 | defined and passed. This function will check the inteface 37 | for the correct signals (attributes) and try to provide useful 38 | feedback what is missing / inconsistent in the interface. 39 | """ 40 | try: 41 | assert isinstance(fbus.wr, SignalType) 42 | assert isinstance(fbus.wdata, SignalType) 43 | 44 | assert isinstance(fbus.rd, SignalType) 45 | assert isinstance(fbus.rdata, SignalType) 46 | 47 | assert len(fbus.wdata) == len(fbus.rdata) 48 | # @todo: the above is a small start ... to be continued ... 49 | except AssertionError, err: 50 | _fifo_intf_dump() 51 | raise err 52 | except Exception, err: 53 | raise err -------------------------------------------------------------------------------- /mn/cores/fifo/_fifo_mem.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2006-2014 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from math import ceil, log 18 | from myhdl import * 19 | 20 | def m_fifo_mem_generic( 21 | wclk, 22 | wr, 23 | din, 24 | addr_w, 25 | 26 | rclk, 27 | dout, 28 | addr_r, 29 | mem_size = 9, 30 | ): 31 | """ 32 | """ 33 | 34 | Asz = int(ceil(log(mem_size, 2))) 35 | assert len(din) == len(dout) 36 | Dsz = len(din) 37 | 38 | mem = [Signal(intbv(0)[Dsz:]) for ii in range(2**Asz)] 39 | _addr_w = Signal(intbv(0)[Asz:]) 40 | _din = Signal(intbv(0)[Dsz:]) 41 | _dout = Signal(intbv(0)[Dsz:]) 42 | _wr = Signal(bool(0)) 43 | 44 | @always_comb 45 | def rtl_dout(): 46 | dout.next = _dout 47 | 48 | @always(rclk.posedge) 49 | def rtl_rd(): 50 | _dout.next = mem[int(addr_r)] 51 | 52 | @always(wclk.posedge) 53 | def rtl_wr(): 54 | _wr.next = wr 55 | _addr_w.next = addr_w 56 | _din.next = din 57 | 58 | @always(wclk.posedge) 59 | def rtl_mem(): 60 | if _wr: 61 | mem[int(_addr_w)].next = _din 62 | 63 | 64 | return rtl_dout, rtl_rd, rtl_wr, rtl_mem 65 | -------------------------------------------------------------------------------- /mn/cores/fifo/_fifo_srl.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from myhdl import * 4 | 5 | def m_fifo_srl(clock, D, ce, addr, Q, Qn=None): 6 | """ 7 | Infer a shift-register-LUT without explicilty instatiating a device 8 | specific primitive. This is typical in most FPGAs and works for std 9 | cell as well (nothing special happens in std cell). 10 | 11 | Information on Xilinx SRL: 12 | http://www.xilinx.com/support/documentation/application_notes/xapp465.pdf 13 | http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_5/xst_v6s6.pdf, page 154 14 | """ 15 | W = 16 16 | assert len(addr) == 4, "this is fixed to a length of 16" 17 | srl = Signal(intbv(0)[W:]) 18 | 19 | @always(clock.posedge) 20 | def rtl(): 21 | if ce: 22 | srl.next = concat(srl[W-2:0], D) 23 | #srl.next[0] = D 24 | #slr.next[W-1:1] = slr[W-2:0] 25 | 26 | @always_comb 27 | def rtl_out(): 28 | Q.next = srl[addr] 29 | 30 | if Qn is not None: 31 | @always_comb 32 | def rtl_outn(): 33 | Qn.next = srl[W-1] 34 | 35 | g = (rtl, rtl_out, rtl_outn) 36 | else: 37 | g = (rtl, rtl_out,) 38 | 39 | return g 40 | 41 | -------------------------------------------------------------------------------- /mn/cores/fifo/_fifo_sync.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2014 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from math import log, fmod, ceil 18 | from myhdl import * 19 | 20 | from _fifo_intf import check_fifo_intf 21 | from _fifo_intf import _fifobus 22 | from _fifo_mem import m_fifo_mem_generic 23 | 24 | def m_fifo_sync(clock, reset, fbus): 25 | """ Simple synchronous FIFO 26 | 27 | PORTS 28 | ===== 29 | 30 | PARAMETERS 31 | ========== 32 | """ 33 | 34 | # @todo: this is intended to be used for small fast fifo's but it 35 | # can be used for large synchronous fifo as well 36 | N = fbus.size 37 | 38 | if fmod(log(N, 2), 1) != 0: 39 | Asz = int(ceil(log(N,2))) 40 | N = 2**Asz 41 | print("@W: m_fifo_sync only supports power of 2 size") 42 | print(" forcing size (depth) to %d instread of " % (N, fbus.size)) 43 | 44 | wptr = Signal(modbv(0, min=0, max=N)) 45 | rptr = Signal(modbv(0, min=0, max=N)) 46 | _vld = Signal(False) 47 | 48 | # generic memory model 49 | g_fifomem = m_fifo_mem_generic(clock, fbus.wr, fbus.wdata, wptr, 50 | clock, fbus.rdata, rptr, 51 | mem_size=fbus.size) 52 | 53 | # @todo: almost full and almost empty flags 54 | read = fbus.rd 55 | write = fbus.wr 56 | @always_seq(clock.posedge, reset=reset) 57 | def rtl_fifo(): 58 | if fbus.clear: 59 | wptr.next = 0 60 | rptr.next = 0 61 | fbus.full.next = False 62 | fbus.empty.next = True 63 | 64 | elif read and not write: 65 | fbus.full.next = False 66 | if not fbus.empty: 67 | rptr.next = rptr + 1 68 | if rptr == (wptr-1): 69 | fbus.empty.next = True 70 | 71 | elif write and not read: 72 | fbus.empty.next = False 73 | if not fbus.full: 74 | wptr.next = wptr + 1 75 | if wptr == (rptr-1): 76 | fbus.full.next = True 77 | 78 | elif write and read: 79 | wptr.next = wptr + 1 80 | rptr.next = rptr + 1 81 | 82 | _vld.next = read 83 | 84 | @always_comb 85 | def rtl_assign(): 86 | fbus.rvld.next = _vld & fbus.rd 87 | 88 | nvacant = Signal(intbv(N, min=-0, max=N+1)) # # empty slots 89 | ntenant = Signal(intbv(0, min=-0, max=N+1)) # # filled slots 90 | 91 | @always_seq(clock.posedge, reset=reset) 92 | def dbg_occupancy(): 93 | if fbus.clear: 94 | nvacant.next = N 95 | ntenant.next = 0 96 | else: 97 | v = nvacant 98 | f = ntenant 99 | 100 | if fbus.rvld: 101 | v = v + 1 102 | f = f - 1 103 | if fbus.wr: 104 | v = v -1 105 | f = f + 1 106 | 107 | nvacant.next = v 108 | ntenant.next = f 109 | 110 | fbus.count = ntenant 111 | 112 | return (g_fifomem, rtl_fifo, rtl_assign, dbg_occupancy,) 113 | 114 | # attached a generic fifo bus object to the module 115 | m_fifo_sync.fbus_intf = _fifobus -------------------------------------------------------------------------------- /mn/cores/fifo/_fifo_syncers.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2006-2014 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from myhdl import * 19 | 20 | def m_sync_rst(clock, rsti, rsto): 21 | """ 22 | """ 23 | rsync = [Signal(bool(rsti.active)) for _ in range(2)] 24 | 25 | 26 | @always_seq(clock.posedge, reset=rsti) 27 | def rtl(): 28 | rsync[0].next = rsti 29 | rsync[1].next = rsync[0] 30 | rsto.next = rsync[1] 31 | 32 | return rtl 33 | 34 | def m_sync_mbits(clock, reset, sigin, sigou): 35 | 36 | d1 = Signal(intbv(0)[len(sigou):]) 37 | 38 | @always_seq(clock.posedge, reset=reset) 39 | def rtl(): 40 | d1.next = sigin 41 | sigou.next = d1 42 | 43 | return rtl -------------------------------------------------------------------------------- /mn/cores/fifo/ramp/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _fifo_ramp import m_fifo_ramp 3 | from _regfile_def import regfile 4 | -------------------------------------------------------------------------------- /mn/cores/fifo/ramp/_fifo_ramp.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2006-2013 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from myhdl import * 18 | from mn.system import Global 19 | from _regfile_def import regfile 20 | 21 | def m_fifo_ramp( 22 | # --[ports]-- 23 | # @todo: use glbl for clock and reset 24 | clock, 25 | reset, 26 | regbus, 27 | fifobus, 28 | 29 | # --[parameters]-- 30 | base_address = 0x00 31 | ): 32 | """ FIFO Ramp module 33 | This module provides a simple 8-bit counter that will generate 34 | a ramp. This ramp is fed to the USB fifo. This can be used 35 | to validate the usb connection and the device to host (IN) data 36 | rates. 37 | """ 38 | glbl = Global(clock=clock, reset=reset) 39 | g_regbus = regbus.add(glbl, regfile, 'fifo_ramp', base_address) 40 | 41 | enable = Signal(False) 42 | ramp = Signal(intbv(0)[fifobus.width:]) 43 | wcnt = Signal(intbv(0x3FF)[32:]) 44 | div = Signal(intbv(0)[32:]) 45 | rcnt = Signal(intbv(0)[32:]) 46 | 47 | # ?? not sure if this makes sense ?? 48 | ramp_mod = int(2**fifobus.width) 49 | 50 | @always_comb 51 | def rtl_assign(): 52 | regfile.cnt3.next = (rcnt >> 24) & 0xFF 53 | regfile.cnt2.next = (rcnt >> 16) & 0xFF 54 | regfile.cnt1.next = (rcnt >> 8) & 0xFF 55 | regfile.cnt0.next = (rcnt >> 0) & 0xFF 56 | 57 | @always_seq(clock.posedge, reset=reset) 58 | def rtl_reg(): 59 | enable.next = regfile.enable 60 | div.next = ((regfile.div3 << 24) | 61 | (regfile.div2 << 16) | 62 | (regfile.div1 << 8) | 63 | (regfile.div0)) 64 | 65 | @always_seq(clock.posedge, reset=reset) 66 | def rtl_ramp(): 67 | if regfile.enable and not fifobus.full: 68 | if wcnt == 0 : 69 | fifobus.wr.next = True 70 | fifobus.wdata.next = ramp 71 | if ramp+1 == ramp_mod: 72 | rcnt.next = rcnt + 1 73 | ramp.next = (ramp + 1) % ramp_mod 74 | wcnt.next = div 75 | else: 76 | fifobus.wr.next = False 77 | wcnt.next = wcnt - 1 78 | else: 79 | fifobus.wr.next = False 80 | fifobus.wdata.next = 0 81 | wcnt.next = div 82 | 83 | return instances() 84 | -------------------------------------------------------------------------------- /mn/cores/fifo/ramp/_regfile_def.py: -------------------------------------------------------------------------------- 1 | 2 | from collections import OrderedDict 3 | from myhdl import * 4 | from mn.system import RegisterFile, Register, RegisterBits 5 | 6 | 7 | regfile = RegisterFile() 8 | # -- a basic configuration register -- 9 | regcfg = Register('cfg',0x00,8,'rw',0) 10 | regcfg.comment = "fifo ramp configuration register" 11 | regcfg.add_named_bits('enable', slice(1,0), "enable fifo ramp") 12 | regfile.add_register(regcfg) 13 | 14 | # -- division register 0 -- 15 | # 32-bit clock division register 16 | for ii,regname in enumerate(('div3','div2','div1','div0')): 17 | regdiv = Register(regname,0x04+ii,8,'rw',0) 18 | regdiv.comment = "division register most significant byte" 19 | regdiv.add_named_bits('%sb'%(regname),slice(8,0),"rate control divisor") 20 | regfile.add_register(regdiv) 21 | 22 | # -- number of ramps completed -- 23 | # 32-bit 24 | for ii,regname in enumerate(('cnt3','cnt2','cnt1','cnt0')): 25 | regcnt = Register(regname,0x08+ii,8,'ro',0) 26 | regcnt.comment = "the number of ramp cycles completed" 27 | regcnt.add_named_bits('%sb'%(regname),slice(8,0),"count") 28 | regfile.add_register(regcnt) 29 | 30 | -------------------------------------------------------------------------------- /mn/cores/misc/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _serio import m_serio 3 | from _assign import m_assign 4 | 5 | from _led_count import m_led_count 6 | from _led_stroby import m_led_stroby 7 | from _led_dance import m_led_dance 8 | from _led_mm_per import m_led_mm_per 9 | from _btn_mm_ctl import m_btn_mm_ctl -------------------------------------------------------------------------------- /mn/cores/misc/_assign.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | def m_assign(a, b): 5 | """ a = b """ 6 | @always_comb 7 | def assign(): 8 | a.next = b 9 | return assign -------------------------------------------------------------------------------- /mn/cores/misc/_btn_debounce.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | 5 | def m_btn_debounce(glbl, bnts, dbnts): 6 | 7 | cnt = Signal(intbv(0, min=0, max=33)) 8 | 9 | # @todo finish and use m_time_strobe that checks 10 | # glbl for a strober 11 | @always(glbl.clock.posedge) 12 | def rtl(): 13 | dbnts.next = bnts 14 | 15 | return rtl -------------------------------------------------------------------------------- /mn/cores/misc/_btn_mm_ctl.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | from _btn_debounce import m_btn_debounce 5 | 6 | def m_btn_mm_ctl(glbl, regbus, btns, led_addr=0x8240): 7 | """ 8 | """ 9 | 10 | clock, reset = glbl.clock, glbl.reset 11 | dbtns = Signal(intbv(0)[len(btns):]) 12 | 13 | # simple interface to control (invoke) the controller 14 | ctl = regbus.get_controller_intf() 15 | 16 | # debounce the buttons 17 | gbtn = m_btn_debounce(glbl, btns, dbtns) 18 | 19 | # use the basic controller defined in the memmap modules 20 | # this basic controller is very simple, a write strobe 21 | # will start a write cycle and a read strobe a read cycle. 22 | gctl = regbus.m_controller_basic(ctl) 23 | 24 | 25 | # @todo: finish, can't use the write's like they are 26 | # but I need a bus agnostic method to read/write 27 | # different buses. 28 | @always_seq(clock.posedge, reset=reset) 29 | def rtl(): 30 | # default values 31 | ctl.write.next = False 32 | ctl.read.next = False 33 | ctl.addr.next = led_addr 34 | 35 | if ctl.done: 36 | if btns != 0: 37 | ctl.write.next = True 38 | 39 | if dbtns[0]: 40 | ctl.wdata.next = 1 41 | elif dbtns[1]: 42 | ctl.wdata.next = 2 43 | elif dbtns[2]: 44 | ctl.wdata.next = 3 45 | elif dbtns[3]: 46 | ctl.wdata.next = 4 47 | 48 | 49 | return gbtn, gctl, rtl -------------------------------------------------------------------------------- /mn/cores/misc/_led_count.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from myhdl import * 4 | from _assign import m_assign 5 | 6 | def m_led_count( 7 | # ~~~[Ports]~~~ 8 | clock, # input : system sync clock 9 | reset, # input : reset (level determined by RST_LEVEL) 10 | leds, # output : to IO ports drive LEDs 11 | 12 | # ~~~[Parameters]~~~ 13 | led_rate = 333e-3, # strobe change rate of 333ms 14 | ): 15 | """ 16 | """ 17 | cnt_max = int(clock.frequency * led_rate) 18 | clk_cnt = Signal(intbv(1, min=0, max=cnt_max)) 19 | rled = Signal(modbv(0)[len(leds):]) 20 | # assign the port LED to the internal register led 21 | gas = m_assign(leds, rled) 22 | 23 | # @todo: create a module to select a rate strobe, 24 | # the module will return a signal that is from 25 | # an existing rate or a geneator and signal 26 | @always_seq(clock.posedge, reset=reset) 27 | def rtl(): 28 | if clk_cnt == 0: 29 | rled.next = rled + 1 30 | clk_cnt.next = clk_cnt + 1 31 | 32 | return gas, rtl 33 | -------------------------------------------------------------------------------- /mn/cores/misc/_led_dance.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from _assign import m_assign 4 | 5 | def m_led_dance( 6 | # ~~~[Ports]~~~ 7 | clock, # input : system sync clock 8 | reset, # input : reset (level determined by RST_LEVEL) 9 | leds, # output : to IO ports drive LEDs 10 | 11 | # ~~~[Parameters]~~~ 12 | led_rate = 33e-3, # strobe change rate of 333ms 13 | ): 14 | """ 15 | """ 16 | cnt_max = int(clock.frequency * led_rate) 17 | clk_cnt = Signal(intbv(1, min=0, max=cnt_max)) 18 | rled = Signal(modbv(0)[len(leds):]) 19 | # assign the port LED to the internal register led 20 | gas = m_assign(leds, rled) 21 | 22 | # @todo: create a module to select a rate strobe, 23 | # the module will return a signal that is from 24 | # an existing rate or a geneator and signal 25 | mb = len(leds)-1 26 | d = modbv(0)[len(leds):] 27 | @always_seq(clock.posedge, reset=reset) 28 | def rtl(): 29 | if clk_cnt == 0: 30 | d[:] = (rled ^ 0x81) << 1 31 | rled.next = concat(d, rled[mb]) 32 | clk_cnt.next = clk_cnt + 1 33 | 34 | return gas, rtl -------------------------------------------------------------------------------- /mn/cores/misc/_led_mm_per.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | 5 | from myhdl import * 6 | from mn.system.regfile import RegisterFile 7 | from mn.system.regfile import Register 8 | 9 | from mn.cores.misc._assign import m_assign 10 | from mn.cores.misc._led_stroby import m_led_stroby 11 | from mn.cores.misc._led_count import m_led_count 12 | from mn.cores.misc._led_dance import m_led_dance 13 | 14 | # create a simple register file for the "core" 15 | regfile = RegisterFile() 16 | select = Register("select", 0x00, 8, 'rw') 17 | regfile.add_register(select) 18 | 19 | 20 | def m_led_mm_per(glbl, regbus, leds, base_address=0x8240): 21 | """ LED memory-map peripheral 22 | This (rather silly) core will select different LED 23 | displays based on the memory-mapped select register. 24 | """ 25 | Ndrv = 3 # the number of different drivers 26 | 27 | clock,reset = glbl.clock, glbl.reset 28 | rleds = Signal(intbv(0)[len(leds):]) 29 | 30 | # assign the LED port to the local register 31 | gas = m_assign(leds, rleds) 32 | 33 | # memory-mapped registers 34 | greg = regbus.add(glbl, regfile, 'led', base_address) 35 | 36 | # led bus from each driver 37 | dled = [Signal(intbv(0)[len(leds):]) 38 | for _ in range(Ndrv)] 39 | 40 | # instantiate different LED drivers 41 | gl = [None for _ in range(Ndrv)] 42 | gl[0] = m_led_stroby(clock, reset, dled[0]) 43 | gl[1] = m_led_count(clock, reset, dled[1]) 44 | gl[2] = m_led_dance(clock, reset, dled[2]) 45 | 46 | @always_seq(clock.posedge, reset=reset) 47 | def rtl(): 48 | for ii in range(Ndrv): 49 | idx = regfile.select 50 | rleds.next = dled[idx-1] 51 | 52 | return gas, gl, greg, rtl -------------------------------------------------------------------------------- /mn/cores/misc/_led_stroby.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2011-2013 Christopher Felton 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU Lesser General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU Lesser General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU Lesser General Public License 14 | # along with this program. If not, see . 15 | # 16 | """ 17 | The following is the HDL description of the stroby LED. 18 | This module requires MyHDL >= 0.8. 19 | 20 | Full tutorial available at : 21 | http://www.fpgarelated.com/showarticle/25.php 22 | """ 23 | 24 | from myhdl import * 25 | 26 | def m_led_stroby( 27 | # ~~~[Ports]~~~ 28 | clock, # input : system sync clock 29 | reset, # input : reset (level determined by RST_LEVEL) 30 | leds, # output : to IO ports drive LEDs 31 | 32 | # ~~~[Parameters]~~~ 33 | led_rate = 333e-3, # strobe change rate of 333ms 34 | num_dumb = 4, # The number of dummy LEDS on each side 35 | ): 36 | """ strobe the LED 37 | """ 38 | 39 | # Number of LEDs 40 | led_bank = len(leds) 41 | 42 | # Need to calculate some constants. Want the value to 43 | # be an integer (non-fractional value only whole number) 44 | cnt_max = int(clock.frequency * led_rate) 45 | 46 | # Some useful definitions (constants) 47 | mb = led_bank + 2*num_dumb 48 | lsb,msb = (0,mb-1,) 49 | msb_reverse_val = (1 << mb-2) 50 | lsb_reverse_val = 2 51 | 52 | # Declare the internal Signals in our design 53 | led_bit_mem = Signal(intbv(1)[mb:]) 54 | left_not_right = Signal(True) 55 | clk_cnt = Signal(intbv(0, min=0, max=cnt_max)) 56 | strobe = Signal(False) 57 | 58 | @always_seq(clock.posedge, reset=reset) 59 | def rtl_beh(): 60 | # Generate the strobe event, use the "greater 61 | # than" for initial condition cases. Count the 62 | # number of clock ticks that equals the LED strobe rate 63 | if clk_cnt >= cnt_max-1: 64 | clk_cnt.next = 0 65 | strobe.next = True 66 | else: 67 | clk_cnt.next = clk_cnt + 1 68 | strobe.next = False 69 | 70 | # The following always changes direction and "resets" when 71 | # either the lsb or msb is set. This handles our initial 72 | # condition as well. 73 | if strobe: 74 | if led_bit_mem[msb]: 75 | led_bit_mem.next = msb_reverse_val 76 | left_not_right.next = False 77 | elif led_bit_mem[lsb]: 78 | led_bit_mem.next = lsb_reverse_val 79 | left_not_right.next = True 80 | else: 81 | if left_not_right: 82 | led_bit_mem.next = led_bit_mem << 1 83 | else: 84 | led_bit_mem.next = led_bit_mem >> 1 85 | 86 | @always_comb 87 | def rtl_map_output(): 88 | leds.next = led_bit_mem[led_bank+num_dumb:num_dumb] 89 | 90 | return rtl_beh, rtl_map_output 91 | 92 | -------------------------------------------------------------------------------- /mn/cores/misc/_serio.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from myhdl import * 4 | 5 | def m_serio(clock, reset, sdi, sdo, pin, pout): 6 | """ serial-in, serial-out 7 | This module is a simple module used for synthesis testing for 8 | particular FPGA devices. This module allows a bunch of inputs 9 | to be tied to a couple IO (pins). Typically this is not used 10 | in a functionally working implementation but a circuit valid 11 | and timing valid implementation to determine a rought number 12 | of resources required for a design. 13 | 14 | Ports 15 | ----- 16 | clock : 17 | reset : 18 | sdi : serial-data in, this should be assigned to a pin on 19 | the device 20 | sdo : serial-data out, this should be assigned to a pin on 21 | the device 22 | pdin : number of inputs desired 23 | pdout : number of outputs desired 24 | 25 | Parameters 26 | None 27 | 28 | Limitations each member in the pin and pout lists need to be 29 | the same type. 30 | ---------- 31 | """ 32 | 33 | # verify pin and pout are lists 34 | assert isinstance(pin, list) 35 | assert isinstance(pout, list) 36 | 37 | Nin = len(pin) # number of inputs (outputs of this module) 38 | Nout = len(pout) # number of outputs (inputs to this module) 39 | nbx = len(pin[0]) # bit lengths of the inputs 40 | nby = len(pout[0]) # bit lengths of the outputs 41 | 42 | Signed = True if pin[0].min < 0 else False 43 | 44 | # make the input and output registers same length 45 | xl,yl = Nin*nbx, Nout*nby 46 | Nbits = max(xl, yl) 47 | irei = Signal(bool(0)) 48 | oreo = Signal(bool(0)) 49 | ireg = [Signal(intbv(0)[nbx:]) for _ in range(Nin)] 50 | oreg = [Signal(intbv(0)[nby:]) for _ in range(Nin)] 51 | 52 | scnt = Signal(intbv(0, min=0, max=Nbits+1)) 53 | imax = scnt.max-1 54 | 55 | 56 | @always_seq(clock.posedge, reset=reset) 57 | def rtl_shifts(): 58 | irei.next = sdi 59 | oreo.next = oreg[Nout-1][nby-1] 60 | sdo.next = oreo 61 | 62 | # build the large shift register out of the logical 63 | # list of signals (array) 64 | for ii in range(Nin): 65 | if ii == 0: 66 | ireg[ii].next = concat(ireg[ii][nbx-1:0], irei) 67 | else: 68 | ireg[ii].next = concat(ireg[ii][nbx-1:0], ireg[ii-1][nbx-1]) 69 | 70 | if scnt == imax: 71 | scnt.next = 0 72 | for oo in range(Nout): 73 | oreg[oo].next = pout[oo] 74 | else: 75 | scnt.next = scnt + 1 76 | for oo in range(Nout): 77 | if oo == 0: 78 | oreg[oo].next = oreg[oo] << 1 79 | else: 80 | oreg[oo].next = concat(oreg[oo][nby-1:0], oreg[oo-1][nby-1]) 81 | 82 | @always_comb 83 | def rtl_assign(): 84 | for ii in range(Nin): 85 | pin[ii].next = ireg[ii] 86 | 87 | return rtl_shifts, rtl_assign 88 | 89 | -------------------------------------------------------------------------------- /mn/cores/sdram/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _intf import SDRAM 3 | from _sdram_sdr import m_sdram 4 | 5 | # specific memory definitions 6 | from _memories import * -------------------------------------------------------------------------------- /mn/cores/sdram/_intf.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from ...utils import extract_freq 4 | 5 | class SDRAM(object): 6 | # timing fields, all in ns 7 | freq = 100e6 8 | timing = { # all timing parameters in ns 9 | 'init' : 200000.0, # min init interval 10 | 'ras' : 45.0, # min interval between active precharge commands 11 | 'rcd' : 20.0, # min interval between active R/W commands 12 | 'ref' : 64000000.0, # max refresh interval 13 | 'rfc' : 65.0, # refresh operaiton duration 14 | 'rp' : 20.0, # min precharge command duration 15 | 'xsr' : 75.0, # exit self-refresh time 16 | 'wr' : 55, # @todo ... 17 | } 18 | 19 | addr_width = 12 # SDRAM address width 20 | data_width = 16 # SDRAM data width 21 | 22 | def __init__(self, clock, Nrows=4096, Ncols=512, Hwidth=23): 23 | self.freq = extract_freq(clock, self.freq) 24 | self.Nrows = Nrows # number of rows in the SDRAM array 25 | self.Ncols = Ncols # number of columns in the SDRAM array 26 | self.Hw = Hwidth # host-side address width 27 | self.Sw = self.addr_width # SDRAM-side address width 28 | 29 | # internal signals 30 | self.lock = Signal(bool(0)) 31 | self.rd = Signal(bool(0)) 32 | self.wr = Signal(bool(0)) 33 | # a_op_begyn, op_begun, rd_pending 34 | self.done = Signal(bool(0)) 35 | self.addr = Signal(intbv(0)[Hwidth:0]) 36 | self.wdata = Signal(intbv(0)[self.data_width:0]) 37 | self.rdata = Signal(intbv(0)[self.data_width:0]) 38 | self.status = Signal(intbv(0)[4:]) 39 | 40 | # externl SDRAM signals 41 | self.sd_cke = Signal(bool(0)) 42 | self.sd_ce = Signal(bool(0)) 43 | self.sd_ras = Signal(bool(0)) 44 | self.sd_we = Signal(bool(0)) 45 | self.sd_bs = Signal(intbv(0)[2:]) 46 | self.sd_addr = Signal(intbv(0)[self.addr_width:]) 47 | self.sd_wdata = Signal(intbv(0)[self.data_width:]) 48 | self.sd_rdata = Signal(intbv(0)[self.data_width:]) 49 | self.sd_dqmh = Signal(bool(0)) # enable upper-byte of SDRAM 50 | self.sd_dqml = Signal(bool(0)) # enable lower-byte of SDRAM 51 | 52 | cycles = {} 53 | for k,v in self.timing.iteritems(): 54 | cycles[k] = v * (self.freq / 1e9) 55 | 56 | # need to add these to the namespace, currently the 57 | # myhdl converter will not extract the constants from 58 | # a data-structure (e.g. dict). 59 | for k,v in cycles.iteritems(): 60 | self.__dict__['cyc_'+k] = v 61 | 62 | self.cycles = 5 # @todo: incorrect, needs to be fixed 63 | -------------------------------------------------------------------------------- /mn/cores/sdram/_memories.py: -------------------------------------------------------------------------------- 1 | 2 | from _intf import SDRAM 3 | 4 | class Winboad_W9812G6JH_75(SDRAM): 5 | 6 | freq = 10e6 # clock frequency in Hz 7 | timing = { # all timing parameters in ns 8 | 'init' : 200000.0, # min init interval 9 | 'ras' : 45.0, # min interval between active precharge commands 10 | 'rcd' : 20.0, # min interval between active R/W commands 11 | 'ref' : 64000000.0, # max refresh interval 12 | 'rfc' : 65.0, # refresh operaiton duration 13 | 'rp' : 20.0, # min precharge command duration 14 | 'xsr' : 75.0, # exit self-refresh time 15 | } 16 | 17 | addr_width = 12 # SDRAM address width 18 | data_width = 16 # SDRAM data width 19 | -------------------------------------------------------------------------------- /mn/cores/sdram/_sdram_sdr.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from ...system import Clock 4 | from _intf import SDRAM 5 | 6 | 7 | def m_sdram(clock, reset, ibus, extram, refresh=True): 8 | """ SDRAM controller 9 | This module is an SDRAM controller to interface and control 10 | SDRAM modules. This module contains a state-machine that 11 | controls the different SDRAM modes including refresh etc. 12 | 13 | This module provides the translation from a flat memory-mapped 14 | bus (e.g. Wishbone, Avalon, AXI, etc.) to the SDRAM interface. 15 | Also intended to support memory-mapped and streaming (FIFO 16 | mode). In streaming / FIFO mode the external memory acts as 17 | one large FIFO. The SDRAM controller type is determine by 18 | the internal interface (ibus) passed. 19 | 20 | This SDRAM controller is a port of the Xess SDRAM controller 21 | for the Xula boards. 22 | https://github.com/xesscorp/XuLA/blob/master/FPGA/XuLA_lib/SdramCntl.vhd 23 | """ 24 | 25 | States = enum('INITWAIT', 'INITPCHG', 'INITSETMODE', 'INITRFSH', 26 | 'RW', 'ACTIVATE', 'REFRESHROW', 'SELFREFRESH') 27 | 28 | Commands = enum('nop', 'active', 'read', 'write', 29 | 'pchg', 'mode', 'rfsh', 30 | encoding='binary') 31 | 32 | cmdlut = (intbv('011100')[5:], 33 | intbv('001100')[5:], 34 | intbv('010100')[5:], 35 | intbv('010000')[5:], 36 | intbv('001000')[5:], 37 | intbv('000000')[5:], 38 | intbv('000100')[5:]) 39 | 40 | 41 | sdram = extram 42 | sdram.cmd = Signal(intbv(0)[5:]) 43 | 44 | timer = Signal(intbv(0, min=0, max=sdram.cyc_init)) 45 | ras_timer = Signal(intbv(0, min=0, max=sdram.cyc_ras)) 46 | wr_timer = Signal(intbv(0, min=0, max=sdram.cyc_wr)) 47 | 48 | state = Signal(States.INITWAIT) 49 | 50 | @always_seq(clock.posedge, reset=reset) 51 | def rtl_sdram_controller(): 52 | 53 | # this is one big state-machine but ... 54 | if state == States.INITWAIT: 55 | if sdram.lock: 56 | timer.next = sdram.cyc_init 57 | state.next = States.initpchg 58 | else: 59 | sdram.sd_cke.next = False 60 | sdram.status.next = 1 61 | 62 | elif state == States.INITPCHG: 63 | sdram.cmd.next = Commands.PCHG 64 | sdram.addr[CMDBITS] = Commands.ALL_BANKS 65 | timer.next = sdram.cycles 66 | 67 | return rtl_sdram_controller 68 | 69 | 70 | # default portmap 71 | clock = Clock(0, frequency=100e6) 72 | m_sdram.portmap = { 73 | 'clock': clock, 74 | 'reset': ResetSignal(0, active=0, async=False), 75 | 'ibus': None, 76 | 'extmem': SDRAM(clock) 77 | } 78 | 79 | 80 | -------------------------------------------------------------------------------- /mn/cores/sdram/_sdram_self_test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/cores/sdram/_sdram_self_test.py -------------------------------------------------------------------------------- /mn/cores/spi/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from _spi import * 4 | from _spibus import SPIBus 5 | -------------------------------------------------------------------------------- /mn/cores/spi/_regfile_def.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from mn.system import RegisterFile, Register, RegisterBits 4 | 5 | """ 6 | ---------------------------------------------------------------- 7 | @todo: resolve the local register file organizaiton with 8 | the memmap organiztion (e.g. this register file is a 9 | colleciton of 8bit registers, if the memmap is setup 10 | as 32 databits and 32 address bits want to organize 11 | these differently (combing into 32 bit registers)) 12 | Registers are on 32bit boundaries and are big-edian. Meaning 13 | the most significant byte is byte 0. Example the first register 14 | byte addresses are: 15 | LSB 3 byte == address 0x63 16 | 2 byte == address 0x62 17 | 1 byte == address 0x61 18 | MSB 0 byte == address 0x60 19 | end todo 20 | ---------------------------------------------------------------- 21 | 22 | 23 | Registers: (Base address +) 24 | 0x58: ???? setup register 25 | Freeze ----------------------------------------------+ 26 | Select streaming (1) or mm ------------------------+ | 27 | | | | | | | | | 28 | 7 6 5 4 3 2 1 0 29 | 30 | 0x60: SPCR control register 31 | Loop ------------------------------------------------+ 32 | SPE System Enable ---------------------------------+ | 33 | ----------------------------------------------+ | | 34 | CPOL Clock Polarity ---------------------------+ | | | 35 | CPHA Clock Phase ----------------------------+ | | | | 36 | ?? Tx FIFO Reset -----------------------------+ | | | | | 37 | ?? Rx FIFO Reset ---------------------------+ | | | | | | 38 | Manual Slave Select Enable ------------+ | | | | | | | 39 | | | | | | | | | 40 | 7 6 5 4 3 2 1 0 41 | 42 | 0x64: SPSR status register 43 | 7 6 5 4 3 2 1 0 44 | 0x68: SPTX transmit register 45 | 7 6 5 4 3 2 1 0 46 | 0x6C: SPRX receive register 47 | 48 | 0x70: SPSS slave select register 49 | 0x74: SPTC transmit fifo count 50 | 0x78: SPRC receive fifo count 51 | 0x7C: SPXX SCK clock divisor (divides wb clk_i) 52 | 0 -- 2 divisor 24 MHz (usbp == 48MHz system clock) 53 | """ 54 | 55 | regfile = RegisterFile() 56 | # -- SPI Setup Register 57 | spst = Register('spst', 0x58, 8, 'rw', 0x00) 58 | spst.add_named_bits('freeze', slice(1,0), 59 | "freeze the core") 60 | spst.add_named_bits('rdata', slice(2,1), 61 | "1 : register file (memmap) feeds TX/RX FIFO") 62 | regfile.add_register(spst) 63 | 64 | # -- SPI Control Register (Control Register 0) -- 65 | spcr = Register('spcr', 0x60, 8, 'rw', 0x98) 66 | spcr.comment = "SPI control register" 67 | spcr.add_named_bits('loop', slice(1,0), "internal loopback") 68 | spcr.add_named_bits('spe', slice(2,1), "system enable") 69 | spcr.add_named_bits('cpol', slice(4,3), "clock polarity") 70 | spcr.add_named_bits('cpha', slice(5,4), "clock phase") 71 | spcr.add_named_bits('msse', slice(8,7), "manual slave select enable") 72 | regfile.add_register(spcr) 73 | 74 | # -- SPI status register -- 75 | spsr = Register('spsr', 0x64, 8, 'ro', 0) 76 | spsr.add_named_bits('rxe', slice(1,0), "RX FIFO empty") 77 | spsr.add_named_bits('rxf', slice(2,1), "RX FIFO full") 78 | spsr.add_named_bits('txe', slice(3,2), "TX FIFO empty") 79 | spsr.add_named_bits('txf', slice(4,3), "TX FIFO full") 80 | spsr.add_named_bits('modf', slice(5,4), "SS line driven external fault") 81 | regfile.add_register(spsr) 82 | 83 | # -- The rest of the registers -- 84 | sptx = Register('sptx', 0x68, 8, 'rw', 0) 85 | sptx.comment = "SPI transmit" 86 | regfile.add_register(sptx) 87 | 88 | sprx = Register('sprx', 0x6C, 8, 'rw', 0) 89 | sprx.comment = "SPI receive" 90 | regfile.add_register(sprx) 91 | 92 | spss = Register('spss', 0x70, 8, 'rw', 0) 93 | spss.comment = "SPI slave select register, manually select external devices" 94 | regfile.add_register(spss) 95 | 96 | sptc = Register('sptc', 0x74, 8, 'rw', 0) 97 | sptc.comment = "transmit FIFO count" 98 | regfile.add_register(sptc) 99 | 100 | sprc = Register('sprc', 0x78, 8, 'rw', 0) 101 | sprc.comment = "receive FIFO count" 102 | regfile.add_register(sprc) 103 | 104 | spxx = Register('spxx', 0x78, 8, 'rw', 0) 105 | spxx.comment = "clock divisor register, sets sck period" 106 | regfile.add_register(spxx) 107 | -------------------------------------------------------------------------------- /mn/cores/spi/_spibus.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import Signal,intbv 3 | 4 | class SPIBus(object): 5 | def __init__(self): 6 | self.sck = Signal(True) 7 | self.mosi = Signal(True) 8 | self.miso = Signal(True) 9 | #self.ss = [Signal(True) for _ in range(8)] 10 | self.ss = Signal(intbv(0)[8:]) 11 | # make into an array 12 | self.csn = Signal(True) 13 | -------------------------------------------------------------------------------- /mn/cores/usbext/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from fpgalink import fpgalink 3 | from fpgalink import m_fpgalink_fx2 4 | 5 | #from usbp import m_usbp 6 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | import _fpgalink_fx2 as fpgalink 3 | from _fpgalink_fx2 import get_interfaces 4 | from _fpgalink_fx2 import m_fpgalink_fx2 5 | from _fl_convert import convert 6 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/_fl_convert.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | import _fpgalink_fx2 as fl 4 | 5 | def comm_fpga_fx2_v2( 6 | clk_in, 7 | reset_in, 8 | fx2FifoSel_out, 9 | fx2Data_in, 10 | fx2Data_out, 11 | fx2Data_sel, 12 | fx2Read_out, 13 | fx2GotData_in, 14 | fx2Write_out, 15 | fx2GotRoom_in, 16 | fx2PktEnd_out, 17 | chanAddr_out, 18 | h2fData_out, 19 | h2fValid_out, 20 | h2fReady_in, 21 | f2hData_in, 22 | f2hValid_in, 23 | f2hReady_out 24 | ): 25 | """ Original port definition 26 | This module bridges the "original" port mapping to the MyHDL 27 | version. 28 | """ 29 | clock,reset,fx2_bus,fl_bus = fl.get_interfaces() 30 | 31 | # assign the ports to the busses 32 | fx2_bus.fifosel = fx2FifoSel_out 33 | fx2_bus.data_i = fx2Data_in 34 | fx2_bus.data_o = fx2Data_out 35 | fx2_bus.data_t = fx2Data_sel 36 | 37 | # get the fpgalink module 38 | g = fl.fpgalink_fx2(clk_in, reset_in, fx2_bus, fl_bus) 39 | 40 | return g 41 | 42 | def comm_fpga_fx2_v1_stub( 43 | clk_in, 44 | reset_in, 45 | fx2FifoSel_out, 46 | fx2Data_in, 47 | fx2Data_out, 48 | fx2Data_sel, 49 | fx2Read_out, 50 | fx2GotData_in, 51 | fx2Write_out, 52 | fx2GotRoom_in, 53 | fx2PktEnd_out, 54 | chanAddr_out, 55 | h2fData_out, 56 | h2fValid_out, 57 | h2fReady_in, 58 | f2hData_in, 59 | f2hValid_in, 60 | f2hReady_out 61 | ): 62 | """ A stub for the Verilog cosimulation 63 | The following does absolutely nothing except let the converter know what 64 | ports are inputs and which arre outputs. 65 | """ 66 | 67 | @always(clk_in.posedge, reset_in.negedge) 68 | def hdl(): 69 | if fx2GotData_in or fx2GotRoom_in or h2fReady_in or f2hValid_in \ 70 | or fx2Data_in == 0 or f2hData_in == 0 : 71 | fx2Data_out.next = 2 72 | fx2Data_sel.next = False 73 | fx2FifoSel_out.next = True 74 | fx2Read_out.next = True 75 | fx2Write_out.next = True 76 | fx2PktEnd_out.next = True 77 | chanAddr_out.next = True 78 | h2fData_out.next = 3 79 | h2fValid_out.next = True 80 | f2hReady_out.next = True 81 | 82 | 83 | return hdl 84 | 85 | def convert(dir=None): 86 | clk_in = Signal(bool(0)) 87 | reset_in = ResetSignal(bool(0), active=0, async=True) 88 | fx2FifoSel_out = Signal(bool(0)) 89 | #fxData_io 90 | fx2Data_in = Signal(intbv(0)[8:]) 91 | fx2Data_out = Signal(intbv(0)[8:]) 92 | fx2Data_sel = Signal(bool(0)) 93 | fx2Read_out = Signal(bool(0)) 94 | fx2GotData_in = Signal(bool(0)) 95 | fx2Write_out = Signal(bool(0)) 96 | fx2GotRoom_in = Signal(bool(0)) 97 | fx2PktEnd_out = Signal(bool(0)) 98 | chanAddr_out = Signal(intbv(0)[7:]) 99 | h2fData_out = Signal(intbv(0)[8:]) 100 | h2fValid_out = Signal(bool(0)) 101 | h2fReady_in = Signal(bool(0)) 102 | f2hData_in = Signal(intbv(0)[8:]) 103 | f2hValid_in = Signal(bool(0)) 104 | f2hReady_out = Signal(bool(0)) 105 | 106 | # create the default tb_* to interface to the original Verilog module 107 | toVerilog(comm_fpga_fx2_v1_stub, clk_in, reset_in, fx2FifoSel_out, 108 | fx2Data_in, fx2Data_out, fx2Data_sel, 109 | fx2Read_out, fx2GotData_in, fx2Write_out, fx2GotRoom_in, fx2PktEnd_out, 110 | chanAddr_out, h2fData_out, h2fValid_out, h2fReady_in, f2hData_in, 111 | f2hValid_in, f2hReady_out) 112 | 113 | # Convert the MyHDL with the original port names 114 | toVerilog(comm_fpga_fx2_v2, clk_in, reset_in, fx2FifoSel_out, 115 | fx2Data_in, fx2Data_out, fx2Data_sel, 116 | fx2Read_out, fx2GotData_in, fx2Write_out, fx2GotRoom_in, fx2PktEnd_out, 117 | chanAddr_out, h2fData_out, h2fValid_out, h2fReady_in, f2hData_in, 118 | f2hValid_in, f2hReady_out) 119 | 120 | toVHDL(comm_fpga_fx2_v2, clk_in, reset_in, fx2FifoSel_out, 121 | fx2Data_in, fx2Data_out, fx2Data_sel, 122 | fx2Read_out, fx2GotData_in, fx2Write_out, fx2GotRoom_in, fx2PktEnd_out, 123 | chanAddr_out, h2fData_out, h2fValid_out, h2fReady_in, f2hData_in, 124 | f2hValid_in, f2hReady_out) 125 | 126 | 127 | if __name__ == '__main__': 128 | convert() 129 | 130 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/_fpgalink_fx2.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | FX2_OUT_FIFO = int('00', base=2) 5 | FX2_IN_FIFO = int('01', base=2) 6 | 7 | class Bus(object): pass 8 | 9 | def get_interfaces(): 10 | """ Single function to get the buses 11 | """ 12 | clock = Signal(bool(1)) 13 | reset = ResetSignal(bool(1), active=0, async=False) 14 | 15 | # Get an object that can be used for the "interfaces" 16 | fx2bus = Bus() # External to the FPGA 17 | flbus = Bus() # Internal 18 | 19 | # I am using a slightly different names 20 | fx2bus.fifosel = Signal(bool(0)) # FIFOADR[0] (FIFOADR[1] = 1) 21 | fx2bus.data_i = Signal(intbv(0)[8:]) # FD[7:0] 22 | fx2bus.data_o = Signal(intbv(0)[8:]) # FD[7:0] 23 | fx2bus.data_t = Signal(bool(0)) # data direction 24 | fx2bus.read = Signal(bool(0)) # SLOE, SLRD 25 | fx2bus.gotdata = Signal(bool(0)) # FLAGC 26 | fx2bus.write = Signal(bool(0)) # SLWR 27 | fx2bus.gotroom = Signal(bool(0)) # FLAGB 28 | fx2bus.pktend = Signal(bool(0)) # PKTEND 29 | 30 | flbus.chan_addr = Signal(intbv(0)[7:])# chanAddr 31 | flbus.data_o = Signal(intbv(0)[8:]) # h2f_data_out 32 | flbus.valid_o = Signal(bool(0)) # h2f_valid_out 33 | flbus.ready_i = Signal(bool(0)) # h2f_ready_in 34 | flbus.data_i = Signal(intbv(0)[8:]) # f2h_data_in 35 | flbus.valid_i = Signal(bool(0)) # f2h_valid_in 36 | flbus.ready_o = Signal(bool(0)) # f2h_ready_out 37 | 38 | return (clock, reset, fx2bus, flbus) 39 | 40 | def m_fpgalink_fx2( 41 | clock, # synchronous FPGA clock 42 | reset, # synchronous FPGA reset 43 | 44 | fx2bus, # external FX2 bus interface 45 | flbus, # internal fpgalink bus interface 46 | ): 47 | """ FPGALINK FX2 External USB Controller Interface 48 | """ 49 | 50 | States = enum('IDLE', 'GET_COUNT0', 'GET_COUNT1', 'GET_COUNT2', 51 | 'GET_COUNT3', 'BEGIN_WRITE', 'WRITE', 'END_WRITE_ALIGNED', 52 | 'END_WRITE_NONALIGNED', 'READ', 'READ_WAIT') 53 | 54 | fopREAD, fopWRITE, fopNOP = [2,1,3] 55 | 56 | # Internal Signals 57 | state = Signal(States.IDLE) 58 | fifop = Signal(intbv(fopNOP)[2:]) 59 | count = Signal(intbv(0)[32:]) 60 | is_aligned = Signal(bool(0)) 61 | is_write = Signal(bool(0)) 62 | 63 | @always_seq(clock.posedge, reset=reset) 64 | def hdl_sm(): 65 | if state == States.GET_COUNT0: 66 | if fx2bus.gotdata: 67 | count.next = fx2bus.data_i << 24 68 | state.next = States.GET_COUNT1 69 | else: 70 | count.next = 0 71 | 72 | elif state == States.GET_COUNT1: 73 | if fx2bus.gotdata: 74 | count.next = count | (fx2bus.data_i << 16) 75 | state.next = States.GET_COUNT2 76 | 77 | elif state == States.GET_COUNT2: 78 | if fx2bus.gotdata: 79 | count.next = count | (fx2bus.data_i << 8) 80 | state.next = States.GET_COUNT3 81 | 82 | elif state == States.GET_COUNT3: 83 | if fx2bus.gotdata: 84 | count.next = count | fx2bus.data_i 85 | if is_write: 86 | state.next = States.BEGIN_WRITE 87 | else: 88 | if flbus.ready_i: 89 | fifop.next = fopREAD 90 | state.next = States.READ 91 | else: 92 | fifop.next = fopNOP 93 | state.next = States.READ_WAIT 94 | 95 | elif state == States.BEGIN_WRITE: 96 | fx2bus.fifosel.next = FX2_IN_FIFO 97 | fifop.next = fopNOP 98 | if count[9:] == 0: 99 | is_aligned.next = True 100 | else: 101 | is_aligned.next = False 102 | state.next = States.WRITE 103 | 104 | elif state == States.WRITE: 105 | if fx2bus.gotroom: 106 | flbus.ready_o.next = True 107 | if fx2bus.gotroom and flbus.valid_i: 108 | fifop.next = fopWRITE 109 | fx2bus.data_o.next = flbus.data_i 110 | fx2bus.data_t.next = True 111 | count.next = count - 1 112 | if count == 1: 113 | if is_aligned: 114 | state.next = States.END_WRITE_ALIGNED 115 | else: 116 | state.next = States.END_WRITE_NONALIGNED 117 | else: 118 | fifop.next = fopNOP 119 | 120 | elif state == States.END_WRITE_ALIGNED: 121 | fx2bus.fifosel.next = FX2_IN_FIFO 122 | fifop.next = fopNOP 123 | state.next = States.IDLE 124 | 125 | elif state == States.END_WRITE_NONALIGNED: 126 | fx2bus.fifosel.next = FX2_IN_FIFO 127 | fifop.next = fopNOP 128 | fx2bus.pktend.next = False 129 | state.next = States.IDLE 130 | 131 | elif state == States.READ: 132 | fx2bus.fifosel.next = FX2_OUT_FIFO 133 | if fx2bus.gotdata and flbus.ready_i: 134 | assert not fx2bus.read 135 | flbus.valid_o.next = True 136 | flbus.data_o.next = fx2bus.data_i 137 | if count <= 1: 138 | state.next = States.IDLE 139 | count.next = 0 140 | else: 141 | count.next = count - 1 142 | 143 | 144 | elif state == States.READ_WAIT: 145 | if fx2bus.gotdata and flbus.ready_i: 146 | state.next = States.READ 147 | fifop.next = fopREAD 148 | 149 | else: # Idle state and others 150 | # The original state-machine left the 'read' control 151 | # signal always active until a write. 152 | fifop.next = fopREAD 153 | count.next = 0 154 | flbus.valid_o.next = False 155 | if fx2bus.gotdata: 156 | flbus.chan_addr.next = fx2bus.data_i[7:] 157 | is_write.next = fx2bus.data_i[7] 158 | state.next = States.GET_COUNT0 159 | 160 | @always_comb 161 | def hdl_assigns(): 162 | fx2bus.read.next = fifop[0] 163 | fx2bus.write.next = fifop[1] 164 | 165 | return hdl_sm, hdl_assigns 166 | 167 | if __name__ == '__main__': 168 | clock,reset,fx2bus,flbus = get_interfaces() 169 | g = fpgalink_fx2(clock, reset, fx2bus, flbus) 170 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/comm_fpga_fx2_v1_stub.v: -------------------------------------------------------------------------------- 1 | // File: comm_fpga_fx2_v1_stub.v 2 | // Generated by MyHDL 0.9dev 3 | // Date: Sat Jul 13 22:29:39 2013 4 | 5 | 6 | `timescale 1ns/10ps 7 | 8 | module comm_fpga_fx2_v1_stub ( 9 | clk_in, 10 | reset_in, 11 | fx2FifoSel_out, 12 | fx2Data_in, 13 | fx2Data_out, 14 | fx2Data_sel, 15 | fx2Read_out, 16 | fx2GotData_in, 17 | fx2Write_out, 18 | fx2GotRoom_in, 19 | fx2PktEnd_out, 20 | chanAddr_out, 21 | h2fData_out, 22 | h2fValid_out, 23 | h2fReady_in, 24 | f2hData_in, 25 | f2hValid_in, 26 | f2hReady_out 27 | ); 28 | // A stub for the Verilog cosimulation 29 | // The following does absolutely nothing except let the converter know what 30 | // ports are inputs and which arre outputs. 31 | 32 | input clk_in; 33 | input reset_in; 34 | output fx2FifoSel_out; 35 | reg fx2FifoSel_out; 36 | input [7:0] fx2Data_in; 37 | output [7:0] fx2Data_out; 38 | reg [7:0] fx2Data_out; 39 | output fx2Data_sel; 40 | reg fx2Data_sel; 41 | output fx2Read_out; 42 | reg fx2Read_out; 43 | input fx2GotData_in; 44 | output fx2Write_out; 45 | reg fx2Write_out; 46 | input fx2GotRoom_in; 47 | output fx2PktEnd_out; 48 | reg fx2PktEnd_out; 49 | output [6:0] chanAddr_out; 50 | reg [6:0] chanAddr_out; 51 | output [7:0] h2fData_out; 52 | reg [7:0] h2fData_out; 53 | output h2fValid_out; 54 | reg h2fValid_out; 55 | input h2fReady_in; 56 | input [7:0] f2hData_in; 57 | input f2hValid_in; 58 | output f2hReady_out; 59 | reg f2hReady_out; 60 | 61 | 62 | 63 | 64 | 65 | 66 | always @(posedge clk_in, negedge reset_in) begin: COMM_FPGA_FX2_V1_STUB_HDL 67 | if ((fx2GotData_in || fx2GotRoom_in || h2fReady_in || f2hValid_in || (fx2Data_in == 0) || (f2hData_in == 0))) begin 68 | fx2Data_out <= 2; 69 | fx2Data_sel <= 1'b0; 70 | fx2FifoSel_out <= 1'b1; 71 | fx2Read_out <= 1'b1; 72 | fx2Write_out <= 1'b1; 73 | fx2PktEnd_out <= 1'b1; 74 | chanAddr_out <= 1'b1; 75 | h2fData_out <= 3; 76 | h2fValid_out <= 1'b1; 77 | f2hReady_out <= 1'b1; 78 | end 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/pck_myhdl_08.vhd: -------------------------------------------------------------------------------- 1 | -- File: pck_myhdl_08.vhd 2 | -- Generated by MyHDL 0.8dev 3 | -- Date: Fri Jan 4 21:24:43 2013 4 | 5 | 6 | library ieee; 7 | use ieee.std_logic_1164.all; 8 | use ieee.numeric_std.all; 9 | 10 | package pck_myhdl_08 is 11 | 12 | attribute enum_encoding: string; 13 | 14 | function stdl (arg: boolean) return std_logic; 15 | 16 | function stdl (arg: integer) return std_logic; 17 | 18 | function to_unsigned (arg: boolean; size: natural) return unsigned; 19 | 20 | function to_signed (arg: boolean; size: natural) return signed; 21 | 22 | function to_integer(arg: boolean) return integer; 23 | 24 | function to_integer(arg: std_logic) return integer; 25 | 26 | function to_unsigned (arg: std_logic; size: natural) return unsigned; 27 | 28 | function to_signed (arg: std_logic; size: natural) return signed; 29 | 30 | function bool (arg: std_logic) return boolean; 31 | 32 | function bool (arg: unsigned) return boolean; 33 | 34 | function bool (arg: signed) return boolean; 35 | 36 | function bool (arg: integer) return boolean; 37 | 38 | function "-" (arg: unsigned) return signed; 39 | 40 | end pck_myhdl_08; 41 | 42 | 43 | package body pck_myhdl_08 is 44 | 45 | function stdl (arg: boolean) return std_logic is 46 | begin 47 | if arg then 48 | return '1'; 49 | else 50 | return '0'; 51 | end if; 52 | end function stdl; 53 | 54 | function stdl (arg: integer) return std_logic is 55 | begin 56 | if arg /= 0 then 57 | return '1'; 58 | else 59 | return '0'; 60 | end if; 61 | end function stdl; 62 | 63 | 64 | function to_unsigned (arg: boolean; size: natural) return unsigned is 65 | variable res: unsigned(size-1 downto 0) := (others => '0'); 66 | begin 67 | if arg then 68 | res(0):= '1'; 69 | end if; 70 | return res; 71 | end function to_unsigned; 72 | 73 | function to_signed (arg: boolean; size: natural) return signed is 74 | variable res: signed(size-1 downto 0) := (others => '0'); 75 | begin 76 | if arg then 77 | res(0) := '1'; 78 | end if; 79 | return res; 80 | end function to_signed; 81 | 82 | function to_integer(arg: boolean) return integer is 83 | begin 84 | if arg then 85 | return 1; 86 | else 87 | return 0; 88 | end if; 89 | end function to_integer; 90 | 91 | function to_integer(arg: std_logic) return integer is 92 | begin 93 | if arg = '1' then 94 | return 1; 95 | else 96 | return 0; 97 | end if; 98 | end function to_integer; 99 | 100 | function to_unsigned (arg: std_logic; size: natural) return unsigned is 101 | variable res: unsigned(size-1 downto 0) := (others => '0'); 102 | begin 103 | res(0):= arg; 104 | return res; 105 | end function to_unsigned; 106 | 107 | function to_signed (arg: std_logic; size: natural) return signed is 108 | variable res: signed(size-1 downto 0) := (others => '0'); 109 | begin 110 | res(0) := arg; 111 | return res; 112 | end function to_signed; 113 | 114 | function bool (arg: std_logic) return boolean is 115 | begin 116 | return arg = '1'; 117 | end function bool; 118 | 119 | function bool (arg: unsigned) return boolean is 120 | begin 121 | return arg /= 0; 122 | end function bool; 123 | 124 | function bool (arg: signed) return boolean is 125 | begin 126 | return arg /= 0; 127 | end function bool; 128 | 129 | function bool (arg: integer) return boolean is 130 | begin 131 | return arg /= 0; 132 | end function bool; 133 | 134 | function "-" (arg: unsigned) return signed is 135 | begin 136 | return - signed(resize(arg, arg'length+1)); 137 | end function "-"; 138 | 139 | end pck_myhdl_08; 140 | 141 | 142 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/tb_comm_fpga_fx2_m.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module tb_comm_fpga_fx2_m; 4 | 5 | reg clk_in; 6 | reg reset_in; 7 | wire fx2FifoSel_out; 8 | reg [7:0] fx2Data_in; 9 | wire [7:0] fx2Data_out; 10 | wire fx2Data_sel; 11 | wire fx2Read_out; 12 | reg fx2GotData_in; 13 | wire fx2Write_out; 14 | reg fx2GotRoom_in; 15 | wire fx2PktEnd_out; 16 | wire [6:0] chanAddr_out; 17 | wire [7:0] h2fData_out; 18 | wire h2fValid_out; 19 | reg h2fReady_in; 20 | reg [7:0] f2hData_in; 21 | reg f2hValid_in; 22 | wire f2hReady_out; 23 | 24 | initial begin 25 | $from_myhdl( 26 | clk_in, 27 | reset_in, 28 | fx2Data_in, 29 | fx2GotData_in, 30 | fx2GotRoom_in, 31 | h2fReady_in, 32 | f2hData_in, 33 | f2hValid_in 34 | ); 35 | $to_myhdl( 36 | fx2FifoSel_out, 37 | fx2Data_out, 38 | fx2Data_sel, 39 | fx2Read_out, 40 | fx2Write_out, 41 | fx2PktEnd_out, 42 | chanAddr_out, 43 | h2fData_out, 44 | h2fValid_out, 45 | f2hReady_out 46 | ); 47 | end 48 | 49 | initial begin 50 | $dumpfile("comm_fpga_fx2_m.vcd"); 51 | $dumpvars(0,tb_comm_fpga_fx2_m); 52 | end 53 | 54 | 55 | wire v1_reset_in = ~reset_in; 56 | comm_fpga_fx2_v1 57 | dut_v1( 58 | .clk_in(clk_in), 59 | .reset_in(v1_reset_in), 60 | .fx2FifoSel_out(fx2FifoSel_out), 61 | .fx2Data_in(fx2Data_in), 62 | .fx2Data_out(fx2Data_out), 63 | .fx2Data_sel(fx2Data_sel), 64 | .fx2Read_out(fx2Read_out), 65 | .fx2GotData_in(fx2GotData_in), 66 | .fx2Write_out(fx2Write_out), 67 | .fx2GotRoom_in(fx2GotRoom_in), 68 | .fx2PktEnd_out(fx2PktEnd_out), 69 | .chanAddr_out(chanAddr_out), 70 | .h2fData_out(h2fData_out), 71 | .h2fValid_out(h2fValid_out), 72 | .h2fReady_in(h2fReady_in), 73 | .f2hData_in(f2hData_in), 74 | .f2hValid_in(f2hValid_in), 75 | .f2hReady_out(f2hReady_out) 76 | ); 77 | 78 | // Add the MyHDL converted version 79 | /// @todo: add separate signals for tracing 80 | comm_fpga_fx2_v2 81 | dut_v2( 82 | .clk_in(clk_in), 83 | .reset_in(reset_in), 84 | //.fx2FifoSel_out(fx2FifoSel_out), 85 | .fx2Data_in(fx2Data_in), 86 | //.fx2Data_out(fx2Data_out), 87 | .fx2Data_sel(fx2Data_sel), 88 | //.fx2Read_out(fx2Read_out), 89 | .fx2GotData_in(fx2GotData_in), 90 | //.fx2Write_out(fx2Write_out), 91 | .fx2GotRoom_in(fx2GotRoom_in), 92 | //.fx2PktEnd_out(fx2PktEnd_out), 93 | .chanAddr_out(chanAddr_out), 94 | //.h2fData_out(h2fData_out), 95 | //.h2fValid_out(h2fValid_out), 96 | .h2fReady_in(h2fReady_in), 97 | .f2hData_in(f2hData_in), 98 | .f2hValid_in(f2hValid_in) 99 | //.f2hReady_out(f2hReady_out) 100 | ); 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/tb_comm_fpga_fx2_v1_stub.v: -------------------------------------------------------------------------------- 1 | module tb_comm_fpga_fx2_v1_stub; 2 | 3 | reg clk_in; 4 | reg reset_in; 5 | wire fx2FifoSel_out; 6 | reg [7:0] fx2Data_in; 7 | wire [7:0] fx2Data_out; 8 | wire fx2Data_sel; 9 | wire fx2Read_out; 10 | reg fx2GotData_in; 11 | wire fx2Write_out; 12 | reg fx2GotRoom_in; 13 | wire fx2PktEnd_out; 14 | wire [6:0] chanAddr_out; 15 | wire [7:0] h2fData_out; 16 | wire h2fValid_out; 17 | reg h2fReady_in; 18 | reg [7:0] f2hData_in; 19 | reg f2hValid_in; 20 | wire f2hReady_out; 21 | 22 | initial begin 23 | $from_myhdl( 24 | clk_in, 25 | reset_in, 26 | fx2Data_in, 27 | fx2GotData_in, 28 | fx2GotRoom_in, 29 | h2fReady_in, 30 | f2hData_in, 31 | f2hValid_in 32 | ); 33 | $to_myhdl( 34 | fx2FifoSel_out, 35 | fx2Data_out, 36 | fx2Data_sel, 37 | fx2Read_out, 38 | fx2Write_out, 39 | fx2PktEnd_out, 40 | chanAddr_out, 41 | h2fData_out, 42 | h2fValid_out, 43 | f2hReady_out 44 | ); 45 | end 46 | 47 | comm_fpga_fx2_v1_stub dut( 48 | clk_in, 49 | reset_in, 50 | fx2FifoSel_out, 51 | fx2Data_in, 52 | fx2Data_out, 53 | fx2Data_sel, 54 | fx2Read_out, 55 | fx2GotData_in, 56 | fx2Write_out, 57 | fx2GotRoom_in, 58 | fx2PktEnd_out, 59 | chanAddr_out, 60 | h2fData_out, 61 | h2fValid_out, 62 | h2fReady_in, 63 | f2hData_in, 64 | f2hValid_in, 65 | f2hReady_out 66 | ); 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /mn/cores/usbext/fpgalink/tb_comm_fpga_fx2_v2.v: -------------------------------------------------------------------------------- 1 | module tb_comm_fpga_fx2_v2; 2 | 3 | reg clk_in; 4 | reg reset_in; 5 | wire fx2FifoSel_out; 6 | reg [7:0] fx2Data_in; 7 | wire [7:0] fx2Data_out; 8 | wire fx2Data_sel; 9 | reg fx2Read_out; 10 | reg fx2GotData_in; 11 | reg fx2Write_out; 12 | reg fx2GotRoom_in; 13 | reg fx2PktEnd_out; 14 | reg [6:0] chanAddr_out; 15 | reg [7:0] h2fData_out; 16 | reg h2fValid_out; 17 | reg h2fReady_in; 18 | reg [7:0] f2hData_in; 19 | reg f2hValid_in; 20 | reg f2hReady_out; 21 | 22 | initial begin 23 | $from_myhdl( 24 | clk_in, 25 | reset_in, 26 | fx2Data_in, 27 | fx2Read_out, 28 | fx2GotData_in, 29 | fx2Write_out, 30 | fx2GotRoom_in, 31 | fx2PktEnd_out, 32 | chanAddr_out, 33 | h2fData_out, 34 | h2fValid_out, 35 | h2fReady_in, 36 | f2hData_in, 37 | f2hValid_in, 38 | f2hReady_out 39 | ); 40 | $to_myhdl( 41 | fx2FifoSel_out, 42 | fx2Data_out, 43 | fx2Data_sel 44 | ); 45 | end 46 | 47 | comm_fpga_fx2_v2 dut( 48 | clk_in, 49 | reset_in, 50 | fx2FifoSel_out, 51 | fx2Data_in, 52 | fx2Data_out, 53 | fx2Data_sel, 54 | fx2Read_out, 55 | fx2GotData_in, 56 | fx2Write_out, 57 | fx2GotRoom_in, 58 | fx2PktEnd_out, 59 | chanAddr_out, 60 | h2fData_out, 61 | h2fValid_out, 62 | h2fReady_in, 63 | f2hData_in, 64 | f2hValid_in, 65 | f2hReady_out 66 | ); 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /mn/cores/usbext/usbp/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from _usbp_wb import usbp_wb 4 | -------------------------------------------------------------------------------- /mn/cores/usbext/usbp/_wb_master_cmd.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2006-2013 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from myhdl import * 18 | 19 | S_BYTE0 = 0 20 | S_BYTE1 = 1 21 | S_CMD = 2 22 | S_ADDRH = 3 23 | S_ADDRL = 4 24 | S_LEN = 5 25 | S_BYTE6 = 6 26 | S_BYTE7 = 7 27 | S_WB_BUS = 8 28 | 29 | S_GET_BYTE0 = 0 30 | S_GET_BYTE1 = 1 31 | S_GET_CMD = 2 32 | S_GET_ADDRH = 3 33 | S_GET_ADDRL = 4 34 | S_GET_LEN = 5 35 | S_GET_BYTE6 = 6 36 | S_GET_BYTE7 = 7 37 | S_DO_WB_BUS = 8 38 | S_DO_WB_ACK = 9 39 | S_DO_WB_END = 10 40 | 41 | 42 | CMD_WRITE = 1 43 | CMD_READ = 2 44 | 45 | def wb_master_cmd( 46 | clk, 47 | reset, 48 | fifo_do, 49 | fifo_do_vld, 50 | fifo_empty, 51 | wb_go, 52 | wb_rd, 53 | wb_wr, 54 | wb_addr, 55 | wb_dat_o, 56 | wb_ack, 57 | wb_cmd_in_prog, 58 | to_ack 59 | ): 60 | """Wishbone command packet decoder 61 | 62 | """ 63 | 64 | wb_len = Signal(intbv(0)[8:]) 65 | wb_cnt = Signal(intbv(0)[8:]) 66 | wb_cmd = Signal(intbv(0)[8:]) 67 | 68 | wb_iaddr = Signal(intbv(0)[16:]) 69 | wb_idat = Signal(intbv(0)[8:]) 70 | 71 | 72 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | # Misc Registers 74 | addr_lo = Signal(intbv(0)[8:]) 75 | addr_hi = Signal(intbv(0)[8:]) 76 | 77 | to_cnt = Signal(intbv(0)[8:]) 78 | 79 | # @todo Re-Write this state-machine!!! Currently too cryptic, simply read 80 | # read command, bus cycle, etc. First implemenation tried to leverage 81 | # index counter and state, keep them separate. 82 | # Update: 83 | # The state-machine has been update but still can use some work. 84 | state = Signal(intbv(0)[4:]) 85 | @always(clk.posedge) 86 | def rtl_state_machine(): 87 | if reset: 88 | state.next = S_GET_BYTE0 89 | wb_len.next = 1 90 | wb_cnt.next = 0 91 | wb_idat.next = 0xCC 92 | addr_lo.next = 0xFF 93 | addr_hi.next = 0xFF 94 | wb_iaddr.next = 0xAAAA 95 | to_cnt.next = 0 96 | to_ack.next = False 97 | else: 98 | if state == S_GET_BYTE0: 99 | if fifo_do_vld: 100 | state.next = S_GET_BYTE1 101 | 102 | elif state == S_GET_BYTE1: 103 | if fifo_do_vld: 104 | state.next = S_GET_CMD 105 | 106 | elif state == S_GET_CMD: 107 | if fifo_do_vld: 108 | wb_cmd.next = fifo_do 109 | state.next = S_GET_ADDRH 110 | 111 | elif state == S_GET_ADDRH: 112 | if fifo_do_vld: 113 | addr_hi.next = fifo_do 114 | state.next = S_GET_ADDRL 115 | 116 | elif state == S_GET_ADDRL: 117 | if fifo_do_vld: 118 | addr_lo.next = fifo_do 119 | state.next = S_GET_LEN 120 | 121 | elif state == S_GET_LEN: 122 | if fifo_do_vld: 123 | # ?? don't need another register for wb_iaddr ?? 124 | wb_iaddr.next = concat(addr_hi, addr_lo) 125 | if fifo_do == 0: 126 | wb_len.next = 1 127 | else: 128 | wb_len.next = fifo_do 129 | 130 | state.next = S_GET_BYTE6 131 | 132 | elif state == S_GET_BYTE6: 133 | if fifo_do_vld: 134 | state.next = S_GET_BYTE7 135 | 136 | elif state == S_GET_BYTE7: 137 | if fifo_do_vld: 138 | state.next = S_DO_WB_BUS 139 | 140 | elif state == S_DO_WB_BUS: 141 | if wb_cnt < wb_len-1: 142 | wb_idat.next = fifo_do 143 | wb_cnt.next = wb_cnt + 1 144 | # @todo validate length vs. number of bytes! 145 | else: 146 | state.next = S_DO_WB_ACK 147 | to_cnt.next = 0 148 | 149 | elif state == S_DO_WB_ACK: 150 | if wb_ack: 151 | state.next = S_DO_WB_END 152 | else: 153 | if to_cnt > 16: 154 | to_ack.next = True 155 | state.next = S_DO_WB_END 156 | to_cnt.next = 0 157 | else: 158 | to_cnt.next = to_cnt + 1 159 | 160 | elif state == S_DO_WB_END: 161 | to_ack.next = False 162 | if not wb_ack: 163 | state.next = S_GET_BYTE0 164 | 165 | 166 | @always_comb 167 | def rtl_addr(): 168 | wb_addr.next = wb_iaddr + wb_cnt 169 | 170 | @always_comb 171 | def rtl_data(): 172 | # will fifo_do be hi fan out?? need to register?? then 173 | # write logic needs to change 174 | wb_dat_o.next = fifo_do #wb_idat 175 | 176 | 177 | @always_comb 178 | def rtl_go(): 179 | if state >= S_GET_BYTE7: 180 | wb_go.next = True 181 | else: 182 | wb_go.next = False 183 | 184 | @always_comb 185 | def rtl_control(): 186 | 187 | if wb_cmd == CMD_WRITE and state == S_DO_WB_BUS: 188 | wb_wr.next = True 189 | else: 190 | wb_wr.next = False 191 | 192 | if wb_cmd == CMD_READ and state == S_DO_WB_BUS: 193 | wb_rd.next = True 194 | else: 195 | wb_rd.next = False 196 | 197 | if state > S_GET_BYTE0: 198 | wb_cmd_in_prog.next = True 199 | else: 200 | wb_cmd_in_prog.next = False 201 | 202 | return instances() 203 | -------------------------------------------------------------------------------- /mn/cores/video/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # generic colorbar generator 3 | from _color_bars import m_color_bars 4 | 5 | # generic VGA core 6 | from vga._vga_intf import VGA 7 | from vga._vga_sync import m_vga_sync 8 | 9 | from _vidmem import VideoMemory 10 | 11 | from hdmi._hdmi import m_hdmi 12 | from hdmi._hdmi_intf import HDMI -------------------------------------------------------------------------------- /mn/cores/video/_color_bars.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | # color bar template 5 | COLOR_BARS = ( 6 | # r, g, b 7 | (1, 1, 1,), # white 8 | (1, 1, 0,), # yellow 9 | (0, 1, 1,), # cyan 10 | (0, 1, 0,), # green 11 | (1, 0, 1,), # magenta 12 | (1, 0, 0,), # red 13 | (0, 0, 1,), # blue 14 | (0, 0, 0,), # black 15 | ) 16 | 17 | 18 | def _update_cbars_with_max(P, width): 19 | global COLOR_BARS 20 | 21 | cbars = [list(clr) for clr in COLOR_BARS] 22 | cbarvals = [None for _ in range(len(cbars))] 23 | 24 | for cc in range(len(cbars)): 25 | for ii in range(3): 26 | if cbars[cc][ii] == 1: 27 | cbars[cc][ii] = P 28 | 29 | # create a single value out of pixel tuple 30 | val = (cbars[cc][0] << 2*width) + \ 31 | (cbars[cc][1] << width) + \ 32 | cbars[cc][2] 33 | 34 | cbarvals[cc] = val 35 | 36 | cbarvals = tuple(cbarvals) 37 | print("Color bar values:") 38 | for ii in range(len(cbarvals)): 39 | print(" {:3d}: {:08X}".format(ii, cbarvals[ii])) 40 | 41 | return cbarvals 42 | 43 | 44 | def m_color_bars(glbl, vmem, resolution=(640, 480), width=10): 45 | """ generate a color bar pattern 46 | """ 47 | global COLOR_BARS 48 | 49 | NUM_COLORS, PMAX, res = len(COLOR_BARS), (2**width)-1, resolution 50 | 51 | cbarvals = _update_cbars_with_max(PMAX, width) 52 | 53 | # the width of each boundary 54 | pw = res[0] / NUM_COLORS 55 | 56 | clock, reset = glbl.clock, glbl.reset 57 | pval = Signal(intbv(0)[3*width:]) 58 | # DEBUG 59 | ssel = Signal(intbv(0)[32:0]) 60 | 61 | @always_comb 62 | def rtl_pval(): 63 | sel = 0 64 | for ii in range(NUM_COLORS): 65 | if vmem.hpxl > (ii*pw): 66 | sel = ii 67 | ssel.next = sel 68 | pval.next = cbarvals[sel] 69 | 70 | W2, W, MASK = 2*width, width, PMAX 71 | 72 | @always_seq(clock.posedge, reset=reset) 73 | def rtl_rgb(): 74 | # unpack the RGB value 75 | vmem.red.next = (pval >> W2) & MASK 76 | vmem.green.next = (pval >> W) & MASK 77 | vmem.blue.next = pval & MASK 78 | 79 | return rtl_pval, rtl_rgb 80 | -------------------------------------------------------------------------------- /mn/cores/video/_vidmem.py: -------------------------------------------------------------------------------- 1 | 2 | import math 3 | from myhdl import * 4 | 5 | class VideoMemory: 6 | def __init__(self, size=128, res=(640,480,), width=10): 7 | aw = math.ceil(math.log(size,2)) 8 | width = width * 3 9 | # write port 10 | #self.wr = Signal(bool(0)) 11 | #self.wdat = Signal(intbv(0)[width:]) 12 | #self.wadr = Signal(intbv(0)[aw:]) 13 | 14 | self.wr = Signal(bool(0)) 15 | self.hpxl = Signal(intbv(0, min=0, max=res[0])) # column 16 | self.vpxl = Signal(intbv(0, min=0, max=res[1])) # row 17 | self.red = Signal(intbv(0)[width:]) 18 | self.green = Signal(intbv(0)[width:]) 19 | self.blue = Signal(intbv(0)[width:]) 20 | 21 | # the memory, if large, eternal required 22 | # @todo: check the size, if larger than?? 23 | #self.mem = [Signal(intbv(0)[width:]) for _ in range(size)] 24 | -------------------------------------------------------------------------------- /mn/cores/video/hdmi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/cores/video/hdmi/__init__.py -------------------------------------------------------------------------------- /mn/cores/video/hdmi/_hdmi.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from myhdl import * 4 | 5 | def m_hdmi(): 6 | pass -------------------------------------------------------------------------------- /mn/cores/video/hdmi/_hdmi_intf.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | class HDMI(object): 5 | def __init__(self): 6 | pass -------------------------------------------------------------------------------- /mn/cores/video/vga/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/cores/video/vga/__init__.py -------------------------------------------------------------------------------- /mn/cores/video/vga/_timing_params.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | SUMMERIED = False 6 | def calc_timings(frequency, resolution, 7 | refresh_rate=60, line_rate=31250): 8 | """ 9 | Arguments 10 | --------- 11 | frequency : the system clock rate, the clock rate the logic 12 | is running 13 | resolution : a two item tuple with the horizontal x veritical 14 | number of pixels 15 | refresh : the refresh rate (vertical rate) in Hz, default=60 16 | 17 | line_rate : the horizontal rate in Hz, default=31,250 18 | 19 | Definitions 20 | ----------- 21 | All of the following are in "counts" but the vendor 22 | specifications are usually in us and ms 23 | A : one full line, ticks 24 | B : horizontal sync, ticks 25 | C : horizontal back porch, ticks 26 | D : RGB pixel , ticks 27 | E : horizontal front porch, ticks 28 | 29 | O : one full screen, ticks 30 | P : vertical sync, ticks 31 | Q : vertical back portch, ticks 32 | R : all lines, ticks 33 | S : vertical front porch, ticks 34 | 35 | Fixed durations 36 | horizontal back porch : ~2us 37 | horizontal front porch : ~1us 38 | horizontal sync pulse : ~4us 39 | vertical sync pulse : ~64us 40 | vertical back porch : left overs 41 | vertical front porch : ~320-340us 42 | 43 | Note: because mfgs could specificy many different values for the 44 | porches (at least back in the day) it isn't that useful to 45 | try and match many different mfg standards. The porch 46 | determines where the pic is on the screen. Most monitors 47 | this can be adjusted on the monitory if the pic is not 48 | centered. The above fixed values for the porches worked 49 | on a set of hardware tested. 50 | """ 51 | global SUMMERIED 52 | 53 | res = resolution 54 | # generate the periods in microseconds 55 | period = 1/frequency 56 | hticks = (1/line_rate)/period 57 | vticks = (1/refresh_rate)/period 58 | 59 | # the line timing in counts of system clock 60 | B = round(4e-6/period) # horizontal pulse width 61 | C = round(2e-6/period) # the back porch time 62 | E = round(1e-6/period) # the front porch 63 | D = hticks - sum([B,C,E]) # hsync active (1) 64 | X = round(D/(res[0])) # pixel clock count 65 | A = sum([B,C,D,E]) # ticks for a complete line != line_rate 66 | 67 | P = round(64e-6/period) # vsync pulse width 68 | R = res[1] * (B+C+D+E) # all lines 69 | S = round(340e-6/period) # vertical front porch 70 | Q = vticks - (P + S + R) # vertical back porch 71 | O = sum([P, Q, R, S]) # full screen ~= refresh_rate 72 | # the pixel count (pixel clock) 73 | Z = res[0]*res[1] 74 | 75 | if not SUMMERIED: 76 | SUMMERIED = True 77 | print(" Video parameters in ticks") 78 | print(" period ........................ %.3f, %.e" % (frequency, 79 | period)) 80 | print(" hticks ........................ %.6f" % (hticks)) 81 | print(" vticks ........................ %.6f" % (vticks)) 82 | print(" A: full line: ................. %d, (%.2f Hz)" % (A, 83 | 1/(A*period))) 84 | print(" B: horizontal pulse width: .... %d" % (B)) 85 | print(" C: horizontal back porch:...... %d" % (C)) 86 | print(" D: horizontal active: ......... %d" % (D)) 87 | print(" E: horizontal front porch: .... %d" % (E)) 88 | 89 | print(" O: full screen ................ %d, (%.2f Hz)" % (O, 90 | 1/(O*period))) 91 | print(" P: vertical pulse width ....... %d" % (P)) 92 | print(" Q: vertical back porch ........ %d" % (Q)) 93 | print(" R: all lines .................. %d" % (R)) 94 | print(" S: vertical front porch ....... %d" % (S)) 95 | print(" X: pixel clock count .......... %.3f" % (X)) 96 | print(" Z: pixel count: ............... %d" % (Z)) 97 | 98 | # @todo: create files for the other languages. 99 | 100 | return map(int, (A,B,C,D,E,O,P,Q,R,S,X,Z,)) 101 | 102 | 103 | def get_timing_dict(frequency, resolution, 104 | refresh_rate=60, line_rate=31250): 105 | """ get the VGA timing parameters in a dictionary 106 | """ 107 | tv = calc_timings(frequency, resolution, 108 | refresh_rate, line_rate) 109 | 110 | tparams = {'A': tv[0], 111 | 'B': tv[1], 112 | 'C': tv[2], 113 | 'D': tv[2], 114 | 'E': tv[2], 115 | 'O': tv[2], 116 | 'P': tv[2], 117 | 'Q': tv[2], 118 | 'R': tv[2], 119 | 'S': tv[2], 120 | 'X': tv[2], 121 | 'Z': tv[2]} 122 | 123 | return tparams 124 | 125 | 126 | def dump_params(tv): 127 | pass -------------------------------------------------------------------------------- /mn/cores/video/vga/_vga_intf.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | class VGA: 5 | def __init__( 6 | self, 7 | hsync=None, vsync=None, 8 | red=None, green=None, blue=None, 9 | pxlen=None, active=None, 10 | color_depth=(10,10,10,) 11 | ): 12 | """ 13 | color_depth the number of bits per RGB 14 | """ 15 | self.N = color_depth 16 | 17 | # the sync signals 18 | self.hsync = Signal(bool(1)) if hsync is None else hsync 19 | self.vsync = Signal(bool(1)) if vsync is None else vsync 20 | # the RGB signals to the video 21 | cd = color_depth 22 | self.red = Signal(intbv(0)[cd[0]:]) if red is None else red 23 | self.green = Signal(intbv(0)[cd[1]:]) if green is None else green 24 | self.blue = Signal(intbv(0)[cd[2]:]) if blue is None else blue 25 | 26 | # logic VGA timing signals, used internally only 27 | self.pxlen = Signal(bool(0)) if pxlen is None else pxlen 28 | self.active = Signal(bool(0)) if active is None else active 29 | 30 | # these are used for verification. 31 | self.States = enum('NONE', 'ACTIVE', 32 | 'HOR_FRONT_PORCH', 'HSYNC', 'HOR_BACK_PORCH', 33 | 'VER_FRONT_PORCH', 'VSYNC', 'VER_BACK_PORCH') 34 | self.state = Signal(self.States.ACTIVE) 35 | 36 | 37 | -------------------------------------------------------------------------------- /mn/cores/video/vga/_vga_sync.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | from myhdl import * 6 | 7 | from _timing_params import calc_timings 8 | 9 | def m_vga_sync( 10 | # [ports and interfaces} 11 | glbl, # global bundle of signals, clock, reset 12 | vga, # signals for the VGA 13 | vmem, # the video memory interface 14 | 15 | # [parameters] 16 | resolution = (640, 480,), # resolution in pixels 17 | refresh_rate = 60, # refresh rate in Hz (vertical rate) 18 | line_rate = 31250 # line rate in Hz (horizontal rate) 19 | ): 20 | """ 21 | The following is the generation of the signals required 22 | to drive a VGA display. This implementation is derived 23 | from the pseudo code provide here: 24 | http://hamsterworks.co.nz/mediawiki/index.php/Module_11 25 | 26 | Well isn't that nice - the Python/MyHDL implementation is 27 | very close to the "pseudo code"! 28 | 29 | Also, this module is intended to be parameterizable and 30 | modular based on the desired video settings 31 | clock.frequency - the clock used to generate the pixel 32 | clock 33 | 34 | video_resolution - in pixels, tVGA resolution 35 | refresh_rate - in Hz, default 60 36 | line_rate - in Hz, default is 31,250 37 | 38 | Ports (arguments): 39 | ------------------ 40 | glbl.clock : system synchronous clock 41 | glbl.reset : system reset 42 | 43 | vga.hsync : horizontal sync 44 | vga.vsync : vertical sync 45 | vga.red : 46 | vga.green : 47 | vga.blue : 48 | 49 | vmem.addr : pixel address 50 | vmem.red : read pixel value 51 | vmem.green : 52 | vmem.blue : 53 | 54 | Parameters: 55 | ----------- 56 | resolution : video resolution 57 | refresh_rate : vertical rate in Hz 58 | line_rate : horizontal rate in Hz 59 | 60 | VGA Timing 61 | ---------- 62 | """ 63 | res = resolution 64 | clock = glbl.clock 65 | reset = glbl.reset 66 | 67 | # compute the limits (counter limits) for the vsync 68 | # and hsync timings. Review the calc_timing function 69 | # for definitions of A,B,C,D,E,O,P,Q,R,S, and Z 70 | (A,B,C,D,E,O, 71 | P,Q,R,S,X,Z,) = calc_timings(clock.frequency, resolution, 72 | refresh_rate, line_rate) 73 | FullScreen = O 74 | 75 | # counters to count the pixel clock (clock) 76 | HPXL, VPXL = res 77 | xcnt = intbv(0, min=-1, max=X+1) # clock div 78 | hcnt = intbv(0, min=0, max=A+1) # hor count in ticks 79 | vcnt = intbv(0, min=0, max=O+1) # ver count in ticks 80 | 81 | hpxl = vmem.hpxl 82 | vpxl = vmem.vpxl 83 | 84 | # debug stuff 85 | hcd = Signal(hcnt) 86 | vcd = Signal(vcnt) 87 | 88 | # the hsync and vsync are periodic so we can start anywhere, 89 | # it is convinient to start at the active pixel area 90 | @always_seq(clock.posedge, reset=reset) 91 | def rtl_sync(): 92 | # horizontal and vertical counters 93 | hcnt[:] = hcnt + 1 94 | vcnt[:] = vcnt + 1 95 | if vcnt == FullScreen: 96 | vcnt[:] = 0 97 | hcnt[:] = 0 98 | elif vcnt > R: 99 | hcnt[:] = A-1 100 | elif hcnt >= A: 101 | hcnt[:] = 0 102 | 103 | # clock divider for pixel enable 104 | xcnt[:] = xcnt + 1 105 | if hcnt == 1: 106 | xcnt[:] = 1 107 | elif xcnt == X: 108 | xcnt[:] = 0 109 | 110 | # tick counter to generate pixel enable 111 | if xcnt == 0 and hcnt <= D: 112 | vga.pxlen.next = True 113 | else: 114 | vga.pxlen.next = False 115 | 116 | # genrate the VGA strobes 117 | if hcnt >= (D+E) and hcnt < (D+E+B): 118 | vga.hsync.next = False 119 | else: 120 | vga.hsync.next = True 121 | 122 | if vcnt >= (R+S) and vcnt < (R+S+P): 123 | vga.vsync.next = False 124 | else: 125 | vga.vsync.next = True 126 | 127 | # current pixel x,y coordinates 128 | if hpxl < (HPXL-1) and xcnt == 0 and hcnt <= D: 129 | hpxl.next = hpxl + 1 130 | elif hcnt > (D+E): 131 | hpxl.next = 0 132 | 133 | if hcnt >= (A-1) and vcnt < (R-1): 134 | vpxl.next = vpxl + 1 135 | elif vcnt > (R+S): 136 | vpxl.next = 0 137 | 138 | # debug and verification 139 | hcd.next = hcnt 140 | vcd.next = vcnt 141 | # end debug stuff 142 | 143 | 144 | # logically define which VGA state currently in. This is 145 | # required for (simplified) verification but will be removed 146 | # by synthesis (outputs dangling) 147 | @always_comb 148 | def rtl_state(): 149 | if not vga.hsync: 150 | vga.state.next = vga.States.HSYNC 151 | elif not vga.vsync: 152 | vga.state.next = vga.States.VSYNC 153 | elif hcd < D: 154 | vga.state.next = vga.States.ACTIVE 155 | elif vcd >= R and vcd < (R+S): 156 | vga.state.next = vga.States.VER_FRONT_PORCH 157 | elif vcd >= (R+S) and vcd < (R+S+P): 158 | pass # should be handled by above 159 | elif vcd >= (R+S+P) and vcd < (FullScreen): 160 | vga.state.next = vga.States.VER_BACK_PORCH 161 | elif hcd >= D and hcd < (D+E): 162 | vga.state.next = vga.States.HOR_FRONT_PORCH 163 | elif hcd >= (D+E) and hcd < (D+E+B): 164 | pass # should be handled by above 165 | elif hcd >= (D+E+B) and hcd < (D+E+B+C): 166 | vga.state.next = vga.States.HOR_BACK_PORCH 167 | 168 | if hcd < D: 169 | vga.active.next = True 170 | else: 171 | vga.active.next = False 172 | 173 | 174 | #_state = Signal(intbv(0)[8:]) 175 | #@always_comb 176 | #def tmon(): 177 | # _state.next = int(vga.state._val._index) 178 | 179 | 180 | # map the video memory pixels to the VGA bus 181 | @always_comb 182 | def rtl_map(): 183 | vga.red.next = vmem.red 184 | vga.green.next = vmem.green 185 | vga.blue.next = vmem.blue 186 | 187 | 188 | return rtl_sync, rtl_state, rtl_map -------------------------------------------------------------------------------- /mn/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/models/__init__.py -------------------------------------------------------------------------------- /mn/models/spi/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _spi_eeprom import SPIEEPROM 3 | -------------------------------------------------------------------------------- /mn/models/spi/_spi_eeprom.py: -------------------------------------------------------------------------------- 1 | 2 | from random import randint 3 | 4 | from myhdl import * 5 | 6 | def _b(s): 7 | s = s.replace('_', '') 8 | s = s.replace('x', '0') 9 | return int(s,2) 10 | 11 | class SPIEEPROM(object): 12 | def __init__(self, addr_width=24, data_width=8, max_size=1024): 13 | 14 | if max_size > 0: 15 | size = max_size 16 | else: 17 | size = 2**addr_width 18 | 19 | self.size = size 20 | self.addr_width = addr_width 21 | self.data_width = data_width 22 | 23 | self.mem = [Signal(intbv(randint(0,255))[8:]) for _ in xrange(size)] 24 | # status register: WPEN, x,x,x,BP1,BP0,WEN,RDY 25 | self.status = Signal(intbv("0000_0000")) 26 | 27 | 28 | # eeprom instructions 29 | self.instr = {'WREN': _b("0000_x110"), # set write enable latch 30 | 'WRDI': _b("0000_x100"), # reset write enable latch 31 | 'RDSR': _b("0000_x101"), # read status register 32 | 'WRSR': _b("0000_x001"), # write status register 33 | 'READ': _b("0000_x011"), # read data from memory array 34 | 'WRITE': _b("0000_x010"), # write data to memory array 35 | } 36 | 37 | def get_init(self): 38 | return map(int,self.mem) 39 | 40 | def gen(self,clock,reset,spibus): 41 | """ 42 | this is modeled after the AT25 series SPI eeprom. 43 | """ 44 | 45 | # max number of bits to shift in 46 | bit_count = self.addr_width + self.data_width + 8 47 | shiftin = Signal(intbv(0)[bit_count:]) 48 | write_enable = Signal(False) 49 | write_protected = Signal(True) 50 | 51 | @instance 52 | def model(): 53 | dowr,dord = False,False 54 | while True: 55 | yield spibus.ss.negedge 56 | count,odata,rnw,dcyc = 0,0,True,False 57 | while count < bit_count: 58 | yield spibus.sck.posedge 59 | if spibus.ss: break 60 | 61 | # most-sig-bit first in time 62 | shiftin.next = concat(shiftin[23:0],spibus.mosi) 63 | count += 1 64 | 65 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 66 | # Instruction 67 | if count == 8: 68 | instr = concat(shiftin[7:0],spibus.mosi) 69 | 70 | # handle WREN, WRDI, RDSR, WRSR here 71 | if instr == self.instr['WREN']: 72 | write_enable.next = True 73 | elif instr == self.instr['WRDI']: 74 | write_enable.next = False 75 | elif instr == self.instr['RDSR']: 76 | odata = self.status 77 | dcyc = True 78 | elif instr == self.instr['WRSR']: 79 | dcyc = True 80 | elif instr == self.instr['READ']: 81 | rnw.next = True 82 | elif instr == self.instr['WRITE']: 83 | rnw.next = False 84 | else: 85 | assert False, "Invalid Instruction %04X"%(instr) 86 | 87 | if (instr != self.instr['WRITE'] and 88 | instr != self.instr['READ']): 89 | break 90 | 91 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 92 | # Address 93 | elif count == 24+8: 94 | addr = concat(shiftin[23:0],spibus.mosi) 95 | 96 | elif count == 24+8+8: 97 | if instr == self.instr['WRSR']: 98 | data = concat(shiftin[7:0],spibus.mosi) 99 | self.status.next = data 100 | break # break out of the transaction loop 101 | elif instr == self.instr['RDSR']: 102 | break # break out of the transaction loop 103 | 104 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 | # Data 106 | elif count == 24+8+8: 107 | data = concat(shiftin[7:0],spibus.mosi) 108 | if not rnw and write_enable and not write_protected: 109 | self.mem[addr].next = data 110 | else: 111 | odata = self.mem[addr] 112 | dcyc = True 113 | 114 | if dcyc: 115 | # msb first in time 116 | spibus.miso.next = (odata >> 8) & 0x01 117 | odata = odata << 1 118 | 119 | return model 120 | 121 | -------------------------------------------------------------------------------- /mn/models/usbext/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from fx2._fx2_model import Fx2Model 3 | from fx2._fpgalink_host import FpgaLinkHost 4 | -------------------------------------------------------------------------------- /mn/models/usbext/fx2/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _fx2_model import SlaveFifo -------------------------------------------------------------------------------- /mn/models/usbext/fx2/_fpgalink_host.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2013 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from array import array 18 | import struct 19 | import time 20 | 21 | from myhdl import now 22 | 23 | from _fx2_model import Fx2Model 24 | 25 | 26 | class FpgaLinkHost(Fx2Model): 27 | """ 28 | """ 29 | 30 | def __init__(self, Verbose=False, Trace=False): 31 | self.commOut = self.EP2 32 | self.commIn = self.EP6 33 | Fx2Model.__init__(self, FifoSize=1024, Config=1, 34 | Verbose=Verbose, Trace=Trace) 35 | 36 | def IsRunning(self): 37 | """ Is the FPGA running 38 | """ 39 | # @todo : complete 40 | return True 41 | 42 | def _wait_empty(self, ep, timeout=100): 43 | ok = False 44 | to = timeout * 1e6 45 | te = now() + to 46 | for ii in range(timeout): 47 | if self.IsEmpty(ep): 48 | ok = True 49 | break 50 | time.sleep(1) 51 | if now() > te: 52 | break 53 | return ok 54 | 55 | def _wait_data(self, ep, Num=1, timeout=100): 56 | ok = False 57 | to = timeout * 1e6 58 | te = now() + to 59 | for ii in range(timeout): 60 | if self.IsData(ep, Num=Num): 61 | ok = True 62 | break 63 | time.sleep(1) 64 | if now() > te: 65 | break 66 | return ok 67 | 68 | def ReadChannel(self, chan, count=1, timeout=100): 69 | """ Read one or more values from the specific channel 70 | Read /count/ bytes from the FPGA channel /chan/ to the data /array/, 71 | with the supplied /timeout/ in milleseconds. 72 | 73 | chan : The FPA channel to read 74 | count : The number of bytes to read 75 | timeout : The time to wait (in milliseconds) for the read to 76 | complete before giving up. 77 | 78 | This is a generator, it needs to be called: 79 | yield fl.ReadChannel(...) 80 | """ 81 | wbuf = [0 for ii in range(5)] 82 | # 0 : chan, 83 | # 1,2,3,4 (MSB in 4, LSB in 1) 84 | wbuf[0] = 0x80 | chan 85 | wbuf[1] = (count >> 24) & 0xFF 86 | wbuf[2] = (count >> 16) & 0xFF 87 | wbuf[3] = (count >> 8) & 0xFF 88 | wbuf[4] = (count >> 0) & 0xFF 89 | self.TracePrint(str(wbuf)) 90 | self.Write(wbuf, self.commOut) 91 | self._wait_empty(self.commOut, timeout=timeout) 92 | self._wait_data(self.commIn, Num=count, timeout=timeout) 93 | 94 | # write the command 95 | # read the number of bytes asked for 96 | return self.Read(self.commIn, Num=count) 97 | 98 | def WriteChannel(self, chan, values, timeout=100): 99 | """ Write one or more bytes to the specified channel 100 | Write /count/ bytes from the /data/ list/array to the FPGA 101 | channel /chan/, with the given /timeout/ in milleseconds. In 102 | the event of a timeout. 103 | """ 104 | assert isinstance(values, (list, tuple)) 105 | dlen = len(values) 106 | wbuf = [0 for ii in range(dlen+5)] 107 | wbuf[0] = chan & 0x7F 108 | wbuf[1] = (dlen >> 24) & 0xFF 109 | wbuf[2] = (dlen >> 16) & 0xFF 110 | wbuf[3] = (dlen >> 8) & 0xFF 111 | wbuf[4] = (dlen >> 0) & 0xFF 112 | wbuf[5:] = values 113 | print(wbuf) 114 | self.Write(wbuf, self.commOut) 115 | self._wait_empty(self.commOut) 116 | 117 | def AppendWriteChannelCommand(chan, count, data): 118 | """ Append a write command to the end of the write buffer 119 | """ 120 | raise NotImplementedError, "Not Implemented" 121 | 122 | def PlayWriteBuffer(chan, count, data): 123 | """ Play the write buffer into the FPGALink device immediately 124 | """ 125 | raise NotImplementedError, "Not Implemented" 126 | 127 | def CleanWriteBuffer(self): 128 | """ Clean the write buffer (if any) 129 | """ 130 | 131 | 132 | def test_simple(): 133 | # The Host interface can start the sim engine 134 | print('1') 135 | # get the host interface 136 | fl = FpgaLinkHost(Verbose=True, Trace=True) 137 | print('2') 138 | fl.setup(fl.GetFx2Bus()) # simulation setup 139 | print('3') 140 | fl.start() # start simulation 141 | print('4') 142 | 143 | print(' reset') 144 | fl.Reset() 145 | print(' write channel') 146 | fl.WriteChannel(1, [1,2,3,4]) 147 | #print(' read channel') 148 | #bb = fl.ReadChannel(1, 4) 149 | 150 | # stop the simulation 151 | fl.stop() 152 | 153 | if __name__ == '__main__': 154 | test_simple() 155 | -------------------------------------------------------------------------------- /mn/models/usbext/fx2/_usbp_host.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2013 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from _fx2_model import Fx2Model 18 | 19 | class UsbpHost(Fx2Model): 20 | """ 21 | """ 22 | 23 | def __init__(self): 24 | Fx2Model.__init__(self, FifoSize=512, Config=0) 25 | 26 | def WriteAddress(self, addr, data): 27 | wbuf = [0xDE, 0xCA, 0x01, 0x00, 0x00, 0x01, 0xFB, 0xAD, 0x00] 28 | rbuf = [0 for ii in range(9)] 29 | 30 | wbuf[3] = (addr >> 8) & 0xFF 31 | wbuf[4] = addr & 0xFF 32 | wbuf[5] = 1 33 | wbuf[8] = data 34 | 35 | self.Write(wbuf, self.EP2) 36 | while not self.IsEmpty(self.EP2): 37 | yield delay(2*self.IFCLK_TICK) 38 | while not self.IsData(self.EP6, 9): 39 | yield delay(2*self.IFCLK_TICK) 40 | 41 | for i in range(9): 42 | rbuf[i] = self.Read(self.EP6) 43 | 44 | # The last byte is the previous value of the register, it will not match 45 | for i in range(8): 46 | if wbuf[i] != rbuf[i]: 47 | print "wbuf ", wbuf 48 | print 'rbuf ', rbuf 49 | assert wbuf[i] == rbuf[i], "Write Address Failed wbuf[%d](%02x) != rbuf[%d](%02x)" % (i, wbuf[i], i, rbuf[i]) 50 | 51 | 52 | def ReadAddress(self, addr, data, w=1): 53 | 54 | plen = 8+w 55 | wbuf = [0]*plen 56 | rbuf = [0]*plen 57 | 58 | wbuf[0] = 0xDE 59 | wbuf[1] = 0xCA 60 | wbuf[2] = 0x02 61 | wbuf[3] = (addr >> 8) & 0xFF 62 | wbuf[4] = addr & 0xFF 63 | wbuf[5] = w 64 | wbuf[6] = 0xFB 65 | wbuf[7] = 0xAD 66 | 67 | self.Write(wbuf, self.EP2) 68 | while not self.IsEmpty(self.EP2): 69 | yield delay(2*self.IFCLK_TICK) 70 | 71 | while not self.IsData(self.EP6, plen): 72 | yield delay(2*self.IFCLK_TICK) 73 | 74 | for i in range(plen): 75 | rbuf[i] = self.Read(self.EP6) 76 | 77 | for i in range(8): 78 | if wbuf[i] != rbuf[i]: 79 | print '[%d] wbuf %s' % (i, wbuf) 80 | print '[%d] rbuf %s' % (i, rbuf) 81 | raise AssertionError, "Read Address Failed wbuf[%d](%02x) != rbuf[%d](%02x)" % (i, wbuf[i], i, rbuf[i]) 82 | 83 | if w == 1: 84 | data[0] = rbuf[8] 85 | elif w == 2: 86 | data[0] = (rbuf[8] << 8) | rbuf[9] 87 | elif w == 3: 88 | data[0] = (rbuf[8] << 16) | (rbuf[9] << 8) | rbuf[10] 89 | if w == 4: 90 | data[0] = (rbuf[9] << 24) | (rbuf[9] << 16) | (rbuf[10] << 8) | rbuf[11] 91 | print rbuf[8], rbuf[9], rbuf[10], rbuf[11] 92 | 93 | 94 | #--------------------------------------------------------------------------- 95 | def HostReadRequest(self, DataInRdy48, BufferSize=4096): 96 | """ Emulated Host request 97 | 98 | In an actual system the host will request N bytes from the USB system. 99 | This is a separate generate that will do a ReadBlock from. If a block is 100 | available it will copy it to the HostQueue. 101 | 102 | For simulation 103 | """ 104 | 105 | @always(DataInRdy48.posedge) 106 | def tm_host_request(): 107 | pass 108 | 109 | return intances() 110 | -------------------------------------------------------------------------------- /mn/models/video/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _video_display import VideoDisplay -------------------------------------------------------------------------------- /mn/system/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import absolute_import 3 | 4 | from mn.system._clock import Clock 5 | from mn.system._reset import Reset 6 | from mn.system._glbl import Global 7 | 8 | from mn.system.regfile._regfile import RegisterBits 9 | from mn.system.regfile._regfile import Register 10 | from mn.system.regfile._regfile import RegisterFile 11 | 12 | # different busses supported by the register file interface 13 | from mn.system.memmap._barebone import Barebone 14 | from mn.system.memmap._wishbone import Wishbone 15 | from mn.system.memmap._avalonmm import AvalonMM 16 | #from mn.system.memmap._axi4 import AXI4 17 | 18 | 19 | # various other busses 20 | from mn.system.fifobus._fifobus import FIFOBus 21 | -------------------------------------------------------------------------------- /mn/system/_clock.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | 4 | import myhdl 5 | from myhdl import instance, delay 6 | 7 | ClockList = [] 8 | 9 | class Clock(myhdl.SignalType): 10 | """ 11 | This is a clock object, it is a thin wrapper around the Signal 12 | object and provides needed attributes and clock generation for 13 | testbenches. 14 | 15 | @note: As of Jul-2014 this obj is duplicated in myhdl_tools 16 | """ 17 | 18 | def __init__(self, val, frequency=1, timescale='1ns'): 19 | self._frequency = frequency 20 | self._period = 1/frequency 21 | self._timescale = timescale 22 | self._set_hticks() 23 | myhdl.SignalType.__init__(self, bool(val)) 24 | ClockList.append(self) 25 | 26 | @property 27 | def timescale(self): 28 | return self._timescale 29 | @timescale.setter 30 | def timescale(self, t): 31 | self._timescale = t 32 | 33 | @property 34 | def frequency(self): 35 | return self._frequency 36 | @frequency.setter 37 | def frequency(self, f): 38 | self._frequency = f 39 | self._period = 1/f 40 | self._set_hticks() 41 | 42 | @property 43 | def period(self): 44 | return self._period 45 | 46 | def _set_hticks(self): 47 | #self._nts = self._convert_timescale(self._timescale) 48 | #self._hticks = int(round(self._period/self._nts)) 49 | self._hticks = 3 50 | 51 | def _convert_timescale(self, ts): 52 | # @todo: need to complete this, ts is in the form 53 | # "[0-9]*["ms","us","ns","ps"], parse the text 54 | # format and retrieve a numerical value 55 | # separate the numerical and text 56 | nts = 1e9 57 | return nts 58 | 59 | def gen(self, hticks=None): 60 | if hticks is None: 61 | hticks = self._hticks 62 | else: 63 | self._hticks = hticks 64 | 65 | #print('hticks %d'%(hticks)) 66 | @instance 67 | def gclock(): 68 | self.next = False 69 | while True: 70 | yield delay(hticks) 71 | self.next = not self.val 72 | 73 | return gclock 74 | -------------------------------------------------------------------------------- /mn/system/_glbl.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | from _clock import Clock 4 | from _reset import Reset 5 | 6 | class Global: 7 | """ global clock, reset, and control signals """ 8 | 9 | def __init__(self, clock=None, reset=None, frequency=1): 10 | if clock is None: 11 | self.clock = Clock(0, frequency=frequency) 12 | else: 13 | self.clock = clock 14 | 15 | if reset is None: 16 | self.reset = Reset(0, active=1, async=False) 17 | else: 18 | self.reset = reset 19 | 20 | self.enable = Signal(bool(0)) -------------------------------------------------------------------------------- /mn/system/_reset.py: -------------------------------------------------------------------------------- 1 | 2 | import myhdl 3 | from myhdl import instance, delay 4 | 5 | class Reset(myhdl.ResetSignal): 6 | def __init__(self, val, active, async): 7 | myhdl.ResetSignal.__init__(self,val,active,async) 8 | 9 | def pulse(self, delays=10): 10 | if isinstance(delays,(int,long)): 11 | self.next = self.active 12 | yield delay(delays) 13 | self.next = not self.active 14 | elif isinstance(delays,tuple): 15 | assert len(delays) in (1,2,3), "Incorrect number of delays" 16 | self.next = not self.active if len(delays)==3 else self.active 17 | for dd in delays: 18 | yield delay(dd) 19 | self.next = not self.val 20 | self.next = not self.active 21 | else: 22 | raise ValueError("%s type not supported"%(type(d))) 23 | -------------------------------------------------------------------------------- /mn/system/fifobus/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/system/fifobus/__init__.py -------------------------------------------------------------------------------- /mn/system/fifobus/_fifobus.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2013-2015 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from argparse import Namespace 18 | 19 | from myhdl import * 20 | 21 | from ...cores.fifo._fifo_async import m_fifo_async 22 | 23 | _fb_num = 0 24 | _fb_list = {} 25 | 26 | def _add_bus(fb, name=''): 27 | """ globally keep track of all the busses added. 28 | """ 29 | global _fb_num, _fb_list 30 | _fb_num += 1 31 | _fb_list[name] = fb 32 | 33 | class FIFOBus(object): 34 | """ 35 | """ 36 | def __init__(self, size=16, width=8): 37 | self.name = "fifobus{0}".format(_fb_num) 38 | 39 | # all the data signals are from the perspective 40 | # of the FIFO being interfaced to. 41 | self.clear = Signal(bool(0)) # fifo clear 42 | #self.wclk = None # write side clock 43 | self.wr = Signal(bool(0)) # write strobe to fifo 44 | self.wdata = Signal(intbv(0)[width:]) # fifo data in 45 | 46 | #self.rclk = None # read side clock 47 | self.rd = Signal(bool(0)) # fifo read strobe 48 | self.rdata = Signal(intbv(0)[width:]) # fifo data out 49 | self.rvld = Signal(bool(0)) 50 | self.empty = Signal(bool(1)) # fifo empty 51 | self.full = Signal(bool(0)) # fifo full 52 | self.count = Signal(intbv(0, min=0, max=size)) 53 | 54 | self.width = width 55 | self.size = size 56 | 57 | _add_bus(self, self.name) 58 | 59 | 60 | def m_fifo(self, reset, wclk, rclk): 61 | #self.wclk = wclk 62 | #self.rclk = rclk 63 | # map the FIFO interface to the actual fifo 64 | gfifo = m_fifo_async(reset, wclk, rclk, self) 65 | return gfifo 66 | 67 | # def get_upstream() 68 | # """ write bus, into the FIFO """ 69 | # def get_downstream() 70 | # """ -------------------------------------------------------------------------------- /mn/system/memmap/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/system/memmap/__init__.py -------------------------------------------------------------------------------- /mn/system/memmap/_axi4.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import absolute_import 3 | 4 | from myhdl import * 5 | 6 | from mn.system import Clock 7 | from mn.system import Reset 8 | from mn.system.memmap._memmap import MemMap 9 | 10 | class AXI4(MemMap): 11 | def __init__(self, glbl, data_width=8, address_width=16): 12 | 13 | # @todo: get clock and reset from global 14 | self.aclk = Clock(0) 15 | self.aresetn = Reset(0, active=0, async=False) 16 | 17 | self.awid = Signal(intbv(0)[4:0]) 18 | self.awvalid = Signal(bool(0)) 19 | 20 | super(AXI4, self).__init__(data_width=data_width, 21 | address_width=address_width) 22 | -------------------------------------------------------------------------------- /mn/system/memmap/_barebone.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import absolute_import 3 | 4 | from mn.system.memmap._memmap import MemMap 5 | 6 | class Barebone(MemMap): 7 | def __init__(self, data_width=8, address_width=16): 8 | self.wr = Signal(False) 9 | self.rd = Signal(False) 10 | self.ack = Signal(False) 11 | self.rdat = Signal(intbv(0)[data_width:]) 12 | self.wdat = Signal(intbv(0)[data_width:]) 13 | self.addr = Signal(intbv(0)[address_width:]) 14 | super(Barebone, self).__init__(data_width=data_width, 15 | address_width=address_width) 16 | 17 | -------------------------------------------------------------------------------- /mn/system/memmap/_bbus.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/mn/system/memmap/_bbus.py -------------------------------------------------------------------------------- /mn/system/memmap/_memmap.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import absolute_import 3 | from __future__ import print_function 4 | 5 | from copy import deepcopy 6 | from myhdl import * 7 | from ..regfile import Register 8 | 9 | # a count of the number of wishbone peripherals 10 | _mm_per = 0 11 | _mm_list = {} 12 | 13 | class MemMapController(object): 14 | def __init__(self, data_width=8, address_width=16): 15 | self.addr = Signal(intbv(0)[address_width:]) 16 | self.wdata = Signal(intbv(0)[data_width:]) 17 | self.rdata = Signal(intbv(0)[data_width:]) 18 | self.read = Signal(bool(0)) 19 | self.write = Signal(bool(0)) 20 | self.done = Signal(bool(0)) 21 | 22 | 23 | class MemMap(object): 24 | def __init__(self, data_width, address_width): 25 | self.data_width = data_width 26 | self.address_width = address_width 27 | self.names = {} 28 | self.regfiles = {} 29 | 30 | def _add_bus(self, name): 31 | """ globally keep track of all per bus 32 | """ 33 | global _mm_per, _mm_list 34 | nkey = "{:04d}".format(_mm_per) if name is None else name 35 | _mm_list[name] = self 36 | _mm_per += 1 37 | 38 | # @todo: make name and base_address attributes of regfile 39 | def add(self, glbl, regfile, name='', base_address=0): 40 | """ add a peripheral register-file to the bus 41 | """ 42 | # want a copy of the register-file so that the 43 | # address can be adjusted. 44 | arf = deepcopy(regfile) 45 | 46 | for k,v in arf.__dict__.iteritems(): 47 | if isinstance(v, Register): 48 | v.addr += base_address 49 | 50 | if self.regfiles.has_key(name): 51 | self.names[name] +=1 52 | name = name.upper() + "_{:03d}".format(self.names[name]) 53 | else: 54 | self.names = {name : 0} 55 | name = name.upper() + "_000" 56 | 57 | self.regfiles[name] = arf 58 | 59 | # @todo: return the peripheral generator 60 | g = self.m_per_interface(glbl, regfile, name, base_address) 61 | 62 | return g 63 | 64 | def m_per_interface(self, glbl, regfile, name, base_address=0): 65 | """ override 66 | :param glbl: global signals, clock and reset 67 | :param rf: register file interfacing to. 68 | :param name: name of this interface 69 | :param base_address: base address for this register file 70 | :return: 71 | """ 72 | pass 73 | 74 | def m_controller_basic(self, ctl): 75 | """ 76 | Bus controllers (masters) are typically custom and 77 | built into whatever the controller is (e.g a processor). 78 | This is a simple example with a simple interface to 79 | invoke bus cycles. 80 | 81 | :param ctl: 82 | :return: 83 | """ 84 | mm = self 85 | States = enum('Idle', 'Write', 'WriteAck', 'Read', 'ReadAck', 'Done') 86 | state = Signal(States.Idle) 87 | TOMAX = 33 88 | tocnt = Signal(intbv(0, min=0, max=TOMAX)) 89 | 90 | @always(mm.clock.posedge) 91 | def rtl_assign(): 92 | mm.address.next = ctl.addr 93 | mm.writedata.next = ctl.wdata 94 | 95 | @always_seq(wb.clock.posedge, reset=wb.reset) 96 | def rtl(): 97 | # ~~~[Idle]~~~ 98 | if state == States.Idle: 99 | if ctl.write: 100 | state.next = States.Write 101 | ctl.done.next = False 102 | elif ctl.read: 103 | state.next = States.Read 104 | ctl.done.next = False 105 | else: 106 | ctl.done.next = True 107 | 108 | # ~~~[Write]~~~ 109 | elif state == States.Write: 110 | if not wb.ack_o: 111 | wb.we_i.next = True 112 | wb.cyc_i.next = True 113 | wb.stb_i.next = True 114 | state.next = States.WriteAck 115 | tocnt.next = 0 116 | 117 | # ~~~[WriteAck]~~~ 118 | elif state == States.WriteAck: 119 | if wb.ack_o: 120 | wb.we_i.next = False 121 | wb.cyc_i.next = False 122 | wb.stb_i.next = False 123 | state.next = States.Done 124 | 125 | # ~~~[Done]~~~ 126 | elif state == States.Done: 127 | ctl.done.next = True 128 | if not (ctl.write or ctl.read): 129 | state.next = States.Idle 130 | 131 | else: 132 | assert False, "Invalid state %s" % (state,) 133 | 134 | return rtl_assign, rtl 135 | -------------------------------------------------------------------------------- /mn/system/regfile/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _regfile import Register 3 | from _regfile import RegisterFile -------------------------------------------------------------------------------- /mn/utils/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _extract import extract_freq -------------------------------------------------------------------------------- /mn/utils/_extract.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def extract_freq(clock, f=1): 4 | if hasattr(clock, 'frequency'): 5 | freq = clock.frequency 6 | else: 7 | freq = f 8 | return freq -------------------------------------------------------------------------------- /mn/utils/test/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from _test_utils import * -------------------------------------------------------------------------------- /mn/utils/test/_test_utils.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import shutil 4 | from glob import glob 5 | import argparse 6 | 7 | def tb_argparser(): 8 | """ common command line arguments 9 | """ 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument('--trace',action='store_true') 12 | parser.add_argument('--test',action='store_true') 13 | parser.add_argument('--convert', action='store_true') 14 | return parser 15 | 16 | def tb_move_v(): 17 | for vf in glob('*.vhd'): 18 | if os.path.isfile(os.path.join('vhd/',vf)): 19 | os.remove(os.path.join('vhd/',vf)) 20 | shutil.move(vf, 'vhd/') 21 | 22 | for vf in glob('*.v'): 23 | if os.path.isfile(os.path.join('ver/',vf)): 24 | os.remove(os.path.join('ver/',vf)) 25 | shutil.move(vf, 'ver/') 26 | 27 | def tb_clean_vcd(name): 28 | if not os.path.isdir('vcd'): 29 | os.mkdir('vcd') 30 | 31 | for vv in glob('vcd/*.vcd.*'): 32 | os.remove(vv) 33 | 34 | nmpth = 'vcd/{}.vcd'.format(name) 35 | if os.path.isfile(nmpth): 36 | os.remove(nmpth) 37 | 38 | # return the VCD path+name minus extension 39 | return nmpth[:-4] 40 | 41 | -------------------------------------------------------------------------------- /scripts/ci/install_myhdl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | git clone https://github.com/jandecaluwe/myhdl 3 | cd myhdl 4 | #git checkout 88cb76b 5 | python setup.py install 6 | make -C cosimulation/icarus 7 | # copy the VPI to the test directory 8 | cp cosimulation/icarus/myhdl.vpi ../test/test_cosim 9 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2013 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | try: 18 | from setuptools import setup 19 | from setuptools import find_packages 20 | except ImportError: 21 | from distutils.core import setup 22 | from pkgutil import walk_packages 23 | 24 | import mn 25 | 26 | # many pypy installs don't have setuptools (?) 27 | def _find_packages(path='.', prefix=''): 28 | yield prefix 29 | prefix = prefix + "." 30 | for _, name, ispkg in walk_packages(path, 31 | prefix, 32 | onerror=lambda x: x): 33 | if ispkg: 34 | yield name 35 | 36 | def find_packages(): 37 | return list(_find_packages(mn.__path__, mn.__name__)) 38 | 39 | 40 | setup(name = "minnesota", 41 | version = "0.1pre", 42 | description = "collection of HDL cores ", 43 | license = "LGPL", 44 | platforms = ["Any"], 45 | keywords = "DSP HDL MyHDL FPGA FX2 USB", 46 | 47 | packages = find_packages(), 48 | # @todo need to add the examples and test directories, 49 | # copy it over ... 50 | ) 51 | 52 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/README.md -------------------------------------------------------------------------------- /test/test_cores/test_eth/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/test_cores/test_eth/README.md -------------------------------------------------------------------------------- /test/test_cores/test_eth/test_gemac_lite.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/test_cores/test_eth/test_gemac_lite.py -------------------------------------------------------------------------------- /test/test_cores/test_fifo/test_ffifo.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014 Christopher L. Felton 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a 5 | # copy of this software and associated documentation files (the "Software"), 6 | # to deal in the Software without restriction, including without limitation 7 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | # and/or sell copies of the Software, and to permit persons to whom the 9 | # Software is furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | 23 | from __future__ import division 24 | from __future__ import print_function 25 | 26 | import os 27 | from argparse import Namespace 28 | 29 | from myhdl import * 30 | 31 | from mn.system import FIFOBus 32 | from mn.cores.fifo import m_fifo_fast 33 | 34 | from mn.utils.test import * 35 | 36 | def test_ffifo(args=None): 37 | """ verify the synchronous FIFO 38 | """ 39 | 40 | if args is None: 41 | args = Namespace(width=8, size=16, name='test') 42 | else: 43 | # @todo: verify args has the attributes needed for the FIFOBus 44 | pass 45 | 46 | reset = ResetSignal(0, active=1, async=True) 47 | clock = Signal(bool(0)) 48 | fbus = FIFOBus(width=args.width, size=args.size) 49 | 50 | def _test(): 51 | 52 | # @todo: use args.fast, args.use_srl_prim 53 | tbdut = m_fifo_fast(clock, reset, fbus, use_srl_prim=False) 54 | 55 | @always(delay(10)) 56 | def tbclk(): 57 | clock.next = not clock 58 | 59 | @instance 60 | def tbstim(): 61 | fbus.wdata.next = 0xFE 62 | reset.next = reset.active 63 | yield delay(33) 64 | reset.next = not reset.active 65 | for ii in range(5): 66 | yield clock.posedge 67 | 68 | # test the normal cases 69 | for num_bytes in range(1, args.size+1): 70 | 71 | # write some bytes 72 | for ii in range(num_bytes): 73 | #print('nbyte %x wdata %x' % (num_bytes, ii)) 74 | yield clock.posedge 75 | fbus.wdata.next = ii 76 | fbus.wr.next = True 77 | 78 | yield clock.posedge 79 | fbus.wr.next = False 80 | fbus.wdata.next = 0xFE 81 | 82 | # if 16 bytes written make sure FIFO is full 83 | yield clock.posedge 84 | if num_bytes == args.size: 85 | assert fbus.full, "FIFO should be full!" 86 | assert not fbus.empty, "FIFO should not be empty" 87 | 88 | for ii in range(num_bytes): 89 | fbus.rd.next = True 90 | yield clock.posedge 91 | #print("rdata %x ii %x " % (fbus.rdata, ii)) 92 | assert fbus.rvld 93 | assert fbus.rdata == ii, "rdata %x ii %x " % (fbus.rdata, ii) 94 | 95 | fbus.rd.next = False 96 | yield clock.posedge 97 | assert fbus.empty 98 | 99 | # Test overflows 100 | # Test underflows 101 | # Test write / read same time 102 | 103 | raise StopSimulation 104 | 105 | 106 | return tbdut, tbclk, tbstim 107 | 108 | tb_clean_vcd('test_fifo_fast_%d' % (args.size)) 109 | g = traceSignals(_test) 110 | Simulation(g).run() 111 | 112 | if __name__ == '__main__': 113 | for size in (4,8,16): 114 | args = Namespace(width=8, size=size, name='test') 115 | test_ffifo(args=args) 116 | -------------------------------------------------------------------------------- /test/test_cores/test_fifo/test_fifo_ramp.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2006-2013 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from __future__ import division 18 | from __future__ import print_function 19 | 20 | from myhdl import * 21 | 22 | from mn.cores.fifo import m_fifo_ramp 23 | 24 | from mn.system import Clock 25 | from mn.system import Reset 26 | from mn.system import Global 27 | from mn.system import Wishbone 28 | from mn.system import FIFOBus 29 | 30 | # @todo: move utils to mn.utils, most of these functions 31 | # will be used by the *examples*. Or move these 32 | # to myhdl_tools 33 | from mn.utils.test import * 34 | 35 | 36 | def test_fifo_ramp(): 37 | 38 | clock = Clock(0, frequency=50e6) 39 | reset = Reset(0, active=1, async=False) 40 | glbl = Global(clock, reset) 41 | regbus = Wishbone(glbl) 42 | fifobus = FIFOBus() 43 | 44 | def _test_fifo_ramp(): 45 | tb_dut = m_fifo_ramp(clock, reset, regbus, fifobus, 46 | base_address=0x0000) 47 | tb_rbor = regbus.m_per_outputs() 48 | tb_clk = clock.gen() 49 | 50 | asserr = Signal(bool(0)) 51 | 52 | @instance 53 | def tb_stim(): 54 | try: 55 | yield delay(100) 56 | yield reset.pulse(111) 57 | 58 | # simply enable, enable the module and then 59 | # verify an incrementing pattern over the 60 | # fifobus 61 | yield regbus.write(0x00, 1) 62 | yield regbus.read(0x00) 63 | assert 1 == regbus.readval, "cfg reg write failed" 64 | 65 | # monitor the bus until ?? ramps 66 | Nramps, rr = 128, 0 67 | while rr < Nramps: 68 | cnt = 0 69 | for ii, sh in enumerate((24, 16, 8, 0,)): 70 | yield regbus.read(0x08+ii) 71 | cnt = cnt | (regbus.readval << sh) 72 | rr = cnt 73 | 74 | except AssertionError, err: 75 | asserr.next = True 76 | for _ in xrange(10): 77 | yield clock.posedge 78 | raise err 79 | 80 | raise StopSimulation 81 | 82 | # monitor the values from the fifo bus, it should 83 | # be a simple "ramp" increasing values 84 | _mask = 0xFF 85 | _cval = Signal(modbv(0, min=0, max=256)) 86 | @always(clock.posedge) 87 | def tb_mon(): 88 | if fifobus.wr: 89 | assert _cval == fifobus.wdata 90 | _cval.next = _cval+1 91 | 92 | return tb_clk, tb_dut, tb_stim, tb_mon, tb_rbor 93 | 94 | tb_clean_vcd('_test_fifo_ramp') 95 | g = traceSignals(_test_fifo_ramp) 96 | Simulation(g).run() 97 | 98 | 99 | if __name__ == '__main__': 100 | test_fifo_ramp() 101 | -------------------------------------------------------------------------------- /test/test_cores/test_fifo/test_sfifo.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014 Christopher L. Felton 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a 5 | # copy of this software and associated documentation files (the "Software"), 6 | # to deal in the Software without restriction, including without limitation 7 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | # and/or sell copies of the Software, and to permit persons to whom the 9 | # Software is furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | 23 | from __future__ import division 24 | from __future__ import print_function 25 | 26 | import os 27 | from argparse import Namespace 28 | 29 | from myhdl import * 30 | 31 | from mn.system import FIFOBus 32 | from mn.cores.fifo import m_fifo_sync 33 | from mn.utils.test import * 34 | 35 | def test_sfifo(args=None): 36 | """ verify the synchronous FIFO 37 | """ 38 | 39 | if args is None: 40 | args = Namespace(width=8, size=16, name='test') 41 | else: 42 | # @todo: verify args has the attributes needed for the FIFOBus 43 | pass 44 | 45 | reset = ResetSignal(0, active=1, async=True) 46 | clock = Signal(bool(0)) 47 | fbus = FIFOBus(width=args.width, size=args.size) 48 | 49 | def _test(): 50 | 51 | # @todo: use args.fast, args.use_srl_prim 52 | tbdut = m_fifo_sync(clock, reset, fbus) 53 | 54 | @always(delay(10)) 55 | def tbclk(): 56 | clock.next = not clock 57 | 58 | @instance 59 | def tbstim(): 60 | fbus.wdata.next = 0xFE 61 | reset.next = reset.active 62 | yield delay(33) 63 | reset.next = not reset.active 64 | for ii in range(5): 65 | yield clock.posedge 66 | 67 | # test the normal cases 68 | for num_bytes in range(1, args.size+1): 69 | 70 | # write some bytes 71 | for ii in range(num_bytes): 72 | #print('nbyte %x wdata %x' % (num_bytes, ii)) 73 | yield clock.posedge 74 | fbus.wdata.next = ii 75 | fbus.wr.next = True 76 | 77 | yield clock.posedge 78 | fbus.wr.next = False 79 | fbus.wdata.next = 0xFE 80 | 81 | # if 16 bytes written make sure FIFO is full 82 | yield clock.posedge 83 | if num_bytes == args.size: 84 | assert fbus.full, "FIFO should be full!" 85 | assert not fbus.empty, "FIFO should not be empty" 86 | 87 | fbus.rd.next = True 88 | yield clock.posedge 89 | for ii in range(num_bytes): 90 | yield clock.posedge 91 | fbus.rd.next = True 92 | #print("rdata %x ii %x " % (fbus.rdata, ii)) 93 | assert fbus.rvld 94 | assert fbus.rdata == ii, "rdata %x ii %x " % (fbus.rdata, ii) 95 | 96 | fbus.rd.next = False 97 | yield clock.posedge 98 | assert fbus.empty 99 | 100 | # Test overflows 101 | # Test underflows 102 | # Test write / read same time 103 | 104 | raise StopSimulation 105 | 106 | 107 | return tbdut, tbclk, tbstim 108 | 109 | 110 | tb_clean_vcd('test_fifo_sync_%d' % (args.size)) 111 | g = traceSignals(_test) 112 | Simulation(g).run() 113 | 114 | if __name__ == '__main__': 115 | for size in (16, 64, 256): 116 | args = Namespace(width=8, size=size, name='test') 117 | test_sfifo(args=args) 118 | -------------------------------------------------------------------------------- /test/test_cores/test_hdmi/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/test_cores/test_hdmi/README.md -------------------------------------------------------------------------------- /test/test_cores/test_hdmi/test_hdmi.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | """ 6 | """ 7 | 8 | import sys 9 | import os 10 | import argparse 11 | from argparse import Namespace 12 | from array import array 13 | 14 | from myhdl import * 15 | 16 | import mn 17 | from mn.system import Global 18 | from mn.cores.video import HDMI 19 | from mn.cores.video import m_hdmi 20 | 21 | # a video desplay model to check the timings 22 | from mn.models.video import VideoDisplay 23 | from mn.utils.test import tb_clean_vcd 24 | 25 | # @todo move cosimulation to cosimulation directory 26 | #from _hdmi_prep_cosim import prep_cosim 27 | #from interfaces import HDMI 28 | 29 | 30 | def test_hdmi(): 31 | """ simple test to demonstrate test framework 32 | """ 33 | 34 | clock = Signal(bool(0)) 35 | reset = ResetSignal(0, active=0, async=True) 36 | 37 | # this currently tests a Verilog version 38 | #tbdut = prep_cosim(clock, reset, args=args) 39 | tbdut = m_hdmi() 40 | 41 | def _test(): 42 | 43 | #tbdut = mm_hdmisys(glbl, vselect, hdmi, 44 | # resolution=res, 45 | # line_rate=line_rate) 46 | 47 | # clock for the design 48 | @always(delay(5)) 49 | def tbclk(): 50 | clock.next = not clock 51 | 52 | @instance 53 | def tbstim(): 54 | yield delay(13) 55 | reset.next = reset.active 56 | yield delay(33) 57 | reset.next = not reset.active 58 | yield clock.posedge 59 | 60 | try: 61 | for ii in range(100): 62 | yield delay(100) 63 | 64 | except AssertionError, err: 65 | print("@E: assertion error @ %d ns" % (now(),)) 66 | print(" %s" % (str(err),)) 67 | # additional simulation cycles after the error 68 | yield delay(111) 69 | raise err 70 | 71 | except Exception, err: 72 | print("@E: error occurred") 73 | print(" %s" % (str(err),)) 74 | raise err 75 | 76 | raise StopSimulation 77 | 78 | return tbclk, tbstim 79 | 80 | # run the above test 81 | vcd = tb_clean_vcd('_test') 82 | traceSignals.timescale = '1ns' 83 | traceSignals.name = vcd 84 | #Simulation((traceSignals(_test), tbdut,)).run() 85 | 86 | 87 | -------------------------------------------------------------------------------- /test/test_cores/test_sdram/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a template for the SDRAM controller 3 | test-framework. -------------------------------------------------------------------------------- /test/test_cores/test_sdram/test_sdram.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import sys 6 | import os 7 | import argparse 8 | from argparse import Namespace 9 | from array import array 10 | 11 | import pytest 12 | 13 | from myhdl import * 14 | 15 | # resuse some of the interfaces 16 | import mn 17 | from mn.system import Clock 18 | from mn.system import Reset 19 | from mn.system import Global 20 | from mn.system import Wishbone 21 | 22 | from mn.cores.sdram import SDRAM 23 | from mn.cores.sdram import m_sdram 24 | #from mn.models.sdram import SDRAMModel 25 | 26 | 27 | @pytest.mark.xfail 28 | def test_sdram(args): 29 | 30 | clock = Clock(0, frequency=50e6) 31 | reset = Reset(0, active=0, async=False) 32 | 33 | 34 | def _test(): 35 | ibus = Wishbone() 36 | extmem = SDRAM(clock) 37 | print(vars(extmem)) 38 | tbdut = m_sdram(clock, reset, ibus, extmem) 39 | glbl = Global(clock=clock, reset=reset) 40 | tbclk = clock.gen() 41 | 42 | @instance 43 | def tbstim(): 44 | reset.next = reset.active 45 | yield delay(18) 46 | reset.next = not reset.active 47 | 48 | for ii in range(100): 49 | yield delay(1000) 50 | 51 | raise StopSimulation 52 | 53 | return tbclk, tbdut, tbstim 54 | 55 | if os.path.isfile('vcd/_test.vcd'): 56 | os.remove('vcd/_test.vcd') 57 | 58 | traceSignals.timescale = '1ns' 59 | traceSignals.name = 'vcd/_test' 60 | Simulation(traceSignals(_test)).run() 61 | #convert() 62 | 63 | if __name__ == '__main__': 64 | test_sdram(Namespace()) 65 | -------------------------------------------------------------------------------- /test/test_cores/test_serio.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | from mn.system import Clock,Reset 5 | from mn.cores.misc import m_serio 6 | from mn.utils.test import * 7 | 8 | def test(): 9 | clock = Clock(0) 10 | reset = Reset(0, active=0, async=False) 11 | sdi,sdo = [Signal(bool(0)) for _ in range(2)] 12 | pin = [Signal(intbv(0)[16:]) for _ in range(7)] 13 | pout = [Signal(intbv(0)[16:]) for _ in range(3)] 14 | 15 | def _test(): 16 | tbclk = clock.gen() 17 | tbdut = m_serio(clock, reset, sdi, sdo, pin, pout) 18 | 19 | @instance 20 | def tbstim(): 21 | yield reset.pulse(13) 22 | yield clock.posedge 23 | 24 | # @todo: actually test something 25 | for ii in range(1000): 26 | yield clock.posedge 27 | 28 | raise StopSimulation 29 | 30 | return tbdut, tbclk, tbstim 31 | 32 | Simulation(traceSignals(_test)).run() 33 | -------------------------------------------------------------------------------- /test/test_cores/test_spi.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2013-2015 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from pprint import pprint 19 | import pytest 20 | 21 | from myhdl import * 22 | 23 | from mn.cores.spi import m_spi 24 | from mn.cores.spi import SPIBus 25 | 26 | from mn.models.spi import SPIEEPROM 27 | 28 | from mn.system import Clock 29 | from mn.system import Reset 30 | from mn.system import Global 31 | from mn.system import Wishbone 32 | from mn.system import FIFOBus 33 | from mn.system.regfile import Register 34 | 35 | from mn.utils.test import * 36 | 37 | def m_test_top(clock, reset, sck, mosi, miso, ss): 38 | # @todo: create a top-level for conversion ... 39 | g_spi = m_spi() 40 | return g_spi 41 | 42 | 43 | def convert(to='ver'): 44 | clock = Clock(0, frequency=50e6) 45 | reset = Reset(0, active=1, async=False) 46 | sck = Signal(bool(0)) 47 | mosi = Signal(bool(0)) 48 | miso = Signal(bool(0)) 49 | ss = Signal(bool(0)) 50 | 51 | toVerilog(m_test_top, clock, reset, sck, mosi, miso, ss) 52 | toVHDL(m_test_top, clock, reset, sck, mosi, miso, ss) 53 | 54 | 55 | @pytest.mark.xfail 56 | def test_spi(): 57 | 58 | base_address = ba = 0x400 59 | clock = Clock(0, frequency=50e6) 60 | reset = Reset(0, active=1, async=False) 61 | glbl = Global(clock, reset) 62 | regbus = Wishbone(glbl) 63 | fiforx,fifotx = FIFOBus(size=16), FIFOBus(size=16) 64 | spiee = SPIEEPROM() 65 | spibus = SPIBus() 66 | asserr = Signal(bool(0)) 67 | 68 | def _test_spi(): 69 | tbdut = m_spi(glbl, regbus, 70 | fiforx, fifotx, spibus, 71 | base_address=base_address) 72 | tbeep = spiee.gen(clock, reset, spibus) 73 | tbclk = clock.gen(hticks=5) 74 | # grab all the register file outputs 75 | tbmap = regbus.m_per_outputs() 76 | 77 | # get a reference to the SPI register file 78 | rf = regbus.regfiles['SPI_000'] 79 | # dumpy the registers for the SPI peripheral 80 | for name,reg in rf.registers.iteritems(): 81 | print("{0} {1:04X} {2:04X}".format(name, reg.addr, int(reg))) 82 | 83 | @instance 84 | def tbstim(): 85 | yield reset.pulse(33) 86 | 87 | try: 88 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 89 | # loop through the registers and check the default 90 | # values, these are the offset values. 91 | for addr,sig in rf.roregs: 92 | yield regbus.read(addr+ba) 93 | assert regbus.readval == int(sig) 94 | 95 | for addr,sig in rf.rwregs: 96 | # need to skip the FIFO read / write 97 | if addr in (0x68, 0x6C,): 98 | pass 99 | else: 100 | yield regbus.read(addr+ba) 101 | assert regbus.readval == int(sig) 102 | 103 | 104 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 | # enable the system 106 | print(" enable the SPI core") 107 | yield regbus.write(rf.spst.addr, 0x02) # register data drives fifo 108 | yield regbus.write(rf.spcr.addr, 0x9A) # default plus enable (98 + 02) 109 | 110 | print(" write to the transmit register") 111 | yield regbus.write(rf.sptx.addr, 0x02) 112 | yield regbus.write(rf.sptx.addr, 0x00) 113 | yield regbus.write(rf.sptx.addr, 0x00) 114 | yield regbus.write(rf.sptx.addr, 0x00) 115 | yield regbus.write(rf.sptx.addr, 0x55) 116 | 117 | yield regbus.read(rf.sptc.addr) 118 | print(regbus.readval) 119 | 120 | yield regbus.read(rf.sprc.addr) 121 | print(regbus.readval) 122 | 123 | yield delay(1000) 124 | 125 | for ii in range(1000): 126 | yield regbus.read(rf.sprc.addr) 127 | if regbus.readval == 5: 128 | break 129 | yield delay(1000) 130 | 131 | for ii in range(5): 132 | yield regbus.read(rf.sprx.addr) 133 | print("spi readback {0}".format(regbus.readval)) 134 | 135 | 136 | except Exception, err: 137 | print("@W: exception {0}".format(err)) 138 | yield delay(100) 139 | raise err 140 | 141 | yield delay(100) 142 | raise StopSimulation 143 | 144 | return tbstim, tbdut, tbeep, tbclk, tbmap 145 | 146 | tb_clean_vcd('_test_spi') 147 | Simulation(traceSignals(_test_spi)).run() 148 | 149 | 150 | if __name__ == '__main__': 151 | test_spi() 152 | #convert() 153 | -------------------------------------------------------------------------------- /test/test_cores/test_vga/mm_vgasys.py: -------------------------------------------------------------------------------- 1 | 2 | from myhdl import * 3 | 4 | import mn 5 | from mn.system import Clock 6 | from mn.system import Reset 7 | from mn.system import Global 8 | from mn.cores.video import VGA 9 | from mn.cores.video import VideoMemory 10 | 11 | from mn.cores.video import m_vga_sync 12 | from mn.cores.video import m_color_bars 13 | 14 | def mm_vgasys( 15 | 16 | # ~~~[PORTS]~~~ 17 | clock, reset, vselect, 18 | hsync, vsync, 19 | red, green, blue, 20 | pxlen, active, 21 | 22 | # ~~~~[PARAMETERS]~~~~ 23 | resolution=(640,480,), 24 | color_depth=(10,10,10,), 25 | refresh_rate=60, 26 | line_rate=31250 27 | ): 28 | 29 | # create the system-level signals, overwrite clock, reset 30 | glbl = Global(clock=clock, reset=reset) 31 | # VGA inteface 32 | vga = VGA(hsync=hsync, vsync=vsync, 33 | red=red, green=green, blue=blue, 34 | pxlen=pxlen, active=active) 35 | 36 | # video memory interface 37 | vmem = VideoMemory() 38 | 39 | # instances of modules 40 | gbar = m_color_bars(glbl, vmem, 41 | resolution=resolution) 42 | 43 | gvga = m_vga_sync(glbl, vga, vmem, 44 | resolution=resolution, 45 | refresh_rate=refresh_rate, 46 | line_rate=line_rate) 47 | 48 | return gvga, gbar 49 | 50 | 51 | def convert(color_depth=(10,10,10,)): 52 | """ convert the vgasys to verilog 53 | """ 54 | clock = Clock(0, frequency=50e6) 55 | reset = Reset(0, active=0, async=False) 56 | vselect = Signal(bool(0)) 57 | 58 | hsync = Signal(bool(0)) 59 | vsync = Signal(bool(0)) 60 | cd = color_depth 61 | red = Signal(intbv(0)[cd[0]:]) 62 | green = Signal(intbv(0)[cd[1]:]) 63 | blue = Signal(intbv(0)[cd[2]:]) 64 | pxlen = Signal(bool(0)) 65 | active = Signal(bool(0)) 66 | 67 | toVerilog.timescale = '1ns/1ns' 68 | toVerilog(mm_vgasys, clock, reset, vselect, 69 | hsync, vsync, red, green, blue, 70 | pxlen, active) 71 | 72 | toVHDL(mm_vgasys, clock, reset, vselect, 73 | hsync, vsync, red, green, blue, 74 | pxlen, active) 75 | 76 | 77 | if __name__ == '__main__': 78 | convert() 79 | -------------------------------------------------------------------------------- /test/test_cores/test_vga/test_vgasys.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from __future__ import division 4 | from __future__ import print_function 5 | 6 | """ 7 | """ 8 | 9 | import argparse 10 | from argparse import Namespace 11 | 12 | from myhdl import * 13 | 14 | import mn 15 | from mn.system import Clock 16 | from mn.system import Reset 17 | from mn.system import Global 18 | from mn.cores.video import VGA 19 | 20 | # a video display model to check the timings 21 | from mn.models.video import VideoDisplay 22 | 23 | from mn.utils.test import * 24 | 25 | # local wrapper to build a VGA system 26 | from mm_vgasys import mm_vgasys 27 | from mm_vgasys import convert 28 | 29 | 30 | def test_vgasys(args=None): 31 | 32 | if args is None: 33 | args = Namespace() 34 | res = (80,60) 35 | line_rate = 4000 36 | refresh_rate = 60 37 | else: 38 | # @todo: retrieve these from ... 39 | res = args.res 40 | refresh_rate = args.refresh_rate 41 | line_rate = args.line_rate 42 | 43 | clock = Clock(0, frequency=1e6) 44 | reset = Reset(0, active=0, async=False) 45 | vselect = Signal(bool(0)) 46 | 47 | vga = VGA(color_depth=(10,10,10), ) 48 | 49 | 50 | def _test(): 51 | # top-level VGA system 52 | tbdut = mm_vgasys(clock, reset, vselect, 53 | vga.hsync, vga.vsync, 54 | vga.red, vga.green, vga.blue, 55 | vga.pxlen, vga.active, 56 | resolution=res, 57 | refresh_rate=refresh_rate, 58 | line_rate=line_rate) 59 | 60 | # group global signals 61 | glbl = Global(clock=clock, reset=reset) 62 | 63 | # a display for each dut 64 | mvd = VideoDisplay(frequency=clock.frequency, 65 | resolution=res, 66 | refresh_rate=refresh_rate, 67 | line_rate=line_rate) 68 | 69 | # connect VideoDisplay model to the VGA signals 70 | tbvd = mvd.process(glbl, vga) 71 | # clock generator 72 | tbclk = clock.gen() 73 | 74 | @instance 75 | def tbstim(): 76 | reset.next = reset.active 77 | yield delay(18) 78 | reset.next = not reset.active 79 | 80 | # Wait till a full screen has been updated 81 | while mvd.update_cnt < 1: 82 | yield delay(1000) 83 | 84 | # @todo: verify video system memory is correct! 85 | # (self checking!) 86 | 87 | raise StopSimulation 88 | 89 | return tbclk, tbvd, tbstim, tbdut 90 | 91 | 92 | vcd = tb_clean_vcd('_test') 93 | traceSignals.timescale = '1ns' 94 | traceSignals.name = vcd 95 | Simulation(traceSignals(_test)).run() 96 | convert() 97 | 98 | 99 | if __name__ == '__main__': 100 | args = Namespace(res=(80,60), line_rate=4000, 101 | refresh_rate=60) 102 | test_vgasys(args) 103 | -------------------------------------------------------------------------------- /test/test_cores/test_vga/test_vgasys_frame_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/test_cores/test_vga/test_vgasys_frame_1.png -------------------------------------------------------------------------------- /test/test_cores/test_vga/test_vgasys_frame_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/test_cores/test_vga/test_vgasys_frame_2.png -------------------------------------------------------------------------------- /test/test_cores/vcd/vcdfiles.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/test_cores/vcd/vcdfiles.txt -------------------------------------------------------------------------------- /test/test_cosim/test_fpgalink/_fpgalink_logic_ex1.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2006-2013 Christopher L. Felton 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with this program. If not, see . 16 | 17 | from myhdl import * 18 | 19 | def m_fpga_logic_ex1(clock, reset, flbus): 20 | """ 21 | Some simple logic to emulate FPGA logic which interfaces 22 | with the fpgalink module. 23 | """ 24 | # ~~~~~~~~~~~~~~~~~~~~~~~~ 25 | # The following is a simple FPGA logic which interfaces with 26 | # the fpgalink module 27 | freg = [Signal(intbv(0)[8:]) for ii in range(4)] 28 | checksum = Signal(intbv(0)[16:]) 29 | 30 | @always_comb 31 | def tb_assigns(): 32 | flbus.valid_i.next = True 33 | flbus.ready_i.next = True 34 | 35 | if flbus.chan_addr == 0: 36 | flbus.data_i.next = 0xCE 37 | elif flbus.chan_addr == 1: 38 | flbus.data_i.next = freg[0] 39 | elif flbus.chan_addr == 2: 40 | flbus.data_i.next = freg[1] 41 | elif flbus.chan_addr == 3: 42 | flbus.data_i.next = freg[2] 43 | elif flbus.chan_addr == 4: 44 | flbus.data_i.next = freg[3] 45 | elif flbus.chan_addr == 5: 46 | flbus.data_i.next = checksum[16:8] 47 | elif flbus.chan_addr == 6: 48 | flbus.data_i.next = checksum[8:0] 49 | else: 50 | flbus.data_i.next = 0 51 | 52 | @always(clock.posedge, reset.negedge) 53 | def tb_checksum(): 54 | if not reset: 55 | checksum.next = 0 56 | for ii in range(4): 57 | freg[ii].next = 0 58 | else: 59 | if flbus.valid_o: 60 | if flbus.chan_addr >= 1 and flbus.chan_addr < 5: 61 | freg[flbus.chan_addr-1].next = flbus.data_o 62 | #print(' setting chanAddr %d to %d' % (chanAddr_out, h2fData_out)) 63 | 64 | 65 | return tb_assigns, tb_checksum 66 | -------------------------------------------------------------------------------- /test/test_cosim/test_fpgalink/_test_utils.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import shutil 4 | from glob import glob 5 | import argparse 6 | 7 | def tb_argparser(): 8 | """ common command line arguments 9 | """ 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument('--trace',action='store_true') 12 | parser.add_argument('--test',action='store_true') 13 | parser.add_argument('--convert', action='store_true') 14 | return parser 15 | 16 | def tb_move_v(): 17 | for vf in glob('*.vhd'): 18 | if os.path.isfile(os.path.join('vhd/',vf)): 19 | os.remove(os.path.join('vhd/',vf)) 20 | shutil.move(vf, 'vhd/') 21 | 22 | for vf in glob('*.v'): 23 | if os.path.isfile(os.path.join('ver/',vf)): 24 | os.remove(os.path.join('ver/',vf)) 25 | shutil.move(vf, 'ver/') 26 | 27 | def tb_clean_vcd(name): 28 | for vv in glob('*.vcd.*'): 29 | os.remove(vv) 30 | 31 | if os.path.isfile('%s.vcd'%(name)): 32 | os.remove('%s.vcd'%(name)) 33 | 34 | -------------------------------------------------------------------------------- /test/test_cosim/test_fpgalink/test_fpgalink.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import os 4 | import time 5 | import argparse 6 | 7 | from myhdl import * 8 | 9 | from mn.models.usbext import FpgaLinkHost 10 | from mn.cores.usbext import fpgalink 11 | from mn.cores.usbext import m_fpgalink_fx2 12 | 13 | # Example FPGA logic which interfaces with fpgalink 14 | from _fpgalink_logic_ex1 import m_fpga_logic_ex1 15 | 16 | from _test_utils import * 17 | 18 | def flcosim(clock, reset, fx2_bus, fl_bus): 19 | f1 = '../mn/cores/usbext/fpgalink/comm_fpga_fx2_v1.v' 20 | f2 = '../mn/cores/usbext/fpgalink/comm_fpga_fx2_v2.v' 21 | f3 = '../mn/cores/usbext/fpgalink/tb_comm_fpga_fx2_m.v' 22 | assert os.path.isfile(f1) 23 | assert os.path.isfile(f2) 24 | assert os.path.isfile(f3) 25 | 26 | cmd = 'iverilog -o fpgalink %s %s %s' % (f1, f2, f3) 27 | os.system(cmd) 28 | cmd = 'vvp -m ./myhdl.vpi fpgalink' 29 | cg = Cosimulation(cmd, 30 | clk_in=clock, 31 | reset_in=reset, 32 | fx2FifoSel_out=fx2_bus.fifosel, 33 | fx2Data_in=fx2_bus.data_i, 34 | fx2Data_out=fx2_bus.data_o, 35 | fx2Data_sel=fx2_bus.data_t, 36 | fx2Read_out=fx2_bus.read, 37 | fx2GotData_in=fx2_bus.gotdata, 38 | fx2Write_out=fx2_bus.write, 39 | fx2GotRoom_in=fx2_bus.gotroom, 40 | fx2PktEnd_out=fx2_bus.pktend, 41 | chanAddr_out=fl_bus.chan_addr, 42 | h2fData_out=fl_bus.data_o, 43 | h2fValid_out=fl_bus.valid_o, 44 | h2fReady_in=fl_bus.ready_i, 45 | f2hData_in=fl_bus.data_i, 46 | f2hValid_in=fl_bus.valid_i, 47 | f2hReady_out=fl_bus.ready_o 48 | ) 49 | 50 | return cg 51 | 52 | 53 | def map_ext_int(clock, reset, fx2_ext, fx2_bus): 54 | """ Map the FX2 signals to the internally defined FX2 bus 55 | """ 56 | fx2_bus.data_i = fx2_ext.FDO 57 | fx2_bus.data_o = fx2_ext.FDI 58 | fx2_bus.read = fx2_ext.SLRD 59 | fx2_ext.SLOE = fx2_ext.SLRD 60 | fx2_bus.gotdata = fx2_ext.FLAGC 61 | fx2_bus.write = fx2_ext.SLWR 62 | fx2_bus.gotroom = fx2_ext.FLAGB 63 | #fx2_bus.pktend = fx2_ext.PKTEND 64 | 65 | faddr = fx2_ext.ADDR 66 | fsel = fx2_bus.fifosel 67 | @always_comb 68 | def tb_assign(): 69 | faddr.next[0] = 0 70 | faddr.next[1] = int(fsel) 71 | 72 | sFDO = Signal(intbv(0)[8:]) 73 | FDO = fx2_ext.FDO 74 | @always(clock.posedge) 75 | def tb_monitor(): 76 | if sFDO != FDO: 77 | #print(" FDO %x data_i %x" % (fx2_ext.FDO, fx2_bus.data_i)) 78 | sFDO.next = FDO 79 | 80 | #if fx2_ext.FDO != 0 or fx2_bus.data_i != 0: 81 | # print('%8d FDO %x data_i %x' % (now(), fx2_ext.FDO, fx2_bus.data_i)) 82 | 83 | return tb_assign, tb_monitor 84 | 85 | 86 | def test_fpgalink(): 87 | args = argparse.Namespace(cosim=False) 88 | tb_clean_vcd('m_fpgalink_fx2') 89 | tb_fpgalink(args) 90 | 91 | 92 | def tb_fpgalink(args): 93 | """ 94 | flbus1 - MyHDL model 95 | flbus2 - original fpgalink Verilog 96 | flbus3 - MyHDL converted Verilog 97 | """ 98 | # Get the FX2 emulations / host API and busses 99 | fl = FpgaLinkHost(Verbose=True) 100 | clock,reset,fx2bus1,flbus1 = fpgalink.get_interfaces() 101 | c,r,fx2bus2,flbus2 = fpgalink.get_interfaces() 102 | 103 | fx2ext = fl.GetFx2Bus() # get the FX2 bus 104 | clock = fx2ext.IFCLK 105 | reset = fx2ext.RST 106 | # connect the busses 107 | gm = map_ext_int(clock, reset, fx2ext, fx2bus1) 108 | # only one model driving the bus, connect the busses 109 | fx2bus2.data_i = fx2bus1.data_i 110 | fx2bus2.gotdata = fx2bus1.gotdata 111 | fx2bus2.gotroom = fx2bus1.gotroom 112 | 113 | # get the two HDL versions (MyHDL and Verilog) 114 | tb_dut = traceSignals(m_fpgalink_fx2, clock, reset, fx2bus1, flbus1) 115 | tb_fl1 = m_fpga_logic_ex1(clock, reset, flbus1) 116 | 117 | if args.cosim: 118 | tb_cosim = flcosim(clock, reset, fx2bus2, flbus2) 119 | tb_fl2 = m_fpga_logic_ex1(clock, reset, flbus2) 120 | else: 121 | tb_cosim = () 122 | tb_fl2 = () 123 | 124 | g = (tb_dut, tb_cosim, tb_fl1, tb_fl2, gm) 125 | 126 | # Start up the simulaiton using the FpgaLinkHost 127 | fl.setup(fx2ext, g=g) # setup the simulation 128 | fl.start() # start the simulation 129 | 130 | assert fx2bus1.data_i is fx2ext.FDO 131 | 132 | # ~~~~~~~~~~~~~~~ 133 | # Test stimulus 134 | fl.Reset() 135 | assert fx2bus1.data_i is fx2ext.FDO 136 | 137 | fl.WriteChannel(1, [9]) 138 | fl.WriteChannel(2, [8]) 139 | fl.WriteChannel(3, [7]) 140 | fl.WriteChannel(4, [6]) 141 | bb = [ii for ii in (0xFE, 0xED, 0xFA, 0xCE)] 142 | bb[0] = fl.ReadChannel(1, 1) 143 | bb[1] = fl.ReadChannel(2, 1) 144 | bb[2] = fl.ReadChannel(3, 1) 145 | bb[3] = fl.ReadChannel(4, 1) 146 | print(bb) 147 | 148 | # ~~~~~~~~~~~~~~~ 149 | # Stop simulation 150 | fl.stop() 151 | time.sleep(1) 152 | 153 | if __name__ == '__main__': 154 | parser = argparse.ArgumentParser() 155 | parser.add_argument('--cosim', action='store_true', default=False, 156 | help='Run cosimulation with verilog version of fpgalink requires icarus') 157 | args = parser.parse_args() 158 | tb_clean_vcd('m_fpgalink_fx2') 159 | tb_fpgalink(args) 160 | 161 | -------------------------------------------------------------------------------- /test/test_cosim/test_hdmi/_hdmi_prep_cosim.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | 4 | from myhdl import * 5 | #from _hdmi_ref_filelist import filelist 6 | filist = [] 7 | 8 | def prep_cosim( 9 | clock, 10 | reset, 11 | hdmi_src=None, 12 | hdmi_snk=None, 13 | args=None): 14 | """ 15 | """ 16 | global filelist 17 | files = filelist + ['tb_hdmi.v'] 18 | print("compiling") 19 | cmd = "iverilog -o hdmi -y xsim %s " % (" ".join(files),) 20 | os.system(cmd) 21 | 22 | if not os.path.exists('vcd'): 23 | os.makedirs('vcd') 24 | 25 | print("cosimulation setup ...") 26 | cmd = "vvp -m ./myhdl.vpi hdmi" 27 | 28 | gcosim = Cosimulation( 29 | cmd, 30 | clock=clock, 31 | reset_n=reset, 32 | # HDMI ports 33 | ) 34 | 35 | return gcosim -------------------------------------------------------------------------------- /test/test_cosim/test_hdmi/tb_hdmi.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfelton/minnesota/e09f036805306730e9ddf2cf492e3a48289710cc/test/test_cosim/test_hdmi/tb_hdmi.v --------------------------------------------------------------------------------