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

当前目录

生成文件的目录。

这是设置它们的语法:

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;