---
hide: navigation
---

## Introduction

The process of developing a new application with RVX involves two main steps:

1. Building the application

    The first step is to write the source code for the new application and build it with the [RISC-V GNU Toolchain](https://github.com/riscv/riscv-gnu-toolchain). The build process generates a `.hex` file that is later used to initialize the memory of RVX.

2. Running on an FPGA

    Once you have built the application, you can run it on RVX. To do this, you need to implement an instance of RVX on an FPGA and initialize it with the `.hex` file generated in the first step.

## Prerequisites

To build software for RISC-V you need the [RISC-V GNU Toolchain](https://github.com/riscv/riscv-gnu-toolchain), a suite of compilers and development tools for the RISC-V architecture. 

Run the commands below to install and configure the RISC-V GNU Toolchain for RVX:

```title="1. Clone the RISC-V GNU Toolchain repository"
git clone https://github.com/riscv-collab/riscv-gnu-toolchain
```

=== "Ubuntu"

    ```title="2. Install dependencies (Ubuntu)"
    sudo apt-get install \
        autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev \
        libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc \
        zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libslirp-dev
    ```

=== "Fedora/CentOS/RHEL/Rocky"

    ```title="2. Install dependencies (Fedora/CentOS/RHEL/Rocky)"
    sudo yum install \
        autoconf automake python3 libmpc-devel mpfr-devel gmp-devel gawk  bison flex \
        texinfo patchutils gcc gcc-c++ zlib-devel expat-devel libslirp-devel
    ```

=== "Arch Linux"

    ```title="2. Install dependencies (Arch Linux)"
    sudo pacman -Syyu \
        autoconf automake curl python3 libmpc mpfr gmp gawk base-devel bison flex texinfo \
        gperf libtool patchutils bc zlib expat libslirp
    ```

=== "OS X"

    ```title="2. Install dependencies (OS X)"
    brew install python3 gawk gnu-sed gmp mpfr libmpc isl zlib expat texinfo flock libslirp
    ```

```title="3. Configure the RISC-V GNU Toolchain for RVX"
cd riscv-gnu-toolchain && ./configure --with-arch=rv32izicsr --with-abi=ilp32 --prefix=/opt/riscv
```

!!! quote ""

    **Important:** The `--prefix` option defines the installation folder. You need to set it to a folder where you have `rwx` permissions. The command above assumes you have `rwx` permissions on `/opt`.

```title="4. Compile and install"
make -j $(nproc)
```

## Building the application

RVX offers two template projects to help you start developing new applications: a **bare-metal** template and a more sophisticated **FreeRTOS** template.

Both templates include a `main.c` file where you place the source code for the new application. These projects use CMake to configure the RISC-V GNU Toolchain for RVX, which simplifies the process of compiling and linking the software.

To start a new application, follow the steps below.

```title="1. Clone RVX repository"
git clone https://github.com/rafaelcalcada/rvx
```

=== "Bare-metal"

    ```title="2. Copy the template project (Bare-metal)"
    cp -r rvx/templates/baremetal my_project/
    ```

=== "FreeRTOS"

    ```title="2. Copy the template project (FreeRTOS)"
    cp -r rvx/templates/freertos my_project/
    ```

<div class="api-doc-text" markdown>

Find the `main.c` file in the project folder and write the code for the new application in this file.

</div>
=== "Bare-metal"

    ```bash title="3. Build the application (Bare-metal)"
    cd my_project/ && make PREFIX=/opt/riscv
    ```

=== "FreeRTOS"

    ```bash title="3. Build the application (FreeRTOS)"
    cd my_project/ && make PREFIX=/opt/riscv CLOCK_FREQUENCY=<freq_in_hertz>
    ```

The `PREFIX` variable must specify the folder where the RISC-V GNU Toolchain is installed. For the FreeRTOS template, you also need to set the `CLOCK_FREQUENCY` variable to match the clock frequency of the FPGA board where the application will run.

A successfull build ends with a message like this:

```title="Successful build report"
Memory init file:   build/freertos.hex
Binary executable:  build/freertos.elf
Disassembly:        build/freertos.objdump

Memory usage report (MEMORY_SIZE = 32K)
      text       data        bss      total filename
     14092        304       9196      23592 freertos.elf
```

The `.hex` file generated by the build process will be used in the next step to initialize the memory of RVX.

## Running on an FPGA

Once you have generated the `.hex` file you can implement RVX on an FPGA to run the application. This process consists of two steps:

- First, create a wrapper module that includes an instance of RVX, configure it for the target FPGA, and initialize it with the application to be run using the `.hex` file.

- Next, use the EDA software provided by your FPGA vendor to synthesize the wrapper module and program the FPGA with it.

<h4>1. Creating the wrapper module</h4>

Using your preferred text editor, create a Verilog file called `rvx_wrapper.v` and add the code provided below. Make sure to modify the file according to the instructions in the comments.

```verilog title="rvx_wrapper.v"

module rvx_wrapper (
  
  input   wire          clock       ,
  input   wire          reset       ,
  input   wire          halt        ,

  // UART pins
  // You can remove them if your application does not use the UART controller
  input   wire          uart_rx     ,
  output  wire          uart_tx     ,

  // General Purpose I/O pins
  // You can remove them if your application does not use the GPIO controller
  input   wire  [3:0]   gpio_input  ,
  output  wire  [3:0]   gpio_oe     ,
  output  wire  [3:0]   gpio_output ,

  // Serial Peripheral Interface (SPI) pins
  // You can remove them if your application does not use the SPI controller
  output  wire          sclk        ,
  output  wire          pico        ,
  input   wire          poci        ,
  output  wire  [0:0]   cs
  
  );

  reg reset_debounced;
  always @(posedge clock) reset_debounced <= reset;

  reg halt_debounced;
  always @(posedge clock) halt_debounced <= halt;

  rvx #(

    // Frequency (in Hertz) of the `clock` pin
    .CLOCK_FREQUENCY          (50000000                   ),

    // Absolute path to the .hex file generated by the build
    .MEMORY_INIT_FILE         ("/path/to/myapp.hex"       ),    
    
    // The size you want for the memory (in bytes)
    .MEMORY_SIZE              (8192                       ),
    
    // The UART baud rate (in bauds per second)
    .UART_BAUD_RATE           (9600                       ),
    
    // Don't change it unless you explicitly modified the boot address
    .BOOT_ADDRESS             (32'h00000000               ),
    
    // Width of the gpio_* ports
    .GPIO_WIDTH               (4                          ),
    
    // Width of the cs port
    .SPI_NUM_CHIP_SELECT      (1                          ))
    
    rvx_instance (
    
    .clock                    (clock                      ),
    .reset                    (reset_debounced            ),
    .halt                     (halt_debounced             ),
    .uart_rx                  (uart_rx                    ),
    .uart_tx                  (uart_tx                    ),
    .gpio_input               (gpio_input                 ),
    .gpio_oe                  (gpio_oe                    ),
    .gpio_output              (gpio_output                ),
    .sclk                     (sclk                       ),
    .pico                     (pico                       ),
    .poci                     (poci                       ),
    .cs                       (cs                         ));

endmodule
```

---

<h4>2. Synthesizing rvx_wrapper.v</h4>

The steps to synthesize a Verilog module can differ based on the FPGA model and vendor, but they generally follow this sequence:

1. *Start a new project*: Open the EDA tool provided by your FPGA vendor (e.g., AMD Vivado, Intel Quartus, Lattice iCEcube).

2. *Add files to the project*: Include `rvx_wrapper.v` to the project and all files in the `hardware/` folder of RVX repository.

3. *Create a design constraints file*: Map the ports of `rvx_wrapper.v` to the corresponding devices on the FPGA board.

4. *Run the synthesis process*: This includes placing and routing, as well as any other necessary steps to generate a bitstream for the FPGA.

4. *Generate the bitstream*: Once completed, program the FPGA with the generated bitstream.

The application will start running immediately after you program the FPGA!



</br>
</br>