├── .github └── FUNDING.yml ├── .gitignore ├── .scalafmt.conf ├── .vscode └── settings.json ├── Readme.md ├── blinky ├── .gitignore ├── .scalafix.conf ├── .scalafmt.conf ├── .travis.yml ├── LICENSE ├── Makefile ├── Makefile.boards ├── README.md ├── build.sbt ├── build.sc ├── chiselblinky.core ├── constraints │ ├── arty_a7.xdc │ ├── de1_soc_revF.sdc │ ├── de1_soc_revF.tcl │ ├── ecp5-evn.lpf │ ├── ecp5-ulx3s.lpf │ ├── fomu-pvt1.lpf │ ├── nexys4ddr.xdc │ ├── orange-crab.lpf │ ├── polarfire_evaluation.pdc │ ├── qmtech-kintex7.xdc │ ├── qmtech-zyjzgw.xdc │ ├── qomu.pcf │ ├── storey_peak_stratixV.sdc │ └── storey_peak_stratixV.tcl ├── openocd │ ├── LFE5U-25F.cfg │ ├── LFE5U-45F.cfg │ ├── LFE5U-85F.cfg │ ├── LFE5UM-25F.cfg │ ├── LFE5UM-45F.cfg │ ├── LFE5UM-85F.cfg │ ├── LFE5UM5G-25F.cfg │ ├── LFE5UM5G-45F.cfg │ ├── LFE5UM5G-85F.cfg │ ├── digilent-hs1.cfg │ ├── ecp5-evn.cfg │ ├── ft231x.cfg │ ├── olimex-arm-usb-tiny-h.cfg │ └── xilinx-xc7.cfg ├── proginfo │ ├── artix7-template.txt │ ├── boardconfig.yaml │ ├── dfu-util.txt │ ├── proginfo.py │ ├── qmtech_k325t-template.txt │ └── ulx3s-template.txt ├── project │ ├── build.properties │ └── plugins.sbt ├── scripts │ └── mill └── src │ ├── main │ ├── resources │ │ ├── pll_artya7-35t.v │ │ ├── pll_de1_soc_revF.v │ │ ├── pll_evn.v │ │ ├── pll_nexys4ddr.v │ │ ├── pll_orange-crab.v │ │ ├── pll_polarfireeval.v │ │ ├── pll_qmtech_k325t.v │ │ ├── pll_qomu.v │ │ ├── pll_storey_peak_stratixV.v │ │ └── pll_ulx3s.v │ └── scala │ │ ├── BlackBoxPLL.scala │ │ ├── Blinky.scala │ │ └── Toplevel.scala │ └── test │ └── scala │ └── BlinkySpec.scala ├── blockram ├── .gitignore ├── .scalafmt.conf ├── Makefile ├── build.sbt ├── project │ ├── build.properties │ ├── metals.sbt │ └── plugins.sbt ├── sample.hex └── src │ └── main │ └── scala │ └── utils │ ├── DualportRAM.scala │ ├── MultiMemory.scala │ ├── SingleportRAM.scala │ └── SubByteMemory.scala ├── fomublink ├── .gitignore ├── .scalafix.conf ├── .scalafmt.conf ├── .vscode │ └── settings.json ├── Makefile ├── Readme.md ├── build.sc ├── constraints │ └── fomu-pvt.pcf ├── fomublink.core ├── post-instructions.txt ├── scripts │ └── mill └── src │ └── main │ └── scala │ ├── Blinky.scala │ ├── ICE40ledDrvBlackBox.scala │ └── ICE40pllBlackbox.scala └── pdf ├── Chisel3-CheatSheet.pdf ├── Chisel3-Documentation.pdf ├── Digital Design with Chisel - Martin Schoeberl.pdf └── UCB-Chisel-Tutorial.pdf /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: carlosedp 4 | patreon: carlosedp 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .metals 2 | .ammonite 3 | .vscode -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = "2.7.5" 2 | maxColumn = 120 3 | align.preset = most 4 | align.multiline = false 5 | continuationIndent.defnSite = 2 6 | assumeStandardLibraryStripMargin = true 7 | docstrings = JavaDoc 8 | lineEndings = preserve 9 | includeCurlyBraceInSelectChains = false 10 | danglingParentheses.preset = true 11 | optIn.annotationNewlines = true 12 | newlines.alwaysBeforeMultilineDef = false 13 | 14 | rewrite.rules = [RedundantBraces] 15 | 16 | rewrite.redundantBraces.generalExpressions = false 17 | rewriteTokens = { 18 | "⇒": "=>" 19 | "→": "->" 20 | "←": "<-" 21 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.watcherExclude": { 3 | "**/target": true 4 | } 5 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Chisel Playground 2 | 3 | The objective of this repo is to hold examples of synthesizable applications written 4 | in [Chisel](https://www.chisel-lang.org/) for learning purposes. 5 | 6 | ## Projects 7 | 8 | * [Blinky](/blinky) - A blink application that can be synthesizable on multiple FPGA boards by using FuseSoc. Can be used as base for new projects. 9 | * [Fomublink](/fomublink) - A port from [Fomu](https://tomu.im/fomu.html) blink application that can be synthesizable for Foum ICE40 FPGA. 10 | 11 | ## Books and Learning Material 12 | 13 | I've collected some documentation to help learn Chisel: 14 | 15 | * Chisel Book - Downloaded from [Martin's page](https://github.com/schoeberl/chisel-book) - [PDF](/pdf/Digital%20Design%20with%20Chisel%20-%20Martin%20Schoeberl.pdf) 16 | * Chisel Cheat Sheet - [PDF](/pdf/Chisel3-CheatSheet.pdf) 17 | * Chisel 3 Documentation - PDF Generated from [Chisel Wiki](https://github.com/chipsalliance/chisel3/wiki) - [PDF](/pdf/Chisel3-Documentation.pdf) 18 | * UCB Chisel Tutorial - PDF Generated from [Wiki](https://github.com/ucb-bar/chisel-tutorial/wiki) - [PDF](/pdf/UCB-Chisel-Tutorial.pdf) -------------------------------------------------------------------------------- /blinky/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | target/ 3 | project/target 4 | project/project 5 | docs/generated 6 | docs-target/ 7 | /*.fir 8 | /*.v 9 | /*.anno.json 10 | /*.swp 11 | /*~ 12 | .addons-dont-touch 13 | /lib/ 14 | /test_lib/ 15 | /testbuild/ 16 | obj_dir 17 | test_run_dir 18 | generated 19 | .metals 20 | .bloop 21 | .bsp 22 | .vscode 23 | -------------------------------------------------------------------------------- /blinky/.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | RemoveUnused, 3 | DisableSyntax, 4 | LeakingImplicitClassVal, 5 | NoAutoTupling, 6 | NoValInForComprehension, 7 | OrganizeImports, 8 | ProcedureSyntax, 9 | ] 10 | 11 | OrganizeImports { 12 | groupedImports = Merge 13 | } 14 | 15 | RemoveUnused { 16 | imports = false // handled by OrganizeImports 17 | } -------------------------------------------------------------------------------- /blinky/.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = "2.7.5" 2 | maxColumn = 120 3 | align.preset = most 4 | align.multiline = false 5 | continuationIndent.defnSite = 2 6 | assumeStandardLibraryStripMargin = true 7 | docstrings = JavaDoc 8 | lineEndings = preserve 9 | includeCurlyBraceInSelectChains = false 10 | danglingParentheses.preset = true 11 | optIn.annotationNewlines = true 12 | newlines.alwaysBeforeMultilineDef = false 13 | 14 | rewrite.rules = [RedundantBraces] 15 | 16 | rewrite.redundantBraces.generalExpressions = false 17 | rewriteTokens = { 18 | "⇒": "=>" 19 | "→": "->" 20 | "←": "<-" 21 | } -------------------------------------------------------------------------------- /blinky/.travis.yml: -------------------------------------------------------------------------------- 1 | language: minimal 2 | install: skip 3 | 4 | services: docker 5 | 6 | before_install: docker pull verilator/verilator:latest 7 | 8 | script: 9 | # Unset the VERILATOR variable so the container won't fail when running inside another container in Travis 10 | docker run --rm -t -v `pwd`:/build -w /build --entrypoint /bin/bash verilator/verilator:latest -c "apt update && apt install -y default-jre-headless python3-pexpect curl && make VERILATOR= check" 11 | -------------------------------------------------------------------------------- /blinky/LICENSE: -------------------------------------------------------------------------------- 1 | License 2 | ======= 3 | 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2021 Carlos Eduardo de Paula (carlosedp@gmail.com) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /blinky/Makefile: -------------------------------------------------------------------------------- 1 | # Define board parameters 2 | include Makefile.boards 3 | SHELL = bash 4 | 5 | # Project name and toplevel 6 | project = toplevel 7 | toplevel = Toplevel 8 | 9 | # Use Docker images 10 | DOCKER=docker 11 | 12 | PWD = $(shell pwd) 13 | USBDEVICE ?= /dev/bus/usb 14 | DOCKERARGS = run --rm -v $(PWD):/src -w /src 15 | VERILATORARGS = run --name verilator --hostname verilator --rm -it --entrypoint= -v $(PWD):/work -w /work 16 | 17 | ifeq ($(DOCKER),docker) 18 | YOSYS = $(DOCKER) $(DOCKERARGS) hdlc/yosys yosys 19 | NEXTPNR = $(DOCKER) $(DOCKERARGS) hdlc/nextpnr nextpnr-$(FPGA) 20 | ECPPACK = $(DOCKER) $(DOCKERARGS) hdlc/prjtrellis ecppack 21 | ICEPACK = $(DOCKER) $(DOCKERARGS) hdlc/icestorm icepack 22 | OPENOCD_DEF = $(DOCKER) $(DOCKERARGS) --privileged --device $(USBDEVICE):/dev/bus/usb hdlc/prog openocd 23 | VERILATOR = $(DOCKER) $(VERILATORARGS) hdlc/verilator 24 | else 25 | YOSYS = yosys 26 | NEXTPNR = nextpnr-$(FPGA) 27 | ECPPACK = ecppack 28 | ICEPACK = icepack 29 | OPENOCD_DEF = openocd 30 | OPENOCD_ULX3S = openocd 31 | VERILATOR = verilator 32 | endif 33 | 34 | scala_files = $(wildcard src/main/scala/*scala) 35 | generated_files = generated 36 | verilog_files = $(generated_files)/*.v 37 | 38 | # Targets 39 | chisel: $(verilog_files) ## Generates Verilog code from Chisel sources using Mill 40 | $(verilog_files): $(scala_files) check-board-vars clean 41 | scripts/mill $(project).run -board ${BOARD} -td $(generated_files) 42 | 43 | chisel-sbt: ## Generates Verilog code from Chisel sources using SBT 44 | sbt "run -board ${BOARD} -td $(generated_files)" 45 | 46 | chisel_tests: 47 | scripts/mill $(project).test 48 | 49 | check: chisel_tests ## Run Chisel tests 50 | 51 | fmt: 52 | scripts/mill all $(project).{reformat,fix} 53 | 54 | synth: check-board-vars $(project).bit ## Synthesizes for target BOARD with "make BOARD=board synth" 55 | 56 | check-board-vars: 57 | @test -n "$(BOARD)" || (echo "Set BOARD variable to a board from:" ; echo -n " "; cat Makefile.boards|grep BOARD| cut -d ',' -f 2 |tr -s ')\n' ', ' | sed 's/, $$/\n/'; echo "Eg. make chisel BOARD=polarfireeval"; echo; exit 1) 58 | 59 | $(project).json: $(verilog_files) 60 | $(YOSYS) -p "read_verilog -sv $^; synth_$(FPGA) -json $(generated_files)/$@ -top $(toplevel)" 61 | 62 | $(project).config: $(project).json $(LPF) 63 | $(NEXTPNR) --json $(generated_files)/$< --lpf $(LPF) --textcfg $(generated_files)/$@ $(NEXTPNR_FLAGS) --package $(PACKAGE) 64 | 65 | $(project).bit: $(project).config 66 | $(PACK) --svf $(generated_files)/$(project).svf $(generated_files)/$< $(generated_files)/$@ 67 | 68 | $(project).svf: $(project).bit 69 | 70 | prog: check-board-vars $(project).svf ## Programs target BOARD with "make BOARD=board prog" 71 | $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf $(generated_files)/$(project).svf; exit" 72 | 73 | clean: ## Clean all generated files 74 | @./scripts/mill clean 75 | @rm -rf obj_dir test_run_dir target 76 | @rm -rf $(generated_files) 77 | @rm -rf out 78 | @rm -f $(project) 79 | 80 | help: 81 | @echo "Makefile targets:" 82 | @echo "" 83 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = "[:##]"}; {printf "\033[36m%-20s\033[0m %s\n", $$2, $$5}' 84 | @echo "" 85 | @echo "Supported boards:" 86 | @echo "" 87 | @grep -E 'BOARD|##' Makefile.boards |sed 's/.*BOARD)\,\(.*\))/\1/' | sed -n 'N;s/\n/ /;p' | awk -F"[ \t]*##" '{printf "\033[36m%-15s\033[0m - %s\n", $$1, $$2}' 88 | 89 | .PHONY: chisel clean prog help 90 | .PRECIOUS: $(project).json $(project).config $(project).bit 91 | .DEFAULT_GOAL := help 92 | -------------------------------------------------------------------------------- /blinky/Makefile.boards: -------------------------------------------------------------------------------- 1 | // code: language=makefile tabSize=4 2 | 3 | ifeq ($(BOARD),evn) 4 | ## ECP5-EVN 5 | FPGA=ecp5 6 | PACK=$(ECPPACK) 7 | LPF=constraints/ecp5-evn.lpf 8 | PLL=pll/pll_ehxplll.v 9 | PACKAGE=CABGA381 10 | NEXTPNR_FLAGS=--um5g-85k --freq 12 11 | OPENOCD=$(OPENOCD_DEF) 12 | OPENOCD_JTAG_CONFIG=openocd/ecp5-evn.cfg 13 | OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg 14 | else ifeq ($(BOARD),ulx3s) 15 | ## Radiona ULX3S with ECP5-85F 16 | FPGA=ecp5 17 | PACK=$(ECPPACK) 18 | LPF=constraints/ecp5-ulx3s.lpf 19 | PLL=pll/pll_ehxplll_25MHz.v 20 | PACKAGE=CABGA381 21 | NEXTPNR_FLAGS=--85k --freq 25 22 | OPENOCD=$(OPENOCD_ULX3S) 23 | OPENOCD_JTAG_CONFIG=openocd/ft231x.cfg 24 | OPENOCD_DEVICE_CONFIG=openocd/LFE5U-85F.cfg 25 | else ifeq ($(BOARD),orangecrab) 26 | ## OrangeCrab with ECP85 27 | FPGA=ecp5 28 | PACK=$(ECPPACK) 29 | LPF=constraints/orange-crab.lpf 30 | PLL=pll/pll_bypass.v 31 | PACKAGE=CSFBGA285 32 | NEXTPNR_FLAGS=--um5g-85k --freq 50 33 | OPENOCD=$(OPENOCD_DEF) 34 | OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg 35 | OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg 36 | else ifeq ($(BOARD),colorlight) 37 | ## Colorlight 5A-75B 38 | FPGA=ecp5 39 | PACK=$(ECPPACK) 40 | LPF=constraints/colorlight_5A-75B.lpf 41 | PLL=pll/pll_ehxplll_25MHz.v 42 | PACKAGE=CABGA256 43 | NEXTPNR_FLAGS=--25k --freq 25 44 | OPENOCD=$(OPENOCD_DEF) 45 | OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg 46 | OPENOCD_DEVICE_CONFIG=openocd/LFE5U-25F.cfg 47 | else ifeq ($(BOARD),fomu) 48 | ## Fomu PVT1 - Test 49 | FPGA=ice40 50 | PACK=$(ICEPACK) 51 | LPF=constraints/fomu-pvt1.lpf 52 | PACKAGE=uwg30 53 | NEXTPNR_FLAGS=--up5k 54 | # TODO - Define parameters below 55 | OPENOCD=$(OPENOCD_DEF) 56 | OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg 57 | OPENOCD_DEVICE_CONFIG=openocd/LFE5U-25F.cfg 58 | else 59 | endif -------------------------------------------------------------------------------- /blinky/README.md: -------------------------------------------------------------------------------- 1 | # Chisel Blinky 2 | 3 | This is a simple Blinky project to demonstrate Chisel functionality with build scripts 4 | and tooling to be able to synth on FPGA boards. 5 | 6 | The Chisel sources uses a `-board` parameter to define which board is used and generate the proper PLL and build. To support this, an utility module was created. 7 | 8 | The project also have a visual test spec that indicates the "blink" behavior that can be run with `./scripts/mill toplevel.test.testOne BlinkySpec`. 9 | 10 | ## Building 11 | 12 | The project provides two building methods. The first and recommended is using [Fusesoc](https://github.com/olofk/fusesoc), a package manager that handles all board backend files and configuration. It also makes adding support to new boards and vendors much easier. 13 | 14 | A second method is using the built-in Makefile that provides support for some boards. 15 | 16 | ### Fusesoc build and generation 17 | 18 | To install Fusesoc (requires Python3 and pip3): 19 | 20 | ```sh 21 | pip3 install --upgrade --user fusesoc 22 | ``` 23 | 24 | Check if it's working: 25 | 26 | ```sh 27 | $ fusesoc --version 28 | 1.12.0 29 | ``` 30 | 31 | If the terminal reports an error about the command not being found check that the directory `~/.local/bin` is in your command search path (`export PATH=~/.local/bin:$PATH`). 32 | 33 | Fusesoc allows multiple boards from different vendors to be supported by the project. It uses chisel-generator to generate Verilog from Scala sources and calls the correct board EDA backend to create it's project files. 34 | 35 | For example, to generate the programming files for the **ULX3s** based on ECP5: 36 | 37 | ```sh 38 | mkdir fusesoc-chiselblinky && cd fusesoc-chiselblinky 39 | 40 | fusesoc library add fusesoc-cores https://github.com/fusesoc/fusesoc-cores 41 | 42 | # Since Blinky is not a standalone repo (but a folder in an umbrella repo) 43 | # We clone it locally and add the library as a local dir. 44 | git clone https://github.com/carlosedp/chisel-playground 45 | fusesoc library add chiselblinky $(pwd)/chisel-playground/blinky 46 | 47 | fusesoc run --target=ulx3s-85 carlosedp:demo:chiselblinky:0 48 | ... 49 | ... 50 | # Output bitstream will be on build/carlosedp_demo_chiselblinky_0/ulx3s-85-trellis 51 | ❯ ll build/carlosedp_demo_chiselblinky_0/ulx3s-85-trellis 52 | total 2.7M 53 | -rw-r--r-- 1 cdepaula staff 774 Apr 7 18:53 carlosedp_demo_chiselblinky_0.eda.yml 54 | -rw-r--r-- 1 cdepaula staff 545 Apr 7 18:53 carlosedp_demo_chiselblinky_0.tcl 55 | -rw-r--r-- 1 cdepaula staff 435 Apr 7 18:53 carlosedp_demo_chiselblinky_0.mk 56 | -rw-r--r-- 1 cdepaula staff 608 Apr 7 18:53 Makefile 57 | -rw-r--r-- 1 cdepaula staff 9.5K Apr 7 18:53 carlosedp_demo_chiselblinky_0.blif 58 | -rw-r--r-- 1 cdepaula staff 655K Apr 7 18:53 carlosedp_demo_chiselblinky_0.json 59 | -rw-r--r-- 1 cdepaula staff 44K Apr 7 18:53 carlosedp_demo_chiselblinky_0.edif 60 | -rw-r--r-- 1 cdepaula staff 45K Apr 7 18:53 yosys.log 61 | -rw-r--r-- 1 cdepaula staff 8.7K Apr 7 18:53 next.log 62 | -rw-r--r-- 1 cdepaula staff 1.9M Apr 7 18:53 carlosedp_demo_chiselblinky_0.bit 63 | ``` 64 | 65 | Just program it to your FPGA with `OpenOCD` or in ULX3S case, [`ujprog`](https://github.com/f32c/tools/tree/master/ujprog) 66 | 67 | And for the **Microchip Polarfire** evaluation board, just change the target: 68 | 69 | ```sh 70 | fusesoc run --target=polarfireeval_es carlosedp:demo:chiselblinky:0 71 | ``` 72 | 73 | ### Building on containers 74 | 75 | The standard build process uses locally installed tools like Java (for Chisel generation)Yosys, NextPNR, Vivado and others. Fusesoc also supports building the complete workflow by using containers thru a command launcher. 76 | 77 | To use it: 78 | 79 | ```sh 80 | # Download the command wrapper 81 | wget https://gist.github.com/carlosedp/c0e29d55e48309a48961f2e3939acfe9/raw/bfeb1cfe2e188c1d5ced0b09aabc9902fdfda6aa/runme.py 82 | chmod +x runme.py 83 | 84 | # Run fusesoc with the wrapper as an environment var 85 | EDALIZE_LAUNCHER=$(realpath ./runme.py) fusesoc run --target=ulx3s-85 carlosedp:demo:chiselblinky:0 86 | 87 | #The output files will be on the local ./build dir like before 88 | ``` 89 | 90 | Here's a demo of it: 91 | 92 | [![asciicast](https://asciinema.org/a/405850.svg)](https://asciinema.org/a/405850) 93 | 94 | ### Adding support to new boards 95 | 96 | Support for new boards can be added in the `chiselblinky.core` file. 97 | 98 | Three sections are required: 99 | 100 | #### Fileset 101 | 102 | Filesets lists the dependency files specific for each board that must be copied to the output project dir and used by EDA. 103 | 104 | ```yaml 105 | polarfireeval: 106 | files: 107 | - constraints/polarfire_evaluation.pdc: { file_type: PDC } 108 | # or for boards that contain programming files 109 | artya7-35t: 110 | files: 111 | - constraints/arty_a7.xdc: { file_type: xdc } 112 | - openocd/digilent-hs1.cfg: { file_type: user } 113 | - openocd/xilinx-xc7.cfg: { file_type: user } 114 | - proginfo/artix7-template.txt: { file_type: user } 115 | ``` 116 | 117 | #### Generate 118 | 119 | The generator section contains the Chisel generator parameters. It has the arguments to be passed to Chisel (the board in this example), the project name and the output files created by the generator to be used by the EDA. Since they all inherit from the Chisel standard generator, it's a matter of using the `*baseparam` tag as: 120 | 121 | ```yaml 122 | polarfireeval: 123 | generator: chisel 124 | parameters: 125 | <<: *baseparam 126 | extraargs: "-board polarfireeval" 127 | 128 | # or if board doesn't use an inverse-reset (pulled down) switch 129 | qomu: 130 | generator: chisel 131 | parameters: 132 | <<: *baseparam 133 | extraargs: "-board qomu -invreset false" 134 | ``` 135 | 136 | #### Target 137 | 138 | Finally the target section has the board information to be passed to the EDA tools. Parameters like the package/die or extra parameters to synthesis or PnR. This is highly dependent of the EDA backend. It's name is the one passed on the `--target=` param on FuseSoc. It also references the fileset and generate configs. Must contain the `base` fileset. 139 | 140 | ```yaml 141 | polarfireeval_es: 142 | default_tool: libero 143 | description: Microsemi Polarfire Evaluation Kit (ES) 144 | filesets: [base, polarfireeval] 145 | generate: [polarfireeval] 146 | tools: 147 | libero: 148 | family: PolarFire 149 | die: MPF300TS_ES 150 | package: FCG1152 151 | toplevel: Toplevel 152 | ``` 153 | 154 | To add support to additional boards, create these sections (or reuse similar ones). More details can be found on [Edalize docs](https://github.com/olofk/edalize/) or using [Corescore](https://github.com/olofk/corescore) and [Blinky](https://github.com/fusesoc/blinky) as examples. 155 | 156 | ### Makefile build and generation 157 | 158 | The Makefiles support synthesis on some FPGAs using the Open Source toolchain based on yosys/nextpnr. This is deprecated might be removed in the future. 159 | 160 |
161 | Click to expand 162 | 163 | At the moment the tools support Lattice ECP5 FPGAs. The build process can use Docker images, so no software other than Docker needs to be installed. If you prefer Podman you can use that too, just adjust it in `Makefile`, `DOCKER=podman`. If the variable is undefined, build proceeds with locally installed tools. 164 | 165 | ### Building and programming the FPGA 166 | 167 | The `Makefile` currently supports the following FPGA boards by defining the `BOARD` parameter on make: 168 | 169 | * Lattice [ECP5 Evaluation Board](http://www.latticesemi.com/ecp5-evaluation) - `evn` 170 | * Radiona [ULX3S](https://radiona.org/ulx3s/) - `ulx3s` 171 | * Greg Davill [Orangecrab](https://github.com/gregdavill/OrangeCrab) - `orangecrab` 172 | * Q3k [Colorlight](https://github.com/q3k/chubby75/tree/master/5a-75b) - `colorlight` 173 | 174 | For example, to build for the ULX3S Board, run: 175 | 176 | ```sh 177 | make BOARD=ulx3s synth` 178 | ``` 179 | 180 | After this command, all files will be generated in the `generated` output dir. 181 | 182 | To program your FPGA: 183 | 184 | ```sh 185 | make BOARD=ulx3s prog 186 | 187 | # or if your USB device has a different path, pass it on USBDEVICE, like: 188 | 189 | make BOARD=ulx3s USBDEVICE=/dev/tty.usbserial-120001 prog 190 | ``` 191 | 192 | Programming using OpenOCD on Docker does not work on Docker Desktop for Mac/Windows since the container is run in a Linux VM and can not see the physical devices connected to the Host. In this case you need OpenOCD installed locally. 193 | 194 | For the ULX3S board, the current OpenOCD does not support ft232 protocol so to program it, download [ujprog](https://github.com/emard/ulx3s-bin/tree/master/usb-jtag) for your platform and program using `./ujprog chiselwatt.bit` or to persist in the flash, `./ujprog -j FLASH chiselwatt.bit`. 195 | 196 |
197 | -------------------------------------------------------------------------------- /blinky/build.sbt: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | lazy val blinky = (project in file(".")) 4 | .settings( 5 | organization := "com.carlosedp", 6 | name := "chisel-blinky", 7 | version := "0.0.1", 8 | scalaVersion := "2.13.8", 9 | semanticdbEnabled := true, 10 | semanticdbVersion := scalafixSemanticdb.revision, 11 | maxErrors := 3 12 | ) 13 | 14 | // Library default versions 15 | val defaultVersions = Map( 16 | "chisel3" -> "3.5.1", 17 | "chisel-iotesters" -> "1.5.3", 18 | "chiseltest" -> "0.5.1", 19 | "scalatest" -> "3.2.11", 20 | "organize-imports" -> "0.5.0", 21 | "scalautils" -> "0.9.0" 22 | ) 23 | // Import libraries 24 | libraryDependencies ++= Seq("chisel3", "chisel-iotesters", "chiseltest").map { dep: String => 25 | "edu.berkeley.cs" %% dep % sys.props 26 | .getOrElse(dep + "Version", defaultVersions(dep)) 27 | } 28 | libraryDependencies += "org.scalatest" %% "scalatest" % defaultVersions("scalatest") 29 | libraryDependencies += "com.carlosedp" %% "scalautils" % defaultVersions("scalautils") 30 | ThisBuild / scalafixDependencies += "com.github.liancheng" %% "organize-imports" % defaultVersions("organize-imports") 31 | 32 | // Aliases 33 | addCommandAlias("com", "all compile test:compile") 34 | addCommandAlias("rel", "reload") 35 | addCommandAlias("fix", "all compile:scalafix test:scalafix") 36 | addCommandAlias("fmt", "all scalafmtSbt scalafmtAll") 37 | 38 | resolvers ++= Seq( 39 | Resolver.sonatypeRepo("snapshots"), 40 | Resolver.sonatypeRepo("releases") 41 | ) 42 | 43 | addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % defaultVersions("chisel3") cross CrossVersion.full) 44 | 45 | scalacOptions ++= Seq( 46 | "-unchecked", 47 | "-deprecation", 48 | "-language:reflectiveCalls", 49 | "-feature", 50 | "-Xcheckinit", 51 | "-Xfatal-warnings", 52 | "-Ywarn-dead-code", 53 | "-Ywarn-unused" 54 | ) 55 | -------------------------------------------------------------------------------- /blinky/build.sc: -------------------------------------------------------------------------------- 1 | import mill._ 2 | import mill.scalalib._ 3 | import scalafmt._ 4 | import coursier.MavenRepository 5 | import $ivy.`com.goyeau::mill-scalafix:0.2.2` 6 | import com.goyeau.mill.scalafix._ 7 | 8 | def mainClass = Some("Toplevel") 9 | 10 | val defaultVersions = Map( 11 | "scala" -> "2.13.8", 12 | "chisel3" -> "3.5.1", 13 | "chisel-iotesters" -> "1.5.3", 14 | "chiseltest" -> "0.5.1", 15 | "scalatest" -> "3.2.11", 16 | "organize-imports" -> "0.6.0", 17 | "scalautils" -> "0.9.0", 18 | "semanticdb-scalac" -> "4.4.35" 19 | ) 20 | 21 | trait HasChisel3 extends ScalaModule { 22 | override def ivyDeps = super.ivyDeps() ++ Agg( 23 | ivy"edu.berkeley.cs::chisel3:${defaultVersions("chisel3")}", 24 | ivy"com.carlosedp::scalautils:${defaultVersions("scalautils")}" 25 | ) 26 | override def scalacPluginIvyDeps = super.scalacPluginIvyDeps() ++ Agg( 27 | ivy"edu.berkeley.cs:::chisel3-plugin:${defaultVersions("chisel3")}" 28 | ) 29 | } 30 | 31 | trait HasChiselTests extends CrossSbtModule { 32 | object test extends Tests { 33 | override def ivyDeps = super.ivyDeps() ++ Agg( 34 | ivy"org.scalatest::scalatest:${defaultVersions("scalatest")}", 35 | ivy"edu.berkeley.cs::chisel-iotesters:${defaultVersions("chisel-iotesters")}", 36 | ivy"edu.berkeley.cs::chiseltest:${defaultVersions("chiseltest")}" 37 | ) 38 | def repositories = super.repositories ++ Seq( 39 | MavenRepository("https://oss.sonatype.org/content/repositories/snapshots") 40 | ) 41 | def testFrameworks = Seq("org.scalatest.tools.Framework") 42 | 43 | def testOne(args: String*) = T.command { 44 | super.runMain("org.scalatest.run", args: _*) 45 | } 46 | } 47 | } 48 | 49 | trait CodeQuality extends ScalafixModule with ScalafmtModule { 50 | def scalafixIvyDeps = Agg(ivy"com.github.liancheng::organize-imports:${defaultVersions("organize-imports")}") 51 | // Override semanticdb version due to unavailable 4.4.10 for Scala 2.12.14. 52 | override def scalacPluginIvyDeps = 53 | super.scalacPluginIvyDeps() ++ Agg(ivy"org.scalameta:::semanticdb-scalac:${defaultVersions("semanticdb-scalac")}") 54 | } 55 | 56 | trait Aliases extends Module { 57 | def fmt() = T.command { 58 | toplevel.reformat() 59 | toplevel.fix() 60 | } 61 | } 62 | 63 | trait ScalacOptions extends ScalaModule { 64 | override def scalacOptions = T { 65 | super.scalacOptions() ++ Seq( 66 | "-unchecked", 67 | "-deprecation", 68 | "-language:reflectiveCalls", 69 | "-feature", 70 | "-Xcheckinit", 71 | "-Xfatal-warnings", 72 | "-Ywarn-dead-code", 73 | "-Ywarn-unused" 74 | ) 75 | } 76 | } 77 | 78 | object toplevel 79 | extends CrossSbtModule 80 | with HasChisel3 81 | with HasChiselTests 82 | with CodeQuality 83 | with Aliases 84 | with ScalacOptions { 85 | override def millSourcePath = super.millSourcePath 86 | def crossScalaVersion = defaultVersions("scala") 87 | } 88 | -------------------------------------------------------------------------------- /blinky/chiselblinky.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name: carlosedp:demo:chiselblinky:0 4 | description: A blinky demo written in Chisel HDL 5 | 6 | filesets: 7 | proginfo: 8 | files: 9 | - proginfo/proginfo.py : {file_type : user, copyto : proginfo.py} 10 | - proginfo/boardconfig.yaml : {file_type : user, copyto : boardconfig.yaml} 11 | 12 | base: 13 | depend: ["fusesoc:utils:generators"] 14 | 15 | polarfireeval: 16 | files: 17 | - constraints/polarfire_evaluation.pdc: { file_type: PDC } 18 | 19 | ulx3s-85: 20 | files: 21 | - constraints/ecp5-ulx3s.lpf: { file_type: LPF } 22 | - openocd/ft231x.cfg: { file_type: user } 23 | - openocd/LFE5U-85F.cfg: { file_type: user } 24 | - proginfo/ulx3s-template.txt: { file_type: user } 25 | 26 | artya7-35t: 27 | files: 28 | - constraints/arty_a7.xdc: { file_type: xdc } 29 | - openocd/digilent-hs1.cfg: { file_type: user } 30 | - openocd/xilinx-xc7.cfg: { file_type: user } 31 | - proginfo/artix7-template.txt: { file_type: user } 32 | 33 | nexys4ddr: 34 | files: 35 | - constraints/nexys4ddr.xdc: { file_type: xdc } 36 | - openocd/digilent-hs1.cfg: { file_type: user } 37 | - openocd/xilinx-xc7.cfg: { file_type: user } 38 | 39 | orange-crab: 40 | files: 41 | - constraints/orange-crab.lpf: { file_type: LPF } 42 | - proginfo/dfu-util.txt: { file_type: user } 43 | 44 | de1_soc_revF: 45 | files: 46 | - constraints/de1_soc_revF.sdc: { file_type: SDC } 47 | - constraints/de1_soc_revF.tcl: { file_type: tclSource } 48 | 49 | storey_peak_stratixV: 50 | files: 51 | - constraints/storey_peak_stratixV.sdc: { file_type: SDC } 52 | - constraints/storey_peak_stratixV.tcl: { file_type: tclSource } 53 | 54 | qomu: 55 | files: 56 | - constraints/qomu.pcf: { file_type: PCF } 57 | - proginfo/qomu-qf-template.txt: { file_type: user } 58 | 59 | qmtech_k325t: 60 | files: 61 | - constraints/qmtech-kintex7.xdc: { file_type: XDC } 62 | - proginfo/qmtech_k325t-template.txt: { file_type: user } 63 | 64 | qmtech_k325t_zyjzgw: 65 | files: 66 | - constraints/qmtech-zyjzgw.xdc: { file_type: XDC } 67 | - proginfo/qmtech_k325t-template.txt: { file_type: user } 68 | 69 | generate: 70 | 71 | default-chisel: 72 | generator: chisel 73 | parameters: &baseparam 74 | extraargs: "-board bypass" 75 | chiselproject: toplevel 76 | copy_core: true 77 | output: 78 | files: 79 | - generated/Toplevel.v: { file_type: verilogSource } 80 | - generated/PLL.v: { file_type: verilogSource } 81 | 82 | 83 | polarfireeval: 84 | generator: chisel 85 | parameters: 86 | <<: *baseparam 87 | extraargs: "-board polarfireeval" 88 | 89 | ulx3s: 90 | generator: chisel 91 | parameters: 92 | <<: *baseparam 93 | extraargs: "-board ulx3s" 94 | 95 | artya7-35t: 96 | generator: chisel 97 | parameters: 98 | <<: *baseparam 99 | extraargs: "-board artya7-35t --target:fpga --emission-options=disableMemRandomization,disableRegisterRandomization" 100 | 101 | nexys4ddr: 102 | generator: chisel 103 | parameters: 104 | <<: *baseparam 105 | extraargs: "-board nexys4ddr -invreset false" 106 | 107 | orange-crab: 108 | generator: chisel 109 | parameters: 110 | <<: *baseparam 111 | extraargs: "-board orange-crab" 112 | 113 | de1_soc_revF: 114 | generator: chisel 115 | parameters: 116 | <<: *baseparam 117 | extraargs: "-board de1_soc_revF" 118 | 119 | storey_peak_stratixV: 120 | generator: chisel 121 | parameters: 122 | <<: *baseparam 123 | extraargs: "-board storey_peak_stratixV" 124 | 125 | qomu: 126 | generator: chisel 127 | parameters: 128 | <<: *baseparam 129 | extraargs: "-board qomu -invreset false" 130 | 131 | qmtech_k325t: 132 | generator: chisel 133 | parameters: 134 | <<: *baseparam 135 | extraargs: "-board qmtech_k325t -invreset true" 136 | 137 | targets: 138 | polarfireeval_es: 139 | default_tool: libero 140 | description: Microsemi Polarfire Evaluation Kit (ES) 141 | filesets: [base, polarfireeval] 142 | generate: [polarfireeval] 143 | tools: 144 | libero: 145 | family: PolarFire 146 | die: MPF300TS_ES 147 | package: FCG1152 148 | toplevel: Toplevel 149 | 150 | ulx3s-85: 151 | default_tool: trellis 152 | description: ULX3S 85k version 153 | filesets: [base, ulx3s-85, proginfo] 154 | generate: [ulx3s] 155 | hooks: 156 | post_run: [ulx3s-85f] 157 | tools: 158 | diamond: 159 | part: LFE5U-85F-6BG381C 160 | trellis: 161 | nextpnr_options: [--package, CABGA381, --85k] 162 | yosys_synth_options: [-abc9, -nowidelut] 163 | toplevel: Toplevel 164 | 165 | artya7-35t: 166 | default_tool : vivado 167 | description: Digilent ArtyA7-35T Board 168 | filesets : [base, artya7-35t] 169 | generate: [artya7-35t] 170 | tools: 171 | vivado: 172 | part : xc7a35ticsg324-1L 173 | toplevel : Toplevel 174 | 175 | nexys4ddr: 176 | default_tool : vivado 177 | description: Digilent Nexys 4 DDR (and Nexys A7) board 178 | filesets : [base, nexys4ddr] 179 | generate: [nexys4ddr] 180 | tools: 181 | vivado: 182 | part : xc7a100tcsg324-1 183 | toplevel : Toplevel 184 | 185 | artya7-35t-oss: 186 | default_tool : symbiflow 187 | description: Digilent ArtyA7-35T Board using Symbiflow OSS Toolchain 188 | filesets : [base, artya7-35t, proginfo] 189 | generate: [artya7-35t] 190 | hooks: 191 | post_run: [artya7-35t] 192 | tools: 193 | symbiflow: 194 | part : xc7a35t 195 | package: csg324-1 196 | vendor: xilinx 197 | pnr: vtr 198 | toplevel : Toplevel 199 | 200 | orange-crab: 201 | default_tool: trellis 202 | description: GsD orangecrab version 0.2 203 | filesets: [base, orange-crab, proginfo] 204 | generate: [orange-crab] 205 | hooks: 206 | post_run: [dfu-util] 207 | tools: 208 | trellis: 209 | nextpnr_options : [--package, CSFBGA285, --25k] 210 | toplevel: Toplevel 211 | 212 | de1_soc_revF: 213 | default_tool : quartus 214 | description: Altera Cyclone V DE1_SoC board, revision F 215 | filesets : [base, de1_soc_revF] 216 | generate : [de1_soc_revF] 217 | tools: 218 | quartus: 219 | family : Cyclone V 220 | device : 5CSEMA5F31C6 221 | board_device_index : 2 222 | toplevel: Toplevel 223 | 224 | storey_peak_stratixV: 225 | default_tool : quartus 226 | description: Microsoft Storey Peak (Catapult) Stratix V FPGA Accelerator 227 | filesets : [base, storey_peak_stratixV] 228 | generate : [storey_peak_stratixV] 229 | tools: 230 | quartus: 231 | family : Stratix V 232 | device : 5SGSMD5K1F40C2 233 | toplevel: Toplevel 234 | 235 | qomu: 236 | default_tool : symbiflow 237 | description: Qomu, a Quicklogic EOS S3 board using Symbiflow OSS Toolchain 238 | filesets : [base, qomu, proginfo] 239 | generate: [qomu] 240 | tools: 241 | symbiflow: 242 | part : ql-eos-s3 243 | package: WR42 244 | vendor: quicklogic 245 | pnr: vtr 246 | toolchain_prefix: ql- 247 | toplevel : Toplevel 248 | 249 | qmtech_k325t: &qmtech_k325t 250 | default_tool : xray 251 | description: QMTech Kintex 7 K325T Board using Project X-Ray OSS Toolchain 252 | filesets : [base, qmtech_k325t, proginfo] 253 | generate: [qmtech_k325t] 254 | hooks: 255 | post_run: [qmtech_k325t] 256 | tools: 257 | xray: 258 | part : xc7k325t 259 | package: ffg676-1 260 | yosys_synth_options: [-abc9, -flatten] 261 | nextpnr_options: [--verbose, --debug] 262 | toplevel : Toplevel 263 | 264 | qmtech_k325t_zyjzgw: 265 | <<: *qmtech_k325t 266 | description: QMTech Kintex 7 K325T ZYJZGW Board using Project X-Ray OSS Toolchain 267 | filesets : [base, qmtech_k325t_zyjzgw, proginfo] 268 | 269 | scripts: 270 | artya7-35t: 271 | cmd : [python3, proginfo.py, artya7-35t] 272 | dfu-util: 273 | cmd : [python3, proginfo.py, dfu-util] 274 | ulx3s-85f: 275 | cmd : [python3, proginfo.py, ulx3s-85f] 276 | qmtech_k325t: 277 | cmd : [python3, proginfo.py, qmtech_k325t] 278 | -------------------------------------------------------------------------------- /blinky/constraints/arty_a7.xdc: -------------------------------------------------------------------------------- 1 | # Clock pin 2 | set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports {clock}] 3 | 4 | # LEDs 5 | set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports {io_led0}] 6 | set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports {io_led1}] 7 | set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports {io_led2}] 8 | 9 | # Switches 10 | set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { reset }] 11 | 12 | # Clock constraints 13 | create_clock -period 10.0 [get_ports {clock}] 14 | -------------------------------------------------------------------------------- /blinky/constraints/de1_soc_revF.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (50 Mhz) 2 | create_clock -name "clk" -period 20.000ns [get_ports {clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /blinky/constraints/de1_soc_revF.tcl: -------------------------------------------------------------------------------- 1 | # Clock 2 | set_location_assignment PIN_AF14 -to clock 3 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to clock 4 | 5 | # Reset 6 | set_location_assignment PIN_AA14 -to reset 7 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to reset 8 | 9 | # LEDs 10 | set_location_assignment PIN_V16 -to io_led0 11 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to io_led0 12 | set_location_assignment PIN_W16 -to io_led1 13 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to io_led1 14 | set_location_assignment PIN_V17 -to io_led2 15 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to io_led2 -------------------------------------------------------------------------------- /blinky/constraints/ecp5-evn.lpf: -------------------------------------------------------------------------------- 1 | LOCATE COMP "clock" SITE "A10"; 2 | IOBUF PORT "clock" IO_TYPE=LVCMOS33; 3 | 4 | LOCATE COMP "reset" SITE "P4"; 5 | IOBUF PORT "reset" IO_TYPE=LVCMOS33; 6 | 7 | LOCATE COMP "io_tx" SITE "P3"; 8 | LOCATE COMP "io_rx" SITE "P2"; 9 | 10 | IOBUF PORT "io_tx" IO_TYPE=LVCMOS33; 11 | IOBUF PORT "io_rx" IO_TYPE=LVCMOS33; 12 | 13 | LOCATE COMP "io_led0" SITE "A13"; 14 | LOCATE COMP "io_led1" SITE "A12"; 15 | LOCATE COMP "io_led2" SITE "B19"; 16 | 17 | IOBUF PORT "io_led0" IO_TYPE=LVCMOS25; 18 | IOBUF PORT "io_led1" IO_TYPE=LVCMOS25; 19 | IOBUF PORT "io_led2" IO_TYPE=LVCMOS25; 20 | -------------------------------------------------------------------------------- /blinky/constraints/ecp5-ulx3s.lpf: -------------------------------------------------------------------------------- 1 | LOCATE COMP "clock" SITE "G2"; 2 | IOBUF PORT "clock" PULLMODE=NONE IO_TYPE=LVCMOS33; 3 | FREQUENCY PORT "clock" 25 MHZ; 4 | 5 | LOCATE COMP "reset" SITE "D6"; 6 | IOBUF PORT "reset" PULLMODE=UP IO_TYPE=LVCMOS33; 7 | 8 | LOCATE COMP "io_tx" SITE "L4"; 9 | LOCATE COMP "io_rx" SITE "M1"; 10 | 11 | IOBUF PORT "io_tx" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; 12 | IOBUF PORT "io_rx" PULLMODE=UP IO_TYPE=LVCMOS33; 13 | 14 | LOCATE COMP "io_led7" SITE "H3"; 15 | LOCATE COMP "io_led6" SITE "E1"; 16 | LOCATE COMP "io_led5" SITE "E2"; 17 | LOCATE COMP "io_led4" SITE "D1"; 18 | LOCATE COMP "io_led3" SITE "D2"; 19 | LOCATE COMP "io_led2" SITE "C1"; 20 | LOCATE COMP "io_led1" SITE "C2"; 21 | LOCATE COMP "io_led0" SITE "B2"; 22 | IOBUF PORT "io_led0" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 23 | IOBUF PORT "io_led1" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 24 | IOBUF PORT "io_led2" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 25 | IOBUF PORT "io_led3" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 26 | IOBUF PORT "io_led4" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 27 | IOBUF PORT "io_led5" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 28 | IOBUF PORT "io_led6" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 29 | IOBUF PORT "io_led7" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; -------------------------------------------------------------------------------- /blinky/constraints/fomu-pvt1.lpf: -------------------------------------------------------------------------------- 1 | set_io clock F4 2 | 3 | set_io io_led0 A5 4 | set_io io_led1 B5 5 | set_io io_led2 C5 6 | 7 | set_io reset E4 8 | set_io touch_2 D5 9 | set_io touch_3 E5 10 | set_io touch_4 F5 11 | 12 | set_io pmod_1 E4 13 | set_io pmod_2 D5 14 | set_io pmod_3 E5 15 | set_io pmod_4 F5 16 | set_io pmoda_1 E4 17 | set_io pmoda_2 D5 18 | set_io pmoda_3 E5 19 | set_io pmoda_4 F5 20 | set_io user_1 E4 21 | set_io user_2 D5 22 | set_io user_3 E5 23 | set_io user_4 F5 24 | set_io spi_mosi F1 25 | set_io spi_miso E1 26 | set_io spi_clk D1 27 | set_io spi_io2 F2 28 | set_io spi_io3 B1 29 | set_io spi_cs C1 30 | set_io usb_dn A2 31 | set_io usb_dp A1 32 | set_io usb_dp_pu A4 33 | -------------------------------------------------------------------------------- /blinky/constraints/nexys4ddr.xdc: -------------------------------------------------------------------------------- 1 | # Clock pin 2 | set_property PACKAGE_PIN E3 [get_ports {clock}] 3 | set_property IOSTANDARD LVCMOS33 [get_ports {clock}] 4 | create_clock -period 10.0 [get_ports {clock}] 5 | 6 | # LEDs 7 | set_property PACKAGE_PIN H17 [get_ports {io_led0}] 8 | set_property PACKAGE_PIN K15 [get_ports {io_led1}] 9 | set_property PACKAGE_PIN J13 [get_ports {io_led2}] 10 | set_property IOSTANDARD LVCMOS33 [get_ports {io_led0}] 11 | set_property IOSTANDARD LVCMOS33 [get_ports {io_led1}] 12 | set_property IOSTANDARD LVCMOS33 [get_ports {io_led2}] 13 | 14 | # Center button assigned to reset 15 | set_property PACKAGE_PIN N17 [get_ports { reset }] 16 | set_property IOSTANDARD LVCMOS33 [get_ports { reset }] 17 | -------------------------------------------------------------------------------- /blinky/constraints/orange-crab.lpf: -------------------------------------------------------------------------------- 1 | LOCATE COMP "clock" SITE "A9"; 2 | IOBUF PORT "clock" IO_TYPE=LVCMOS33; 3 | FREQUENCY PORT "clock" 48.000 MHZ; 4 | 5 | LOCATE COMP "reset" SITE "J17"; 6 | IOBUF PORT "reset" IO_TYPE=SSTL135_I; 7 | 8 | LOCATE COMP "io_tx" SITE "N17"; 9 | LOCATE COMP "io_rx" SITE "M18"; 10 | 11 | IOBUF PORT "io_tx" IO_TYPE=LVCMOS33; 12 | IOBUF PORT "io_rx" IO_TYPE=LVCMOS33; 13 | 14 | LOCATE COMP "io_led0" SITE "K4"; 15 | LOCATE COMP "io_led1" SITE "M3"; 16 | LOCATE COMP "io_led2" SITE "J3"; 17 | 18 | IOBUF PORT "io_led0" IO_TYPE=LVCMOS33; 19 | IOBUF PORT "io_led1" IO_TYPE=LVCMOS33; 20 | IOBUF PORT "io_led2" IO_TYPE=LVCMOS33; 21 | -------------------------------------------------------------------------------- /blinky/constraints/polarfire_evaluation.pdc: -------------------------------------------------------------------------------- 1 | set_io -port_name {clock} -pin_name E25 -io_std LVCMOS18 -fixed true 2 | set_io -port_name {reset} -pin_name K22 -io_std LVCMOS18 -fixed true 3 | 4 | set_io -port_name {io_sw0} -pin_name B27 -io_std LVCMOS18 -fixed true 5 | set_io -port_name {io_sw1} -pin_name C21 -io_std LVCMOS18 -fixed true 6 | set_io -port_name {io_sw2} -pin_name A25 -io_std LVCMOS18 -fixed true 7 | set_io -port_name {io_sw3} -pin_name B19 -io_std LVCMOS18 -fixed true 8 | 9 | set_io -port_name {io_tx} -pin_name H18 -io_std LVCMOS18 -fixed true 10 | set_io -port_name {io_rx} -pin_name G17 -io_std LVCMOS18 -fixed true 11 | 12 | set_io -port_name {io_led0} -pin_name F22 -io_std LVCMOS18 -fixed true 13 | set_io -port_name {io_led1} -pin_name B26 -io_std LVCMOS18 -fixed true 14 | set_io -port_name {io_led2} -pin_name C26 -io_std LVCMOS18 -fixed true 15 | set_io -port_name {io_led3} -pin_name D25 -io_std LVCMOS18 -fixed true 16 | set_io -port_name {io_led4} -pin_name C27 -io_std LVCMOS18 -fixed true 17 | set_io -port_name {io_led5} -pin_name F23 -io_std LVCMOS18 -fixed true 18 | set_io -port_name {io_led6} -pin_name H22 -io_std LVCMOS18 -fixed true 19 | set_io -port_name {io_led7} -pin_name H21 -io_std LVCMOS18 -fixed true 20 | 21 | set_io -port_name {io_dip1} -pin_name H23 -io_std LVCMOS18 -fixed true 22 | set_io -port_name {io_dip2} -pin_name D21 -io_std LVCMOS18 -fixed true 23 | set_io -port_name {io_dip3} -pin_name H24 -io_std LVCMOS18 -fixed true 24 | set_io -port_name {io_dip4} -pin_name C22 -io_std LVCMOS18 -fixed true 25 | set_io -port_name {io_dip5} -pin_name B21 -io_std LVCMOS18 -fixed true 26 | set_io -port_name {io_dip6} -pin_name G20 -io_std LVCMOS18 -fixed true 27 | set_io -port_name {io_dip7} -pin_name F24 -io_std LVCMOS18 -fixed true 28 | set_io -port_name {io_dip8} -pin_name F25 -io_std LVCMOS18 -fixed true 29 | -------------------------------------------------------------------------------- /blinky/constraints/qmtech-kintex7.xdc: -------------------------------------------------------------------------------- 1 | ##### Core board ##### 2 | # Clock 3 | set_property LOC F22 [get_ports clock] 4 | set_property IOSTANDARD LVCMOS33 [get_ports {clock}] 5 | 6 | # LED2_FPGA J26 7 | set_property LOC J26 [get_ports io_led0] 8 | set_property IOSTANDARD LVCMOS33 [get_ports {io_led0}] 9 | 10 | # LED3_FPGA H26 11 | set_property LOC H26 [get_ports io_led2] 12 | set_property IOSTANDARD LVCMOS33 [get_ports {io_led2}] 13 | 14 | ##Buttons 15 | # Sw 2 - AF9 16 | # set_property LOC AF9 [get_ports reset] 17 | # set_property IOSTANDARD LVCMOS33 [get_ports {reset}] 18 | 19 | # Sw 3 - AF10 20 | # set_property LOC AF10 [get_ports sw3] 21 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw3}] 22 | 23 | ##### Daughter board ##### 24 | 25 | # LED0 26 | # set_property LOC A18 [get_ports io_led0] 27 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_led0}] 28 | 29 | # LED1 30 | # set_property LOC A19 [get_ports io_led1] 31 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_led1}] 32 | 33 | # LED2 34 | # set_property LOC C17 [get_ports io_led2] 35 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_led2}] 36 | 37 | # LED3 38 | # set_property LOC C18 [get_ports io_led3] 39 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_led3}] 40 | 41 | # LED4 42 | # set_property LOC E18 [get_ports io_GPIO0[3]] 43 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_GPIO0[3]}] 44 | 45 | ##Buttons 46 | # SW2 47 | set_property LOC B20 [get_ports reset] 48 | set_property IOSTANDARD LVCMOS33 [get_ports {reset}] 49 | # SW3 50 | # set_property LOC A20 [get_ports d_sw3] 51 | # set_property IOSTANDARD LVCMOS33 [get_ports {d_sw3}] 52 | # SW4 53 | # set_property LOC C19 [get_ports d_sw4] 54 | # set_property IOSTANDARD LVCMOS33 [get_ports {d_sw4}] 55 | # SW5 56 | # set_property LOC B19 [get_ports d_sw5] 57 | # set_property IOSTANDARD LVCMOS33 [get_ports {d_sw5}] 58 | 59 | 60 | ##USB-UART Interface (On jp3 in daughter board) Pin 1 - GND, Pin 3 - TX, Pin 5 - RX 61 | # set_property LOC B12 [get_ports io_UART0tx] 62 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_UART0tx}] 63 | # set_property LOC B11 [get_ports io_UART0rx] 64 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_UART0rx}] -------------------------------------------------------------------------------- /blinky/constraints/qmtech-zyjzgw.xdc: -------------------------------------------------------------------------------- 1 | ##### Core board ##### 2 | 3 | set_property LOC F22 [get_ports clock] 4 | set_property IOSTANDARD LVCMOS33 [get_ports {clock}] 5 | 6 | # LED2_FPGA R26 7 | set_property LOC R26 [get_ports io_led0] 8 | set_property IOSTANDARD LVCMOS33 [get_ports {io_led0}] 9 | 10 | # LED3_FPGA P26 11 | set_property LOC P26 [get_ports io_led2] 12 | set_property IOSTANDARD LVCMOS33 [get_ports {io_led2}] 13 | 14 | ##Buttons 15 | # Sw 2 - AB26 16 | set_property LOC AB26 [get_ports reset] 17 | set_property IOSTANDARD LVCMOS33 [get_ports {reset}] 18 | 19 | # Sw 3 - AC26 20 | # set_property LOC AC26 [get_ports sw3] 21 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw3}] 22 | 23 | ##### Daughter board ##### 24 | 25 | # LED3_FPGA BANK14_E25 26 | # set_property LOC E25 [get_ports io_led1] 27 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_led1}] 28 | 29 | # LED4_FPGA BANK16_C14 30 | # set_property LOC C14 [get_ports io_GPIO0[2]] 31 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_GPIO0[2]}] 32 | 33 | # LED5_FPGA BANK16_B14 34 | # set_property LOC B14 [get_ports io_GPIO0[3]] 35 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_GPIO0[3]}] 36 | 37 | ##Buttons 38 | # Sw1 39 | # set_property LOC Y22 [get_ports sw1] 40 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw1}] 41 | # Sw2 42 | # set_property LOC AA22 [get_ports sw2] 43 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw2}] 44 | # Sw3 45 | # set_property LOC Y23 [get_ports sw3] 46 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw3}] 47 | # Sw4 48 | # set_property LOC AA24 [get_ports sw4] 49 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw4}] 50 | # Sw5 51 | # set_property LOC AC23 [get_ports sw5] 52 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw5}] 53 | # Sw6 54 | # set_property LOC AC24 [get_ports sw6] 55 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw6}] 56 | # Sw7 57 | # set_property LOC AA25 [get_ports sw7] 58 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw7}] 59 | # Sw8 60 | # set_property LOC AB25 [get_ports sw8] 61 | # set_property IOSTANDARD LVCMOS33 [get_ports {sw8}] 62 | 63 | 64 | ##USB-UART Interface (On jp3 in daughter board) Pin 1 - GND, Pin 3 - TX, Pin 5 - RX 65 | # set_property LOC AE26 [get_ports io_UART0tx] 66 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_UART0tx}] 67 | # set_property LOC AD26 [get_ports io_UART0rx] 68 | # set_property IOSTANDARD LVCMOS33 [get_ports {io_UART0rx}] -------------------------------------------------------------------------------- /blinky/constraints/qomu.pcf: -------------------------------------------------------------------------------- 1 | // QuickFeather uses the QFN package, others mostly use the BGA package. 2 | // can do (QFN) : set_io SIGNAL_NAME QFN_PIN_NUM 3 | // can do (BGA) : set_io SIGNAL_NAME BGA_BALL_NUM 4 | // can do (WLCSP) : set_io SIGNAL_NAME WLCSP_PIN_NUM 5 | // can do (ALL) : set_io SIGNAL_NAME IO_PAD_NUM 6 | // 7 | // RED LED, for example is on IO_22, which is QFN_PIN_NUM 34 (BGA BALL G7) 8 | // so, 9 | // (QFN) : set_io red_led 34 10 | // (BGA) : set_io red_led G7 11 | // (ALL) : set_io red_led IO_22 12 | // are equivalent 13 | // NOTE that the WLSCP version of EOSS3 does not have IO_22 brought out at all! 14 | // So, this signal cannot be used with the WLCSP package. 15 | // 16 | // by using the IO_PAD_NUM -> we don't need to change PCF across chip package variants. 17 | // However, we need to be careful that the relevant IO_PAD is actually brought out in the variant we are using. 18 | // WLCSP package of EOSS3 has a much lower number of IOs compared to the BGA/QFN package. 19 | // 20 | // signals defined here, can be directly accessed in the Verilog code. 21 | 22 | // Qomu Pinout 23 | // 24 | // D2 - Red LED 25 | // A6 - Green LED 26 | // F4 - Blue LED 27 | // B5 - Touch 1 28 | // D1 - Touch 2 29 | // A7 - Touch 3 30 | // E3 - Touch 4 31 | // E7 - UART TX 32 | // F7 - UART RX 33 | // D5 - SPI SCLK 34 | // F5 - SPI MISO 35 | // E6 - SPI MOSI 36 | 37 | set_io io_led0 D2 38 | set_io io_led1 A6 39 | set_io io_led2 F4 -------------------------------------------------------------------------------- /blinky/constraints/storey_peak_stratixV.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (125 Mhz) 2 | create_clock -name "clk" -period 8.000ns [get_ports {clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /blinky/constraints/storey_peak_stratixV.tcl: -------------------------------------------------------------------------------- 1 | # Global 2 | set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "As output driving ground" 3 | 4 | # Clock 5 | set_location_assignment PIN_M23 -to clock 6 | set_instance_assignment -name IO_STANDARD "SSTL-135" -to clock 7 | 8 | # Reset 9 | 10 | # LEDs 11 | set_location_assignment PIN_A11 -to io_led0 12 | set_instance_assignment -name IO_STANDARD "2.5 V" -to io_led0 13 | set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to io_led0 14 | set_instance_assignment -name SLEW_RATE 0 -to io_led0 15 | 16 | set_location_assignment PIN_A10 -to io_led1 17 | set_instance_assignment -name IO_STANDARD "2.5 V" -to io_led1 18 | set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to io_led1 19 | set_instance_assignment -name SLEW_RATE 0 -to io_led1 20 | 21 | set_location_assignment PIN_B10 -to io_led2 22 | set_instance_assignment -name IO_STANDARD "2.5 V" -to io_led2 23 | set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to io_led2 24 | set_instance_assignment -name SLEW_RATE 0 -to io_led2 25 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5U-25F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5U-45F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x41112043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5U-85F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x41113043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5UM-25F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x01111043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5UM-45F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x01112043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5UM-85F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x01113043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5UM5G-25F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x81111043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5UM5G-45F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x81112043 2 | -------------------------------------------------------------------------------- /blinky/openocd/LFE5UM5G-85F.cfg: -------------------------------------------------------------------------------- 1 | jtag newtap ecp5 tap -irlen 8 -expected-id 0x81113043 2 | -------------------------------------------------------------------------------- /blinky/openocd/digilent-hs1.cfg: -------------------------------------------------------------------------------- 1 | # this supports JTAG-HS1 and JTAG-SMT1 2 | # (the later being the OEM on-board version) 3 | 4 | interface ftdi 5 | ftdi_device_desc "Digilent USB Device" 6 | ftdi_vid_pid 0x0403 0x6010 7 | # channel 1 does not have any functionality 8 | ftdi_channel 0 9 | # just TCK TDI TDO TMS, no reset 10 | ftdi_layout_init 0x0088 0x008b 11 | reset_config none 12 | 13 | # default speed 14 | adapter_khz 5000 15 | -------------------------------------------------------------------------------- /blinky/openocd/ecp5-evn.cfg: -------------------------------------------------------------------------------- 1 | # this supports ECP5 Evaluation Board 2 | 3 | interface ftdi 4 | ftdi_device_desc "Lattice ECP5 Evaluation Board" 5 | ftdi_vid_pid 0x0403 0x6010 6 | # channel 1 does not have any functionality 7 | ftdi_channel 0 8 | # just TCK TDI TDO TMS, no reset 9 | ftdi_layout_init 0xfff8 0xfffb 10 | reset_config none 11 | 12 | # default speed 13 | adapter_khz 5000 14 | -------------------------------------------------------------------------------- /blinky/openocd/ft231x.cfg: -------------------------------------------------------------------------------- 1 | adapter driver ft232r 2 | ft232r_vid_pid 0x0403 0x6015 3 | # ULX3S specific GPIO setting 4 | ft232r_tck_num DSR 5 | ft232r_tms_num DCD 6 | ft232r_tdi_num RI 7 | ft232r_tdo_num CTS 8 | # trst/srst are not used but must have different values than above 9 | ft232r_trst_num RTS 10 | ft232r_srst_num DTR 11 | adapter speed 1000 12 | -------------------------------------------------------------------------------- /blinky/openocd/olimex-arm-usb-tiny-h.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Olimex ARM-USB-TINY-H 3 | # 4 | # http://www.olimex.com/dev/arm-usb-tiny-h.html 5 | # 6 | 7 | interface ftdi 8 | ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" 9 | ftdi_vid_pid 0x15ba 0x002a 10 | 11 | ftdi_layout_init 0x0808 0x0a1b 12 | ftdi_layout_signal nSRST -oe 0x0200 13 | ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 14 | ftdi_layout_signal LED -data 0x0800 15 | 16 | # default speed 17 | adapter_khz 5000 18 | -------------------------------------------------------------------------------- /blinky/openocd/xilinx-xc7.cfg: -------------------------------------------------------------------------------- 1 | # xilinx series 7 (artix, kintex, virtex) 2 | # http://www.xilinx.com/support/documentation/user_guides/ug470_7Series_Config.pdf 3 | 4 | if { [info exists CHIPNAME] } { 5 | set _CHIPNAME $CHIPNAME 6 | } else { 7 | set _CHIPNAME xc7 8 | } 9 | 10 | # the 4 top bits (28:31) are the die stepping/revisions. ignore it. 11 | jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \ 12 | -expected-id 0x03622093 \ 13 | -expected-id 0x03620093 \ 14 | -expected-id 0x037C4093 \ 15 | -expected-id 0x0362F093 \ 16 | -expected-id 0x037C8093 \ 17 | -expected-id 0x037C7093 \ 18 | -expected-id 0x037C3093 \ 19 | -expected-id 0x0362E093 \ 20 | -expected-id 0x037C2093 \ 21 | -expected-id 0x0362D093 \ 22 | -expected-id 0x0362C093 \ 23 | -expected-id 0x03632093 \ 24 | -expected-id 0x03631093 \ 25 | -expected-id 0x03636093 \ 26 | -expected-id 0x03647093 \ 27 | -expected-id 0x0364C093 \ 28 | -expected-id 0x03651093 \ 29 | -expected-id 0x03747093 \ 30 | -expected-id 0x03656093 \ 31 | -expected-id 0x03752093 \ 32 | -expected-id 0x03751093 \ 33 | -expected-id 0x03671093 \ 34 | -expected-id 0x036B3093 \ 35 | -expected-id 0x036B7093 \ 36 | -expected-id 0x036BB093 \ 37 | -expected-id 0x036BF093 \ 38 | -expected-id 0x03667093 \ 39 | -expected-id 0x03682093 \ 40 | -expected-id 0x03687093 \ 41 | -expected-id 0x03692093 \ 42 | -expected-id 0x03691093 \ 43 | -expected-id 0x03696093 \ 44 | -expected-id 0x036D5093 \ 45 | -expected-id 0x036D9093 \ 46 | -expected-id 0x036DB093 47 | 48 | pld device virtex2 $_CHIPNAME.tap 1 49 | 50 | set XC7_JSHUTDOWN 0x0d 51 | set XC7_JPROGRAM 0x0b 52 | set XC7_JSTART 0x0c 53 | set XC7_BYPASS 0x3f 54 | 55 | proc xc7_program {tap} { 56 | global XC7_JSHUTDOWN XC7_JPROGRAM XC7_JSTART XC7_BYPASS 57 | irscan $tap $XC7_JSHUTDOWN 58 | irscan $tap $XC7_JPROGRAM 59 | runtest 60000 60 | #JSTART prevents this from working... 61 | #irscan $tap $XC7_JSTART 62 | runtest 2000 63 | irscan $tap $XC7_BYPASS 64 | runtest 2000 65 | } 66 | -------------------------------------------------------------------------------- /blinky/proginfo/artix7-template.txt: -------------------------------------------------------------------------------- 1 | # Programming instructions for Digilent Arty A7 - Artix 7 2 | 3 | ## To program the board using OpenOCD, use the command: 4 | 5 | openocd -f $interfaceConfig -f $boardConfig -c "transport select jtag;init; pld load 0 $bitstream; exit" 6 | -------------------------------------------------------------------------------- /blinky/proginfo/boardconfig.yaml: -------------------------------------------------------------------------------- 1 | # This is the board programming files config 2 | # The board parameters must match the template for each board 3 | 4 | boards: 5 | ulx3s-85f: 6 | templateFile: ulx3s-template.txt 7 | interfaceConfig: ft231x.cfg 8 | boardConfig: LFE5U-85F.cfg 9 | bitstream: carlosedp_demo_chiselblinky_0.bit 10 | bitstreamSVF: carlosedp_demo_chiselblinky_0.svf 11 | 12 | artya7-35t: 13 | templateFile: artix7-template.txt 14 | interfaceConfig: digilent-hs1.cfg 15 | boardConfig: xilinx-xc7.cfg 16 | bitstream: Toplevel.bit 17 | 18 | qmtech_k325t: 19 | templateFile: qmtech_k325t-template.txt 20 | bitstream: carlosedp_demo_chiselblinky_0.bit 21 | -------------------------------------------------------------------------------- /blinky/proginfo/dfu-util.txt: -------------------------------------------------------------------------------- 1 | # Programming instructions for Fomu 2 | 3 | ## To program the board using dfu-util, use the command: 4 | 5 | dfu-util -e -d 1209:5bf0 -D $bitstream 6 | -------------------------------------------------------------------------------- /blinky/proginfo/proginfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import os 3 | import sys 4 | import glob 5 | import yaml 6 | from string import Template 7 | 8 | def main(): 9 | print("Build completed") 10 | with open(findFile('boardconfig.yaml')) as file: 11 | fullfile = yaml.full_load(file) 12 | boards = fullfile['boards'] 13 | boardFiles = {} 14 | if sys.argv[1] in boards: 15 | for param in boards[sys.argv[1]]: 16 | boardFiles[param] = findFile(boards[sys.argv[1]][param]) 17 | render(boardFiles, findFile(boards[sys.argv[1]]['templateFile'])) 18 | else: 19 | print("ERROR: Board " + sys.argv[1] + " not found in boardconfig.yaml") 20 | exit(1) 21 | print("") 22 | 23 | # Utility Functions 24 | 25 | def findFile(f, filter=""): 26 | r = glob.glob("../**/" + f, recursive=True) 27 | if filter != "": 28 | r = [s for s in r if filter in s] 29 | if not r: 30 | print("ERROR: Could not find file " + f) 31 | exit(1) 32 | return os.path.realpath(r[0]) 33 | 34 | def render(d, template): 35 | with open(os.path.join(os.getcwd(),template)) as f: 36 | src = Template(f.read()) 37 | output = src.substitute(d) 38 | print(output) 39 | 40 | if __name__ == "__main__": 41 | if len(sys.argv) <= 1: 42 | print("Board not supplied") 43 | exit(1) 44 | main() 45 | -------------------------------------------------------------------------------- /blinky/proginfo/qmtech_k325t-template.txt: -------------------------------------------------------------------------------- 1 | # Programming instructions for QMTech Kintex 7 board 2 | 3 | ## To program the board using OpenFPGAloader (), use the command: 4 | 5 | openfpgaloader -c ft232 $bitstream 6 | -------------------------------------------------------------------------------- /blinky/proginfo/ulx3s-template.txt: -------------------------------------------------------------------------------- 1 | # Programming instructions for ULX3S based on Lattice ECP5 2 | 3 | ## To program with ujprog: 4 | 5 | ujprog $bitstreamSVF 6 | 7 | ## To program the board using OpenOCD, use the command: 8 | 9 | openocd -f $interfaceConfig -f $boardConfig -c "transport select jtag; init; scan_chain; svf -quiet -progress $bitstreamSVF; exit" 10 | 11 | Other programming options are listed here https://github.com/emard/ulx3s/blob/master/doc/MANUAL.md#programming-options 12 | -------------------------------------------------------------------------------- /blinky/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.5.7 2 | -------------------------------------------------------------------------------- /blinky/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") 2 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.29") 3 | addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.19") 4 | -------------------------------------------------------------------------------- /blinky/scripts/mill: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This is a wrapper script, that automatically download mill from GitHub release pages 4 | # You can give the required mill version with MILL_VERSION env variable 5 | # If no version is given, it falls back to the value of DEFAULT_MILL_VERSION 6 | DEFAULT_MILL_VERSION=0.9.9 7 | 8 | set -e 9 | 10 | if [ -z "$MILL_VERSION" ] ; then 11 | if [ -f ".mill-version" ] ; then 12 | MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)" 13 | elif [ -f "mill" ] && [ "$BASH_SOURCE" != "mill" ] ; then 14 | MILL_VERSION=$(grep -F "DEFAULT_MILL_VERSION=" "mill" | head -n 1 | cut -d= -f2) 15 | else 16 | MILL_VERSION=$DEFAULT_MILL_VERSION 17 | fi 18 | fi 19 | 20 | if [ "x${XDG_CACHE_HOME}" != "x" ] ; then 21 | MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download" 22 | else 23 | MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download" 24 | fi 25 | MILL_EXEC_PATH="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" 26 | 27 | version_remainder="$MILL_VERSION" 28 | MILL_MAJOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}" 29 | MILL_MINOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}" 30 | 31 | if [ ! -x "$MILL_EXEC_PATH" ] ; then 32 | mkdir -p $MILL_DOWNLOAD_PATH 33 | if [ "$MILL_MAJOR_VERSION" -gt 0 ] || [ "$MILL_MINOR_VERSION" -ge 5 ] ; then 34 | ASSEMBLY="-assembly" 35 | fi 36 | DOWNLOAD_FILE=$MILL_EXEC_PATH-tmp-download 37 | MILL_DOWNLOAD_URL="https://github.com/lihaoyi/mill/releases/download/${MILL_VERSION%%-*}/$MILL_VERSION${ASSEMBLY}" 38 | curl --fail -L -o "$DOWNLOAD_FILE" "$MILL_DOWNLOAD_URL" 39 | chmod +x "$DOWNLOAD_FILE" 40 | mv "$DOWNLOAD_FILE" "$MILL_EXEC_PATH" 41 | unset DOWNLOAD_FILE 42 | unset MILL_DOWNLOAD_URL 43 | fi 44 | 45 | unset MILL_DOWNLOAD_PATH 46 | unset MILL_VERSION 47 | 48 | exec $MILL_EXEC_PATH "$@" 49 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_artya7-35t.v: -------------------------------------------------------------------------------- 1 | `timescale 1ps/1ps 2 | 3 | // Input clock is 100Mhz 4 | // Output clock is 25Mhz 5 | 6 | module PLL0 7 | 8 | ( 9 | output clko, 10 | output lock, 11 | input clki 12 | ); 13 | // Input buffering 14 | //------------------------------------ 15 | wire clki_clk_wiz_0; 16 | IBUF clkin1_ibufg 17 | (.O (clki_clk_wiz_0), 18 | .I (clki)); 19 | 20 | // Clocking PRIMITIVE 21 | //------------------------------------ 22 | 23 | // Instantiation of the MMCM PRIMITIVE 24 | // * Unused inputs are tied off 25 | // * Unused outputs are labeled unused 26 | 27 | wire clko_clk_wiz_0; 28 | wire clk_out2_clk_wiz_0; 29 | wire clk_out3_clk_wiz_0; 30 | wire clk_out4_clk_wiz_0; 31 | wire clk_out5_clk_wiz_0; 32 | wire clk_out6_clk_wiz_0; 33 | wire clk_out7_clk_wiz_0; 34 | 35 | wire [15:0] do_unused; 36 | wire drdy_unused; 37 | wire psdone_unused; 38 | wire lock_int; 39 | wire clkfbout_clk_wiz_0; 40 | wire clkfbout_buf_clk_wiz_0; 41 | wire clkfboutb_unused; 42 | wire clkout1_unused; 43 | wire clkout2_unused; 44 | wire clkout3_unused; 45 | wire clkout4_unused; 46 | wire clkout5_unused; 47 | wire clkout6_unused; 48 | wire clkfbstopped_unused; 49 | wire clkinstopped_unused; 50 | 51 | PLLE2_ADV 52 | #(.BANDWIDTH ("OPTIMIZED"), 53 | .COMPENSATION ("INTERNAL"), 54 | .STARTUP_WAIT ("FALSE"), 55 | .DIVCLK_DIVIDE (4), 56 | .CLKFBOUT_MULT (33), 57 | .CLKFBOUT_PHASE (0.000), 58 | .CLKOUT0_DIVIDE (33), 59 | .CLKOUT0_PHASE (0.000), 60 | .CLKOUT0_DUTY_CYCLE (0.500), 61 | .CLKIN1_PERIOD (10.000), 62 | .CLKIN2_PERIOD (10.312)) 63 | plle2_adv_inst 64 | // Output clocks 65 | ( 66 | .CLKFBOUT (clkfbout_clk_wiz_0), 67 | .CLKOUT0 (clko_clk_wiz_0), 68 | .CLKOUT1 (clkout1_unused), 69 | .CLKOUT2 (clkout2_unused), 70 | .CLKOUT3 (clkout3_unused), 71 | .CLKOUT4 (clkout4_unused), 72 | .CLKOUT5 (clkout5_unused), 73 | // Input clock control 74 | .CLKFBIN (clkfbout_buf_clk_wiz_0), 75 | .CLKIN1 (clki_clk_wiz_0), 76 | .CLKIN2 (clki_clk_wiz_0), 77 | .CLKINSEL (1'b1), 78 | // Ports for dynamic reconfiguration 79 | .DADDR (7'h0), 80 | .DCLK (1'b0), 81 | .DEN (1'b0), 82 | .DI (16'h0), 83 | .DO (do_unused), 84 | .DRDY (drdy_unused), 85 | .DWE (1'b0), 86 | // Other control and status signals 87 | .LOCKED (lock_int), 88 | .PWRDWN (1'b0), 89 | .RST (1'b0)); 90 | 91 | assign lock = lock_int; 92 | // Clock Monitor clock assigning 93 | //-------------------------------------- 94 | // Output buffering 95 | //----------------------------------- 96 | 97 | BUFG clkf_buf 98 | (.O (clkfbout_buf_clk_wiz_0), 99 | .I (clkfbout_clk_wiz_0)); 100 | 101 | BUFG clkout1_buf 102 | (.O (clko), 103 | .I (clko_clk_wiz_0)); 104 | 105 | endmodule 106 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_de1_soc_revF.v: -------------------------------------------------------------------------------- 1 | // This isn't really a PLL, but it halves the clock. 2 | module PLL0 3 | ( 4 | input clki, // 50 MHz 5 | output clko, // 25 MHz 6 | output lock 7 | ); 8 | 9 | reg half_clk; 10 | assign clko = half_clk; 11 | 12 | always @(posedge clki) begin 13 | half_clk <= !half_clk; 14 | end 15 | 16 | endmodule 17 | 18 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_evn.v: -------------------------------------------------------------------------------- 1 | module PLL0( 2 | input clki, 3 | output clko, 4 | output lock 5 | ); 6 | (* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *) 7 | 8 | EHXPLLL #( 9 | .PLLRST_ENA("DISABLED"), 10 | .INTFB_WAKE("DISABLED"), 11 | .STDBY_ENABLE("DISABLED"), 12 | .DPHASE_SOURCE("DISABLED"), 13 | .CLKOP_FPHASE(0), 14 | .CLKOP_CPHASE(11), 15 | .OUTDIVIDER_MUXA("DIVA"), 16 | .CLKOP_ENABLE("ENABLED"), 17 | .CLKOP_DIV(12), 18 | .CLKFB_DIV(25), 19 | .CLKI_DIV(6), 20 | .FEEDBK_PATH("CLKOP") 21 | ) pll_i ( 22 | .CLKI(clki), 23 | .CLKFB(clko), 24 | .CLKOP(clko), 25 | .LOCK(lock), 26 | .RST(1'b0), 27 | .STDBY(1'b0), 28 | .PHASESEL0(1'b0), 29 | .PHASESEL1(1'b0), 30 | .PHASEDIR(1'b0), 31 | .PHASESTEP(1'b0), 32 | .PLLWAKESYNC(1'b0), 33 | .ENCLKOP(1'b0) 34 | ); 35 | 36 | endmodule 37 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_nexys4ddr.v: -------------------------------------------------------------------------------- 1 | `timescale 1ps/1ps 2 | 3 | module PLL0 4 | 5 | ( 6 | output clko, 7 | output lock, 8 | input clki 9 | ); 10 | // Input buffering 11 | //------------------------------------ 12 | wire clki_clk_wiz_0; 13 | IBUF clkin1_ibufg 14 | (.O (clki_clk_wiz_0), 15 | .I (clki)); 16 | 17 | // Clocking PRIMITIVE 18 | //------------------------------------ 19 | 20 | // Instantiation of the MMCM PRIMITIVE 21 | // * Unused inputs are tied off 22 | // * Unused outputs are labeled unused 23 | 24 | wire clko_clk_wiz_0; 25 | wire clk_out2_clk_wiz_0; 26 | wire clk_out3_clk_wiz_0; 27 | wire clk_out4_clk_wiz_0; 28 | wire clk_out5_clk_wiz_0; 29 | wire clk_out6_clk_wiz_0; 30 | wire clk_out7_clk_wiz_0; 31 | 32 | wire [15:0] do_unused; 33 | wire drdy_unused; 34 | wire psdone_unused; 35 | wire lock_int; 36 | wire clkfbout_clk_wiz_0; 37 | wire clkfbout_buf_clk_wiz_0; 38 | wire clkfboutb_unused; 39 | wire clkout1_unused; 40 | wire clkout2_unused; 41 | wire clkout3_unused; 42 | wire clkout4_unused; 43 | wire clkout5_unused; 44 | wire clkout6_unused; 45 | wire clkfbstopped_unused; 46 | wire clkinstopped_unused; 47 | 48 | PLLE2_ADV 49 | #(.BANDWIDTH ("OPTIMIZED"), 50 | .COMPENSATION ("ZHOLD"), 51 | .STARTUP_WAIT ("FALSE"), 52 | .DIVCLK_DIVIDE (4), 53 | .CLKFBOUT_MULT (33), 54 | .CLKFBOUT_PHASE (0.000), 55 | .CLKOUT0_DIVIDE (33), 56 | .CLKOUT0_PHASE (0.000), 57 | .CLKOUT0_DUTY_CYCLE (0.500), 58 | .CLKIN1_PERIOD (10.000), 59 | .CLKIN2_PERIOD (10.312)) 60 | plle2_adv_inst 61 | // Output clocks 62 | ( 63 | .CLKFBOUT (clkfbout_clk_wiz_0), 64 | .CLKOUT0 (clko_clk_wiz_0), 65 | .CLKOUT1 (clkout1_unused), 66 | .CLKOUT2 (clkout2_unused), 67 | .CLKOUT3 (clkout3_unused), 68 | .CLKOUT4 (clkout4_unused), 69 | .CLKOUT5 (clkout5_unused), 70 | // Input clock control 71 | .CLKFBIN (clkfbout_buf_clk_wiz_0), 72 | .CLKIN1 (clki_clk_wiz_0), 73 | .CLKIN2 (clki_clk_wiz_0), 74 | .CLKINSEL (1'b1), 75 | // Ports for dynamic reconfiguration 76 | .DADDR (7'h0), 77 | .DCLK (1'b0), 78 | .DEN (1'b0), 79 | .DI (16'h0), 80 | .DO (do_unused), 81 | .DRDY (drdy_unused), 82 | .DWE (1'b0), 83 | // Other control and status signals 84 | .LOCKED (lock_int), 85 | .PWRDWN (1'b0), 86 | .RST (1'b0)); 87 | 88 | assign lock = lock_int; 89 | // Clock Monitor clock assigning 90 | //-------------------------------------- 91 | // Output buffering 92 | //----------------------------------- 93 | 94 | BUFG clkf_buf 95 | (.O (clkfbout_buf_clk_wiz_0), 96 | .I (clkfbout_clk_wiz_0)); 97 | 98 | BUFG clkout1_buf 99 | (.O (clko), 100 | .I (clko_clk_wiz_0)); 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_orange-crab.v: -------------------------------------------------------------------------------- 1 | module PLL0 2 | ( 3 | input clki, // 48 MHz, 0 deg 4 | output clko, // 25 MHz, 0 deg 5 | output lock 6 | ); 7 | (* FREQUENCY_PIN_CLKI="48" *) 8 | (* FREQUENCY_PIN_CLKOP="25.6" *) 9 | (* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *) 10 | EHXPLLL #( 11 | .PLLRST_ENA("DISABLED"), 12 | .INTFB_WAKE("DISABLED"), 13 | .STDBY_ENABLE("DISABLED"), 14 | .DPHASE_SOURCE("DISABLED"), 15 | .OUTDIVIDER_MUXA("DIVA"), 16 | .OUTDIVIDER_MUXB("DIVB"), 17 | .OUTDIVIDER_MUXC("DIVC"), 18 | .OUTDIVIDER_MUXD("DIVD"), 19 | .CLKI_DIV(15), 20 | .CLKOP_ENABLE("ENABLED"), 21 | .CLKOP_DIV(23), 22 | .CLKOP_CPHASE(11), 23 | .CLKOP_FPHASE(0), 24 | .FEEDBK_PATH("CLKOP"), 25 | .CLKFB_DIV(8) 26 | ) pll_i ( 27 | .RST(1'b0), 28 | .STDBY(1'b0), 29 | .CLKI(clki), 30 | .CLKOP(clko), 31 | .CLKFB(clko), 32 | .CLKINTFB(), 33 | .PHASESEL0(1'b0), 34 | .PHASESEL1(1'b0), 35 | .PHASEDIR(1'b1), 36 | .PHASESTEP(1'b1), 37 | .PHASELOADREG(1'b1), 38 | .PLLWAKESYNC(1'b0), 39 | .ENCLKOP(1'b0), 40 | .LOCK(lock) 41 | ); 42 | endmodule 43 | 44 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_polarfireeval.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/100 ps 2 | // Version: v12.4 12.900.0.16 3 | 4 | module PLL0( 5 | input clki, // 50 MHz, 0 deg 6 | output clko, // 25 MHz, 0 deg 7 | output lock 8 | ); 9 | 10 | wire gnd_net, vcc_net, pll_inst_0_clkint_0; 11 | 12 | CLKINT clkint_0 (.A(pll_inst_0_clkint_0), .Y(clko)); 13 | PLL #( .VCOFREQUENCY(5000), .DELAY_LINE_SIMULATION_MODE(""), .DATA_RATE(0.0) 14 | , .FORMAL_NAME(""), .INTERFACE_NAME(""), .INTERFACE_LEVEL(3'b0) 15 | , .SOFTRESET(1'b0), .SOFT_POWERDOWN_N(1'b1), .RFDIV_EN(1'b1), .OUT0_DIV_EN(1'b1) 16 | , .OUT1_DIV_EN(1'b0), .OUT2_DIV_EN(1'b0), .OUT3_DIV_EN(1'b0), .SOFT_REF_CLK_SEL(1'b0) 17 | , .RESET_ON_LOCK(1'b1), .BYPASS_CLK_SEL(4'b0), .BYPASS_GO_EN_N(1'b1) 18 | , .BYPASS_PLL(4'b0), .BYPASS_OUT_DIVIDER(4'b0), .FF_REQUIRES_LOCK(1'b0) 19 | , .FSE_N(1'b0), .FB_CLK_SEL_0(2'b00), .FB_CLK_SEL_1(1'b0), .RFDIV(6'b000001) 20 | , .FRAC_EN(1'b0), .FRAC_DAC_EN(1'b0), .DIV0_RST_DELAY(3'b000) 21 | , .DIV0_VAL(7'b0110010), .DIV1_RST_DELAY(3'b0), .DIV1_VAL(7'b1) 22 | , .DIV2_RST_DELAY(3'b0), .DIV2_VAL(7'b1), .DIV3_RST_DELAY(3'b0) 23 | , .DIV3_VAL(7'b1), .DIV3_CLK_SEL(1'b0), .BW_INT_CTRL(2'b0), .BW_PROP_CTRL(2'b01) 24 | , .IREF_EN(1'b1), .IREF_TOGGLE(1'b0), .LOCK_CNT(4'b1000), .DESKEW_CAL_CNT(3'b110) 25 | , .DESKEW_CAL_EN(1'b1), .DESKEW_CAL_BYPASS(1'b0), .SYNC_REF_DIV_EN(1'b0) 26 | , .SYNC_REF_DIV_EN_2(1'b0), .OUT0_PHASE_SEL(3'b000), .OUT1_PHASE_SEL(3'b0) 27 | , .OUT2_PHASE_SEL(3'b0), .OUT3_PHASE_SEL(3'b0), .SOFT_LOAD_PHASE_N(1'b1) 28 | , .SSM_DIV_VAL(6'b1), .FB_FRAC_VAL(24'b0), .SSM_SPREAD_MODE(1'b0) 29 | , .SSM_MODULATION(5'b00101), .FB_INT_VAL(12'b000001100100), .SSM_EN_N(1'b1) 30 | , .SSM_EXT_WAVE_EN(2'b0), .SSM_EXT_WAVE_MAX_ADDR(8'b0), .SSM_RANDOM_EN(1'b0) 31 | , .SSM_RANDOM_PATTERN_SEL(3'b0), .CDMUX0_SEL(2'b0), .CDMUX1_SEL(1'b1) 32 | , .CDMUX2_SEL(1'b0), .CDELAY0_SEL(8'b0), .CDELAY0_EN(1'b0), .DRI_EN(1'b1) 33 | ) pll_inst_0 (.LOCK(lock), .SSCG_WAVE_TABLE_ADDR({nc0, 34 | nc1, nc2, nc3, nc4, nc5, nc6, nc7}), .DELAY_LINE_OUT_OF_RANGE() 35 | , .POWERDOWN_N(vcc_net), .OUT0_EN(vcc_net), .OUT1_EN(gnd_net), 36 | .OUT2_EN(gnd_net), .OUT3_EN(gnd_net), .REF_CLK_SEL(gnd_net), 37 | .BYPASS_EN_N(vcc_net), .LOAD_PHASE_N(vcc_net), 38 | .SSCG_WAVE_TABLE({gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 39 | gnd_net, gnd_net, gnd_net}), .PHASE_DIRECTION(gnd_net), 40 | .PHASE_ROTATE(gnd_net), .PHASE_OUT0_SEL(gnd_net), 41 | .PHASE_OUT1_SEL(gnd_net), .PHASE_OUT2_SEL(gnd_net), 42 | .PHASE_OUT3_SEL(gnd_net), .DELAY_LINE_MOVE(gnd_net), 43 | .DELAY_LINE_DIRECTION(gnd_net), .DELAY_LINE_WIDE(gnd_net), 44 | .DELAY_LINE_LOAD(vcc_net), .REFCLK_SYNC_EN(gnd_net), 45 | .REF_CLK_0(clki), .REF_CLK_1(gnd_net), .FB_CLK(gnd_net), 46 | .OUT0(pll_inst_0_clkint_0), .OUT1(), .OUT2(), .OUT3(), 47 | .DRI_CLK(gnd_net), .DRI_CTRL({gnd_net, gnd_net, gnd_net, 48 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 49 | gnd_net}), .DRI_WDATA({gnd_net, gnd_net, gnd_net, gnd_net, 50 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 51 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 52 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 53 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 54 | gnd_net}), .DRI_ARST_N(vcc_net), .DRI_RDATA({nc8, nc9, nc10, 55 | nc11, nc12, nc13, nc14, nc15, nc16, nc17, nc18, nc19, nc20, 56 | nc21, nc22, nc23, nc24, nc25, nc26, nc27, nc28, nc29, nc30, 57 | nc31, nc32, nc33, nc34, nc35, nc36, nc37, nc38, nc39, nc40}), 58 | .DRI_INTERRUPT()); 59 | VCC vcc_inst (.Y(vcc_net)); 60 | GND gnd_inst (.Y(gnd_net)); 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_qmtech_k325t.v: -------------------------------------------------------------------------------- 1 | `timescale 1ps/1ps 2 | 3 | // Input clock is 50Mhz 4 | // Output clock is 25Mhz 5 | 6 | module PLL0 7 | 8 | ( 9 | output clko, 10 | output lock, 11 | input clki 12 | ); 13 | // Input buffering 14 | //------------------------------------ 15 | wire clki_clk_wiz_0; 16 | IBUF clkin1_ibufg 17 | (.O (clki_clk_wiz_0), 18 | .I (clki)); 19 | 20 | // Clocking PRIMITIVE 21 | //------------------------------------ 22 | 23 | // Instantiation of the MMCM PRIMITIVE 24 | // * Unused inputs are tied off 25 | // * Unused outputs are labeled unused 26 | 27 | wire clko_clk_wiz_0; 28 | wire clk_out2_clk_wiz_0; 29 | wire clk_out3_clk_wiz_0; 30 | wire clk_out4_clk_wiz_0; 31 | wire clk_out5_clk_wiz_0; 32 | wire clk_out6_clk_wiz_0; 33 | wire clk_out7_clk_wiz_0; 34 | 35 | wire [15:0] do_unused; 36 | wire drdy_unused; 37 | wire psdone_unused; 38 | wire lock_int; 39 | wire clkfbout_clk_wiz_0; 40 | wire clkfbout_buf_clk_wiz_0; 41 | wire clkfboutb_unused; 42 | wire clkout1_unused; 43 | wire clkout2_unused; 44 | wire clkout3_unused; 45 | wire clkout4_unused; 46 | wire clkout5_unused; 47 | wire clkout6_unused; 48 | wire clkfbstopped_unused; 49 | wire clkinstopped_unused; 50 | 51 | PLLE2_ADV 52 | #(.BANDWIDTH ("OPTIMIZED"), 53 | .COMPENSATION ("INTERNAL"), 54 | .STARTUP_WAIT ("FALSE"), 55 | .DIVCLK_DIVIDE (2), 56 | .CLKFBOUT_MULT (33), 57 | .CLKFBOUT_PHASE (0.000), 58 | .CLKOUT0_DIVIDE (33), 59 | .CLKOUT0_PHASE (0.000), 60 | .CLKOUT0_DUTY_CYCLE (0.500), 61 | .CLKIN1_PERIOD (10.000), 62 | .CLKIN2_PERIOD (10.312)) 63 | plle2_adv_inst 64 | // Output clocks 65 | ( 66 | .CLKFBOUT (clkfbout_clk_wiz_0), 67 | .CLKOUT0 (clko_clk_wiz_0), 68 | .CLKOUT1 (clkout1_unused), 69 | .CLKOUT2 (clkout2_unused), 70 | .CLKOUT3 (clkout3_unused), 71 | .CLKOUT4 (clkout4_unused), 72 | .CLKOUT5 (clkout5_unused), 73 | // Input clock control 74 | .CLKFBIN (clkfbout_buf_clk_wiz_0), 75 | .CLKIN1 (clki_clk_wiz_0), 76 | .CLKIN2 (clki_clk_wiz_0), 77 | .CLKINSEL (1'b1), 78 | // Ports for dynamic reconfiguration 79 | .DADDR (7'h0), 80 | .DCLK (1'b0), 81 | .DEN (1'b0), 82 | .DI (16'h0), 83 | .DO (do_unused), 84 | .DRDY (drdy_unused), 85 | .DWE (1'b0), 86 | // Other control and status signals 87 | .LOCKED (lock_int), 88 | .PWRDWN (1'b0), 89 | .RST (1'b0)); 90 | 91 | assign lock = lock_int; 92 | // Clock Monitor clock assigning 93 | //-------------------------------------- 94 | // Output buffering 95 | //----------------------------------- 96 | 97 | BUFG clkf_buf 98 | (.O (clkfbout_buf_clk_wiz_0), 99 | .I (clkfbout_clk_wiz_0)); 100 | 101 | BUFG clkout1_buf 102 | (.O (clko), 103 | .I (clko_clk_wiz_0)); 104 | 105 | endmodule 106 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_qomu.v: -------------------------------------------------------------------------------- 1 | // This isn't really a PLL but a connection between the eFPGA and the MCU 2 | module PLL0 3 | ( 4 | input clki, // No input since the MCU generates the clock 5 | output clko, // 24 MHz output from the MCU clock generator (bootloader has 24Mhz and 48Mhz clocks) 6 | output lock 7 | ); 8 | 9 | /* CPU <-> FPGA interface 10 | * here only one of the two clock sources 11 | * and corresponding reset signal are used 12 | * Sys_Clk0/Sys_Clk0_Rst: C16 clock domain (default as 24Mhz from bootloader) 13 | * Sys_Clk1/Sys_Clk1_Rst: C21 clock domain (default as 48Mhz from bootloader) 14 | */ 15 | qlal4s3b_cell_macro u_qlal4s3b_cell_macro ( 16 | .Sys_Clk0 (clko), // we expect 25Mhz but the default 24Mhz from MCU is close :) 17 | .Sys_Clk0_Rst (), 18 | .Sys_Clk1 (), 19 | .Sys_Clk1_Rst () 20 | ); 21 | 22 | endmodule 23 | 24 | -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_storey_peak_stratixV.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module PLL0 3 | ( 4 | input clki, // 125 MHz 5 | output clko, // 25 MHz 6 | output lock 7 | ); 8 | 9 | altera_pll #( 10 | .fractional_vco_multiplier("false"), 11 | .reference_clock_frequency("125.0 MHz"), 12 | .operation_mode("direct"), 13 | .number_of_clocks(1), 14 | .output_clock_frequency0("25.000000 MHz"), 15 | .phase_shift0("0 ps"), 16 | .duty_cycle0(50), 17 | .output_clock_frequency1("0 MHz"), 18 | .phase_shift1("0 ps"), 19 | .duty_cycle1(50), 20 | .output_clock_frequency2("0 MHz"), 21 | .phase_shift2("0 ps"), 22 | .duty_cycle2(50), 23 | .output_clock_frequency3("0 MHz"), 24 | .phase_shift3("0 ps"), 25 | .duty_cycle3(50), 26 | .output_clock_frequency4("0 MHz"), 27 | .phase_shift4("0 ps"), 28 | .duty_cycle4(50), 29 | .output_clock_frequency5("0 MHz"), 30 | .phase_shift5("0 ps"), 31 | .duty_cycle5(50), 32 | .output_clock_frequency6("0 MHz"), 33 | .phase_shift6("0 ps"), 34 | .duty_cycle6(50), 35 | .output_clock_frequency7("0 MHz"), 36 | .phase_shift7("0 ps"), 37 | .duty_cycle7(50), 38 | .output_clock_frequency8("0 MHz"), 39 | .phase_shift8("0 ps"), 40 | .duty_cycle8(50), 41 | .output_clock_frequency9("0 MHz"), 42 | .phase_shift9("0 ps"), 43 | .duty_cycle9(50), 44 | .output_clock_frequency10("0 MHz"), 45 | .phase_shift10("0 ps"), 46 | .duty_cycle10(50), 47 | .output_clock_frequency11("0 MHz"), 48 | .phase_shift11("0 ps"), 49 | .duty_cycle11(50), 50 | .output_clock_frequency12("0 MHz"), 51 | .phase_shift12("0 ps"), 52 | .duty_cycle12(50), 53 | .output_clock_frequency13("0 MHz"), 54 | .phase_shift13("0 ps"), 55 | .duty_cycle13(50), 56 | .output_clock_frequency14("0 MHz"), 57 | .phase_shift14("0 ps"), 58 | .duty_cycle14(50), 59 | .output_clock_frequency15("0 MHz"), 60 | .phase_shift15("0 ps"), 61 | .duty_cycle15(50), 62 | .output_clock_frequency16("0 MHz"), 63 | .phase_shift16("0 ps"), 64 | .duty_cycle16(50), 65 | .output_clock_frequency17("0 MHz"), 66 | .phase_shift17("0 ps"), 67 | .duty_cycle17(50), 68 | .pll_type("General"), 69 | .pll_subtype("General") 70 | ) altera_pll_i ( 71 | .rst (1'b0), 72 | .outclk ({clko}), 73 | .locked (lock), 74 | .fboutclk ( ), 75 | .fbclk (1'b0), 76 | .refclk (clki) 77 | ); 78 | 79 | endmodule -------------------------------------------------------------------------------- /blinky/src/main/resources/pll_ulx3s.v: -------------------------------------------------------------------------------- 1 | module PLL0 2 | ( 3 | input clki, // 25 MHz, 0 deg 4 | output clko, // 25 MHz, 0 deg 5 | output lock 6 | ); 7 | (* FREQUENCY_PIN_CLKI="25" *) 8 | (* FREQUENCY_PIN_CLKOP="25" *) 9 | (* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *) 10 | EHXPLLL #( 11 | .PLLRST_ENA("DISABLED"), 12 | .INTFB_WAKE("DISABLED"), 13 | .STDBY_ENABLE("DISABLED"), 14 | .DPHASE_SOURCE("DISABLED"), 15 | .OUTDIVIDER_MUXA("DIVA"), 16 | .OUTDIVIDER_MUXB("DIVB"), 17 | .OUTDIVIDER_MUXC("DIVC"), 18 | .OUTDIVIDER_MUXD("DIVD"), 19 | .CLKI_DIV(1), 20 | .CLKOP_ENABLE("ENABLED"), 21 | .CLKOP_DIV(24), 22 | .CLKOP_CPHASE(11), 23 | .CLKOP_FPHASE(0), 24 | .FEEDBK_PATH("CLKOP"), 25 | .CLKFB_DIV(1) 26 | ) pll_i ( 27 | .RST(1'b0), 28 | .STDBY(1'b0), 29 | .CLKI(clki), 30 | .CLKOP(clko), 31 | .CLKFB(clko), 32 | .CLKINTFB(), 33 | .PHASESEL0(1'b0), 34 | .PHASESEL1(1'b0), 35 | .PHASEDIR(1'b1), 36 | .PHASESTEP(1'b1), 37 | .PHASELOADREG(1'b1), 38 | .PLLWAKESYNC(1'b0), 39 | .ENCLKOP(1'b0), 40 | .LOCK(lock) 41 | ); 42 | endmodule -------------------------------------------------------------------------------- /blinky/src/main/scala/BlackBoxPLL.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | import scala.io.Source 5 | 6 | class PLL0(board: String) extends BlackBox with HasBlackBoxInline { 7 | val io = IO(new Bundle() { 8 | val clki = Input(Clock()) 9 | val clko = Output(Clock()); 10 | val lock = Output(Clock()) 11 | }) 12 | 13 | val filename = "pll_" + board + ".v" 14 | val verilog = Source.fromResource(filename).getLines().mkString("\n") 15 | setInline("PLL.v", verilog) 16 | } 17 | -------------------------------------------------------------------------------- /blinky/src/main/scala/Blinky.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util._ 3 | 4 | /** 5 | * The blinking LED component. 6 | */ 7 | class Blinky(freq: Int, startOn: Boolean = false) extends Module { 8 | val io = IO(new Bundle { 9 | val led0 = Output(Bool()) 10 | val led1 = Output(Bool()) 11 | val led2 = Output(Bool()) 12 | }) 13 | 14 | // Alternate blink leds every second 15 | val led = RegInit(startOn.B) 16 | val (_, counterWrap) = Counter(true.B, freq / 2) 17 | when(counterWrap) { 18 | led := ~led 19 | } 20 | 21 | io.led0 := led 22 | io.led1 := ~led 23 | 24 | // 1 beathe cycle every second 25 | io.led2 := breathe(freq, 1000) 26 | 27 | // To set a specific PWM value instead (Eg. 10% duty cycle) 28 | // io.led2 := pwmAbs(10.U) 29 | 30 | //-------------- Utility Functions -------------- 31 | /** 32 | * pwmAbs creates a PWM output from a 0 to 100 Duty Cycle 33 | * 34 | * @param dutyCycle UInt from 0 to 100 (as in percent) 35 | * @return Bool output 36 | */ 37 | def pwmAbs(dutyCycle: UInt) = { 38 | // Divide input frequency by 1024 to avoid switchind the LEDs at high freq 39 | val clockDiv = RegInit(0.U(log2Ceil(1024).W)) 40 | clockDiv := clockDiv + 1.U 41 | val cnt = RegInit(0.U(7.W)) 42 | val out = RegInit(false.B) 43 | when(clockDiv === 0.U) { 44 | cnt := Mux(cnt === 100.U, 0.U, cnt + 1.U) 45 | out := dutyCycle > cnt 46 | } 47 | out 48 | } 49 | 50 | /** 51 | * breathe creates a gradual off-on-off cycle with pwmAbs function 52 | * 53 | * @param freq is the module clock frequency 54 | * @param speed in miliseconts for a full off-on-off cycle 55 | * @return Bool output 56 | */ 57 | def breathe(freq: Int, speed: Int) = { 58 | val pwmRange = 100 59 | val pwm = RegInit(0.U(log2Ceil(pwmRange).W)) 60 | val upReg = RegInit(true.B) 61 | val (_, cw) = Counter(true.B, (freq * (speed.toFloat / 1000) / 2 / pwmRange).toInt) 62 | when(cw) { 63 | when(pwm < pwmRange.U && upReg)(pwm := pwm + 1.U) 64 | .elsewhen(pwm === pwmRange.U && upReg)(upReg := false.B) 65 | .elsewhen(pwm > 0.U && !upReg)(pwm := pwm - 1.U) 66 | .otherwise(upReg := true.B) 67 | } 68 | pwmAbs(pwm) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /blinky/src/main/scala/Toplevel.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import com.carlosedp.scalautils.ParseArguments 3 | 4 | // Blinking LED top layer 5 | class Toplevel(board: String, invReset: Boolean = true) extends Module { 6 | val io = IO(new Bundle { 7 | val led0 = Output(Bool()) 8 | val led1 = Output(Bool()) 9 | val led2 = Output(Bool()) 10 | }) 11 | 12 | // Instantiate PLL module based on board 13 | val pll = Module(new PLL0(board)) 14 | pll.io.clki := clock 15 | // Define if reset should be inverted based on board switch 16 | val customReset = if (invReset) ~reset.asBool() else reset 17 | 18 | // Wrap all module instantiation using our PLL clock and custom Reset 19 | withClockAndReset(pll.io.clko, customReset) { 20 | // Instantiate the Blink module using 25Mhz from PLL output 21 | val bl = Module(new Blinky(25000000)) 22 | 23 | // Connect IO between Toplevel and Blinky 24 | bl.io <> io 25 | } 26 | } 27 | 28 | // The Main object extending App to generate the Verilog code. 29 | object Toplevel extends App { 30 | 31 | // Parse command line arguments and extract required parameters 32 | // pass the input arguments and a list of parameters to be extracted 33 | // The funcion will return the parameters map and the remaining non-extracted args 34 | val (params, chiselargs) = ParseArguments(args, List("board", "invreset")) 35 | val board: String = 36 | params.getOrElse("board", throw new IllegalArgumentException("The '-board' argument should be informed.")) 37 | val invReset: Boolean = 38 | params.getOrElse("invreset", "true").toBoolean 39 | 40 | // Generate Verilog 41 | (new chisel3.stage.ChiselStage).emitVerilog( 42 | new Toplevel(board, invReset), 43 | chiselargs 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /blinky/src/test/scala/BlinkySpec.scala: -------------------------------------------------------------------------------- 1 | import chisel3.iotesters._ 2 | import org.scalatest.flatspec._ 3 | import org.scalatest.matchers.should._ 4 | 5 | class BlinkySpec extends AnyFlatSpec with Matchers { 6 | "Blinky" should "pass" in { 7 | chisel3.iotesters.Driver(() => new Blinky(25000)) { c => 8 | new PeekPokeTester(c) { 9 | 10 | println("Start the blinking LED") 11 | for (_ <- 0 until 25) { 12 | step(10000) 13 | val l0 = if (peek(c.io.led0) == 0) 'o' else '*' 14 | val l1 = if (peek(c.io.led1) == 0) 'o' else '*' 15 | val l2 = if (peek(c.io.led2) == 0) 'o' else '*' 16 | printf("Leds: " + l0 + " " + l1 + " " + l2 + "\r") 17 | } 18 | println("\nEnd the blinking LED") 19 | } 20 | } should be(true) 21 | } 22 | } 23 | 24 | // Verilator sim 25 | class VerilatorSpec extends AnyFlatSpec with Matchers { 26 | "VerilatorSim" should "pass" in { 27 | Driver.execute( 28 | Array("--backend-name", "verilator"), 29 | () => new Blinky(1) 30 | ) { c => 31 | new WaveformCounterTester(c, 25) 32 | } should be(true) 33 | } 34 | } 35 | 36 | // Generate VCD output 37 | class WaveformCounterSpec extends AnyFlatSpec with Matchers { 38 | "WaveformCounter" should "pass" in { 39 | Driver.execute( 40 | Array("--generate-vcd-output", "on"), 41 | () => new Blinky(1) 42 | ) { c => 43 | new WaveformCounterTester(c, 25) 44 | } should be(true) 45 | } 46 | } 47 | 48 | class WaveformCounterTester(dut: Blinky, cycles: Int) extends PeekPokeTester(dut) { 49 | for (_ <- 0 until cycles) { 50 | step(1) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /blockram/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | target/ 3 | project/target 4 | project/project 5 | docs/generated 6 | docs-target/ 7 | *.fir 8 | *.v 9 | *.anno.json 10 | *.swp 11 | firrtl_black_box_resource_files.f 12 | *~ 13 | .addons-dont-touch 14 | /lib/ 15 | /test_lib/ 16 | /testbuild/ 17 | obj_dir 18 | test_run_dir 19 | generated 20 | .metals 21 | .bloop 22 | .bsp 23 | .vscode 24 | -------------------------------------------------------------------------------- /blockram/.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = "2.7.5" 2 | maxColumn = 120 3 | align.preset = most 4 | align.multiline = false 5 | continuationIndent.defnSite = 2 6 | assumeStandardLibraryStripMargin = true 7 | docstrings = JavaDoc 8 | lineEndings = preserve 9 | includeCurlyBraceInSelectChains = false 10 | danglingParentheses.preset = true 11 | optIn.annotationNewlines = true 12 | newlines.alwaysBeforeMultilineDef = false 13 | 14 | rewrite.rules = [RedundantBraces] 15 | 16 | rewrite.redundantBraces.generalExpressions = false 17 | rewriteTokens = { 18 | "⇒": "=>" 19 | "→": "->" 20 | "←": "<-" 21 | } -------------------------------------------------------------------------------- /blockram/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = bash 2 | 3 | # Project name and toplevel 4 | project = toplevel 5 | toplevel = Toplevel 6 | 7 | # Use Docker images 8 | DOCKER=docker 9 | 10 | PWD = $(shell pwd) 11 | USBDEVICE ?= /dev/bus/usb 12 | DOCKERARGS = run --rm -v $(PWD):/src -w /src 13 | VERILATORARGS = run --name verilator --hostname verilator --rm -it --entrypoint= -v $(PWD):/work -w /work 14 | 15 | YOSYS = $(DOCKER) $(DOCKERARGS) hdlc/yosys yosys 16 | NEXTPNR = $(DOCKER) $(DOCKERARGS) hdlc/nextpnr nextpnr-$(FPGA) 17 | ECPPACK = $(DOCKER) $(DOCKERARGS) hdlc/prjtrellis ecppack 18 | 19 | scala_files = $(wildcard src/main/scala/*scala) 20 | generated_files = generated 21 | verilog_files = $(generated_files)/*.v 22 | 23 | # Targets 24 | chisel: $(verilog_files) ## Generates Verilog code from Chisel sources using Mill 25 | $(verilog_files): $(scala_files) check-board-vars clean 26 | sbt "run -td $(generated_files)" 27 | 28 | chisel_tests: 29 | sbt test 30 | 31 | check: chisel_tests ## Run Chisel tests 32 | 33 | fmt: 34 | scripts/mill $(project).reformat 35 | scripts/mill $(project).fix 36 | 37 | synth: check-board-vars $(project).bit ## Synthesizes for target BOARD with "make BOARD=board synth" 38 | 39 | check-board-vars: 40 | @test -n "$(BOARD)" || (echo "Set BOARD variable to a board from:" ; echo -n " "; cat Makefile.boards|grep BOARD| cut -d ',' -f 2 |tr -s ')\n' ', ' | sed 's/, $$/\n/'; echo "Eg. make chisel BOARD=polarfireeval"; echo; exit 1) 41 | 42 | $(project).json: $(verilog_files) 43 | $(YOSYS) -p "read_verilog -sv $^; synth_$(FPGA) -json $(generated_files)/$@ -top $(toplevel)" 44 | 45 | $(project).config: $(project).json $(LPF) 46 | $(NEXTPNR) --json $(generated_files)/$< --lpf $(LPF) --textcfg $(generated_files)/$@ $(NEXTPNR_FLAGS) --package $(PACKAGE) 47 | 48 | $(project).bit: $(project).config 49 | $(PACK) --svf $(generated_files)/$(project).svf $(generated_files)/$< $(generated_files)/$@ 50 | 51 | $(project).svf: $(project).bit 52 | 53 | prog: check-board-vars $(project).svf ## Programs target BOARD with "make BOARD=board prog" 54 | $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf $(generated_files)/$(project).svf; exit" 55 | 56 | clean: ## Clean all generated files 57 | @./scripts/mill clean 58 | @rm -rf obj_dir test_run_dir target 59 | @rm -rf $(generated_files) 60 | @rm -rf out 61 | @rm -f $(project) 62 | @rm -f *.v 63 | @rm -f *.json 64 | @rm -f *.fir 65 | 66 | help: 67 | @echo "Makefile targets:" 68 | @echo "" 69 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = "[:##]"}; {printf "\033[36m%-20s\033[0m %s\n", $$2, $$5}' 70 | @echo "" 71 | @echo "Supported boards:" 72 | @echo "" 73 | @grep -E 'BOARD|##' Makefile.boards |sed 's/.*BOARD)\,\(.*\))/\1/' | sed -n 'N;s/\n/ /;p' | awk -F"[ \t]*##" '{printf "\033[36m%-15s\033[0m - %s\n", $$1, $$2}' 74 | 75 | .PHONY: chisel clean prog help 76 | .PRECIOUS: $(project).json $(project).config $(project).bit 77 | .DEFAULT_GOAL := help 78 | -------------------------------------------------------------------------------- /blockram/build.sbt: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | lazy val blinky = (project in file(".")) 4 | .settings( 5 | organization := "com.carlosedp", 6 | name := "blockram", 7 | version := "0.0.1", 8 | scalaVersion := "2.12.13", 9 | semanticdbEnabled := true, 10 | semanticdbVersion := scalafixSemanticdb.revision, 11 | maxErrors := 3 12 | ) 13 | 14 | crossScalaVersions := Seq("2.12.10") 15 | // Library default versions 16 | val defaultVersions = Map( 17 | "chisel3" -> "3.5-SNAPSHOT", 18 | "chisel-iotesters" -> "1.5.3", 19 | "chiseltest" -> "0.3.3", 20 | "scalatest" -> "3.2.9", 21 | "organize-imports" -> "0.5.0" 22 | ) 23 | // Import libraries 24 | libraryDependencies ++= Seq("chisel3", "chisel-iotesters", "chiseltest").map { dep: String => 25 | "edu.berkeley.cs" %% dep % sys.props 26 | .getOrElse(dep + "Version", defaultVersions(dep)) 27 | } 28 | libraryDependencies += "org.scalatest" %% "scalatest" % defaultVersions("scalatest") 29 | 30 | ThisBuild / scalafixDependencies += "com.github.liancheng" %% "organize-imports" % defaultVersions("organize-imports") 31 | 32 | // Aliases 33 | addCommandAlias("com", "all compile test:compile") 34 | addCommandAlias("rel", "reload") 35 | addCommandAlias("fix", "all compile:scalafix test:scalafix") 36 | addCommandAlias("fmt", "all scalafmtSbt scalafmtAll") 37 | 38 | resolvers ++= Seq( 39 | Resolver.sonatypeRepo("snapshots"), 40 | Resolver.sonatypeRepo("releases") 41 | ) 42 | 43 | addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % defaultVersions("chisel3") cross CrossVersion.full) 44 | 45 | scalacOptions ++= Seq( 46 | "-unchecked", 47 | "-deprecation", 48 | "-language:reflectiveCalls", 49 | "-feature", 50 | "-Xfatal-warnings", 51 | "-Ywarn-value-discard", 52 | "-Ywarn-dead-code", 53 | "-Ywarn-unused", 54 | "-Xsource:2.11" 55 | ) 56 | -------------------------------------------------------------------------------- /blockram/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.5.5 2 | -------------------------------------------------------------------------------- /blockram/project/metals.sbt: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT! This file is auto-generated. 2 | // This file enables sbt-bloop to create bloop config files. 3 | 4 | addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.4.8-19-4d9f966b") 5 | -------------------------------------------------------------------------------- /blockram/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | logLevel := Level.Warn 2 | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") 3 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.29") 4 | addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.19") 5 | -------------------------------------------------------------------------------- /blockram/sample.hex: -------------------------------------------------------------------------------- 1 | 000000004800012c 2 | 0000000000000000 3 | 4800002408000048 4 | 01006b69a600607d 5 | a602487d05009f42 6 | a64b5a7d14004a39 7 | 2402004ca64b7b7d 8 | 00000000480000f4 9 | 0000000000000000 10 | 0000000000000000 11 | 0000000000000000 12 | 0000000000000000 13 | 0000000000000000 14 | 0000000000000000 15 | 0000000000000000 16 | 0000000000000000 17 | 0000000000000000 18 | 0000000000000000 19 | 0000000000000000 20 | 0000000000000000 21 | 0000000000000000 22 | 0000000000000000 23 | 0000000000000000 24 | 0000000000000000 25 | 0000000000000000 26 | 0000000000000000 27 | 0000000000000000 28 | 0000000000000000 29 | 0000000000000000 30 | 0000000000000000 31 | 0000000000000000 32 | 0000000000000000 33 | 4800002408000048 34 | 01006b69a600607d 35 | a602487d05009f42 36 | a64b5a7d14004a39 37 | 2402004ca64b7b7d 38 | 3c20000048000004 39 | 782107c660210000 40 | 60211f0064210000 41 | 618c00003d800000 42 | 658c0000798c07c6 43 | 7d8903a6618c1190 44 | 480000004e800421 45 | 0000000000000000 46 | 0000000000000000 47 | 0000000000000000 48 | 0000000000000000 49 | 0000000000000000 50 | 0000000000000000 51 | 0000000000000000 52 | 0000000000000000 53 | 0000000000000000 54 | 0000000000000000 55 | 0000000000000000 56 | 0000000000000000 57 | 0000000000000000 58 | 0000000000000000 59 | 0000000000000000 60 | 0000000000000000 61 | 0000000000000000 62 | 0000000000000000 63 | 0000000000000000 64 | 0000000000000000 65 | 0000000000000000 66 | 0000000000000000 67 | 0000000000000000 68 | 0000000000000000 69 | 0000000000000000 70 | 0000000000000000 71 | 0000000000000000 72 | 0000000000000000 73 | 0000000000000000 74 | 0000000000000000 75 | 0000000000000000 76 | 0000000000000000 77 | 0000000000000000 78 | 0000000000000000 79 | 0000000000000000 80 | 0000000000000000 81 | 0000000000000000 82 | 0000000000000000 83 | 0000000000000000 84 | 0000000000000000 85 | 0000000000000000 86 | 0000000000000000 87 | 0000000000000000 88 | 0000000000000000 89 | 0000000000000000 90 | 0000000000000000 91 | 0000000000000000 92 | 0000000000000000 93 | 0000000000000000 94 | 0000000000000000 95 | 0000000000000000 96 | 0000000000000000 97 | 0000000048000000 98 | 0000000000000000 99 | 0000000000000000 100 | 0000000000000000 101 | 0000000000000000 102 | 0000000000000000 103 | 0000000000000000 104 | 0000000000000000 105 | 0000000000000000 106 | 0000000000000000 107 | 0000000000000000 108 | 0000000000000000 109 | 0000000000000000 110 | 0000000000000000 111 | 0000000000000000 112 | 0000000000000000 113 | 0000000048000000 114 | 0000000000000000 115 | 0000000000000000 116 | 0000000000000000 117 | 0000000000000000 118 | 0000000000000000 119 | 0000000000000000 120 | 0000000000000000 121 | 0000000000000000 122 | 0000000000000000 123 | 0000000000000000 124 | 0000000000000000 125 | 0000000000000000 126 | 0000000000000000 127 | 0000000000000000 128 | 0000000000000000 129 | 0000000048000000 130 | 0000000000000000 131 | 0000000000000000 132 | 0000000000000000 133 | 0000000000000000 134 | 0000000000000000 135 | 0000000000000000 136 | 0000000000000000 137 | 0000000000000000 138 | 0000000000000000 139 | 0000000000000000 140 | 0000000000000000 141 | 0000000000000000 142 | 0000000000000000 143 | 0000000000000000 144 | 0000000000000000 145 | 0000000048000000 146 | 0000000000000000 147 | 0000000000000000 148 | 0000000000000000 149 | 0000000000000000 150 | 0000000000000000 151 | 0000000000000000 152 | 0000000000000000 153 | 0000000000000000 154 | 0000000000000000 155 | 0000000000000000 156 | 0000000000000000 157 | 0000000000000000 158 | 0000000000000000 159 | 0000000000000000 160 | 0000000000000000 161 | 0000000048000000 162 | 0000000000000000 163 | 0000000000000000 164 | 0000000000000000 165 | 0000000000000000 166 | 0000000000000000 167 | 0000000000000000 168 | 0000000000000000 169 | 0000000000000000 170 | 0000000000000000 171 | 0000000000000000 172 | 0000000000000000 173 | 0000000000000000 174 | 0000000000000000 175 | 0000000000000000 176 | 0000000000000000 177 | 0000000000000000 178 | 0000000000000000 179 | 0000000000000000 180 | 0000000000000000 181 | 0000000000000000 182 | 0000000000000000 183 | 0000000000000000 184 | 0000000000000000 185 | 0000000000000000 186 | 0000000000000000 187 | 0000000000000000 188 | 0000000000000000 189 | 0000000000000000 190 | 0000000000000000 191 | 0000000000000000 192 | 0000000000000000 193 | 0000000048000000 194 | 0000000000000000 195 | 0000000000000000 196 | 0000000000000000 197 | 0000000000000000 198 | 0000000000000000 199 | 0000000000000000 200 | 0000000000000000 201 | 0000000000000000 202 | 0000000000000000 203 | 0000000000000000 204 | 0000000000000000 205 | 0000000000000000 206 | 0000000000000000 207 | 0000000000000000 208 | 0000000000000000 209 | 0000000000000000 210 | 0000000000000000 211 | 0000000000000000 212 | 0000000000000000 213 | 0000000000000000 214 | 0000000000000000 215 | 0000000000000000 216 | 0000000000000000 217 | 0000000000000000 218 | 0000000000000000 219 | 0000000000000000 220 | 0000000000000000 221 | 0000000000000000 222 | 0000000000000000 223 | 0000000000000000 224 | 0000000000000000 225 | 0000000048000000 226 | 0000000000000000 227 | 0000000000000000 228 | 0000000000000000 229 | 0000000000000000 230 | 0000000000000000 231 | 0000000000000000 232 | 0000000000000000 233 | 0000000000000000 234 | 0000000000000000 235 | 0000000000000000 236 | 0000000000000000 237 | 0000000000000000 238 | 0000000000000000 239 | 0000000000000000 240 | 0000000000000000 241 | 0000000000000000 242 | 0000000000000000 243 | 0000000000000000 244 | 0000000000000000 245 | 0000000000000000 246 | 0000000000000000 247 | 0000000000000000 248 | 0000000000000000 249 | 0000000000000000 250 | 0000000000000000 251 | 0000000000000000 252 | 0000000000000000 253 | 0000000000000000 254 | 0000000000000000 255 | 0000000000000000 256 | 0000000000000000 257 | 0000000048000000 258 | 0000000000000000 259 | 0000000000000000 260 | 0000000000000000 261 | 0000000000000000 262 | 0000000000000000 263 | 0000000000000000 264 | 0000000000000000 265 | 0000000000000000 266 | 0000000000000000 267 | 0000000000000000 268 | 0000000000000000 269 | 0000000000000000 270 | 0000000000000000 271 | 0000000000000000 272 | 0000000000000000 273 | 0000000000000000 274 | 0000000000000000 275 | 0000000000000000 276 | 0000000000000000 277 | 0000000000000000 278 | 0000000000000000 279 | 0000000000000000 280 | 0000000000000000 281 | 0000000000000000 282 | 0000000000000000 283 | 0000000000000000 284 | 0000000000000000 285 | 0000000000000000 286 | 0000000000000000 287 | 0000000000000000 288 | 0000000000000000 289 | 0000000048000000 290 | 0000000000000000 291 | 0000000000000000 292 | 0000000000000000 293 | 0000000000000000 294 | 0000000000000000 295 | 0000000000000000 296 | 0000000000000000 297 | 0000000000000000 298 | 0000000000000000 299 | 0000000000000000 300 | 0000000000000000 301 | 0000000000000000 302 | 0000000000000000 303 | 0000000000000000 304 | 0000000000000000 305 | 0000000048000000 306 | 0000000000000000 307 | 0000000000000000 308 | 0000000000000000 309 | 0000000000000000 310 | 0000000000000000 311 | 0000000000000000 312 | 0000000000000000 313 | 0000000000000000 314 | 0000000000000000 315 | 0000000000000000 316 | 0000000000000000 317 | 0000000000000000 318 | 0000000000000000 319 | 0000000000000000 320 | 0000000000000000 321 | 0000000048000000 322 | 0000000000000000 323 | 0000000000000000 324 | 0000000000000000 325 | 0000000000000000 326 | 0000000000000000 327 | 0000000000000000 328 | 0000000000000000 329 | 0000000000000000 330 | 0000000000000000 331 | 0000000000000000 332 | 0000000000000000 333 | 0000000000000000 334 | 0000000000000000 335 | 0000000000000000 336 | 0000000000000000 337 | 0000000000000000 338 | 0000000000000000 339 | 0000000000000000 340 | 0000000000000000 341 | 0000000000000000 342 | 0000000000000000 343 | 0000000000000000 344 | 0000000000000000 345 | 0000000000000000 346 | 0000000000000000 347 | 0000000000000000 348 | 0000000000000000 349 | 0000000000000000 350 | 0000000000000000 351 | 0000000000000000 352 | 0000000000000000 353 | 0000000048000000 354 | 0000000000000000 355 | 0000000000000000 356 | 0000000000000000 357 | 0000000000000000 358 | 0000000000000000 359 | 0000000000000000 360 | 0000000000000000 361 | 0000000000000000 362 | 0000000000000000 363 | 0000000000000000 364 | 0000000000000000 365 | 0000000000000000 366 | 0000000000000000 367 | 0000000000000000 368 | 0000000000000000 369 | 0000000000000000 370 | 0000000000000000 371 | 0000000000000000 372 | 0000000000000000 373 | 0000000000000000 374 | 0000000000000000 375 | 0000000000000000 376 | 0000000000000000 377 | 0000000000000000 378 | 0000000000000000 379 | 0000000000000000 380 | 0000000000000000 381 | 0000000000000000 382 | 0000000000000000 383 | 0000000000000000 384 | 0000000000000000 385 | 0000000048000000 386 | 0000000000000000 387 | 0000000000000000 388 | 0000000000000000 389 | 0000000000000000 390 | 0000000000000000 391 | 0000000000000000 392 | 0000000000000000 393 | 0000000000000000 394 | 0000000000000000 395 | 0000000000000000 396 | 0000000000000000 397 | 0000000000000000 398 | 0000000000000000 399 | 0000000000000000 400 | 0000000000000000 401 | 0000000000000000 402 | 0000000000000000 403 | 0000000000000000 404 | 0000000000000000 405 | 0000000000000000 406 | 0000000000000000 407 | 0000000000000000 408 | 0000000000000000 409 | 0000000000000000 410 | 0000000000000000 411 | 0000000000000000 412 | 0000000000000000 413 | 0000000000000000 414 | 0000000000000000 415 | 0000000000000000 416 | 0000000000000000 417 | 0000000048000000 418 | 0000000000000000 419 | 0000000000000000 420 | 0000000000000000 421 | 0000000000000000 422 | 0000000000000000 423 | 0000000000000000 424 | 0000000000000000 425 | 0000000000000000 426 | 0000000000000000 427 | 0000000000000000 428 | 0000000000000000 429 | 0000000000000000 430 | 0000000000000000 431 | 0000000000000000 432 | 0000000000000000 433 | 0000000000000000 434 | 0000000000000000 435 | 0000000000000000 436 | 0000000000000000 437 | 0000000000000000 438 | 0000000000000000 439 | 0000000000000000 440 | 0000000000000000 441 | 0000000000000000 442 | 0000000000000000 443 | 0000000000000000 444 | 0000000000000000 445 | 0000000000000000 446 | 0000000000000000 447 | 0000000000000000 448 | 0000000000000000 449 | 0000000048000000 450 | 0000000000000000 451 | 0000000000000000 452 | 0000000000000000 453 | 0000000048000000 454 | 0000000000000000 455 | 0000000000000000 456 | 0000000000000000 457 | 0000000048000000 458 | 0000000000000000 459 | 0000000000000000 460 | 0000000000000000 461 | 0000000048000000 462 | 0000000000000000 463 | 0000000000000000 464 | 0000000000000000 465 | 0000000048000000 466 | 0000000000000000 467 | 0000000000000000 468 | 0000000000000000 469 | 0000000000000000 470 | 0000000000000000 471 | 0000000000000000 472 | 0000000000000000 473 | 0000000000000000 474 | 0000000000000000 475 | 0000000000000000 476 | 0000000000000000 477 | 0000000000000000 478 | 0000000000000000 479 | 0000000000000000 480 | 0000000000000000 481 | 0000000048000000 482 | 0000000000000000 483 | 0000000000000000 484 | 0000000000000000 485 | 0000000048000000 486 | 0000000000000000 487 | 0000000000000000 488 | 0000000000000000 489 | 0000000048000000 490 | 0000000000000000 491 | 0000000000000000 492 | 0000000000000000 493 | 0000000048000000 494 | 0000000000000000 495 | 0000000000000000 496 | 0000000000000000 497 | 0000000048000000 498 | 0000000000000000 499 | 0000000000000000 500 | 0000000000000000 501 | 0000000000000000 502 | 0000000000000000 503 | 0000000000000000 504 | 0000000000000000 505 | 0000000000000000 506 | 0000000000000000 507 | 0000000000000000 508 | 0000000000000000 509 | 0000000000000000 510 | 0000000000000000 511 | 0000000000000000 512 | 0000000000000000 513 | e8010010ebc1fff0 514 | 7c0803a6ebe1fff8 515 | 3c4000014e800020 516 | 3d20c0003842a000 517 | 6129200060000000 518 | f922800079290020 519 | 394000d83d20c000 520 | 7929002061292018 521 | 4e800020f9490000 522 | 0000000000000000 523 | 3c40000100000000 524 | 600000003842a000 525 | 39090010e9228000 526 | 714a0001e9480000 527 | e86900084082fff8 528 | 4e8000205463063e 529 | 0000000000000000 530 | 3c40000100000000 531 | 600000003842a000 532 | 39090010e9228000 533 | 714a0008e9480000 534 | f86900004082fff8 535 | 000000004e800020 536 | 0000000000000000 537 | 3842a0003c400001 538 | fbc1fff07c0802a6 539 | 7fc32214fbe1fff8 540 | f80100107c7f1b78 541 | 7c3ff040f821ffd1 542 | 382100304082000c 543 | 887f00004bffff10 544 | 4bffff993bff0001 545 | 000000004bffffe4 546 | 0000028001000000 547 | 386000007c691b78 548 | 2c0a00007d4918ae 549 | 386300014d820020 550 | 000000004bfffff0 551 | 0000000000000000 552 | 3842a0003c400001 553 | fbc1fff07c0802a6 554 | 7c7e1b78fbe1fff8 555 | f80100103be00000 556 | 7fc3f378f821ffd1 557 | 7c23f8404bffffb1 558 | 382100304181000c 559 | 7c7ef8ae4bfffe90 560 | 4bffff193bff0001 561 | 000000004bffffdc 562 | 0000028001000000 563 | 3842a0003c400001 564 | fbe1fff87c0802a6 565 | 3bff72403fe2ffff 566 | f821ffd1f8010010 567 | 3c62ffff4bfffe6d 568 | 4bffff8538637200 569 | 386372383c62ffff 570 | 4bfffe914bffff79 571 | 2803000d5463063e 572 | 7fe3fb7840820010 573 | 4bffffe84bffff61 574 | 4bffffe04bfffead 575 | 0100000000000000 576 | 0000000000000180 577 | 7266206f6c6c6548 578 | 6573696843206d6f 579 | 61202c747461776c 580 | 6f506e65704f206e 581 | 636f727020726577 582 | 0a0d21726f737365 583 | 0000000000000000 584 | 000000000000203e 585 | 00000000203e0a0d 586 | 0000000000000010 587 | 0141780400527a01 588 | 0000001000010c1b 589 | fffffdb000000018 590 | 0000000000000040 591 | 0000002c00000010 592 | 00000038fffffddc 593 | 0000001000000000 594 | fffffe0000000040 595 | 0000000000000034 596 | 0000005400000028 597 | 00000050fffffe20 598 | 9f029e0041094500 599 | 437e4111300e4401 600 | 4106dedf41000e0a 601 | 000000100000000b 602 | fffffe4400000080 603 | 0000000000000028 604 | 0000009400000028 605 | 00000058fffffe58 606 | 9f029e0041094500 607 | 457e4111300e4401 608 | 4106dedf41000e0a 609 | 0000001c0000000b 610 | fffffe84000000c0 611 | 410944000000006c 612 | 4111300e44019f00 613 | 000000000000007e 614 | -------------------------------------------------------------------------------- /blockram/src/main/scala/utils/DualportRAM.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util.log2Ceil 3 | import chisel3.util.experimental.loadMemoryFromFileInline 4 | import chisel3.experimental.{annotate, ChiselAnnotation} 5 | import firrtl._ 6 | 7 | class MemoryPort(val bitWidth: Int, val words: Int, val rw: Boolean = true) extends Bundle { 8 | val addr = Output(UInt(log2Ceil(words).W)) 9 | val readData = Input(UInt(bitWidth.W)) 10 | 11 | val writeEnable = if (rw) Some(Output(Bool())) else None 12 | val writeData = if (rw) Some(Output(UInt(bitWidth.W))) else None 13 | // val writeEnable = (Output(Bool())) 14 | // val writeData = (Output(UInt(bitWidth.W))) 15 | } 16 | 17 | class DualPortRAM( 18 | sizeBytes: Int = 1, 19 | bitWidth: Int = 32, 20 | memoryFile: String = "" 21 | ) extends Module { 22 | val words = sizeBytes / bitWidth 23 | val io = IO(new Bundle() { 24 | val loadStorePort = Flipped(new MemoryPort(bitWidth, words, true)) 25 | val fetchPort = Flipped(new MemoryPort(bitWidth, words, false)) 26 | }) 27 | 28 | println(s"Dual-port Memory Parameters:") 29 | println(s" Words: $words") 30 | println(s" Size: " + words * bitWidth + " Kb") 31 | println(s" Bit width: $bitWidth bit") 32 | println(s" Addr Width: " + io.loadStorePort.addr.getWidth + " bit") 33 | 34 | // This is required to have readmem outside `ifndef SYNTHESIS` and be synthesized by FPGA tools 35 | annotate(new ChiselAnnotation { 36 | override def toFirrtl = 37 | firrtl.annotations.MemorySynthInit 38 | }) 39 | 40 | val mem = SyncReadMem(words, UInt(bitWidth.W)) 41 | if (memoryFile.trim().nonEmpty) { 42 | println(s" Load memory file: " + memoryFile) 43 | loadMemoryFromFileInline(mem, memoryFile) 44 | } 45 | 46 | io.loadStorePort.readData := mem.read(io.loadStorePort.addr) 47 | io.fetchPort.readData := mem.read(io.fetchPort.addr) 48 | 49 | when(io.loadStorePort.writeEnable.get) { 50 | mem.write(io.loadStorePort.addr, io.loadStorePort.writeData.get) 51 | } 52 | } 53 | 54 | object DualPortRAMObj extends App { 55 | (new chisel3.stage.ChiselStage).emitVerilog( 56 | new DualPortRAM( 57 | sizeBytes = 8, 58 | bitWidth = 8, 59 | memoryFile = "sample.hex" 60 | ), 61 | Array("-X", "verilog") ++ args 62 | ) 63 | } 64 | -------------------------------------------------------------------------------- /blockram/src/main/scala/utils/MultiMemory.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util.log2Ceil 3 | import chisel3.util.experimental.loadMemoryFromFileInline 4 | import chisel3.experimental.{annotate, ChiselAnnotation} 5 | 6 | class MultiMem extends Module { 7 | val io = IO(new Bundle() { 8 | val loadStorePort = Flipped(new MemoryPort2(32, 32, true)) 9 | val loadStorePort2 = Flipped(new MemoryPort2(32, 32, true)) 10 | }) 11 | // This is required to have readmem outside `ifndef SYNTHESIS` and be synthesized by FPGA tools 12 | annotate(new ChiselAnnotation { 13 | override def toFirrtl = 14 | firrtl.annotations.MemorySynthInit 15 | }) 16 | val mem1 = 17 | Module( 18 | new DualPortMultiRAM( 19 | sizeBytes = 32 * 1024, 20 | bitWidth = 32, 21 | memoryFile = "sample.hex" 22 | ) 23 | ) 24 | mem1.io.loadStorePort <> io.loadStorePort 25 | 26 | val mem2 = 27 | Module( 28 | new DualPortMultiRAM( 29 | sizeBytes = 32 * 1024, 30 | bitWidth = 32, 31 | memoryFile = "sample2.hex" 32 | ) 33 | ) 34 | mem2.io.loadStorePort <> io.loadStorePort2 35 | } 36 | 37 | class MemoryPort2(val bitWidth: Int, val words: Int, val rw: Boolean) extends Bundle { 38 | val addr = Output(UInt(log2Ceil(words).W)) 39 | val readData = Input(UInt(bitWidth.W)) 40 | 41 | val writeEnable = if (rw) Some(Output(Bool())) else None 42 | val writeData = if (rw) Some(Output(UInt(bitWidth.W))) else None 43 | } 44 | 45 | class DualPortMultiRAM( 46 | sizeBytes: Int = 1, 47 | bitWidth: Int = 32, 48 | memoryFile: String = "" 49 | ) extends Module { 50 | val words = sizeBytes / bitWidth 51 | val io = IO(new Bundle() { 52 | val loadStorePort = Flipped(new MemoryPort2(bitWidth, words, true)) 53 | }) 54 | 55 | println(s"Dual-port Memory $name Parameters:") 56 | println(s" Words: $words") 57 | println(s" Size: " + words * bitWidth + " Kb") 58 | println(s" Bit width: $bitWidth bit") 59 | println(s" Addr Width: " + io.loadStorePort.addr.getWidth + " bit") 60 | 61 | val mem = SyncReadMem(words, UInt(bitWidth.W)) 62 | // This prevents deduping this memory module 63 | // Ref. https://github.com/chipsalliance/firrtl/issues/2168 64 | val dedupBlock = WireInit(mem.hashCode.U) 65 | 66 | if (memoryFile.trim().nonEmpty) { 67 | println(s" Load memory file: " + memoryFile) 68 | loadMemoryFromFileInline(mem, memoryFile) 69 | } 70 | 71 | io.loadStorePort.readData := mem.read(io.loadStorePort.addr) 72 | 73 | when(io.loadStorePort.writeEnable.get) { 74 | mem.write(io.loadStorePort.addr, io.loadStorePort.writeData.get) 75 | } 76 | } 77 | 78 | object MultiMem extends App { 79 | (new chisel3.stage.ChiselStage).emitVerilog( 80 | new MultiMem(), 81 | Array() ++ args 82 | ) 83 | } 84 | -------------------------------------------------------------------------------- /blockram/src/main/scala/utils/SingleportRAM.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.util.experimental.loadMemoryFromFileInline 3 | import chisel3.experimental.{annotate, ChiselAnnotation} 4 | 5 | class SinglePortRAM(words: Int = 1, width: Int = 32, memoryFile: String = "") extends Module { 6 | val addrWidth = chiselTypeOf((words * 1024).U) 7 | val io = IO(new Bundle { 8 | val addr1 = Input(addrWidth) 9 | val dataIn1 = Input(UInt(width.W)) 10 | val en1 = Input(Bool()) 11 | val we1 = Input(Bool()) 12 | val dataOut1 = Output(UInt(width.W)) 13 | }) 14 | println(s"Dual-port Memory Parameters:") 15 | println(s" Size (words): $words") 16 | println(s" Size (kb): " + words * width + " Kb") 17 | println(s" Width: $width bit") 18 | println(s" Addr Width: " + io.addr1.getWidth + " bit") 19 | 20 | // This is required to have readmem outside `ifndef SYNTHESIS` and be synthesized by FPGA tools 21 | annotate(new ChiselAnnotation { 22 | override def toFirrtl = 23 | firrtl.annotations.MemorySynthInit 24 | }) 25 | 26 | val mem = SyncReadMem(words, UInt(width.W)) 27 | if (memoryFile.trim().nonEmpty) { 28 | println(s" Load memory file: " + memoryFile) 29 | loadMemoryFromFileInline(mem, memoryFile) 30 | } 31 | 32 | when(io.we1) { 33 | mem.write(io.addr1, io.dataIn1) 34 | } 35 | io.dataOut1 := mem.read(io.addr1, io.en1) 36 | } 37 | 38 | object SinglePortRAMObj extends App { 39 | (new chisel3.stage.ChiselStage).emitVerilog( 40 | new SinglePortRAM(16, width = 64, memoryFile = "sample.hex"), 41 | Array("-X", "verilog") ++ args 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /blockram/src/main/scala/utils/SubByteMemory.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | // import chisel3.experimental.{ChiselAnnotation, annotate} 3 | // import firrtl.annotations.MemoryFileInlineAnnotation 4 | 5 | class SubByteMemory(words: Int, bits: Int, addrBits: Int, filename: String) extends Module { 6 | val io = IO(new Bundle { 7 | val dataOut = Output(Vec(bits / 8, UInt(8.W))) 8 | val dataIn = Input(Vec(bits / 8, UInt(8.W))) 9 | val readAddr = Input(UInt(addrBits.W)) 10 | val readEnable = Input(Bool()) 11 | val writeAddr = Input(UInt(addrBits.W)) 12 | val writeMask = Input(Vec(bits / 8, Bool())) 13 | }) 14 | 15 | println(s"Memory initialized with file: $filename") 16 | val mem = SyncReadMem(words, Vec(bits / 8, UInt(8.W))) 17 | mem.write(io.writeAddr, io.dataIn, io.writeMask) 18 | io.dataOut := mem.read(io.readAddr, io.readEnable) 19 | } 20 | 21 | object SubByteMemoryObj extends App { 22 | (new chisel3.stage.ChiselStage).emitVerilog( 23 | new SubByteMemory(16, 64, 32, "sample.hex"), 24 | Array("-X", "verilog") ++ args 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /fomublink/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | target/ 3 | project/target 4 | project/project 5 | docs/generated 6 | docs-target/ 7 | *.fir 8 | *.v 9 | *.anno.json 10 | *.swp 11 | *~ 12 | .addons-dont-touch 13 | /lib/ 14 | /test_lib/ 15 | /testbuild/ 16 | obj_dir 17 | test_run_dir 18 | generated 19 | .metals 20 | .bloop 21 | .bsp 22 | .vscode 23 | -------------------------------------------------------------------------------- /fomublink/.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | RemoveUnused, 3 | DisableSyntax, 4 | LeakingImplicitClassVal, 5 | NoAutoTupling, 6 | NoValInForComprehension, 7 | OrganizeImports, 8 | ProcedureSyntax, 9 | ] 10 | 11 | OrganizeImports { 12 | groupedImports = Merge 13 | } 14 | 15 | RemoveUnused { 16 | imports = false // handled by OrganizeImports 17 | } -------------------------------------------------------------------------------- /fomublink/.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = "2.7.5" 2 | maxColumn = 120 3 | align.preset = most 4 | align.multiline = false 5 | continuationIndent.defnSite = 2 6 | assumeStandardLibraryStripMargin = true 7 | docstrings = JavaDoc 8 | lineEndings = preserve 9 | includeCurlyBraceInSelectChains = false 10 | danglingParentheses.preset = true 11 | optIn.annotationNewlines = true 12 | newlines.alwaysBeforeMultilineDef = false 13 | 14 | rewrite.rules = [RedundantBraces] 15 | 16 | rewrite.redundantBraces.generalExpressions = false 17 | rewriteTokens = { 18 | "⇒": "=>" 19 | "→": "->" 20 | "←": "<-" 21 | } -------------------------------------------------------------------------------- /fomublink/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.watcherExclude": { 3 | "**/target": true 4 | } 5 | } -------------------------------------------------------------------------------- /fomublink/Makefile: -------------------------------------------------------------------------------- 1 | project = toplevel 2 | toplayer = BlinkTop 3 | 4 | scala_files = $(wildcard src/main/scala/*scala) 5 | generated_files = generated 6 | verilog_files = $(generated_files)/*.v 7 | 8 | # Params for Fomu PVT 9 | YOSYSFLAGS ?= -D PVT=1 10 | PNRFLAGS ?= --up5k --package uwg30 11 | PCF ?= constraints/fomu-pvt.pcf 12 | FPGA ?= ice40 13 | 14 | # Tools Configuration 15 | DOCKER=docker 16 | PWD = $(shell pwd) 17 | DOCKERARGS = run --rm -v $(PWD):/src -w /src 18 | # Using Docker containers 19 | # YOSYS = $(DOCKER) $(DOCKERARGS) hdlc/yosys yosys 20 | # NEXTPNR = $(DOCKER) $(DOCKERARGS) hdlc/nextpnr nextpnr-$(FPGA) 21 | # ICEPACK = $(DOCKER) $(DOCKERARGS) hdlc/icestorm icepack 22 | 23 | # Using local tools 24 | YOSYS = yosys 25 | NEXTPNR = nextpnr-$(FPGA) 26 | ICEPACK = icepack 27 | 28 | # Targets 29 | all: $(project).dfu 30 | 31 | # Generate Verilog files from Chisel 32 | chisel: $(verilog_files) 33 | $(verilog_files): $(scala_files) 34 | scripts/mill $(project).run -td $(generated_files) 35 | 36 | fmt: 37 | scripts/mill all $(project).{reformat,fix} 38 | 39 | # Use *Yosys* to generate the synthesized netlist. 40 | # This is called the **synthesis** and **tech mapping** step. 41 | $(project).json: $(verilog_files) 42 | $(YOSYS) \ 43 | $(YOSYSFLAGS) \ 44 | -p 'synth_$(FPGA) -top $(toplayer) -json $(generated_files)/$(project).json' $(verilog_files) 45 | 46 | # Use **nextpnr** to generate the FPGA configuration. 47 | # This is called the **place** and **route** step. 48 | $(project).asc: $(project).json $(PCF) 49 | $(NEXTPNR) \ 50 | $(PNRFLAGS) \ 51 | --pcf $(PCF) \ 52 | --json $(generated_files)/$(project).json \ 53 | --asc $(generated_files)/$(project).asc 54 | 55 | # Use icepack to convert the FPGA configuration into a "bitstream" loadable onto the FPGA. 56 | # This is called the bitstream generation step. 57 | $(project).bit: $(project).asc 58 | $(ICEPACK) $(generated_files)/$(project).asc $(generated_files)/$(project).bit 59 | 60 | # Use dfu-suffix to generate the DFU image from the FPGA bitstream. 61 | $(project).dfu: $(project).bit 62 | cp $(generated_files)/$(project).bit $(generated_files)/$(project).dfu 63 | dfu-suffix -v 1209 -p 70b1 -a $(generated_files)/$(project).dfu 64 | 65 | # Use df-util to load the DFU image onto the Fomu. 66 | load: clean $(project).dfu 67 | dfu-util -D $(generated_files)/$(project).dfu 68 | 69 | clean: ## Clean all generated files 70 | @./scripts/mill clean 71 | @rm -f $(project).fir $(project).anno.json $(project).v 72 | @rm -rf obj_dir test_run_dir target 73 | @rm -rf $(generated_files) 74 | @rm -f $(project) 75 | @rm -rf *.bit *.json *.svf *.config out *.fir *.v *.f 76 | 77 | .PHONY: clean -------------------------------------------------------------------------------- /fomublink/Readme.md: -------------------------------------------------------------------------------- 1 | # Chisel Blinky on FOMU 2 | 3 | This is a simple Blinky project to demonstrate Chisel functionality with scripts and tooling to be able to synth and run on [Fomu](https://tomu.im/fomu.html). 4 | 5 | This project uses two blackbox modules to import Verilog code from ICE40 IP, one for it's' PLL and another for the RGB led driver. 6 | 7 | ## Synthesis using Open Source tools (yosys/nextpnr) 8 | 9 | The faster way to get started is using FuseSoc and generating the files in containers. You would need **Docker** and **FuseSoc**. To program, use [dfu-util](http://dfu-util.sourceforge.net/). 10 | 11 | To install Fusesoc (requires Python3 and pip3) and add to your path: 12 | 13 | ```sh 14 | pip3 install --upgrade --user fusesoc 15 | export PATH=~/.local/bin:$PATH 16 | 17 | #Check if it's working: 18 | 19 | $ fusesoc --version 20 | 1.12.0 21 | ``` 22 | 23 | Then create the project dir and files: 24 | 25 | ```sh 26 | mkdir fusesoc-fomublink && cd fusesoc-fomublink 27 | fusesoc library add fusesoc-cores https://github.com/fusesoc/fusesoc-cores 28 | 29 | # Since Fomublink is not a standalone repo (but a folder in an umbrella repo) 30 | # we clone it locally and add the library as a local dir. 31 | git clone https://github.com/carlosedp/chisel-playground 32 | fusesoc library add fomublink $(pwd)/chisel-playground/fomublink 33 | 34 | # Get the container wrapper 35 | wget https://gist.github.com/carlosedp/c0e29d55e48309a48961f2e3939acfe9/raw/bfeb1cfe2e188c1d5ced0b09aabc9902fdfda6aa/runme.py 36 | chmod +x runme.py 37 | 38 | # Generate the files (Chisel to Verilog, Synthesys, Place'nRoute, Bitstream packing) 39 | EDALIZE_LAUNCHER=$(realpath ../runme.py) fusesoc run --target=fomu-pvt carlosedp:demo:fomublink:0 40 | ``` 41 | 42 | Then program the bitstream to the Fomu with provided instructions on terminal. 43 | 44 | 45 | [![https://pbs.twimg.com/ext_tw_video_thumb/1381699719907442690/pu/img/hn2VBCXfQ2d6clcd.jpg](https://pbs.twimg.com/ext_tw_video_thumb/1381699719907442690/pu/img/hn2VBCXfQ2d6clcd.jpg)](https://twitter.com/carlosedp/status/1381700282246119425) 46 | 47 | Another option is using local tools. For this you need to download fomu-toolchain from and add it to your path. 48 | 49 | For example, on Mac: 50 | 51 | ```sh 52 | wget https://github.com/im-tomu/fomu-toolchain/releases/download/v1.5.6/fomu-toolchain-macos-v1.5.6.zip 53 | unzip fomu-toolchain-macos-v1.5.6.zip 54 | 55 | # Add to path 56 | export PATH=$(realpath ./bin):$PATH 57 | ``` 58 | 59 | Build the bitstream: 60 | 61 | ```sh 62 | make 63 | ``` 64 | 65 | And finally, with the Fomu connected, program the bitstream: 66 | 67 | ```sh 68 | make load 69 | ``` 70 | -------------------------------------------------------------------------------- /fomublink/build.sc: -------------------------------------------------------------------------------- 1 | import mill._ 2 | import mill.scalalib._ 3 | import scalafmt._ 4 | import coursier.MavenRepository 5 | import $ivy.`com.goyeau::mill-scalafix:0.2.1` 6 | import com.goyeau.mill.scalafix.ScalafixModule 7 | 8 | def mainClass = Some("Blink") 9 | 10 | val defaultVersions = Map( 11 | "scala" -> "2.12.12", 12 | "chisel3" -> "3.4.3", 13 | "chisel-iotesters" -> "1.5.0", 14 | "chiseltest" -> "0.3.1", 15 | "scalatest" -> "3.2.2", 16 | "organize-imports" -> "0.5.0", 17 | "paradise" -> "2.1.1" 18 | ) 19 | val binCrossScalaVersions = Seq("2.12.10", "2.11.12") 20 | 21 | trait HasChisel3 extends ScalaModule { 22 | override def ivyDeps = Agg( 23 | ivy"edu.berkeley.cs::chisel3:${defaultVersions("chisel3")}" 24 | ) 25 | } 26 | 27 | trait HasChiselTests extends CrossSbtModule { 28 | object test extends Tests { 29 | override def ivyDeps = Agg( 30 | ivy"org.scalatest::scalatest:${defaultVersions("scalatest")}", 31 | ivy"edu.berkeley.cs::chisel-iotesters:${defaultVersions("chisel-iotesters")}", 32 | ivy"edu.berkeley.cs::chiseltest:${defaultVersions("chiseltest")}" 33 | ) 34 | def repositories = super.repositories ++ Seq( 35 | MavenRepository("https://oss.sonatype.org/content/repositories/snapshots") 36 | ) 37 | def testFrameworks = Seq("org.scalatest.tools.Framework") 38 | 39 | def testOne(args: String*) = T.command { 40 | super.runMain("org.scalatest.run", args: _*) 41 | } 42 | } 43 | } 44 | 45 | trait HasMacroParadise extends ScalaModule { 46 | // Enable macro paradise for @chiselName et al 47 | val macroPlugins = Agg( 48 | ivy"org.scalamacros:::paradise:${defaultVersions("paradise")}" 49 | ) 50 | def scalacPluginIvyDeps = macroPlugins 51 | def compileIvyDeps = macroPlugins 52 | } 53 | 54 | /** 55 | * Scala 2.12 module that is source-compatible with 2.11. 56 | * This is due to Chisel's use of structural types. See 57 | * https://github.com/freechipsproject/chisel3/issues/606 58 | */ 59 | trait HasXsource211 extends ScalaModule { 60 | override def scalacOptions = T { 61 | super.scalacOptions() ++ Seq( 62 | "-deprecation", 63 | "-unchecked", 64 | "-Xsource:2.11" 65 | ) 66 | } 67 | } 68 | 69 | trait CodeQuality extends ScalafixModule with ScalafmtModule { 70 | def scalafixIvyDeps = 71 | Agg( 72 | ivy"com.github.liancheng::organize-imports:${defaultVersions("organize-imports")}" 73 | ) 74 | } 75 | 76 | trait ScalacOptions extends ScalaModule { 77 | override def scalacOptions = T { 78 | super.scalacOptions() ++ Seq( 79 | "-language:reflectiveCalls", 80 | "-feature", 81 | "-Xfatal-warnings", 82 | "-Ywarn-value-discard", 83 | "-Ywarn-dead-code", 84 | "-Ywarn-unused" 85 | ) 86 | } 87 | } 88 | 89 | object toplevel 90 | extends CrossSbtModule 91 | with HasChisel3 92 | with HasChiselTests 93 | with HasXsource211 94 | with HasMacroParadise 95 | with CodeQuality 96 | with ScalacOptions { 97 | override def millSourcePath = super.millSourcePath 98 | def crossScalaVersion = defaultVersions("scala") 99 | } 100 | -------------------------------------------------------------------------------- /fomublink/constraints/fomu-pvt.pcf: -------------------------------------------------------------------------------- 1 | set_io io_clki F4 2 | set_io io_rgb0 A5 3 | set_io io_rgb1 B5 4 | set_io io_rgb2 C5 5 | set_io io_usb_dn A2 6 | set_io io_usb_dp A1 7 | set_io io_usb_dp_pu A4 8 | set_io pmod_1 E4 9 | set_io pmod_2 D5 10 | set_io pmod_3 E5 11 | set_io pmod_4 F5 12 | set_io pmoda_1 E4 13 | set_io pmoda_2 D5 14 | set_io pmoda_3 E5 15 | set_io pmoda_4 F5 16 | set_io user_1 E4 17 | set_io user_2 D5 18 | set_io user_3 E5 19 | set_io user_4 F5 20 | set_io touch_1 E4 21 | set_io touch_2 D5 22 | set_io touch_3 E5 23 | set_io touch_4 F5 24 | set_io spi_mosi F1 25 | set_io spi_miso E1 26 | set_io spi_clk D1 27 | set_io spi_io2 F2 28 | set_io spi_io3 B1 29 | set_io spi_cs C1 30 | -------------------------------------------------------------------------------- /fomublink/fomublink.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name: carlosedp:demo:fomublink:0 4 | 5 | filesets: 6 | fomu-pvt: 7 | depend: ["fusesoc:utils:generators:0.1.6"] 8 | files: 9 | - constraints/fomu-pvt.pcf : {file_type : PCF} 10 | - post-instructions.txt: 11 | { file_type: user, copyto: post-instructions.txt } 12 | 13 | generate: 14 | fomu-pvt: 15 | generator: chisel 16 | parameters: 17 | chiselproject: toplevel 18 | copy_core: true 19 | output: 20 | files: 21 | - generated/BlinkTop.v: { file_type: verilogSource } 22 | 23 | targets: 24 | fomu-pvt: 25 | default_tool : icestorm 26 | description : Fomu PVT with Lattice ICE40UP5K based open-source board 27 | hooks: 28 | post_run: [dfu-util-fomu] 29 | filesets : [fomu-pvt] 30 | generate: [fomu-pvt] 31 | tools: 32 | icestorm: 33 | nextpnr_options : ["--up5k", "--package", "uwg30"] 34 | pnr : next 35 | toplevel : BlinkTop 36 | 37 | scripts: 38 | dfu-util-fomu: 39 | cmd: ["python3", "-c", "import os;print(open('post-instructions.txt','r').read().replace('{}',os.path.join(os.getcwd(), 'carlosedp_demo_fomublink_0.bin')))"] -------------------------------------------------------------------------------- /fomublink/post-instructions.txt: -------------------------------------------------------------------------------- 1 | Programming instructions: 2 | 3 | Download and install dfu-util from http://dfu-util.sourceforge.net/ 4 | Run: 5 | dfu-util -e -d 1209:5bf0 -D {} -------------------------------------------------------------------------------- /fomublink/scripts/mill: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This is a wrapper script, that automatically download mill from GitHub release pages 4 | # You can give the required mill version with MILL_VERSION env variable 5 | # If no version is given, it falls back to the value of DEFAULT_MILL_VERSION 6 | DEFAULT_MILL_VERSION=0.9.6 7 | 8 | set -e 9 | 10 | if [ -z "$MILL_VERSION" ] ; then 11 | if [ -f ".mill-version" ] ; then 12 | MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)" 13 | elif [ -f "mill" ] && [ "$BASH_SOURCE" != "mill" ] ; then 14 | MILL_VERSION=$(grep -F "DEFAULT_MILL_VERSION=" "mill" | head -n 1 | cut -d= -f2) 15 | else 16 | MILL_VERSION=$DEFAULT_MILL_VERSION 17 | fi 18 | fi 19 | 20 | if [ "x${XDG_CACHE_HOME}" != "x" ] ; then 21 | MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download" 22 | else 23 | MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download" 24 | fi 25 | MILL_EXEC_PATH="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" 26 | 27 | version_remainder="$MILL_VERSION" 28 | MILL_MAJOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}" 29 | MILL_MINOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}" 30 | 31 | if [ ! -x "$MILL_EXEC_PATH" ] ; then 32 | mkdir -p $MILL_DOWNLOAD_PATH 33 | if [ "$MILL_MAJOR_VERSION" -gt 0 ] || [ "$MILL_MINOR_VERSION" -ge 5 ] ; then 34 | ASSEMBLY="-assembly" 35 | fi 36 | DOWNLOAD_FILE=$MILL_EXEC_PATH-tmp-download 37 | MILL_DOWNLOAD_URL="https://github.com/lihaoyi/mill/releases/download/${MILL_VERSION%%-*}/$MILL_VERSION${ASSEMBLY}" 38 | curl --fail -L -o "$DOWNLOAD_FILE" "$MILL_DOWNLOAD_URL" 39 | chmod +x "$DOWNLOAD_FILE" 40 | mv "$DOWNLOAD_FILE" "$MILL_EXEC_PATH" 41 | unset DOWNLOAD_FILE 42 | unset MILL_DOWNLOAD_URL 43 | fi 44 | 45 | unset MILL_DOWNLOAD_PATH 46 | unset MILL_VERSION 47 | 48 | exec $MILL_EXEC_PATH "$@" 49 | -------------------------------------------------------------------------------- /fomublink/src/main/scala/Blinky.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | import chisel3.experimental._ 3 | import chisel3.util._ 4 | import firrtl.annotations.PresetAnnotation 5 | 6 | // Blinking LED top layer 7 | // We use RawModule to avoid Chisel creating a module with implicit clock and reset 8 | class BlinkTop extends RawModule { 9 | val io = IO(new Bundle { 10 | // 48MHz Clock input 11 | val clki = Input(Clock()) 12 | val reset = Input(AsyncReset()) 13 | 14 | // LED outputs 15 | // -------- 16 | val rgb0 = Output(Bool()) 17 | val rgb1 = Output(Bool()) 18 | val rgb2 = Output(Bool()) 19 | 20 | // USB Pins (which should be statically driven if not being used). 21 | // -------- 22 | val usb_dp = Output(Bool()) 23 | val usb_dn = Output(Bool()) 24 | val usb_dp_pu = Output(Bool()) 25 | }) 26 | 27 | // initialize registers to their reset value when the bitstream is programmed since there is no reset wire 28 | annotate(new ChiselAnnotation { 29 | override def toFirrtl = PresetAnnotation(io.reset.toTarget) 30 | }) 31 | 32 | // Disconnect USB pins 33 | io.usb_dp := false.B 34 | io.usb_dn := false.B 35 | io.usb_dp_pu := false.B 36 | 37 | // Instantiate the PLL with clock 38 | val pll = Module(new SB_GB()) 39 | pll.io.USER_SIGNAL_TO_GLOBAL_BUFFER := io.clki 40 | 41 | // Instantiate the RGB Led driver from ICE40 FPGA. 42 | val ledDrv = Module(new SB_RGBA_DRV()) 43 | io.rgb0 := ledDrv.io.RGB0 44 | io.rgb1 := ledDrv.io.RGB1 45 | io.rgb2 := ledDrv.io.RGB2 46 | ledDrv.io.CURREN := true.B 47 | ledDrv.io.RGBLEDEN := true.B 48 | 49 | chisel3.withClockAndReset(pll.io.GLOBAL_BUFFER_OUTPUT, io.reset) { 50 | // In this withClock scope, all synchronous elements are clocked against pll.io.clko. 51 | val (counterValue, _) = Counter(true.B, 48000000) 52 | ledDrv.io.RGB2PWM := counterValue(23) 53 | ledDrv.io.RGB1PWM := counterValue(24) 54 | ledDrv.io.RGB0PWM := counterValue(25) 55 | } 56 | } 57 | 58 | /** 59 | * An object extending App to generate the Verilog code. 60 | */ 61 | object Blink extends App { 62 | (new chisel3.stage.ChiselStage).emitVerilog( 63 | new BlinkTop(), 64 | args 65 | ) 66 | } 67 | -------------------------------------------------------------------------------- /fomublink/src/main/scala/ICE40ledDrvBlackBox.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | // import chisel3.util.HasBlackBoxInline 3 | 4 | /** 5 | * Instantiate iCE40 LED driver hard logic, connecting up 6 | * counter state and LEDs. 7 | * 8 | * Note that it's possible to drive the LEDs directly, 9 | * however that is not current-limited and results in 10 | * overvolting the red LED. 11 | * 12 | * See also: 13 | * https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/IK/ICE40LEDDriverUsageGuide.ashx?document_id=50668 14 | */ 15 | 16 | // Instantiate the IP directly instead of using inline Verilog 17 | class SB_RGBA_DRV() 18 | extends BlackBox( 19 | Map( 20 | "CURRENT_MODE" -> "0b1", // half current 21 | "RGB0_CURRENT" -> "0b000011", // 4 mA 22 | "RGB1_CURRENT" -> "0b000011", // 4 mA 23 | "RGB2_CURRENT" -> "0b000011" // 4 mA 24 | ) 25 | ) { 26 | val io = IO(new Bundle { 27 | val CURREN = Input(Bool()) 28 | val RGBLEDEN = Input(Bool()) 29 | val RGB2PWM = Input(Bool()) // Blue 30 | val RGB1PWM = Input(Bool()) // Red 31 | val RGB0PWM = Input(Bool()) // Green 32 | val RGB0 = Output(Bool()) 33 | val RGB1 = Output(Bool()) 34 | val RGB2 = Output(Bool()) 35 | }) 36 | } 37 | 38 | // Instantiate thru inline verilog. Just here for documentation since 39 | // instantiation above does the same. 40 | // class ICE40ledDrvBlackBox() extends BlackBox with HasBlackBoxInline { 41 | // val io = IO(new Bundle() { 42 | // // LED inputs and outputs 43 | // val rgb0_in = Input(Bool()) 44 | // val rgb1_in = Input(Bool()) 45 | // val rgb2_in = Input(Bool()) 46 | // val rgb0_out = Output(Bool()) 47 | // val rgb1_out = Output(Bool()) 48 | // val rgb2_out = Output(Bool()) 49 | // }) 50 | 51 | // setInline( 52 | // "ICE40ledDrvBlackBox.v", 53 | // s""" 54 | // | module ICE40ledDrvBlackBox( 55 | // | input rgb0_in, 56 | // | input rgb1_in, 57 | // | input rgb2_in, 58 | // | output rgb0_out, 59 | // | output rgb1_out, 60 | // | output rgb2_out 61 | // | ); 62 | // | 63 | // | SB_RGBA_DRV #( 64 | // | .CURRENT_MODE("0b1"), // half current 65 | // | .RGB0_CURRENT("0b000011"), // 4 mA 66 | // | .RGB1_CURRENT("0b000011"), // 4 mA 67 | // | .RGB2_CURRENT("0b000011") // 4 mA 68 | // | ) RGBA_DRIVER ( 69 | // | .CURREN(1'b1), 70 | // | .RGBLEDEN(1'b1), 71 | // | .RGB2PWM(rgb0_in), // Blue 72 | // | .RGB1PWM(rgb1_in), // Red 73 | // | .RGB0PWM(rgb2_in), // Green 74 | // | .RGB0(rgb0_out), 75 | // | .RGB1(rgb1_out), 76 | // | .RGB2(rgb2_out) 77 | // | ); 78 | // | 79 | // | endmodule 80 | // |""".stripMargin 81 | // ) 82 | // } 83 | -------------------------------------------------------------------------------- /fomublink/src/main/scala/ICE40pllBlackbox.scala: -------------------------------------------------------------------------------- 1 | import chisel3._ 2 | // import chisel3.util.HasBlackBoxInline 3 | 4 | // Instantiate the IP directly 5 | class SB_GB extends BlackBox() { 6 | val io = IO(new Bundle { 7 | val USER_SIGNAL_TO_GLOBAL_BUFFER = Input(Clock()) 8 | val GLOBAL_BUFFER_OUTPUT = Output(Clock()) 9 | }) 10 | } 11 | 12 | // Instantiate thru inline verilog. Just here for documentation since 13 | // instantiation above does the same. 14 | // class ICE40pllBlackbox() extends BlackBox with HasBlackBoxInline { 15 | // val io = IO(new Bundle() { 16 | // val clki = Input(Clock()) 17 | // val clko = Output(Clock()) 18 | // }) 19 | 20 | // setInline( 21 | // "ICE40pllBlackbox.v", 22 | // s""" 23 | // | module ICE40pllBlackbox( 24 | // | input clki, 25 | // | output clko 26 | // | ); 27 | // | 28 | // | SB_GB clk_gb ( 29 | // | .USER_SIGNAL_TO_GLOBAL_BUFFER(clki), 30 | // | .GLOBAL_BUFFER_OUTPUT(clko) 31 | // | ); 32 | // | endmodule 33 | // |""".stripMargin 34 | // ) 35 | // } 36 | -------------------------------------------------------------------------------- /pdf/Chisel3-CheatSheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlosedp/chisel-playground/11ce6dd4c252696f28a7823e2253e92ce309ec06/pdf/Chisel3-CheatSheet.pdf -------------------------------------------------------------------------------- /pdf/Chisel3-Documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlosedp/chisel-playground/11ce6dd4c252696f28a7823e2253e92ce309ec06/pdf/Chisel3-Documentation.pdf -------------------------------------------------------------------------------- /pdf/Digital Design with Chisel - Martin Schoeberl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlosedp/chisel-playground/11ce6dd4c252696f28a7823e2253e92ce309ec06/pdf/Digital Design with Chisel - Martin Schoeberl.pdf -------------------------------------------------------------------------------- /pdf/UCB-Chisel-Tutorial.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlosedp/chisel-playground/11ce6dd4c252696f28a7823e2253e92ce309ec06/pdf/UCB-Chisel-Tutorial.pdf --------------------------------------------------------------------------------