diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bcff26f..cba7147 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ jobs: Bitstream-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive @@ -14,51 +14,31 @@ jobs: run: | sudo apt-get update sudo apt-get install -y python3-pip bzip2 cmake build-essential clang bison flex tcl-dev libffi-dev mercurial graphviz xdot pkg-config python3 libftdi-dev python3-dev libeigen3-dev zlib1g-dev - sudo apt update sudo apt-get install -y libboost-dev libboost-filesystem-dev libboost-thread-dev libboost-program-options-dev libboost-iostreams-dev libboost-dev libboost-system-dev libboost-python-dev libboost-filesystem-dev - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - ./install.sh + sudo apt-get install -y gcc-riscv64-unknown-elf - - name: Install yosys + - name: Install OSS CAD tools run: | - git clone https://github.com/YosysHQ/yosys.git - cd yosys - make config-gcc - make -j`nproc` - sudo make install - cd .. - rm -rf yosys - - - name: Install prjoxide - run: | - git clone --recursive https://github.com/gatecat/prjoxide - cd prjoxide/libprjoxide - export PATH=$HOME/.cargo/bin:$PATH - cargo install --path prjoxide - cd ../../ - rm -rf prjoxide - - - name: Install nextpnr - run: | - git clone --recursive https://github.com/YosysHQ/nextpnr - cd nextpnr - cmake -DARCH=nexus -DOXIDE_INSTALL_PREFIX=$HOME/.cargo . - make -j`nproc` - sudo make install - cd .. - rm -rf nextpnr + curl -s https://api.github.com/repos/YosysHQ/oss-cad-suite-build/releases/latest \ + | grep "browser_download_url.*oss-cad-suite-linux-x64-" \ + | cut -d : -f 2,3 \ + | tr -d \" \ + | wget -qi - + tar -xf oss-cad-suite-linux-x64-*.tgz + rm -v oss-cad-suite-linux-x64-*.tgz - name: Build bitstream run: | + source oss-cad-suite/environment source ./init - pip3 install packaging + pip3 install packaging meson ninja echo $PATH - ./make.py --board=sdi_mipi_bridge --toolchain=oxide --build --csr-json csr.json + ./make.py --board=sdi_mipi_bridge --toolchain=oxide --build --csr-json csr.json --with_all - name: Generate dts and config run: ./third_party/litex/litex/tools/litex_json2dts_zephyr.py --dts overlay.dts --config overlay.config csr.json - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: ${{github.job}} path: | @@ -70,9 +50,9 @@ jobs: runs-on: ubuntu-22.04 needs: Bitstream-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: Bitstream-build @@ -85,9 +65,7 @@ jobs: - name: Download Zephyr SDK run: | - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.15.0/zephyr-sdk-0.15.0_linux-x86_64.tar.gz - tar xvf zephyr-sdk-0.15.0_linux-x86_64.tar.gz - rm -v zephyr-sdk-0.15.0_linux-x86_64.tar.gz + wget -q -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.8/zephyr-sdk-0.16.8_linux-x86_64.tar.xz | tar -J -xf - - name: Prepare Zephyr run: | @@ -101,13 +79,13 @@ jobs: - name: Install Zephyr SDK run: | - cd zephyr-sdk-0.15.0/ + cd zephyr-sdk-* ./setup.sh -h -t riscv64-zephyr-elf cd ../ - name: Build Zephyr App run: | - export CMAKE_PREFIX_PATH=$PWD/zephyr-sdk-0.15.0 + export ZEPHYR_SDK_INSTALL_DIR=$PWD cd zephyrproject/zephyr cat ../../Bitstream-build/overlay.config | xargs west build -b litex_vexriscv samples/philosophers/ -- -DDTC_OVERLAY_FILE= ../../Bitstream-build/overlay.dts cd ../../ diff --git a/.gitmodules b/.gitmodules index ed23258..711c92e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,6 +31,9 @@ [submodule "third_party/litex-boards"] path = third_party/litex-boards url = https://github.com/litex-hub/litex-boards.git +[submodule "third_party/litespi"] + path = third_party/litespi + url = https://github.com/litex-hub/litespi.git [submodule "third_party/liteiclink"] path = third_party/liteiclink url = https://github.com/enjoy-digital/liteiclink.git diff --git a/README.md b/README.md index 77f958e..1e1ef26 100644 --- a/README.md +++ b/README.md @@ -62,10 +62,12 @@ Build options | --with_i2s | Enable i2s | | --sys-clk-freq | System clock frequency | | --with_spi | Enable SPI | +| --with_spi_flash | Enable SPI flash | | --with_i2c | Enable i2c | | --with_pwm | Enable PWM | | --spi-data-width | SPI data width | | --spi-clk-freq | SPI clock frequency | +| --spi_flash_rate | SPI flash rate | | --with_mmcm | Enable MMCM | | --local-ip | local IP address | | --remote-ip | remote IP address | diff --git a/init b/init index 58a455d..0ffe8ee 100755 --- a/init +++ b/init @@ -1,7 +1,7 @@ export PATH="${PWD}/third_party/litex/litex/tools:$PATH" export PATH="${PWD}/tools/conda/bin:$PATH" -directories=(litedram liteeth liteiclink litepcie litesata litescope litevideo litex litex-boards litex-renode migen nmigen pythondata-cpu-vexriscv pythondata-software-compiler_rt pythondata-software-picolibc) +directories=(litedram liteeth liteiclink litepcie litespi litesata litescope litevideo litex litex-boards litex-renode migen nmigen pythondata-cpu-vexriscv pythondata-software-compiler_rt pythondata-software-picolibc) for directory in "${directories[@]}"; do diff --git a/make.py b/make.py index 2ba47bc..3161f1b 100755 --- a/make.py +++ b/make.py @@ -67,24 +67,44 @@ def main(): parser.add_argument("--toolchain", default="symbiflow", help="FPGA toolchain - vivado, symbiflow or oxide (yosys+nextpnr).") parser.add_argument("--board", required=True, help="FPGA board") parser.add_argument("--build", action="store_true", help="build bitstream") + parser.add_argument("--flash", action="store_true", help="Flash bitstream.") parser.add_argument("--variant", default=None, help="FPGA board variant") parser.add_argument("--load", action="store_true", help="load bitstream (to SRAM). set path to bitstream") + parser.add_argument("--with_all", action="store_true", help="Enable all peripherals") parser.add_argument("--with_ethernet", action="store_true", help="Enable ethernet (Arty target only)") + parser.add_argument("--with_etherbone", action="store_true", help="Enable etherbone (Arty target only)") parser.add_argument("--with_i2s", action="store_true", help="Enable i2s (Arty target only)") parser.add_argument("--sys-clk-freq", default=100e6, help="System clock frequency.") parser.add_argument("--with_spi", action="store_true", help="Enable spi (Arty target only)") + parser.add_argument("--with_spi_flash", action="store_true", help="Enable spi flash (Arty target only)") parser.add_argument("--with_i2c", action="store_true", help="Enable i2c (Arty target only)") parser.add_argument("--with_pwm", action="store_true", help="Enable pwm (Arty target only)") parser.add_argument("--spi-data-width", type=int, default=8, help="SPI data width (maximum transfered bits per xfer, Arty target only)") parser.add_argument("--spi-clk-freq", type=int, default=1e6, help="SPI clock frequency (Arty target only)") + parser.add_argument("--spi_flash_rate", default="1:1", help="SPI flash rate, can be 1:1 or 1:2 (Arty target only)") parser.add_argument("--with_mmcm", action="store_true", help="Enable mmcm (Arty target only)") - parser.add_argument("--local-ip", default="192.168.1.50", help="local IP address (Arty target only)") + parser.add_argument("--with_watchdog", action="store_true", help="Enable watchdog") + parser.add_argument("--watchdog_width", type=int, default=32, help="Watchdog width") + parser.add_argument("--watchdog_reset_delay", type=int, default=None, help="Watchdog reset delay") + parser.add_argument("--etherbone-ip", default="192.168.1.50", help="etherbone IP address (Arty target only)") + parser.add_argument("--local-ip", default="192.168.1.51", help="local IP address (Arty target only)") parser.add_argument("--remote-ip", default="192.168.1.100", help="remote IP address of TFTP server (Arty target only)") builder_args(parser) vivado_build_args(parser) oxide_args(parser) args = parser.parse_args() + if args.with_all: + args.with_ethernet = True + args.with_etherbone = True + args.with_i2s = True + args.with_spi = True + args.with_spi_flash = True + args.with_i2c = True + args.with_pwm = True + args.with_mmcm = True + args.with_watchdog = True + if args.board == "all": board_names = list(supported_boards.keys()) else: @@ -108,15 +128,30 @@ def main(): soc = SoCZephyr(board.soc_cls, **soc_kwargs) + if args.with_watchdog: + soc.add_watchdog(name="watchdog0" ,width=args.watchdog_width, reset_delay=args.watchdog_reset_delay) + if board_name == "arty": - if args.with_ethernet: - soc.add_eth(local_ip=args.local_ip, remote_ip=args.remote_ip) + if args.with_ethernet or args.with_etherbone: + from liteeth.phy.mii import LiteEthPHYMII + soc.ethphy = LiteEthPHYMII( + clock_pads = soc.platform.request("eth_clocks"), + pads = soc.platform.request("eth")) + if args.with_etherbone: + soc.add_etherbone(phy=soc.ethphy, ip_address=args.etherbone_ip, with_ethmac=args.with_ethernet, ethmac_local_ip=args.local_ip, ethmac_remote_ip=args.remote_ip) + elif args.with_ethernet: + soc.add_ethernet(phy=soc.ethphy, local_ip=args.local_ip, remote_ip=args.remote_ip) if args.with_mmcm: soc.add_mmcm(board.mmcm_freq) if args.with_pwm: soc.add_rgb_led() if args.with_spi: - soc.add_spi(args.spi_data_width, args.spi_clk_freq) + soc.add_spi_master(name="spi", data_width=args.spi_data_width, spi_clk_freq=args.spi_clk_freq) + if args.with_spi_flash: + from litespi.modules import S25FL128L + from litespi.opcodes import SpiNorFlashOpCodes as Codes + assert args.spi_flash_rate in ["1:1", "1:2"] + soc.add_spi_flash(mode="4x", module=S25FL128L(Codes.READ_1_1_4), rate=args.spi_flash_rate, with_master=True) if args.with_i2c: soc.add_i2c() if args.with_i2s: @@ -139,6 +174,10 @@ def main(): if args.load: board.load(soc, filename=os.path.join(build_dir, "gateware", board.bitstream_name + board.bitstream_ext)) + + if args.flash: + prog = soc.platform.create_programmer() + prog.flash(0, os.path.join(build_dir, "gateware", board.bitstream_name + board.bitstream_ext)) if __name__ == "__main__": main() diff --git a/soc_zephyr.py b/soc_zephyr.py index eb55565..9192125 100644 --- a/soc_zephyr.py +++ b/soc_zephyr.py @@ -49,6 +49,9 @@ class _SoCZephyr(soc_cls): "i2s_rx": 21, # addr: 0xe000a800 "i2s_tx": 22, # addr: 0xe000b000 "ddrphy": 23, # addr: 0xe000b800 + "spiflash_core": 24, # addr: 0xe000c000 + "spiflash_phy": 25, # addr: 0xe000c800 + "watchdog0": 26, # addr: 0xe000d000 }} interrupt_map = {**soc_cls.interrupt_map, **{ @@ -57,12 +60,14 @@ class _SoCZephyr(soc_cls): "ethmac": 3, "i2s_rx": 6, "i2s_tx": 7, + "watchdog0": 8, }} mem_map_zephyr = { "rom": 0x00000000, "sram": 0x01000000, "main_ram": 0x40000000, + "spiflash": 0x60000000, "ethmac": 0xb0000000, "i2s_rx": 0xb1000000, "i2s_tx": 0xb2000000, @@ -79,10 +84,6 @@ def __init__(self, cpu_variant="standard", **kwargs): **kwargs) soc_cls.mem_map.update(self.mem_map_zephyr) - def add_spi(self, data_width, spi_clk_freq): - spi_pads = self.platform.request("spi", 0) - self.submodules.spi = SPIMaster(spi_pads, data_width, self.clk_freq, spi_clk_freq) - def add_rgb_led(self): rgb_led_pads = self.platform.request("rgb_led", 0) setattr(self.submodules, "rgb_led_r0", PWM(getattr(rgb_led_pads, 'r'))) @@ -142,49 +143,4 @@ def add_mmcm(self, freqs={}): self.mmcm.expose_drp() self.comb += self.mmcm.reset.eq(self.mmcm.drp_reset.re) - def add_eth(self, local_ip, remote_ip): - local_ip = local_ip.split(".") - remote_ip = remote_ip.split(".") - - self.add_constant("LOCALIP1", int(local_ip[0])) - self.add_constant("LOCALIP2", int(local_ip[1])) - self.add_constant("LOCALIP3", int(local_ip[2])) - self.add_constant("LOCALIP4", int(local_ip[3])) - - self.add_constant("REMOTEIP1", int(remote_ip[0])) - self.add_constant("REMOTEIP2", int(remote_ip[1])) - self.add_constant("REMOTEIP3", int(remote_ip[2])) - self.add_constant("REMOTEIP4", int(remote_ip[3])) - self.submodules.ethphy = LiteEthPHYMII( - clock_pads = self.platform.request("eth_clocks"), - pads = self.platform.request("eth")) - phy = self.ethphy - # Imports - from liteeth.mac import LiteEthMAC - # MAC - ethmac = LiteEthMAC( - phy=phy, - dw=32, - interface="wishbone", - endianness=self.cpu.endianness) - - self.submodules.ethmac = ethmac - name="ethmac" - ethmac_region=SoCRegion(origin=self.mem_map_zephyr.get(name, None), size=0x2000, cached=False) - self.bus.add_slave(name=name, slave=ethmac.bus, region=ethmac_region) - - # Timing constraints - if hasattr(phy, "crg"): - eth_rx_clk = phy.crg.cd_eth_rx.clk - eth_tx_clk = phy.crg.cd_eth_tx.clk - else: - eth_rx_clk = phy.cd_eth_rx.clk - eth_tx_clk = phy.cd_eth_tx.clk - self.platform.add_period_constraint(eth_rx_clk, 1e9/phy.rx_clk_freq) - self.platform.add_period_constraint(eth_tx_clk, 1e9/phy.tx_clk_freq) - self.platform.add_false_path_constraints( - self.crg.cd_sys.clk, - eth_rx_clk, - eth_tx_clk) - return _SoCZephyr(**kwargs) diff --git a/third_party/litedram b/third_party/litedram index f94366c..5ece090 160000 --- a/third_party/litedram +++ b/third_party/litedram @@ -1 +1 @@ -Subproject commit f94366c769d460d50131937fa3b1bb5bc23afe0a +Subproject commit 5ece0901553b0134a94206604796a53c5669743c diff --git a/third_party/liteeth b/third_party/liteeth index 97dccdb..7d24ac3 160000 --- a/third_party/liteeth +++ b/third_party/liteeth @@ -1 +1 @@ -Subproject commit 97dccdb294fa2081536f26f4ef6235c004007432 +Subproject commit 7d24ac33ae5c8109c48465cf676101b692cf6453 diff --git a/third_party/liteiclink b/third_party/liteiclink index 91f07ac..b3ccc51 160000 --- a/third_party/liteiclink +++ b/third_party/liteiclink @@ -1 +1 @@ -Subproject commit 91f07ac01d142afa590fb55404b039842b677b39 +Subproject commit b3ccc51cc62ed2b88b9429d55a7f5a39b6f6e234 diff --git a/third_party/litepcie b/third_party/litepcie index 5062d9e..5767a49 160000 --- a/third_party/litepcie +++ b/third_party/litepcie @@ -1 +1 @@ -Subproject commit 5062d9e58d5b24fb002f3609acb46f3caaf97332 +Subproject commit 5767a4905ed03b77d6f4e20cc2cf6b626e81f385 diff --git a/third_party/litesata b/third_party/litesata index e222360..4dc440d 160000 --- a/third_party/litesata +++ b/third_party/litesata @@ -1 +1 @@ -Subproject commit e222360cfcf9e26d6039eb04785fa50b1256a40e +Subproject commit 4dc440d1f637e878d4abbc670a619cd00acdb6ef diff --git a/third_party/litescope b/third_party/litescope index 7105b47..976656b 160000 --- a/third_party/litescope +++ b/third_party/litescope @@ -1 +1 @@ -Subproject commit 7105b474026383fff6e3c829e487b56754b6e380 +Subproject commit 976656b5194db2cdf6c3257c5975e4fa1233f859 diff --git a/third_party/litespi b/third_party/litespi new file mode 160000 index 0000000..3a0651d --- /dev/null +++ b/third_party/litespi @@ -0,0 +1 @@ +Subproject commit 3a0651d91248a8547c13e2365733f02fd6789fb8 diff --git a/third_party/litex b/third_party/litex index c054dc1..1ad0f82 160000 --- a/third_party/litex +++ b/third_party/litex @@ -1 +1 @@ -Subproject commit c054dc13d9a14674ba7d0fd35e334f0891b31519 +Subproject commit 1ad0f828bbbaad83cdb7b5f5be6f5a1de4b00b9e diff --git a/third_party/litex-boards b/third_party/litex-boards index 549905b..95f5e03 160000 --- a/third_party/litex-boards +++ b/third_party/litex-boards @@ -1 +1 @@ -Subproject commit 549905bc38b6c8af23c0483260da88083a838d1d +Subproject commit 95f5e030e5628444d248af7bb81a9ea1dbffc22c diff --git a/third_party/migen b/third_party/migen index ccaee68..4790bb5 160000 --- a/third_party/migen +++ b/third_party/migen @@ -1 +1 @@ -Subproject commit ccaee68e14d3636e1d8fb2e0864dd89b1b1f7384 +Subproject commit 4790bb577681a8c3a8d226bc196a4e5deb39e4df diff --git a/third_party/pythondata-cpu-vexriscv b/third_party/pythondata-cpu-vexriscv index e75700d..1979a64 160000 --- a/third_party/pythondata-cpu-vexriscv +++ b/third_party/pythondata-cpu-vexriscv @@ -1 +1 @@ -Subproject commit e75700dff2ab9662f3e26dd89ab59a5f6da65687 +Subproject commit 1979a644dbe64d8d32dfbdd970dccee6add63723