在Bits的基础上,SpinalHDL提供了UInt、SInt数据类型,从而能够进行有符号/无符号数操作。
变量定义/初始化
UInt/SInt的初始化与Bits类型相似:
myUInt := U(2,8 bits)
myUInt := U(2)
myUInt := U"0000_0101" // Base per default is binary => 5
myUInt := U"h1A" // Base could be x (base 16)
// h (base 16)
// d (base 10)
// o (base 8)
// b (base 2)
myUInt := U"8'h1A"
myUInt := 2 // You can use a Scala Int as a literal value
val myBool := myUInt === U(7 -> true,(6 downto 0) -> false)
val myBool := myUInt === U(myUInt.range -> true)
// For assignment purposes, you can omit the U/S, which also allows the use of the [default -> ???] feature
myUInt := (default -> true) // Assign myUInt with "11111111"
myUInt := (myUInt.range -> true) // Assign myUInt with "11111111"
myUInt := (7 -> true, default -> false) // Assign myUInt with "10000000"
myUInt := ((4 downto 1) -> true, default -> false) // Assign myUInt with "00011110"
逻辑操作符
UInt/SInt逻辑操作符与Bits差别不大:
// Bitwise operator
val a, b, c = SInt(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 uint_10bits = uint_8bits << 2 // shift left (resulting in 10 bits)
val shift_8bits = uint_8bits |<< 2 // shift left (resulting in 8 bits)
// Logical rotation
val myBits = uint_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
}
对于SInt左移操作,其提供的算数左移操作将会进行位宽扩展,若想位宽保持不变,可以进行位宽截取(SpinalHDL里提供了非常方便的位宽截取处理方式)。而逻辑左移操作的处理方式与UInt无二差别。
val a, b, c = SInt(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 uint_10bits = uint_8bits << 2 // shift left (resulting in 10 bits)
val shift_8bits = uint_8bits |<< 2 // shift left (resulting in 8 bits)
// Logical rotation
val myBits = uint_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的算术操作符相较于Verilog提供了更丰富的运算符:
针对加法和减法,SpinalHDL均提供了三种方式实现:
- x+y、x-y: 与Verilog中的加减操作符相同,对于溢出不做处理。
- x+^y、x-^y: 为了防止加减法溢出,该方法提供了带位宽扩展的操作处理。
- x+|y、x-|y:该操作符对于溢出场景,做截断饱和处理。
比较操作符
比较操作符与Verilog中的比较操作符基本无差别:
// Comparison between two SInts
myBool := mySInt_1 > mySInt_2
// Comparison between a UInt and a literal
myBool := myUInt_8bits >= U(3, 8 bits)
when(myUInt_8bits === 3) {
..
}
类型转换
对于intoSInt,其会扩展一位(最高位):
// Cast an SInt to Bits
val myBits = mySInt.asBits
// Create a Vector of Bool
val myVec = myUInt.asBools
// Cast a Bits to SInt
val mySInt = S(myBits)
Bit extraction
位操作与Bits所提供的方法基本相同:
val myBool = myUInt(4)
// assign bit 1 to True
mySInt(1) := True
// Range
val myUInt_8bits = myUInt_16bits(7 downto 0)
val myUInt_7bits = myUInt_16bits(0 to 6)
val myUInt_6bits = myUInt_16Bits(0 until 6)
mySInt_8bits(3 downto 0) := mySInt_4bits
其他方法
myBool := mySInt.lsb // equivalent to mySInt(0)
// Concatenation
val mySInt = mySInt_1 @@ mySInt_1 @@ myBool
val myBits = mySInt_1 ## mySInt_1 ## myBool
// Subdivide
val sel = UInt(2 bits)
val mySIntWord = mySInt_128bits.subdivideIn(32 bits)(sel)
// sel = 0 => mySIntWord = mySInt_128bits(127 downto 96)
// sel = 1 => mySIntWord = mySInt_128bits( 95 downto 64)
// sel = 2 => mySIntWord = mySInt_128bits( 63 downto 32)
// sel = 3 => mySIntWord = mySInt_128bits( 31 downto 0)
// If you want to access in reverse order you can do:
val myVector = mySInt_128bits.subdivideIn(32 bits).reverse
val mySIntWord = myVector(sel)
// Resize
myUInt_32bits := U"32'x112233344"
myUInt_8bits := myUInt_32bits.resized // automatic resize (myUInt_8bits = 0x44)
myUInt_8bits := myUInt_32bits.resize(8) // resize to 8 bits (myUInt_8bits = 0x44)
// Two's complement
mySInt := myUInt.twoComplement(myBool)
// Absolute value
mySInt_abs := mySInt.abs
END
作者:玉骐
原文链接:https://mp.weixin.qq.com/s/rmmcopcNynSdKXk2K9ylNg
微信公众号:
推荐阅读
更多SpinalHDL技术干货请关注Spinal FPGA专栏。