写在前面
本文主要介绍了spinal HDL语言的复合数据类型,主要对Bundle、Vec进行介绍,同时对UFix/SFix进行了介绍。
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)
}
运算操作
以下运算符可用于该Bundle
类型:
Operator | Description | Return type |
x === y | 相等 | Bool |
x =/= y | 不相等 | Bool |
类型转换
Operator | Description | Return |
x.asBits | 二进制转换为Bits | Bits(w(x) bits) |
val color1 = Color(8)
val myBits := color1.asBits
将 Bits 转换回 Bundle
该.assignFromBits
操作可以被看作是.asBits
相反的操作。
Operator | Description | Return |
x.assignFromBits(y) | 转换Bits (y) 为 Bundle(x) | Unit |
x.assignFromBits(y, hi, lo) | 转换 Bits (y) 为 Bundle(x)具有高/低边界 | Unit |
以下示例将名为 CommonDataBus 的 Bundle 保存到循环缓冲区(第 3 方内存)中,稍后读取位并将它们转换回 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 时,需要指定其方向。
如果 bundle 的所有元素都在同一个方向,你可以使用 in(MyBundle()) 或 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())
语法。
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))
}
Vec
Vec 是一种复合类型,它在单个名称下定义一组索引信号(任何 SpinalHDL 基本类型)。
声明
Declaration | Description |
Vec(type: Data, size: Int) | 创建一个能够容纳“数据”类型的“大小”元素的向量 |
Vec(x, y, …) | 创建一个向量,其中索引指向提供的元素。此构造函数支持混合元素宽度。 |
示例
// Create a vector of 2 signed integers
val myVecOfSInt = Vec(SInt(8 bits), 2)
myVecOfSInt(0) := 2
myVecOfSInt(1) := myVecOfSInt(0) + 3
// Create a vector of 3 different type elements
val myVecOfMixedUInt = Vec(UInt(3 bits), UInt(5 bits), UInt(8 bits))
val x, y, z = UInt(8 bits)
val myVecOf_xyz_ref = Vec(x, y, z)
// Iterate on a vector
for(element <- myVecOf_xyz_ref) {
element := 0 // Assign x, y, z with the value 0
}
// Map on vector
myVecOfMixedUInt.map(_ := 0) // Assign all elements with value 0
// Assign 3 to the first element of the vector
myVecOf_xyz_ref(1) := 3
运算操作
以下运算符可用于该Vec
类型:
比较操作
Operator | Description | Return type |
x === y | 相等 | Bool |
x =/= y | 不相等 | Bool |
示例
// Create a vector of 2 signed integers
val vec2 = Vec(SInt(8 bits), 2)
val vec1 = Vec(SInt(8 bits), 2)
myBool := vec2 === vec1 // Compare all elements
类型转换
Operator | Description | Return |
x.asBits | 二进制转化为Bits | Bits(w(x) bits) |
示例
// Create a vector of 2 signed integers
val vec1 = Vec(SInt(8 bits), 2)
myBits_16bits := vec1.asBits
其他
Operator | Description | Return |
x.getBitsWidth | 返回 Vec 的完整大小 | Int |
示例
// Create a vector of 2 signed integers
val vec1 = Vec(SInt(8 bits), 2)
println(vec1.getBitsWidth) // 16
UFix/SFix
UFix 和 SFix 类型对应于可用于定点算术的位向量。
声明
声明定点数的语法如下:
Unsigned Fixed-Point
Syntax | bit width | resolution | max | min |
UFix(peak: ExpNumber, resolution: ExpNumber) | 峰值分辨率 | 2^分辨率 | 2peak-2resolution | 0 |
UFix(peak: ExpNumber, width: BitCount) | 宽度 | 2^(峰宽) | 2peak-2(peak-width) | 0 |
Signed Fixed-Point
Syntax | bit width | resolution | max | min |
SFix(peak: ExpNumber, resolution: ExpNumber) | 峰值分辨率+1 | 2^分辨率 | 2peak-2分辨率 | -(2^peak) |
SFix(peak: ExpNumber, width: BitCount) | 宽度 | 2^(峰宽-1) | 2peak-2(peak-width-1) | -(2^peak) |
格式
所选格式遵循使用 Q 表示法定义定点数格式的常用方法。例如 Q8.2 将表示 8+2 位的定点数,其中 8 位用于自然部分,2 位用于小数部分。如果定点数是有符号的,则多使用一位作为符号。分辨率定义为可以用这个数字表示的 2 的最小幂。
为了使表示 2 的幂的数字更不容易出错,在spinal.core
called 中有一个数字类型,ExpNumber
用于定点类型构造函数。这种类型的便利包装器以exp
函数的形式存在(在本页的代码示例中使用)。
示例
// Unsigned Fixed-Point
val UQ_8_2 = UFix(peak = 8 exp, resolution = -2 exp) // bit width = 8 - (-2) = 10 bits
val UQ_8_2 = UFix(8 exp, -2 exp)
val UQ_8_2 = UFix(peak = 8 exp, width = 10 bits)
val UQ_8_2 = UFix(8 exp, 10 bits)
// Signed Fixed-Point
val Q_8_2 = SFix(peak = 8 exp, resolution = -2 exp) // bit width = 8 - (-2) + 1 = 11 bits
val Q_8_2 = SFix(8 exp, -2 exp)
val Q_8_2 = SFix(peak = 8 exp, width = 11 bits)
val Q_8_2 = SFix(8 exp, 11 bits)
赋值操作
当没有比特丢失时,对定点值的赋值是有效的。任何位丢失都会导致错误。如果源定点值太大,该.truncated
函数将允许您调整源数字的大小以匹配目标大小。
示例
val i16_m2 = SFix(16 exp, -2 exp)
val i16_0 = SFix(16 exp, 0 exp)
val i8_m2 = SFix( 8 exp, -2 exp)
val o16_m2 = SFix(16 exp, -2 exp)
val o16_m0 = SFix(16 exp, 0 exp)
val o14_m2 = SFix(14 exp, -2 exp)
o16_m2 := i16_m2 // OK
o16_m0 := i16_m2 // Not OK, Bit loss
o14_m2 := i16_m2 // Not OK, Bit loss
o16_m0 := i16_m2.truncated // OK, as it is resized
o14_m2 := i16_m2.truncated // OK, as it is resized
Scala常量
在分配给 UFix 或 SFix 信号时,Scala BigInt 或 Double 类型可用作常量。
val i4_m2 = SFix(4 exp, -2 exp)
i4_m2 := 1.25 // Will load 5 in i4_m2.raw
i4_m2 := 4 // Will load 16 in i4_m2.raw
原始值
可以使用该raw
属性读取或写入定点数的整数表示。
val UQ_8_2 = UFix(8 exp, 10 bits)
UQ_8_2.raw := 4 // Assign the value corresponding to 1.0
UQ_8_2.raw := U(17) // Assign the value corresponding to 4.25
运算操作
以下运算符可用于该UFix
类型:
算术运算
Operator | Description | Returned resolution | Returned amplitude |
x + y | 加 | Min(x.resolution, y.resolution) | Max(x.amplitude, y.amplitude) |
x - y | 减 | Min(x.resolution, y.resolution) | Max(x.amplitude, y.amplitude) |
x * y | 乘 | x.resolution * y.resolution) | x.amplitude * y.amplitude |
x >> y | 算术右移, y : Int | x.amplitude >> y | x.resolution >> y |
x << y | 算术左移, y : Int | x.amplitude << y | x.resolution << y |
x >>| y | 算术右移, y : Int | x.amplitude >> y | x.resolution |
x <<| y | 算术左移, y : Int | x.amplitude << y | x.resolution |
Comparison
Operator | Description | Return type |
x === y | 相等 | Bool |
x =/= y | 不相等 | Bool |
x > y | 大于 | Bool |
x >= y | 大于等于 | Bool |
x > y | 小于 | Bool |
x >= y | 小于等于 | Bool |
类型转换
Operator | Description | Return |
x.asBits | 二进制转换为 Bits | Bits(w(x) bits) |
x.asUInt | 二进制转换为 UInt | UInt(w(x) bits) |
x.asSInt | 二进制转换为 SInt | SInt(w(x) bits) |
x.asBools | 转换成 Bool 数组 | Vec(Bool,width(x)) |
x.toUInt | 返回对应的 UInt(带截断) | UInt |
x.toSInt | 返回对应的 SInt(带截断) | SInt |
x.toUFix | 返回对应的 UFix | UFix |
x.toSFix | 返回对应的SFix | SFix |
其他
Name | Return | Description |
x.maxValue | 返回可存储的最大值 | Double |
x.minValue | 返回可存储的最小值 | Double |
x.resolution | x.amplitude * y.amplitude | Double |
Reference
- spinal HDL官方文档