编码规范

简介

SpinalHDL 中使用的编码规范与 Scala 风格指南 中的规定相同。

一些额外的细节和案例将在下几页中解释。

类与样例类

当您定义一个 BundleComponent 时,最好将其声明为案例类。

原因是:

  • 它避免使用 new 关键字。在某些情况下,永远不必使用它比有时使用它要好。

  • case class 提供了 clone 函数。当需要克隆 Bundle 时,该函数非常有用。例如,当您定义新的 Reg 或某种新的 Stream 时。

  • 构造参数从外部直接可见。

样例类/类

所有类名称都应以大写字母开头

class Fifo extends Component {

}

class Counter extends Area {

}

case class Color extends Bundle {

}

伴生对象

伴随对象 应该以大写字母开头。

object Fifo {
  def apply(that: Stream[Bits]): Stream[Bits] = {...}
}

object MajorityVote {
  def apply(that: Bits): UInt = {...}
}

此规则的一个例外是当伴生对象用作函数时(其中包含了 apply 函数),并且这些 apply 函数不生成硬件:

object log2 {
  def apply(value: Int): Int = {...}
}

函数

函数应始终以小写字母开头:

def sinTable = (0 until sampleCount).map(sampleIndex => {
  val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)
  S((sinValue * ((1 << resolutionWidth) / 2 - 1)).toInt, resolutionWidth bits)
})

val rom =  Mem(SInt(resolutionWidth bits), initialContent = sinTable)

实例

类的实例应始终以小写字母开头:

val fifo   = new Fifo()
val buffer = Reg(Bits(8 bits))

if / when

Scala中的 if 和 SpinalHDL中的 when 通常应按以下方式编写:

if(cond) {
  ...
} else if(cond) {
  ...
} else {
  ...
}

when(cond) {
  ...
} elsewhen(cond) {
  ...
} otherwise {
  ...
}

例外情况可能是:

  • 可以在关键字前添加一个点,例如方法 .elsewhen.otherwise

  • 如果可以提高代码可读性,可以将 if/when 语句压缩到一行中。

switch

SpinalHDL中的 switch 通常应按以下方式编写:

switch(value) {
  is(key) {

  }
  is(key) {

  }
  default {

  }
}

如果可以提高代码可读性,可以将 is/default 语句压缩到一行中。

参数

在样例类中对 Component/Bundle 的参数进行分组通常是受欢迎的,因为:

  • 更容易使用/操作设计的配置

  • 更好的可维护性

case class RgbConfig(rWidth: Int, gWidth: Int, bWidth: Int) {
  def getWidth = rWidth + gWidth + bWidth
}

case class Rgb(c: RgbConfig) extends Bundle {
  val r = UInt(c.rWidth bits)
  val g = UInt(c.gWidth bits)
  val b = UInt(c.bWidth bits)
}

但这不应该适用于所有情况。例如:在 FIFO 中,将 dataType 参数与 fifo 的 depth 参数分组是没有意义的。因为一般情况下, dataType 与设计相关,而 depth 则与设计的配置有关。

class Fifo[T <: Data](dataType: T, depth: Int) extends Component {

}