Bits类型是spinalHDL扩展的基础类型,是一个vec向量类型,每个元素都是Bool(Bool是spinalHDL也是扩展的基础类型,注意和scala原生的Boolean类型的不同),bits可以转化为UInt或 SInt类型,但是Bits类型本身没有数值大小的概念。
一、如何实例化一个bits类型对象?
如上所示,可以使用Bits或B关键字来实列化,返回类型是Bits,图中[]表示可选项
// Declaration
val myBits = Bits() // the size is inferred
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
// Element
val myBits5 = B(8 bits, default -> True) // "11111111"
val myBits6 = B(8 bits, (7 downto 5) -> B"101", 4 -> true, 3 -> True, default -> false) // "10111000"
val myBits7 = Bits(8 bits)
myBits7 := (7 -> true, default -> false) // "10000000" (For assignment purposes, you can omit the B)
二、常用的bits类的方法
1)图中[]表示可选项,w(x)表示求Bits类型的对象x的位宽
2)xorR、orR、andR是对象x的各个位自己相互异或、或、与运算,结果是Bool类型,不是Bits类型
3)注意>>运算结果的位宽与|>>不同,|>>运算结果可能才是大家一般的理解
4)注意<<运算结果的位宽与|<<不同,|<<运算结果可能才是大家一般的理解
5)rotateLeft是循环左移,即最高位移入最低位;rotateRight是循环右移,最低位移入最高位;关于它们转化为verilog的示例,可以参看以往的讲解视频。
// 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}
三、相等与不相等比较
注意:spinalHDL用自定义的===表示相等比较,和scala原生的==不同,==往往表示是否是同一个对象,而此处比较是两个不同bits对象的内容是否相同;类似scala的!=与spinalHDL的=/=是有差异的;而且spinalHDL的比较,返回类型是Bool不是scala的Boolean。虽然Bool类与Boolean类有相似的意思,但是它们并不是一个相同的类。
四、常用的类型转化
注意:最后的B(x:T),表示把任意类型T的对象转化为bits类型的对象,能够这样做是有前提条件的:比如你已经定义了某个类型T到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)
五、位提取
上图中的range 有三种情况,比如7 downto 2, 2 to 7, 2 until 8;注意x(hi,lo)与x(offset, width bits)的不同,比如x(8,4)和x(8, 4 bits),其中的关键字bits就是区分两者的标志。
// get the element at the index 4
val myBool = myBits(4)
// assign
myBits(1) := True
// Range
val myBits_8bits = myBits_16bits(7 downto 0)
val myBits_7bits = myBits_16bits(0 to 6)
val myBits_6bits = myBits_16Bits(0 until 6)
myBits_8bits(3 downto 0) := myBits_4bits
六、杂项
println(myBits_32bits.getWidth) // 32
myBool := myBits.lsb // Equivalent to myBits(0)
// Concatenation
myBits_24bits := bits_8bits_1 ## bits_8bits_2 ## bits_8bits_3
// Subdivide
val sel = UInt(2 bits)
val myBitsWord = myBits_128bits.subdivideIn(32 bits)(sel)
// sel = 0 => myBitsWord = myBits_128bits(127 downto 96)
// sel = 1 => myBitsWord = myBits_128bits( 95 downto 64)
// sel = 2 => myBitsWord = myBits_128bits( 63 downto 32)
// sel = 3 => 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 myBitsWord = myVector(sel)
// 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)
视频讲解1:
视频讲解2:
视频讲解3:
欢迎大家加入我的知识星球:硬件电路设计与研究,今后准备在此星球里面和大家分享资料和信息