文章目录
- 1.1、描述
- 1.2、声明
- 1.2.1、条件信号(Conditional signals)
- 1.3、运算符
- 1.3.1、比较(Comparison)
- 1.3.2、类型转换(Type cast)
- 1.3.3、将比特转换回 Bundle
- 1.4、IO元素方向
- 1.4.1、in/out
- 1.4.2、master/slave
1.1、描述
Bundle是一种复合类型,它定义了一组命名信号(任何SpinalHDL基本类型)在一个名称下。
Bundle可用于建模数据结构、总线和接口。
1.2、声明
声明一个 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)
}
例如,一个包含Color的Bundle可以被定义为
1.2.1、条件信号(Conditional signals)
Bundle中的信号可以有条件地定义。除非dataWidth大于0,否则在展开的myBundle中将没有数据信号,如下面的示例所示。
case class myBundle(dataWidth: Int) extends Bundle {
val data = (dataWidth > 0) generate (UInt(dataWidth bits))
}
1.3、运算符
Bundle类型支持以下运算符:
1.3.1、比较(Comparison)
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
1.3.2、类型转换(Type cast)
val color1 = Color(8)
val myBits := color1.asBits
Bundle的元素将按照定义的顺序映射到其位置。因此,color1中的r将占用myBits(LSB)的0到8位,然后是g和b。
1.3.3、将比特转换回 Bundle
.assignFromBits 运算符可以被视为 .asBits 的反向操作。
以下示例将名为CommonDataBus的Bundle保存到循环缓冲区(第三方内存)中,稍后读取Bits并将其转换回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)
}
1.4、IO元素方向
当您在组件的IO定义中定义Bundle时,需要指定其方向。
1.4.1、in/out
如果您的Bundle中所有元素都朝着同一个方向,您可以使用in(MyBundle())或out(MyBundle())。
例如:
val io = new Bundle {
val input = in (Color(8))
val output = out(Color(8))
}
1.4.2、master/slave
如果您的接口遵循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)
// 你需要实现asMaster函数。
// 这个函数应该从master的角度设置每个信号的方向
override def asMaster(): Unit = {
out(valid, payload)
in(ready)
}
}
val io = new Bundle {
val input = slave(HandShake(8))
val output = master(HandShake(8))
}