文章目录
- 1.1、描述
- 1.2、声明
- 1.3、运算符
- 1.3.1、逻辑运算(Logic)
- 1.3.2、比较(Comparison)
- 1.3.3、类型转换(Type cast)
- 1.3.4、部分赋值/提取操作符(Bit extraction)
- 1.3.5、杂项(Misc)
- 1.3.6、MaskedLiteral
1.1、描述
Bits类型对应于一个不传达任何算术含义的位向量。
1.2、声明
声明位向量的语法如下:(方括号中的所有内容都是可选项)
// 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)
1.3、运算符
以下运算符可用于 Bits 类型:
1.3.1、逻辑运算(Logic)
// 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
}
注意:
-
1、 这里值得注意的是:
&、|、^
操作符中x,y的宽度必须保持一致,否则在生成RTL代码时将提示不能正常编译(可使用resized
方法自动扩展剪裁位宽),相当于把RTL中的位宽不匹配警报消除在设计阶段。 -
2、对于逻辑右移操作:
x>>y
,y变量类型的不同所产生的结果也不同。y为UInt时和Verilog是比较符合的,移位前后位数不变。实验代码如下:
有点意思的东西,可以琢磨一下!
SpinalHDL代码:
package test
import spinal.core._
case class BitsInst() extends Component {
val data_in1=in Bits(16 bits)
val data_out1=out Bits()
val data_out2=out Bits()
data_out1:=data_in1>>3
data_out2:=data_in1>>U(3) //类型转换为UInt,默认是Int
}
object MyTopLevelApp extends App{
SpinalConfig().generateSystemVerilog(BitsInst())
}
注意:直接写数字,代表Scala中的Int。
// Generator : SpinalHDL v1.6.0 git head : 73c8d8e2b86b45646e9d0b2e729291f2b65e6be3
// Component : BitsInst
module BitsInst (
input [15:0] data_in1,
output [12:0] data_out1,
output [15:0] data_out2
);
assign data_out1 = (data_in1 >>> 3); //默认Int移位后进行截断,不会高位补0
assign data_out2 = (data_in1 >>> 2'b11); //移位后还是原来的位数,高位补0
endmodule
1.3.2、比较(Comparison)
when(myBits === 3) {
}
when(myBits_32 =/= B"32’x44332211") {
}
1.3.3、类型转换(Type cast)
将 Bool、UInt 或 SInt 转换为 Bits,您可以使用 B(something):
// 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)
1.3.4、部分赋值/提取操作符(Bit extraction)
对于
x(offset,width bits)
,其意味着从offset比特位开始,向上截取width比特位宽
// 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
有点意思的东西,可以琢磨一下!
Range的三种表示范围:
- 简而言之:
to
和downto
是左右闭区间,until
是左闭右开区间。
1.3.5、杂项(Misc)
注意:validRange仅适用于最小值和最大值适合于有符号32位整数的类型。 (这是由Scala范围类型给出的限制,它使用Int)
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的取值个数,平均分成这么多份!
// 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)
resized 有点意思的东西,可以琢磨一下!
1.3.6、MaskedLiteral
MaskedLiteral
值是带有“-”的位向量,表示不关心的值。【下面的M
就表示MaskedLiteral】
val myBits = B"1101
val test1 = myBits === M"1-01" // True
val test2 = myBits === M"0---" // False
val test3 = myBits === M"1--1" // True