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),然后依次是 g 和 b ,b.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 格式。
 
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))
}