F P G A   

 Limerick(5) - SpinalHDL Tutorial: the Design Flow of Hello World 3/11/2023

Hello, everyone! Welcome to the fifth episode of FPGA limerick. In this episode, we will take a close look at the “Hello World” example for SpinalHDL. And based on that, we will also demonstrate the basic design flow for SpinalHDL.

As mentioned in previous episodes, the Hello World can be checked out like

git clone --depth 1 --branch v1.1.4 https://github.com/PulseRain/FpgaLimerick.git


The folder structure of Hello World

And for a fresh checkout, it has the following files:

*) Files at the top level

                build.sbt: configuration file for SBG

                .scalafix.conf: configuration file for scalafix (linter)

                scalastyle-config.xml: configuration file for scalastyle (linter)

                .scalafmt.conf: configuration file for scalafmt (formatter)


*) Folder:

                src/spinal: project source for SpinalHDL

                src/main/resources/log4j2.xml: configuration file for log4j2

                test/spinal: test bench in SpinalHDL

                test/cocotb: test bench using cocotb

                project: additional configuration files for SBT


And the HelloWorld can also serve as a template for other projects. You can find a script called “make_new_prj.sh” under the scripts folder. And it can be used to create a new project folder using HelloWorld as the template. (Please run it under WSL.)


The design flow of SpinalHDL


As illustrated above, the general design flow for SpinalHDL is to:
1. Setup the Parameters of the SpinalHDL top module
2. Feed the source code into SpinalConfig
3. Generate the output in Verilog, System Verilog or VHDL

And now let's take a close look to the HelloWorld example to see how the flow works.

The background of the HelloWorld Example: NCO Counter

The HelloWorld is actually an example of NCO Counter. NCO stands for Numerically Controlled Oscillator. It tries to output a new clock (an enable pulse train actually) from on a base clock. The frequency of the output clock and the frequency of the base clock are predefined by parameters.

And mathematically, we need to do the following:
1.    Find the GCD of the base clock and the output clock
2.    Use the GCD to simplify the ratio between output clock and the base clock, i.e:

3.    Once we get the simplified ratio of n over m, we can set the NCO counter like the following:
  a)    Set the counter value to be zero (The initial phase)
  b)    For every base clock cycle, counter = (counter + n) mod m
  c)    Generate a pulse (output clock) every time the counter rolls over m


The code structure of the SpinalHDL module

Now let’s take a look at the code structure of the HelloWorld Example:

1.    package

To following the naming convention of JAVA package, the package name is often the reverse form of a URL. But you are also free to choose other name formats as you see fit. For example, in our FpgaLimerick repo, all the common code is placed in a package called “common”

2.    import

This is like the include section for Verilog or C++. And you can use scalafix to find and remove the unused imports.

3.    case class extends Component

This is similar to the “module” in Verilog. The SpinalHDL coding convention recommends using “case class” instead of “class” in scala.

4.    The parameters of the module. Here we use the convention for parameters as all capital letter with G_ prefix. (G stands for generics, a reminiscent from VHDL)

5.    A bundle for port list

6.    The main body of the design (combinatorial logic and sequential logic)

7.    And a companion object that contains the main function, which will generate the verilog / system verilog / VHDL based on the configuration.

Now, comparing to verilog, it is a cinch for SpinalHDL to get GCD value, as SpinalHDL is based on a high level programming language scala. If we want to do the same implementation in verilog, we have to jump through a lot of hoops to get the GCD value, as verilog’s system functions are very primitive and do not cover GCD directly. Even if you can find a way to calculate the GCD with verilog’s system functions, I bet the code would be bulky and messy.

Configuration and Code Generation

The Hello World uses the MainConfig to generate the code. The MainConfig can be found in common/MainConfig.scala, which is derived from SpinalConfig (in Spinal.scala from spinalhdl-core)

And in the MainConfig, the targetDirectory to be “gen”, and it sets the async reset to be active low.


From the Hello World example, it shows that the SpinalHDL is much more powerful and flexible for design parameterization.

    Posted by FPGA Limerick at March 11, 2023


Post a Comment

<< Home  





*) Legal Disclaimer
*) Introduction


*) GitHub Repo
*) YouTube
*) reddit
*) SpinalHDL
*) cocotb

*) FCC Wireless
*) PAPA System