Bundle

描述

Bundle 是一种复合类型,它在单个名称下定义一组具有命名的信号(任何 SpinalHDL 基本类型)。

Bundle 可用于对数据结构、总线和接口进行建模。

声明

声明线束的语法如下:

case class myBundle extends Bundle {
  val bundleItem0 = AnyType
  val bundleItem1 = AnyType
  val bundleItemN = AnyType
}

例如,包含颜色的线束可以定义为:

case class Color(channelWidth: Int) extends Bundle {
  val r, g, b = UInt(channelWidth bits)
}

您可以在 Spinal HDL examples 中找到 APB3 definition

条件信号

Bundle 中的信号可以有条件地定义。除非 dataWidth 大于 0,否则在实力细化后的 myBundle``中将不会有 ``data 信号,如下例所示。

case class myBundle(dataWidth: Int) extends Bundle {
  val data = (dataWidth > 0) generate (UInt(dataWidth bits))
}

备注

另请参阅 generate 了解有关此 SpinalHDL 方法的信息。

运算符

以下运算符可用于 Bundle 类型:

比较运算

运算符

描述

返回类型

x === y

等价性判断

Bool

x =/= y

不等价判断运算

Bool

val color1 = Color(8)
color1.r := 0
color1.g := 0
color1.b := 0

val color2 = Color(8)
color2.r := 0
color2.g := 0
color2.b := 0

myBool := color1 === color2  // Compare all elements of the bundle
// is equivalent to:
// myBool := color1.r === color2.r && color1.g === color2.g && color1.b === color2.b

类型转换

运算符

描述

返回类型

x.asBits

二进制转换为 Bits

Bits(w(x) bits)

val color1 = Color(8)
val myBits := color1.asBits

线束中的元素将按其定义的顺序映射到位,按LSB 先放置的顺序。因此,color1 中的 r 将占据 myBits 的第 0 至 8 位(LSB),然后依次是 gbb.msb 也是最终 Bits 类型的 MSB。

将位转换回线束

.assignFromBits 运算符可以被视为 .asBits 的逆操作。

运算符

描述

返回类型

x.assignFromBits(y)

将Bits (y)转换为Bundle(x)

Unit

x.assignFromBits(y, hi, lo)

将Bits (y) 转换为具有高/低边界的 Bundle(x)

Unit

下面的示例将名为 CommonDataBus 的线束保存到循环缓冲区(第三方内存)中,随后读出比特,并将其转换回 CommonDataBus 格式。

../../_images/CommonDataBus.png
case class TestBundle () extends Component {
  val io = new Bundle {
    val we      = in     Bool()
    val addrWr  = in     UInt (7 bits)
    val dataIn  = slave  (CommonDataBus())

    val addrRd  = in     UInt (7 bits)
    val dataOut = master (CommonDataBus())
  }

  val mm = Ram3rdParty_1w_1rs (G_DATA_WIDTH = io.dataIn.getBitsWidth,
                               G_ADDR_WIDTH = io.addrWr.getBitsWidth,
                               G_VENDOR     = "Intel_Arria10_M20K")

  mm.io.clk_in    := clockDomain.readClockWire
  mm.io.clk_out   := clockDomain.readClockWire

  mm.io.we        := io.we
  mm.io.addr_wr   := io.addrWr.asBits
  mm.io.d         := io.dataIn.asBits

  mm.io.addr_rd   := io.addrRd.asBits
  io.dataOut.assignFromBits(mm.io.q)
}

IO元件方向

当您在组件的 IO 定义中实现 Bundle 时需要指定其方向。

in/out

如果线束的所有元素中的信号都朝同一方向传播,则可以使用 in(MyBundle()) or out(MyBundle())

例如:

val io = new Bundle {
  val input  = in (Color(8))
  val output = out(Color(8))
}

master/slave

如果您的接口遵循主/从拓扑结构,您可以使用 IMasterSlave 特征。然后你必须实现函数 def asMaster(): Unit 从master的角度设置每个元素的方向。然后你可以在 IO 定义中使用 master(MyBundle())slave(MyBundle()) 语法来使用。

有些函数定义为 toXXX,例如 Flow 类的 toStream 方法。这些函数通常可以由master端调用。另外,fromXXX函数是为slave侧设计的。通常master端可用的功能多于slave端。

例如:

case class HandShake(payloadWidth: Int) extends Bundle with IMasterSlave {
  val valid   = Bool()
  val ready   = Bool()
  val payload = Bits(payloadWidth bits)

  // You have to implement this asMaster function.
  // This function should set the direction of each signals from an master point of view
  override def asMaster(): Unit = {
    out(valid, payload)
    in(ready)
  }
}

val io = new Bundle {
  val input  = slave(HandShake(8))
  val output = master(HandShake(8))
}