You're reading an pre-release version of this documentation.
For the latest stable release version, please have a look at master.

VHDL and Verilog generation

Generate VHDL and Verilog from a SpinalHDL Component

To generate the VHDL from a SpinalHDL component you just need to call SpinalVhdl(new YourComponent) in a Scala main.

Generating Verilog is exactly the same, but with SpinalVerilog in place of SpinalVHDL

import spinal.core._

// A simple component definition.
class MyTopLevel extends Component {
  // Define some input/output signals. Bundle like a VHDL record or a Verilog struct.
  val io = new Bundle {
    val a = in  Bool()
    val b = in  Bool()
    val c = out Bool()
  }

  // Define some asynchronous logic.
  io.c := io.a & io.b
}

// This is the main function that generates the VHDL and the Verilog corresponding to MyTopLevel.
object MyMain {
  def main(args: Array[String]) {
    SpinalVhdl(new MyTopLevel)
    SpinalVerilog(new MyTopLevel)
  }
}

Important

SpinalVhdl and SpinalVerilog may need to create multiple instances of your component class, therefore the first argument is not a Component reference, but a function that returns a new component.

Important

The SpinalVerilog implementation began the 5th of June, 2016. This backend successfully passes the same regression tests as the VHDL one (RISCV CPU, Multicore and pipelined mandelbrot, UART RX/TX, Single clock fifo, Dual clock fifo, Gray counter, …).

If you have any issues with this new backend, please make a Github issue describing the problem.

Parametrization from Scala

Argument name

Type

Default

Description

mode

SpinalMode

null

Set the SpinalHDL hdl generation mode.
Can be set to VHDL or Verilog

defaultConfigForClockDomains

ClockDomainConfig

RisingEdgeClock
AsynchronousReset
ResetActiveHigh
ClockEnableActiveHigh

Set the clock configuration that will be used as the default value for all new ClockDomain.

onlyStdLogicVectorAtTopLevelIo

Boolean

false

Change all unsigned/signed toplevel io into std_logic_vector.

defaultClockDomainFrequency

IClockDomainFrequency

 UnknownFrequency

Default clock frequency.

targetDirectory

String

Current directory

Directory where files are generated.

oneFilePerComponent

Boolean

false

Instead of generating one big VHDL/Verilog file, every component will get its own VHDL/Verilog file.

netlistFileName

String

ToplevelClassName.(vhd|v)

Allow to change the name of the generated VHDL/Verilog.

globalPrefix

String

“”

Will add the given prefix in the front of every global symboles in the VHDL/Verilog (components/modules/enums). This allows to avoid naming conflict between multiple generated file.

privateNamespace

Boolean

false

Every generated Component/Modules names will get prefixed with the toplevel Component/Module name (excepted for the toplevel). This allows to avoid naming conflict between multiple generated file.

formalAsserts

Boolean

false

Enable the generation of the formal assertions in the VHDL/Verilog.

anonymSignalPrefix

String

“zz_”

Set the prefix added to unnamed signals.

inlineRom

Boolean

false

Configure the Verilog backend to incorporate the ROM values initialization in the verilog itself instead of an bin file.

caseRom

Boolean

false

Generate the ROM as a big switch case.

mergeAsyncProcess

Boolean

false

Will merge process/always blocks for combinatorial signal which share at least one conditional assignement (if/switch statment)

mergeSyncProcess

Boolean

true

Will merge process/always blocks for flip-flops which use the same clock domain (if/switch statment)

genLineComments

Boolean

false

For each hardware assignment in the generated VHDL/Verilog code, will attach a comment which specifies in which scala file, at which line, the assignement happend. Ex : a = 1’b1; // @ MyDesign.scala l1135

noAssert

Boolean

false

Remove all the asserts from the generated code

headerWithDate

Boolean

false

Add the date at which the VHDL/Verilog was generated in its header.

headerWithRepoHash

Boolean

true

Add the current directory git hash in the generated VHDL/Verilog header.

dontCareGenAsZero

Boolean

false

Replace mySignal.assignDontCare() by mySignal := 0

obfuscateNames

Boolean

false

Will obfuscate the generated components and signal names.

rtlHeader

String

disabled

Allow to manualy specify the VHDL/Verilog file header

withTimescale

Boolean

True

Enable the addition of the timescale in the generated Verilog

And this is the syntax to specify them:

SpinalConfig(mode=VHDL, targetDirectory="temp/myDesign").generate(new UartCtrl)

// Or for Verilog in a more scalable formatting:
SpinalConfig(
  mode=Verilog,
  targetDirectory="temp/myDesign"
).generate(new UartCtrl)

Parametrization from shell

You can also specify generation parameters by using command line arguments.

def main(args: Array[String]): Unit = {
  SpinalConfig.shell(args)(new UartCtrl)
}

The syntax for command line arguments is:

Usage: SpinalCore [options]

  --vhdl
        Select the VHDL mode
  --verilog
        Select the Verilog mode
  -d | --debug
        Enter in debug mode directly
  -o <value> | --targetDirectory <value>
        Set the target directory

Generated VHDL and Verilog

How a SpinalHDL RTL description is translated into VHDL and Verilog is important:

  • Names in Scala are preserved in VHDL and Verilog.

  • Component hierarchy in Scala is preserved in VHDL and Verilog.

  • when statements in Scala are emitted as if statements in VHDL and Verilog.

  • switch statements in Scala are emitted as case statements in VHDL and Verilog in all standard cases.

Organization

When you use the VHDL generator, all modules are generated into a single file which contain three sections:

  1. A package that contains the definition of all Enums

  2. A package that contains functions used by the architectural elements

  3. All components needed by your design

When you use the Verilog generation, all modules are generated into a single file which contains two sections:

  1. All enumeration definitions used

  2. All modules needed by your design

Combinational logic

Scala:

class TopLevel extends Component {
  val io = new Bundle {
    val cond           = in  Bool()
    val value          = in  UInt(4 bits)
    val withoutProcess = out UInt(4 bits)
    val withProcess    = out UInt(4 bits)
  }
  io.withoutProcess := io.value
  io.withProcess := 0
  when(io.cond) {
    switch(io.value) {
      is(U"0000") {
        io.withProcess := 8
      }
      is(U"0001") {
        io.withProcess := 9
      }
      default {
        io.withProcess := io.value+1
      }
    }
  }
}

VHDL:

entity TopLevel is
  port(
    io_cond : in std_logic;
    io_value : in unsigned(3 downto 0);
    io_withoutProcess : out unsigned(3 downto 0);
    io_withProcess : out unsigned(3 downto 0)
  );
end TopLevel;

architecture arch of TopLevel is
begin
  io_withoutProcess <= io_value;
  process(io_cond,io_value)
  begin
    io_withProcess <= pkg_unsigned("0000");
    if io_cond = '1' then
      case io_value is
        when pkg_unsigned("0000") =>
          io_withProcess <= pkg_unsigned("1000");
        when pkg_unsigned("0001") =>
          io_withProcess <= pkg_unsigned("1001");
        when others =>
          io_withProcess <= (io_value + pkg_unsigned("0001"));
      end case;
    end if;
  end process;
end arch;

Sequential logic

Scala:

class TopLevel extends Component {
  val io = new Bundle {
    val cond   = in Bool()
    val value  = in UInt (4 bits)
    val resultA = out UInt(4 bits)
    val resultB = out UInt(4 bits)
  }

  val regWithReset = Reg(UInt(4 bits)) init(0)
  val regWithoutReset = Reg(UInt(4 bits))

  regWithReset := io.value
  regWithoutReset := 0
  when(io.cond) {
    regWithoutReset := io.value
  }

  io.resultA := regWithReset
  io.resultB := regWithoutReset
}

VHDL:

entity TopLevel is
  port(
    io_cond : in std_logic;
    io_value : in unsigned(3 downto 0);
    io_resultA : out unsigned(3 downto 0);
    io_resultB : out unsigned(3 downto 0);
    clk : in std_logic;
    reset : in std_logic
  );
end TopLevel;

architecture arch of TopLevel is

  signal regWithReset : unsigned(3 downto 0);
  signal regWithoutReset : unsigned(3 downto 0);
begin
  io_resultA <= regWithReset;
  io_resultB <= regWithoutReset;
  process(clk,reset)
  begin
    if reset = '1' then
      regWithReset <= pkg_unsigned("0000");
    elsif rising_edge(clk) then
      regWithReset <= io_value;
    end if;
  end process;

  process(clk)
  begin
    if rising_edge(clk) then
      regWithoutReset <= pkg_unsigned("0000");
      if io_cond = '1' then
        regWithoutReset <= io_value;
      end if;
    end if;
  end process;
end arch;

VHDL and Verilog attributes

In some situations, it is useful to give attributes for some signals in a design to modify how they are synthesized.

To do that, you can call the following functions on any signals or memories in the design:

Syntax

Description

addAttribute(name)

Add a boolean attribute with the given name set to true

addAttribute(name, value)

Add a string attribute with the given name set to value

Example:

val pcPlus4 = pc + 4
pcPlus4.addAttribute("keep")

Produced declaration in VHDL:

attribute keep : boolean;
signal pcPlus4 : unsigned(31 downto 0);
attribute keep of pcPlus4: signal is true;

Produced declaration in Verilog:

(* keep *) wire [31:0] pcPlus4;