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
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.
Summary
From the Hello World example, it shows that the SpinalHDL is much more powerful and flexible for design parameterization.
Post a Comment