位
Bits
类型表示多位向量,不传达任何算术含义。
声明
声明位向量的语法如下([]之间的所有内容都是可选的):
语法 |
描述 |
---|---|
Bits [()] |
创建Bits,其位数是从构造后最宽的赋值语句推断出来的 |
Bits(x bits) |
创建具有 x 位的Bits |
B(value: Int[, x bits])
B(value: BigInt[, x bits])
|
创建 x 位Bits,且赋值为’value’ |
B”[[size’]base]value” |
创建Bits并赋值为’value’(基数:“h”、“d”、“o”、“b”) |
B([x bits,] elements: Element*) |
创建并赋值由 elements 指定值的Bits |
val myBits1 = Bits(32 bits)
val myBits2 = B(25, 8 bits)
val myBits3 = B"8'xFF" // Base could be x,h (base 16)
// d (base 10)
// o (base 8)
// b (base 2)
val myBits4 = B"1001_0011" // _ can be used for readability
// Bits with all ones ("11111111")
val myBits5 = B(8 bits, default -> True)
// initialize with "10111000" through a few elements
val myBits6 = B(8 bits, (7 downto 5) -> B"101", 4 -> true, 3 -> True, default -> false)
// "10000000" (For assignment purposes, you can omit the B)
val myBits7 = Bits(8 bits)
myBits7 := (7 -> true, default -> false)
当推断 Bits
的宽度时,赋予值的宽度仍然必须与信号的最终宽度相匹配:
// Declaration
val myBits = Bits() // the size is inferred from the widest assignment
// ....
// .resized needed to prevent WIDTH MISMATCH error as the constants
// width does not match size that is inferred from assignment below
myBits := B("1010").resized // auto-widen Bits(4 bits) to Bits(6 bits)
when(condxMaybe) {
// Bits(6 bits) is inferred for myBits, this is the widest assignment
myBits := B("110000")
}
运算符
以下运算符可用于 Bits
类型:
逻辑运算
运算符 |
描述 |
返回类型 |
---|---|---|
~x |
按位非 |
Bits(w(x) bits) |
x & y |
按位与 |
Bits(w(xy) bits) |
x | y |
按位或 |
Bits(w(xy) bits) |
x ^ y |
按位异或 |
Bits(w(xy) bits) |
x.xorR |
对 x 的所有位进行异或 |
Bool |
x.orR |
对x 的所有位做或运算 |
Bool |
x.andR |
对x 的所有位做与运算 |
Bool |
y = 1 // 整数
x >> y
|
逻辑右移,y: Int
结果的宽度可能会变少
|
Bits(w(x) - y bits) |
y = U(1) // UInt
x >> y
|
逻辑右移,y: UInt
结果宽度相同
|
Bits(w(x) bits) |
y = 1 // 整数
x << y
|
逻辑左移,y: Int
结果的宽度可能会增加
|
Bits(w(x) + y bits) |
y = U(1) // UInt
x << y
|
逻辑左移,y: UInt
结果的宽度可能会增加
|
Bits(w(x) + max(y) bits) |
x |>> y |
逻辑右移,y: Int/UInt
结果宽度相同
|
Bits(w(x) bits) |
x |<< y |
逻辑左移,y: Int/UInt
结果宽度相同
|
Bits(w(x) bits) |
x.rotateLeft(y) |
逻辑循环左移,y: UInt/Int
结果宽度相同
|
Bits(w(x) bits) |
x.rotateRight(y) |
逻辑循环右移,y:UInt/Int
结果宽度相同
|
Bits(w(x) bits) |
x.clearAll[()] |
清零所有位 |
修改x |
x.setAll[()] |
将所有的位设置为1 |
修改x |
x.setAllTo(value: Boolean) |
将所有位设置为给定的布尔值(Scala Boolean) |
修改x |
x.setAllTo(value: Bool) |
将所有位设置为给定的布尔值(Spinal Bool) |
修改x |
// Bitwise operator
val a, b, c = Bits(32 bits)
c := ~(a & b) // Inverse(a AND b)
val all_1 = a.andR // Check that all bits are equal to 1
// Logical shift
val bits_10bits = bits_8bits << 2 // shift left (results in 10 bits)
val shift_8bits = bits_8bits |<< 2 // shift left (results in 8 bits)
// Logical rotation
val myBits = bits_8bits.rotateLeft(3) // left bit rotation
// Set/clear
val a = B"8'x42"
when(cond) {
a.setAll() // set all bits to True when cond is True
}
比较运算
运算符 |
描述 |
返回类型 |
---|---|---|
x === y |
等价性判断 |
Bool |
x =/= y |
不等价判断运算 |
Bool |
when(myBits === 3) {
// ...
}
val notMySpecialValue = myBits_32 =/= B"32'x44332211"
类型转换
运算符 |
描述 |
返回类型 |
---|---|---|
x.asBits |
二进制转换为 Bits |
Bits(w(x) bits) |
x.asUInt |
二进制转换为 UInt |
UInt(w(x) bits) |
x.asSInt |
二进制转换为SInt |
SInt(w(x) bits) |
x.asBools |
转换为一个布尔数组 |
Vec(Bool(), w(x)) |
x.asBool |
提取 |
Bool(x.lsb) |
B(x: T) |
将数据转换为 |
Bits(w(x) bits) |
要将 Bool
、 UInt
或 SInt
转换为 Bits
,您可以使用 B(something)
或 B(something[, x bits])
:
// cast a Bits to SInt
val mySInt = myBits.asSInt
// create a Vector of bool
val myVec = myBits.asBools
// Cast a SInt to Bits
val myBits = B(mySInt)
// Cast the same SInt to Bits but resize to 3 bits
// (will expand/truncate as necessary, retaining LSB)
val myBits = B(mySInt, 3 bits)
位提取
所有位提取操作均可用于读取一个位/一组位。与其他 HDL 一样,提取运算符也可用于为 Bits
的一部分赋值。
所有位提取操作均可用于读取一个位/一组位。与其他 HDL 一样,它们也可用于选择要写入位的范围。
运算符 |
描述 |
返回类型 |
---|---|---|
x(y: Int) |
静态访问第 y 位 |
Bool |
x(y: UInt) |
访问第 y 位,这里y为可变的信号 |
Bool |
x(offset: Int, width bits) |
固定地选择偏移量和宽度, |
Bits(width bits) |
x(offset: UInt, width bits) |
选择偏移量可变和宽度固定的信号, |
Bits(width bits) |
x(range: Range) |
访问Bits的 范围 。例如:myBits(4 downto 2) |
Bits(range.size bits) |
x.subdivideIn(y slices, [strict: Boolean]) |
将x分割为y片,y: Int |
Vec(Bits(…), y) |
x.subdivideIn(y bits, [strict: Boolean]) |
将 x 分割为 y 位的多个切片,y: Int |
Vec(Bits(y bit), …) |
x.msb |
访问 x 的最高有效位(最高索引) |
Bool |
x.lsb |
访问 x 的最低有效位(索引 0) |
Bool |
一些基本示例:
// get the element at the index 4
val myBool = myBits(4)
// assign element 1
myBits(1) := True
// index dynamically
val index = UInt(2 bit)
val indexed = myBits(index, 2 bit)
// range index
val myBits_8bit = myBits_16bit(7 downto 0)
val myBits_7bit = myBits_16bit(0 to 6)
val myBits_6bit = myBits_16bit(0 until 6)
// assign to myBits_16bit(3 downto 0)
myBits_8bit(3 downto 0) := myBits_4bit
// equivalent slices, no reversing occurs
val a = myBits_16bit(8 downto 4)
val b = myBits_16bit(4 to 8)
// read / assign the msb / leftmost bit / x.high bit
val isNegative = myBits_16bit.msb
myBits_16bit.msb := False
分割细节
两个 subdivideIn
函数的所有参数都有一个可选参数 strict
参数(即 subdivideIn(slices: SlicesCount, strict: Boolean = true)
)。如果 strict
为 true
,则如果输入无法等分,将引发错误。如果设置为 false
,最后一个元素可能比其他(大小相等)元素小。
// Subdivide
val sel = UInt(2 bits)
val myBitsWord = myBits_128bits.subdivideIn(32 bits)(sel)
// sel = 3 => myBitsWord = myBits_128bits(127 downto 96)
// sel = 2 => myBitsWord = myBits_128bits( 95 downto 64)
// sel = 1 => myBitsWord = myBits_128bits( 63 downto 32)
// sel = 0 => myBitsWord = myBits_128bits( 31 downto 0)
// If you want to access in reverse order you can do:
val myVector = myBits_128bits.subdivideIn(32 bits).reverse
val myRevBitsWord = myVector(sel)
// We can also assign through subdivides
val output8 = Bits(8 bit)
val pieces = output8.subdivideIn(2 slices)
// assign to output8
pieces(0) := 0xf
pieces(1) := 0x5
杂项
与上面列出的位提取操作相反,上述函数不能使用其返回值给原始信号赋值。
运算符 |
描述 |
返回类型 |
---|---|---|
x.getWidth |
返回位数 |
Int |
x.bitsRange |
返回范围(0 到 x.high) |
范围 |
x.valueRange |
返回最小到最大 x 值的范围,理解为无符号整数(0 到 2 ** width - 1)。 |
范围 |
x.high |
返回 MSB(最高有效位) 的索引(x的最高索引,该索引从0开始计数) |
Int |
x.reversed |
返回 x 的副本,其位顺序相反,MSB<>LSB 是镜像的。 |
Bits(w(x) bits) |
x ## y |
连接Bits,x->高位,y->低位 |
Bits(w(x) + w(y) bits) |
x #* n |
n次重复x并合并 |
Bits(w(x) * n bits) |
x.resize(y) |
返回一个新的信号与 x 信号直接连接但位宽变成了y位。如果位宽变大了,则根据需要在 MSB 处用零填充进行扩展,y: Int |
Bits(y bits) |
x.resized |
返回一个允许自动调整位宽的 x 的副本信号。调整位宽操作被推迟到稍后的赋值操作。调整位宽可能会加宽或截断原信号,但保留 LSB。 |
Bits(w(x) bits) |
x.resizeLeft(x) |
调整位宽时保持 MSB 位置不变,x:Int 调整位宽可能会加宽或截断信号,同时保留 MSB。 |
Bits(x bits) |
x.getZero |
返回新的 Bits 的实例,该实例被分配了与 x 宽度相同的0值(常量)。 |
Bits(0, w(x) bits) |
x.getAllTrue |
返回 Bits 的新实例,该实例被赋予了与 x 宽度相同的1值(常量)。 |
Bits(w(x) bits).setAll() |
备注
validRange 只能用于最小值和最大值能够保存在32 位有符号整数的情况下。 (这是由于 Scala scala.collection.immutable.Range
类型使用 Int 作为范围描述)
println(myBits_32bits.getWidth) // 32
// Concatenation
myBits_24bits := bits_8bits_1 ## bits_8bits_2 ## bits_8bits_3
// or
myBits_24bits := Cat(bits_8bits_1, bits_8bits_2, bits_8bits_3)
// Resize
myBits_32bits := B"32'x112233344"
myBits_8bits := myBits_32bits.resized // automatic resize (myBits_8bits = 0x44)
myBits_8bits := myBits_32bits.resize(8) // resize to 8 bits (myBits_8bits = 0x44)
myBits_8bits := myBits_32bits.resizeLeft(8) // resize to 8 bits (myBits_8bits = 0x11)
掩码字面量
MaskedLiteral 值带有”不关心”值的位向量,其中”不关心”值用 -
表示。它们可用于直接比较或用于 switch
和 mux
等语句。
val myBits = B"1101"
val test1 = myBits === M"1-01" // True
val test2 = myBits === M"0---" // False
val test3 = myBits === M"1--1" // True