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

提取 x 的 LSB

Bool(x.lsb)

B(x: T)

将数据转换为 Bits

Bits(w(x) bits)

要将 BoolUIntSInt 转换为 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(x: UInt)

访问第 y 位,这里y为可变的信号

Bool

x(offset: Int, width bits)

固定地选择偏移量和宽度,offset 为选择信号中LSB的索引

Bits(width bits)

x(offset: UInt, width bits)

选择偏移量可变和宽度固定的信号,offset 为选择信号中LSB的索引 (可为另一信号)

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) )。如果 stricttrue,则如果输入无法等分,将引发错误。如果设置为 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 值带有”不关心”值的位向量,其中”不关心”值用 - 表示。它们可用于直接比较或用于 switchmux 等语句。

val myBits = B"1101"

val test1 = myBits === M"1-01" // True
val test2 = myBits === M"0---" // False
val test3 = myBits === M"1--1" // True