Creating core files
===================
ifdef::env-github,env-browser[:outfilesuffix: .adoc]

The basics
----------

In order to create our first core, we will start with some example verilog code. link:example/spi_slave.v[This] is a simple SPI slave to GPIO bridge that will be used in the first examples.

Create the following directory structure, and put `spi_slave.v` in `rtl/verilog`

* spi_slave
** rtl
*** verilog
**** spi_slave.v

.File and directory names
***********************
File and directory names for the source code are not important in FuseSoC. The structure described above is just a convention that is quite commonly used
***********************

These are all the preparations we need to create our first FuseSoC .core.

In the `spi_slave` directory, create a file called `spi_slave.core`. On the first line of the file enter `CAPI=1`. This will let FuseSoC know that this is a .core file which is using version 1 of the core API (which is currently the only version), which gives information on how to parse the rest of the file. CAPI1 files are standard link:https://en.wikipedia.org/wiki/INI_file[INI files], which are parsed by Python's link:https://docs.python.org/3/library/configparser.html[configparser]

On the next line, enter `[main]`. This starts the main configuration section. Add a single option to the `main` section by writing `name = ::spi_slave:0` on a new line.

.Core name
**********
Technically, the name option can be left out in this case, see link:corenamingrules{outfilesuffix}[core naming rules] for more information
**********

Create a new fileset section by writing `[fileset rtl]` on a new line. The name of the fileset (i.e. `rtl`) is not important, but should preferrably describe what kind of files that goes into each fileset. List the source files on a new line by writing `files = rtl/verilog/spi_slave.v`. File paths are relative to the core root, which in this case is where the `.core` file resides. Also describe the file type of the files in the fileset by adding a new line with `file_type = verilogSource`

.Verilog sections
*****************
Many older cores have a section called `verilog` instead of filesets. This section is deprecated, and information on how to migrate to filesets can be found in the link:migrations{outfilesuffix}[migrations] document
*****************

The complete .core file should now look like this

    CAPI=1
    [main]
    
    name = ::spi_slave:0
    
    [fileset rtl]
    files = rtl/verilog/spi_slave.v
    file_type=verilogSource

You can now use FuseSoC to get information about your core, and confirm that it has been picked up correctly. Run `fusesoc --cores-root=<core path> core-info spi_slave`, where `<core path>` is the path to the `spi_slave` directory.

FuseSoC should return something like this

    CORE INFO
    Name:                   ::spi_slave:0
    Core root:              /home/olof/code/staging/spi_slave
    == fileset ==
    rtl
    File sets:
    
     Name  : rtl
     Scope : public
     Usage : sim/synth
     Files :
      rtl/verilog/spi_slave.v verilogSource False

Please verify that `Core root` points to the correct directory, in case there is some other core with the same name that is being picked up by the FuseSoC configuration files.

Congratulations, you have now finished writing your first .core file, and anyone who wants to use your code can now add a dependency on your core in their .core file. We will now investigate how dependencies work in FuseSoC and making our core a bit more useful by making the spi_slave core depend on some other cores, and by adding a testbench.

.Core API
*********
For all options that are introduced in this tutorial, you can see the link:capi1{outfilesuffix}[core API] definitions to learn more about them and other options available for core files
*********

Adding simulation support
-------------------------

In order to convince the world and ourselves that the core actually works, we want to add a testbench to the core and be able to run a simulation. For this we will create two new files. link:example/spi_slave_tb.v[spi_slave_tb] is the top-level testbench and link:example/spi_bfm.v[spi_bfm] is a BFM module to create SPI transactions. These files are put in a new directory called `bench` as shown below. Again, the file and directory names are not important. It's just a convention.

* spi_slave
** bench
*** spi_bfm.v
*** spi_slave_tb.v
** rtl
*** verilog
**** spi_slave.v

In order to let FuseSoC know about the two testbench files, they must be added to the .core file. In this case, we will create two new filesets for reasons that will be soon explained. The first one for `spi_bfm.v` looks like this:

    [fileset bfm]
    files = bench/spi_bfm.v
    file_type=verilogSource
    usage = sim

And the one for `spi_slave_tb.v` looks like this:

    [fileset tb]
    files = bench/spi_slave_tb.v
    file_type=verilogSource
    scope = private
    usage = sim

The main difference between these two filesets is the use of the `scope` parameter. For the top-level testbench, `scope` is defined to `private`, instead of its default value `public`. Setting it to `private` means that if the files in this fileset will only be visible if we run operations (such as simulations) directly on the core. If the core is used as a dependency of another core, the `private` filesets will not be seen. As another core might want to use `spi_bfm.v`, we make this public, but top-level testbenches are usually only used when directly simulating the core.

The testbench also instantiates a module called `vlog_tb_utils`. This isn't part of the `spi_slave` core, but is defined in a core in the FuseSoC base library called `vlog_tb_utils`. In order to use this module, we must therefore list `vlog_tb_utils` as a dependency of our core. We do this by adding `depend = vlog_tb_utils` to our `[main]` section.

The next thing to do is to list which simulators that can be used to simulate the core. This is done by setting the `simulators` option in the `[main]` section to a space-separated list of simulator names. The first one listed, will be used as the default simulator, unless the simulator argument `--sim` is added to teh command-line to manually select the simulator

.List of simulators
*******************
As any value can be specified with the `--sim` parameter, regardless if they are in the list of simulators, only the first entry in the list (the default simulator) has any meaning.
*******************

The last thing we need to do before running a simulation is to specify the name of the top-level module used for the testbench. Please note that this is not the file name, but the name of the verilog module or VHDL entity to be used. This is done by creating a new section with the following contents:

    [simulator]
    toplevel = spi_slave_tb

The complete .core file should now look like this

    CAPI=1
    [main]
    
    name = ::spi_slave:0
    simulators = icarus
    depend = vlog_tb_utils
    
    [fileset rtl]
    files = rtl/verilog/spi_slave.v
    file_type=verilogSource
    
    [fileset bfm]
    files = bench/spi_bfm.v
    file_type=verilogSource
    usage = sim
    
    [fileset tb]
    files = bench/spi_slave_tb.v
    file_type=verilogSource
    scope = private
    usage = sim
    
    [simulator]
    toplevel = spi_slave_tb

The simulation can now be started by executing `fusesoc --cores-root=<core path> sim spi_slave`. If everything works as expected, it should print out some information and then finally `Test passed!`. Congratulations, you have now run your first simulation with FuseSoC

