十二 · 2021年10月27日

SpinalHDL—数据类型:UInt/SIn

在Bits的基础上,SpinalHDL提供了UInt、SInt数据类型,从而能够进行有符号/无符号数操作。

变量定义/初始化

UInt/SInt的初始化与Bits类型相似:

b5bc259087121f800b43b1f4d6c8ae27.png

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差别不大:

29b0ab18a1a8411bce63bdfe5ee5e333.png

// 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提供了更丰富的运算符:

2c27461a51d42e22bddf7c01340673ba.png

针对加法和减法,SpinalHDL均提供了三种方式实现:

  • x+y、x-y: 与Verilog中的加减操作符相同,对于溢出不做处理。
  • x+^y、x-^y: 为了防止加减法溢出,该方法提供了带位宽扩展的操作处理。
  • x+|y、x-|y:该操作符对于溢出场景,做截断饱和处理。

比较操作符

c6132792808e823e5a5ff269f7bfb8a5.png

比较操作符与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) {
  ..
}

类型转换

7e6d4a9da40d56130874b41b06c7f9d6.png

对于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

9e0ba9e9a01a6e2149f4ad3ff926fca3.png

位操作与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

其他方法

82240290b6e5eb98800d6ce8918b298b.png

image.png

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
微信公众号:
 title=

推荐阅读

更多SpinalHDL技术干货请关注Spinal FPGA专栏。
推荐阅读
关注数
1581
内容数
133
用SpinalHDL提升生产力
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息