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

VHDL 和 Verilog 生成

从 SpinalHDL 组件生成 VHDL 和 Verilog

要从 SpinalHDL 组件生成 VHDL,您只需在 Scala main 函数中调用 SpinalVhdl(new YourComponent) 即可。

生成 Verilog 完全相同,但用 SpinalVerilog 代替 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)
  }
}

重要

SpinalVhdlSpinalVerilog 可能需要创建组件类的多个实例,因此第一个参数不是 Component 引用,而是返回新组件的函数。

重要

SpinalVerilog 实施于 2016 年 6 月 5 日开始。该后端成功通过了与 VHDL 相同的回归测试(RISCV CPU、多核和流水线 Mandelbrot、UART RX/TX、单时钟域 fifo、双时钟域 fifo、格雷码计数器, …)。

如果您对这个新后端有任何问题,请创建 Github 工单 描述问题。

Scala 的参数化

参数名称

类型

默认值

描述

mode

SpinalMode

null

设置 SpinalHDL 生成HDL的模式。
可以设置为 VHDLVerilog

defaultConfigForClockDomains

ClockDomainConfig

RisingEdgeClock
AsynchronousReset
ResetActiveHigh
ClockEnableActiveHigh

设置将用作所有新 ``ClockDomain``时钟域默认值的配置。

onlyStdLogicVectorAtTopLevelIo

Boolean

false

将所有无符号/有符号顶级 io 更改为 std_logic_vector类型。

defaultClockDomainFrequency

IClockDomainFrequency

 UnknownFrequency

默认时钟频率。

targetDirectory

String

当前目录

生成文件的目录。

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

这是设置它们的语法:

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)

来自 shell 的参数化

您还可以使用命令行参数指定生成参数。

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

命令行参数的语法是:

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

生成的 VHDL 和 Verilog

如何将 SpinalHDL RTL 描述转换为 VHDL 和 Verilog 非常重要:

  • Scala 中变量的名称将保留在 VHDL 和 Verilog 中。

  • Scala 中的 Component 组件层次结构会保留在 VHDL 和 Verilog 中。

  • Scala 中的 when 语句会生成为 VHDL 和 Verilog 中的 if 语句。

  • Scala 中的 switch 语句在所有标准情况下都生成为 VHDL 和 Verilog 中的 case 语句。

组织

当您使用 VHDL 生成器时,所有模块都会生成到一个文件中,其中包含三个部分:

  1. 包含所有 Enum 定义的包

  2. 包含架构中所有元素使用函数的包

  3. 您的设计所需的所有组件

当您使用 Verilog 生成时,所有模块都会生成到一个文件中,其中包含两个部分:

  1. 使用的所有枚举定义

  2. 您的设计需要的所有模块

组合逻辑

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;

时序逻辑

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 和 Verilog 属性

在某些情况下,为设计中的某些信号提供属性以修改它们的综合方式很有用。

为此,您可以对设计中的任何信号或存储器调用以下函数:

语法

描述

addAttribute(name)

添加一个名为 name 的布尔属性,并将给定值设置为 true

addAttribute(name, value)

添加一个字符串属性,并将给定的 name 设置为 value

示例:

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

用 VHDL 生成声明:

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

用 Verilog 生成声明:

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