commit 6d8c1059fa4bf43890fbdc116a10f39f13fed693 Author: Aadi Desai <21363892+supleed2@users.noreply.github.com> Date: Sun Feb 5 00:56:34 2023 +0000 Initial commit to prevent data loss such as in the case of sudden laptop death diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6513c6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.vscode/ +/build/ diff --git a/make.py b/make.py new file mode 100755 index 0000000..4341661 --- /dev/null +++ b/make.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python3 + +# Modified from original gsd_orangecrab.py from LiteX-Boards. +# +# Copyright (c) Greg Davill +# SPDX-License-Identifier: BSD-2-Clause + +import os +import sys + +from migen import * +from migen.genlib.misc import WaitTimer +from migen.genlib.resetsync import AsyncResetSynchronizer + +from litex.gen import LiteXModule + +from litex_boards.platforms import gsd_orangecrab + +from litex.soc.cores.clock import * +from litex.soc.integration.soc_core import * +from litex.soc.integration.builder import * +from litex.soc.cores.led import LedChaser + +from litedram.modules import MT41K64M16, MT41K128M16, MT41K256M16, MT41K512M16 +from litedram.phy import ECP5DDRPHY + +# CRG --------------------------------------------------------------------------------------------- + +class _CRG(LiteXModule): + def __init__(self, platform, sys_clk_freq, with_usb_pll=False): + self.rst = Signal() + self.cd_por = ClockDomain() + self.cd_sys = ClockDomain() + + # # # + + # Clk / Rst + clk48 = platform.request("clk48") + rst_n = platform.request("usr_btn", loose=True) + if rst_n is None: rst_n = 1 + + # Power on reset + por_count = Signal(16, reset=2**16-1) + por_done = Signal() + self.comb += self.cd_por.clk.eq(clk48) + self.comb += por_done.eq(por_count == 0) + self.sync.por += If(~por_done, por_count.eq(por_count - 1)) + + # PLL + self.pll = pll = ECP5PLL() + self.comb += pll.reset.eq(~por_done | ~rst_n | self.rst) + pll.register_clkin(clk48, 48e6) + pll.create_clkout(self.cd_sys, sys_clk_freq) + + # USB PLL + if with_usb_pll: + self.cd_usb_12 = ClockDomain() + self.cd_usb_48 = ClockDomain() + usb_pll = ECP5PLL() + self.submodules += usb_pll + self.comb += usb_pll.reset.eq(~por_done) + usb_pll.register_clkin(clk48, 48e6) + usb_pll.create_clkout(self.cd_usb_48, 48e6) + usb_pll.create_clkout(self.cd_usb_12, 12e6) + + # FPGA Reset (press usr_btn for 1 second to fallback to bootloader) + reset_timer = WaitTimer(int(48e6)) + reset_timer = ClockDomainsRenamer("por")(reset_timer) + self.submodules += reset_timer + self.comb += reset_timer.wait.eq(~rst_n) + self.comb += platform.request("rst_n").eq(~reset_timer.done) + + +class _CRGSDRAM(LiteXModule): + def __init__(self, platform, sys_clk_freq, with_usb_pll=False): + self.rst = Signal() + self.cd_init = ClockDomain() + self.cd_por = ClockDomain() + self.cd_sys = ClockDomain() + self.cd_sys2x = ClockDomain() + self.cd_sys2x_i = ClockDomain() + + # # # + + self.stop = Signal() + self.reset = Signal() + + # Clk / Rst + clk48 = platform.request("clk48") + rst_n = platform.request("usr_btn", loose=True) + if rst_n is None: rst_n = 1 + + # Power on reset + por_count = Signal(16, reset=2**16-1) + por_done = Signal() + self.comb += self.cd_por.clk.eq(clk48) + self.comb += por_done.eq(por_count == 0) + self.sync.por += If(~por_done, por_count.eq(por_count - 1)) + + # PLL + sys2x_clk_ecsout = Signal() + self.pll = pll = ECP5PLL() + self.comb += pll.reset.eq(~por_done | ~rst_n | self.rst) + pll.register_clkin(clk48, 48e6) + pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq) + pll.create_clkout(self.cd_init, 24e6) + self.specials += [ + Instance("ECLKBRIDGECS", + i_CLK0 = self.cd_sys2x_i.clk, + i_SEL = 0, + o_ECSOUT = sys2x_clk_ecsout), + Instance("ECLKSYNCB", + i_ECLKI = sys2x_clk_ecsout, + i_STOP = self.stop, + o_ECLKO = self.cd_sys2x.clk), + Instance("CLKDIVF", + p_DIV = "2.0", + i_ALIGNWD = 0, + i_CLKI = self.cd_sys2x.clk, + i_RST = self.reset, + o_CDIVX = self.cd_sys.clk), + AsyncResetSynchronizer(self.cd_sys, ~pll.locked | self.reset), + ] + + # USB PLL + if with_usb_pll: + self.cd_usb_12 = ClockDomain() + self.cd_usb_48 = ClockDomain() + usb_pll = ECP5PLL() + self.submodules += usb_pll + self.comb += usb_pll.reset.eq(~por_done) + usb_pll.register_clkin(clk48, 48e6) + usb_pll.create_clkout(self.cd_usb_48, 48e6) + usb_pll.create_clkout(self.cd_usb_12, 12e6) + + # FPGA Reset (press usr_btn for 1 second to fallback to bootloader) + reset_timer = WaitTimer(int(48e6)) + reset_timer = ClockDomainsRenamer("por")(reset_timer) + self.submodules += reset_timer + self.comb += reset_timer.wait.eq(~rst_n) + self.comb += platform.request("rst_n").eq(~reset_timer.done) + +# BaseSoC ------------------------------------------------------------------------------------------ + +class BaseSoC(SoCCore): + def __init__(self, revision="0.2", device="25F", sys_clk_freq=48e6, toolchain="trellis", + sdram_device = "MT41K64M16", + with_led_chaser = True, + **kwargs): + platform = gsd_orangecrab.Platform(revision=revision, device=device ,toolchain=toolchain) + + # CRG -------------------------------------------------------------------------------------- + crg_cls = _CRGSDRAM if kwargs.get("integrated_main_ram_size", 0) == 0 else _CRG + self.crg = crg_cls(platform, sys_clk_freq, with_usb_pll=True) + + # SoCCore ---------------------------------------------------------------------------------- + # Defaults to USB ACM through ValentyUSB. + kwargs["uart_name"] = "usb_acm" + SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on OrangeCrab", **kwargs) + + # DDR3 SDRAM ------------------------------------------------------------------------------- + if not self.integrated_main_ram_size: + available_sdram_modules = { + "MT41K64M16": MT41K64M16, + "MT41K128M16": MT41K128M16, + "MT41K256M16": MT41K256M16, + "MT41K512M16": MT41K512M16, + } + sdram_module = available_sdram_modules.get(sdram_device) + + ddram_pads = platform.request("ddram") + self.ddrphy = ECP5DDRPHY( + pads = ddram_pads, + sys_clk_freq = sys_clk_freq, + dm_remapping = {0:1, 1:0}, + cmd_delay = 0 if sys_clk_freq > 64e6 else 100) + self.ddrphy.settings.rtt_nom = "disabled" + if hasattr(ddram_pads, "vccio"): + self.comb += ddram_pads.vccio.eq(0b111111) + if hasattr(ddram_pads, "gnd"): + self.comb += ddram_pads.gnd.eq(0) + self.comb += self.crg.stop.eq(self.ddrphy.init.stop) + self.comb += self.crg.reset.eq(self.ddrphy.init.reset) + self.add_sdram("sdram", + phy = self.ddrphy, + module = sdram_module(sys_clk_freq, "1:2"), + l2_cache_size = kwargs.get("l2_size", 8192) + ) + + # Leds ------------------------------------------------------------------------------------- + if with_led_chaser: + self.leds = LedChaser( + pads = platform.request_all("user_led"), + sys_clk_freq = sys_clk_freq) + +# Build -------------------------------------------------------------------------------------------- + +def main(): + from litex.build.parser import LiteXArgumentParser + parser = LiteXArgumentParser(platform=gsd_orangecrab.Platform, description="LiteX SoC on OrangeCrab.") + parser.add_target_argument("--sys-clk-freq", default=48e6, type=float, help="System clock frequency.") + parser.add_target_argument("--revision", default="0.2", help="Board Revision (0.1 or 0.2).") + parser.add_target_argument("--device", default="25F", help="ECP5 device (25F, 45F or 85F).") + parser.add_target_argument("--sdram-device", default="MT41K64M16", help="SDRAM device (MT41K64M16, MT41K128M16, MT41K256M16 or MT41K512M16).") + parser.add_target_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.") + args = parser.parse_args() + + soc = BaseSoC( + toolchain = args.toolchain, + revision = args.revision, + device = args.device, + sdram_device = args.sdram_device, + sys_clk_freq = args.sys_clk_freq, + **parser.soc_argdict) + if args.with_spi_sdcard: + soc.add_spi_sdcard() + builder = Builder(soc, **parser.builder_argdict) + if args.build: + builder.build(**parser.toolchain_argdict) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(builder.get_bitstream_filename(mode="sram")) + +if __name__ == "__main__": + main() diff --git a/options.sh b/options.sh new file mode 100644 index 0000000..2abdd1c --- /dev/null +++ b/options.sh @@ -0,0 +1,142 @@ +[-h] +[--toolchain {trellis,diamond}] +[--build] +[--load] +[--log-filename LOG_FILENAME] +[--log-level LOG_LEVEL] +[--sys-clk-freq SYS_CLK_FREQ] +[--revision REVISION] +[--device DEVICE] +[--sdram-device SDRAM_DEVICE] +[--with-spi-sdcard] +[--output-dir OUTPUT_DIR] +[--gateware-dir GATEWARE_DIR] +[--software-dir SOFTWARE_DIR] +[--include-dir INCLUDE_DIR] +[--generated-dir GENERATED_DIR] +[--build-backend BUILD_BACKEND] +[--no-compile] +[--no-compile-software] +[--no-compile-gateware] +[--csr-csv CSR_CSV] +[--csr-json CSR_JSON] +[--csr-svd CSR_SVD] +[--memory-x MEMORY_X] +[--doc] +[--bios-lto] +[--bios-console {full,no-history,no-autocomplete,lite,disable}] +[--bus-standard BUS_STANDARD] +[--bus-data-width BUS_DATA_WIDTH] +[--bus-address-width BUS_ADDRESS_WIDTH] +[--bus-timeout BUS_TIMEOUT] +[--bus-bursting] +[--bus-interconnect BUS_INTERCONNECT] +[--cpu-type CPU_TYPE] +[--cpu-variant CPU_VARIANT] +[--cpu-reset-address CPU_RESET_ADDRESS] +[--cpu-cfu CPU_CFU] +[--no-ctrl] +[--integrated-rom-size INTEGRATED_ROM_SIZE] +[--integrated-rom-init INTEGRATED_ROM_INIT] +[--integrated-sram-size INTEGRATED_SRAM_SIZE] +[--integrated-main-ram-size INTEGRATED_MAIN_RAM_SIZE] +[--csr-data-width CSR_DATA_WIDTH] +[--csr-address-width CSR_ADDRESS_WIDTH] +[--csr-paging CSR_PAGING] +[--csr-ordering CSR_ORDERING] +[--ident IDENT] +[--no-ident-version] +[--no-uart] +[--uart-name UART_NAME] +[--uart-baudrate UART_BAUDRATE] +[--uart-fifo-depth UART_FIFO_DEPTH] +[--no-timer] +[--timer-uptime] +[--l2-size L2_SIZE] +[--yosys-nowidelut] +[--yosys-abc9] +[--yosys-flow3] +[--nextpnr-timingstrict] +[--nextpnr-ignoreloops] +[--nextpnr-seed NEXTPNR_SEED] +[--ecppack-bootaddr ECPPACK_BOOTADDR] +[--ecppack-spimode ECPPACK_SPIMODE] +[--ecppack-freq ECPPACK_FREQ] +[--ecppack-compress] + + +# Target options: + --build # Build design. (default: False) + --load # Load bitstream. (default: False) + --sys-clk-freq SYS_CLK_FREQ + # System clock frequency. (default: 48000000.0) + --revision 0.2 + --device 25F + --sdram-device MT41K64M16 + --with-spi-sdcard + # Enable SPI-mode SDCard support. (default: False) + +# Logging options: + --log-filename build.log + --log-level warning # (or debug, info (default), error or critical) + +# Builder options: + --no-compile + # Disable Software and Gateware compilation. (default: False) + --no-compile-software + # Disable Software compilation only. (default: False) + --no-compile-gateware + # Disable Gateware compilation only. (default: False) + --doc # Generate SoC Documentation. (default: False) + +# SoC options: + --bus-standard axi-lite + # Select bus standard: wishbone, axi-lite, axi. (default: wishbone) + --bus-data-width BUS_DATA_WIDTH + # Bus data-width. (default: 32) + --bus-address-width BUS_ADDRESS_WIDTH + # Bus address-width. (default: 32) + --bus-bursting + # Enable burst cycles on the bus if supported. (default: False) + --bus-interconnect BUS_INTERCONNECT + # Select bus interconnect: shared (default) or crossbar. (default: shared) + --cpu-type CPU_TYPE + # Select CPU: None, marocchino, zynq7000, mor1kx, zynqmp, cv32e41p, openc906, cortex_m1, cva6, eos_s3, ibex, + # cortex_m3, blackparrot, femtorv, vexriscv, rocket, picorv32, vexriscv_smp, lm32, firev, serv, naxriscv, cva5, + # microwatt, neorv32, cv32e40p, gowin_emcu, minerva. (default: vexriscv) + --cpu-variant CPU_VARIANT + # CPU variant. (default: None) + --no-ctrl + # Disable Controller. (default: False) + --integrated-rom-size INTEGRATED_ROM_SIZE + # Size/Enable the integrated (BIOS) ROM (Automatically resized to BIOS size when smaller). (default: 131072) + --integrated-rom-init INTEGRATED_ROM_INIT + # Integrated ROM binary initialization file (override the BIOS when specified). (default: None) + --no-uart + # Disable UART. (default: False) + --uart-name UART_NAME + # UART type/name. (default: serial) + --uart-baudrate UART_BAUDRATE + # UART baudrate. (default: 115200) + +# Trellis toolchain options: + --yosys-nowidelut + # Use Yosys's nowidelut mode. (default: False) + --yosys-abc9 + # Use Yosys's abc9 mode. (default: False) + --yosys-flow3 + # Use Yosys's abc9 mode with the flow3 script. (default: False) + --nextpnr-timingstrict + # Use strict Timing mode (Build will fail when Timings are not met). (default: False) + --nextpnr-ignoreloops + # Ignore combinatorial loops in Timing Analysis. (default: False) + --nextpnr-seed NEXTPNR_SEED + # Set Nextpnr's seed. (default: 1) + --ecppack-bootaddr ECPPACK_BOOTADDR + # Set boot address for next image. (default: 0) + --ecppack-spimode ECPPACK_SPIMODE + # Set slave SPI programming mode. (default: None) + --ecppack-freq ECPPACK_FREQ + # Set SPI MCLK frequency. (default: None) + --ecppack-compress + # Use Bitstream compression. (default: False) diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..206d55d --- /dev/null +++ b/readme.md @@ -0,0 +1,73 @@ +# StackSynth Final Year Project + +## Project Notes + +### Useful links + +- [Litex Wiki: reusing SV or other cores](https://github.com/enjoy-digital/litex/wiki/Reuse-a-(System)Verilog,-VHDL,-(n)Migen,-Spinal-HDL,-Chisel-core) +- [Litex for Hardware Engineers](https://github.com/enjoy-digital/litex/wiki/LiteX-for-Hardware-Engineers) +- [Example of RTOS on LiteX](https://numato.com/kb/running-zephyr-rtos-on-mimas-a7-using-litex-and-risc-v/) +- [Blog on using FreeRTOS on stock VexRiscV Core](https://hackmd.io/@4a740UnwQE6K9pc5tNlJpg/H1olFPOCD) +- [FreeRTOS on RiscV Blog Post](https://hackmd.io/@oscarshiang/freertos_on_riscv) +- [Video on FreeRTOS on RiscV](https://www.youtube.com/watch?v=tM0hiBVP728) +- [VexRiscV Source](https://github.com/SpinalHDL/VexRiscv) +- [Summon FPGA Tools Repo](https://github.com/open-tool-forge/summon-fpga-tools) +- [Broken Flag issue when building litex](https://github.com/enjoy-digital/litex/issues/825) + +### Possible reference links + +- [OrangeCrab FPGA Product Page](https://www.latticesemi.com/products/developmentboardsandkits/orangecrab) +- [OrangeCrab FPGA Hardware Repo](https://github.com/orangecrab-fpga/orangecrab-hardware) +- [OrangeCrab FPGA Example Repo](https://github.com/orangecrab-fpga/orangecrab-examples) + - Use both the Verilog and Blink examples, the CircuitPython example did not work due to the version of CircuitPython needed (I think?) +- [OrangeCrab FPGA Store Listing](https://1bitsquared.com/products/orangecrab) +- [OrangeCrab FPGA Github Docs](https://orangecrab-fpga.github.io/orangecrab-hardware/r0.2/) +- [Hackster post on OrangeCrab FPGA](https://www.hackster.io/news/orangecrab-a-formidable-feature-packed-fpga-feather-04fd6c99eb0f) +- [element14 post on OrangeCrab FPGA](https://community.element14.com/products/roadtest/rv/roadtest_reviews/1481/summer_of_fpgas_oran_1) +- [CNX Software post on OrangeCrab FPGA](https://www.cnx-software.com/2019/08/28/orangecrab-is-an-open-source-hardware-feather-compatible-lattice-ecp5-fpga-board/) +- [Example writeup of using OrangeCrab FPGA](https://codeconstruct.com.au/docs/microwatt-orangecrab/) +- [Amaranth / Migen Crash Course](https://cfu-playground.readthedocs.io/en/latest/crash-course/gateware.html) +- [LiteX Soft-CPU, FPGA and Firmware Support](https://docs.google.com/spreadsheets/d/e/2PACX-1vRavhDreE8bIVYJGl6nKMut_hneywklO9EHSfusXk4Txy3U_l_Ld7ssVO9roR0bTElYEny-DuNLtxAw/pubhtml?gid=0&single=true) +- [FPGA MicroPython (FμPy)](https://fupy.github.io/) +- [FuPy (FPGA MicroPython) on Mimas v2 and Arty](https://ewen.mcneill.gen.nz/blog/entry/2018-01-17-fupy-fpga-micropython-on-mimas-v2-and-arty-a7/) +- [enjoy-digital/litex GitHub](https://github.com/enjoy-digital/litex) +- [litex/boot.c · enjoy-digital/litex](https://github.com/enjoy-digital/litex/blob/master/litex/soc/software/bios/boot.c#L386) +- [litex/litex_setup.py · enjoy-digital/litex](https://github.com/enjoy-digital/litex/blob/master/litex_setup.py) +- [picolibc switch Issue #1045 · enjoy-digital/litex](https://github.com/enjoy-digital/litex/issues/1045) +- [Vexriscv secure CPU Issue #1585 · enjoy-digital/litex](https://github.com/enjoy-digital/litex/issues/1585) +- [LD_FLAGS Issue #825 · enjoy-digital/litex](https://github.com/enjoy-digital/litex/issues/825) +- [Home · enjoy-digital/litex Wiki](https://github.com/enjoy-digital/litex/wiki) +- [gregdavill/linux-on-litex-vexriscv](https://github.com/gregdavill/linux-on-litex-vexriscv/tree/orangecrab) +- [OrangeCrab-test-sw/hw](https://github.com/gregdavill/OrangeCrab-test-sw/tree/main/hw) +- [gregdavill:orangecrab vs upstream · litex-hub/linux-on-litex-vexriscv](https://github.com/litex-hub/linux-on-litex-vexriscv/compare/master...gregdavill:linux-on-litex-vexriscv:orangecrab) +- [Prebuilt Bitstreams and Linux/OpenSBI images for linux on litex](https://github.com/litex-hub/linux-on-litex-vexriscv/issues/164) +- [linux-on-litex-vexriscv/buildroot/board](https://github.com/litex-hub/linux-on-litex-vexriscv/tree/master/buildroot/board) +- [litex-hub/litex-boards: LiteX boards files](https://github.com/litex-hub/litex-boards) +- [litex-boards/lattice_ecp5_evn.py](https://github.com/litex-hub/litex-boards/blob/master/litex_boards/targets/lattice_ecp5_evn.py) +- [litex-boards/lattice_ecp5_vip.py](https://github.com/litex-hub/litex-boards/blob/master/litex_boards/targets/lattice_ecp5_vip.py) +- [litex-boards/litex_boards/targets](https://github.com/litex-hub/litex-boards/tree/master/litex_boards/targets) +- [mwelling/orangecrab-test](https://github.com/mwelling/orangecrab-test) +- [Use read_verilog in Yosys orangecrab example command](https://github.com/orangecrab-fpga/orangecrab-examples/commit/32a8c075bbcdb2d8bb7da99e4cde6d9997d88463) +- [litex example cannot find Yosys or nextpnr-ecp5 programs](https://github.com/orangecrab-fpga/orangecrab-examples/issues/10) +- [Migrate nMigen examples to Amaranth in orangecrab example](https://github.com/orangecrab-fpga/orangecrab-examples/pull/30) +- [RISC-V with custom gateware Issue #35 · orangecrab-fpga/orangecrab-hardware](https://github.com/orangecrab-fpga/orangecrab-hardware/issues/35) +- [Lattice Diamond Compatibility Issue #41 · orangecrab-fpga/orangecrab-hardware](https://github.com/orangecrab-fpga/orangecrab-hardware/issues/41) +- [timvideos/litex-buildenv](https://github.com/timvideos/litex-buildenv) +- [Bare Metal · timvideos/litex-buildenv Wiki](https://github.com/timvideos/litex-buildenv/wiki/Bare-Metal) +- [YosysHQ/nextpnr: nextpnr portable FPGA place and route tool](https://github.com/YosysHQ/nextpnr) +- [Lattice FPGA SBCs can run Linux on RISC-V softcore](https://linuxgizmos.com/lattice-fpga-sbcs-can-run-linux-on-risc-v-softcore/) +- [litex_liteeth.c:undefined reference to `devm_platform_ioremap_resource_byname'](https://lore.kernel.org/lkml/202202070822.w4rpU462-lkp@intel.com/T/) +- [Linux on LiteX-Vexriscv - Hacker News](https://news.ycombinator.com/item?id=25726356) +- [Running Zephyr RTOS on Mimas A7 using LiteX and RISC-V](https://numato.com/kb/running-zephyr-rtos-on-mimas-a7-using-litex-and-risc-v/) +- [Downloads | OrangeCrab Docs](https://orangecrab-fpga.github.io/orangecrab-hardware/r0.2/docs/downloads/) +- [Zephyr on Fomu FPGA](https://workshop.fomu.im/en/latest/renode-zephyr.html) +- [Building a SoC with Litex. – controlpaths blog](https://www.controlpaths.com/2022/01/17/building-a-soc-with-litex/) +- [Running Linux on a Litex SoC. – controlpaths blog](https://www.controlpaths.com/2022/03/28/running-linux-on-a-litex-soc/) +- [Say “Hello” to the OrangeCrab - Hackster.io](https://www.hackster.io/news/say-hello-to-the-orangecrab-16835001f36a) +- [LiteX Research Paper???](https://www.researchgate.net/publication/341202045_LiteX_an_open-source_SoC_builder_and_library_based_on_Migen_Python_DSL) +- [learn-fpga/toolchain.md · BrunoLevy/learn-fpga](https://github.com/BrunoLevy/learn-fpga/blob/master/FemtoRV/TUTORIALS/toolchain.md) +- [Testing the OrangeCrab r0.1 Blog](https://whatnicklife.blogspot.com/2020/01/testing-orangecrab-r01.html) +- [FOSS-for_FPGA Slideshow](https://indico.ictp.it/event/9443/session/258/contribution/587/material/slides/0.pdf) +- [FPGA Tooling on Ubuntu 20.04 - FPGA Dev](https://projectf.io/posts/fpga-dev-ubuntu-20.04/) +- [Reddit question on riscv core on fpga](https://www.reddit.com/r/RISCV/comments/t1raxb/is_it_possible_to_build_a_riscv_core_on_fpga/) +- [linux-on-litex-vexriscv/orangecrab_with_enc28j60_on_spi.md](https://github.com/niw/linux-on-litex-vexriscv/blob/add_enc28j60_to_orange_crab/orangecrab_with_enc28j60_on_spi.md)