Beginner / 60 min

Run your first DungV program

Let's build the processor, load a program, and get some color out of the board. After that, we'll change the program without rebuilding the processor itself.

Get the project and its tools

Download and extract OSS CAD Suite following its installation instructions. Add its bin directory to your terminal's path, replacing the example location with your own:

export PATH="$HOME/Documents/oss-cad-suite/bin:$PATH"

This setting applies to the current terminal session. Keep using that terminal for the builds below.

Next, download DungV:

git clone https://github.com/skerr92/DungV.git
cd DungV
git -c submodule.OASIS.url=https://github.com/skerr92/OASIS.git submodule update --init OASIS
make examples
make -C rtl/dungv build

Run these from your computer's terminal. DungV includes OASIS as a submodule: a separate repository held at a particular version inside the project. The longer Git command downloads that pinned version over HTTPS, so you don't need a GitHub SSH key just to follow along.

If you already keep OASIS beside DungV on your computer, leave that separate checkout alone. These commands use the copy inside DungV/OASIS, which is the version this design expects.

make examples turns the assembly examples into program files. The second Make command builds the FPGA hardware. At the end, check for these two files:

rtl/dungv/top.bin
.build/examples/pwm_rgb_rainbow.spi16

The .build folder starts with a dot, so your file manager may hide it. Enable hidden files if needed. You won't need a C compiler for this example.

Prepare the RP2040

Back up existing board files, then install the stable .uf2 from the RPGA Feather CircuitPython download page. Hold BOOT while connecting USB, release it, and copy the firmware onto RPI-RP2. Wait for the board to restart as CIRCUITPY.

If CircuitPython is already installed for this board, you can keep it. Open the serial console and press Ctrl+C to stop the current program before replacing project files.

From the CircuitPython library bundles matching your firmware's major version, copy oakdevtech_icepython.mpy from the community bundle and the adafruit_bus_device folder from the Adafruit bundle into CIRCUITPY/lib. IcePython loads the FPGA configuration; Bus Device supplies its supporting SPI interface. Source .py versions can also be used in place of the compiled .mpy files.

If this is your first time using the console, follow the CircuitPython serial console instructions. We'll use it to tell the difference between loading the FPGA and loading the CPU's program.

Select the onboard LED example

Copy circuitpython/code.py from DungV into a working folder on your computer and open that copy in a text editor. The repository's loader defaults to an eight-pixel external LED strip. We're choosing the onboard RGB PWM example instead.

Near the top, replace the DUNGV_PROGRAM_IMAGE assignment with:

DUNGV_PROGRAM_IMAGE = "pwm_rgb_rainbow.spi16"

Near the bottom, replace the two status messages describing the eight-pixel demo and its data pin with this one line:

print("DungV onboard RGB PWM demo running")

Inside the missing-file error handler, also change its copy instruction to:

    print("copy pwm_rgb_rainbow.spi16 to CIRCUITPY")

Keep that line indented with the other lines in the error handler. The rest of the loader stays as supplied by DungV. In particular, keep the FPGA SPI setup and F3 programming control.

Copy the built top.bin and .build/examples/pwm_rgb_rainbow.spi16 onto the board, then save your edited loader as CIRCUITPY/code.py last:

CIRCUITPY/
  code.py
  top.bin
  pwm_rgb_rainbow.spi16
  lib/
    oakdevtech_icepython.mpy
    adafruit_bus_device/

Disconnect external circuits while trying this example. The onboard LED needs no jumper wires, and other FPGA peripherals may share connections with attached hardware. If you're switching from the networking guide, replace its top.bin and code.py with the DungV versions.

Load it and watch

Press Ctrl+D in the console. You should first see a message saying the FPGA was programmed from top.bin, followed by a message reporting how many SPI16 frames were sent from pwm_rgb_rainbow.spi16. Then you'll see your new onboard-demo status message.

The LED should fade from red to green to blue and repeat. That visible behavior is the useful check that the DungV program is running. The loader's printed status tells us it sent the file; it doesn't independently verify every instruction or LED output.

At this point, CircuitPython has done its loading job and is waiting in its final loop. The color changes come from DungV running inside the FPGA.

Read a few instructions

Open examples/pwm_rgb_rainbow.oas on your computer. The beginning sets up a few values and enables the PWM hardware:

MVI r1, 1
MVI r2, 0x00ff
MVI r3, 0x0000
MVI r4, 0x0000
MSI io:[0x010], 0x0001

MVI puts a value in a register, a small storage location inside the processor. Here, r2, r3, and r4 start with our red, green, and blue brightness values. 0x means the number is written in hexadecimal; 0x00ff is 255 in decimal.

MSI writes an immediate value to an address. The io: prefix says we're talking to a peripheral rather than ordinary program data. Address 0x010 controls RGB PWM, and writing 1 enables it.

The next part sends the three brightness values and applies them together:

MVT r2, io:[0x011]
MVT r3, io:[0x012]
MVT r4, io:[0x013]
MSI io:[0x014], 0x0001

MVT writes a register's value to the selected address. The first three writes prepare new brightness settings; the last write commits them. The rest of the example slowly transfers brightness between colors, with a counting loop to space out the updates.

You may see this called memory-mapped I/O, or MMIO. For this project, the useful idea is simple: the CPU controls hardware by reading and writing agreed-upon addresses. The DungV peripheral guide lists them when you're ready for more.

Change the fade speed

Find the three occurrences of this instruction in the assembly file:

MVI r5, 0xffff

Each starts a delay counter for one part of the color cycle. Change all three to:

MVI r5, 0x3fff

Save the source and, from the DungV repository's main folder, run:

make examples

Copy the updated .build/examples/pwm_rgb_rainbow.spi16 onto CIRCUITPY, then press Ctrl+D. The fade should run faster because the CPU spends less time counting between brightness updates. The delay isn't a precise clock, but it's an easy change to see.

You don't need to rebuild top.bin for this change. We changed the instructions the CPU runs, and the existing hardware already understands them. If we change the processor or add a peripheral in Verilog later, then we'll rebuild the FPGA configuration too.

When something doesn't work

If the program stops with an exception, start with its line number and message. Get back to the unchanged rainbow example before making another experiment.

Where to go next

Try the GPIO or UART assembly examples next, reading their wiring and register notes before connecting anything. A processor becomes more interesting when it has something to talk to.

OASIS also has C/C++ toolchain work, but compiler output uses additional instructions. Check DungV's current compatibility report before choosing that path; an available compiler doesn't by itself tell us which programs a particular FPGA build can run.

For now, you've built a processor in an FPGA, given it a program, and changed what it does. That's a solid place to start. The DungV examples and OASIS instruction documentation are there when the next question comes along.