【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

这篇具有很好参考价值的文章主要介绍了【SpinalHDL快速入门】4.3、基本类型之UInt/SInt。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

1.1、描述

UInt/SInt类型对应于一组bits,可用于有符号/无符号整数运算。

1.2、声明

声明整数的语法如下:([] 中的所有内容都是可选项)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

val myUInt = UInt(8 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【注意,直接写数字默认是Int】

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"

1.3、运算符

UInt和SInt类型支持以下运算符:

1.3.1、逻辑运算(Logic)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

注意:x rotateLeft yx rotateRight y 也是有效的语法。

注意:请注意 x >> 2:T(w(x)-2)x >> U(2):T(w(x)) 之间的区别。两者的不同在于,在第一种情况下,数字 2 是一个 Int(可以看作是“elaboration integer”),而在第二种情况下它是一个硬件信号。【类比上一节中的 >> y的类型】

val a, b, c = SInt(32 bits)
a := S(5)
b := S(10)

// Bitwise operators
c := ~(a & b) // Inverse(a AND b)
assert(c.getWidth == 32)

// Shift
val arithShift = UInt(8 bits) << 2 // shift left (resulting in 10 bits)
val logicShift = UInt(8 bits) |<< 2 // shift left (resulting in 8 bits)
assert(arithShift.getWidth == 10)
assert(logicShift.getWidth == 8)

// Rotation
val rotated = UInt(8 bits) rotateLeft 3 // left bit rotation
assert(rotated.getWidth == 8)

// Set all bits of b to True when all bits of a are True
when(a.andR) { b.setAll() }

注意:对于SInt左移操作,其提供的算数左移操作将会进行位宽扩展,若想位宽保持不变,可以进行位宽截取(SpinalHDL里提供了非常方便的位宽截取处理方式)。而逻辑左移操作的处理方式与UInt无二差别。

1.3.2、算术运算(Arithmetic)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

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

  • x+y、x-y: 与Verilog中的加减操作符相同,对于溢出不做处理。
  • x+^y、x-^y: 为了防止加减法溢出,该方法提供了带位宽扩展的操作处理
  • x+|y、x-|y:该操作符对于溢出场景,做截断饱和处理
val a, b, c = UInt(8 bits)
a := U"xf0"
b := U"x0f"

c := a + b
assert(c === U"8’xff")

val d = a +^ b
assert(d === U"9’x0ff")

val e = a +| U"8’x20"
assert(e === U"8’xff")

注意:请注意这里如何进行仿真断言(simulation assertions)(使用===),而不是前面示例中的elaboration assertions(使用==)。

1.3.3、比较(Comparison)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

val a = U(5, 8 bits)
val b = U(10, 8 bits)
val c = UInt(2 bits)

when (a > b) {
	c := U"10"
} elsewhen (a =/= b) {
	c := U"01"
} elsewhen (a === U(0)) {
	c.setAll()
} otherwise {
	c.clearAll()
}

注意:当以允许“环绕(wraparound)”行为的方式比较UInt值时,意味着当它们超过最大值时,这些值将“环绕”到最小值。可以使用UInt的wrap方法作为x.wrap < y来处理UInt变量x、y,如果在环绕意义下x小于y,则结果为true。【不是太懂????】

1.3.4、类型转换(Type Cast)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt
将 Bool、Bits 或 SInt 转换为 UInt,可以使用 U(something)。要将东西转换为 SInt,可以使用 S(something)。

// 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)

1.3.5、部分赋值/提取操作符(Bit extraction)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

// get the bit at index 4
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

1.3.6、杂项(Misc)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

  • ##@@操作符均为拼接操作符,两者差别在于返回结果类型不同##返回类型为Bits,而@@返回类型为x变量类型
  • twoCompelment可将UInt通过二进制补码转换为SInt(en为True)。
  • expand对于SInt而言会扩展符号位
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 = 3 => mySIntWord = mySInt_128bits(127 downto 96)
// sel = 2 => mySIntWord = mySInt_128bits( 95 downto 64)
// sel = 1 => mySIntWord = mySInt_128bits( 63 downto 32)
// sel = 0 => 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)
val lowest_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

1.4、固定点运算(FixPoint operations)【了解】

对于定点数,我们可以将其分为两部分:

  • 低位操作(舍入方法)Lower bit operations (rounding methods)
  • 高位操作(饱和运算)High bit operations (saturation operations)

1.4.1、低位操作(Lower bit operations)

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

注意:RoundToEvenRoundToOdd模式非常特殊,用于一些高精度的大数据统计领域。目前SpinalHDL还不支持这两种模式。

你会发现ROUNDUP,ROUNDDOWN,ROUNDTOZERO,ROUNDTOINF,ROUNDTOEVEN和ROUNTOODD的行为非常相似,其中ROUNDTOINF是最常见的。不同编程语言中舍入的行为可能有所不同。

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt

注意:在SpinalHDL中,ROUNDTOINF是默认的RoundType(round = roundToInf)

val A = SInt(16 bits)
val B = A.roundToInf(6 bits) //默认使用带进位的“align = false”,得到了11位 = 16-6+1
val B = A.roundToInf(6 bits, align = true) // sat 1 carry bit, got 10 bit = 16-6
val B = A.floor(6 bits) // return 10 bit
val B = A.floorToZero(6 bits) // return 10 bit
val B = A.ceil(6 bits) // ceil with carry so return 11 bit
val B = A.ceil(6 bits, align = true) // ceil with carry then sat 1 bit return 10 bit
val B = A.ceilToInf(6 bits)
val B = A.roundUp(6 bits)
val B = A.roundDown(6 bits)
val B = A.roundToInf(6 bits)
val B = A.roundToZero(6 bits)
val B = A.round(6 bits) // SpinalHDL uses roundToInf as the default rounding mode
val B0 = A.roundToInf(6 bits, align = true) // ---+
											// |--> equal
val B1 = A.roundToInf(6 bits, align = false).sat(1) // ---+

注意:仅 floor 和 floorToZero 可以在不使用 align 选项的情况下工作;它们不需要进位比特。其他舍入操作默认使用进位比特

1.4.2、高位操作(High bit operations )

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt
【SpinalHDL快速入门】4.3、基本类型之UInt/SInt
对于SInt,Symmetric是唯一有效的。

val A = SInt(8 bits)
val B = A.sat(3 bits) // return 5 bits with saturated highest 3 bits
val B = A.sat(3) // equal to sat(3 bits)
val B = A.trim(3 bits) // return 5 bits with the highest 3 bits discarded
val B = A.trim(3 bits) // return 5 bits with the highest 3 bits discarded
val C = A.symmetry // return 8 bits and symmetry as (-128~127 to -127~127)
val C = A.sat(3).symmetry // return 5 bits and symmetry as (-16~15 to -15~15)

1.4.3、fixTo function

在UInt/SInt中提供了两种方法来进行定点数:

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt
在RTL工作中强烈推荐使用 fixTo,无需像上图中的Way1那样手动处理进位比特对齐和比特宽度计算

具有自动饱和功能的Factory Fix函数:

【SpinalHDL快速入门】4.3、基本类型之UInt/SInt文章来源地址https://www.toymoban.com/news/detail-474468.html

val A = SInt(16 bits)
val B = A.fixTo(10 downto 3) // default RoundType.ROUNDTOINF, sym = false
val B = A.fixTo( 8 downto 0, RoundType.ROUNDUP)
val B = A.fixTo( 9 downto 3, RoundType.CEIL, sym = false)
val B = A.fixTo(16 downto 1, RoundType.ROUNDTOINF, sym = true )
val B = A.fixTo(10 downto 3, RoundType.FLOOR) // floor 3 bit, sat 5 bit @ highest
val B = A.fixTo(20 downto 3, RoundType.FLOOR) // floor 3 bit, expand 2 bit @ highest

到了这里,关于【SpinalHDL快速入门】4.3、基本类型之UInt/SInt的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C# int和uint类型学习

    在C#中,使用int表示整数类型,对应于.NET的System.Int32结构; C#中的int类型占4字节(4*8=32位)内存空间,其范围从-2,147,483,648 到 2,147,483,647; int类型是默认的整数类型,并且默认值是0; uint类型也是整数类型,占4字节(32位)内存空间,范围是0-4294967295之间的正整数,对应于.NET的

    2024年02月12日
    浏览(41)
  • 32位 STM32 打印 uint64_t 类型

    测试代码,未整理,可参考!

    2024年02月11日
    浏览(35)
  • typedef uint8_t u8;(stm32数据类型)

    在stm32单片机的库文件里有这么一段u8和u16的定义 typedef uint8_t  u8; typedef uint16_t u16; 而uint8_t和uint16_t的定义是这样的 typedef unsigned          char uint8_t; typedef unsigned short     int uint16_t; 意味着u8就是就是指代的unsigned char 意味着u16就是就是指代的unsigned short int C语言之数据类型

    2024年02月04日
    浏览(53)
  • Flutter Dart FFI Pointer<Uint8>类型如何转成数组或String

    继上一次发布的 Flutter 直接调用so动态库,或调用C/C++源文件内函数 内容,最终我选择了第二种方式, 直接把整个 Native C++ 的项目源代码放进了 Flutter 工程里编译 (放在iOS的目录是因为它不支持自定义源码路径,Android是可以的)。这样的好处是 Android 和 iOS 两个平台都不需要

    2024年02月04日
    浏览(47)
  • Rust 基础入门 —— 基本类型

    在Rust 中,作为强类型语言,自然会独立一块内容用作类型管理工作,而rust 中 为应用领域的扩展, 兼容了很多的数学计算方面的 内容,加到了基本类型中,例如 复数, 在有向图和 矢量图计算中的应用,rust 通过自带的类型设计避免了 程序员再开发的任务难度。 总的来说

    2024年02月12日
    浏览(37)
  • 关于C或C++,数组的强制类型转换,uint8_t与char的区别,uint8_t*与char*的兼容性问题以及一些指针的常见问题

    1.类型定义: uint8_t:这是一个无符号 8 位整数类型,定义在 stdint.h 或 inttypes.h 头文件中。它是标准的固定宽度整数类型之一,确保在所有平台上占用 8 位(1 字节)。 char:这是 C 语言的基本字符存储类型,用于存储单个字符。在不同的系统和编译器中,char 可以是有符号的

    2024年01月24日
    浏览(36)
  • Redis入门 - 5种基本数据类型

    原文首更地址,阅读效果更佳! Redis入门 - 5种基本数据类型 | CoderMast编程桅杆 https://www.codermast.com/database/redis/five-base-datatype.html 说明 在我们平常的业务中基本只会使用到Redis的基本数据类型(String、List、Hash、Set、Sorted Set),特殊类型(Geo、Bitmap、Hyperloglog)类型只有在特殊

    2024年02月09日
    浏览(31)
  • 【openGauss基本概念---快速入门】

    👈【上一篇】 💖The Begin💖 点点关注,收藏不迷路💖 【下一篇】👉 🔰 1.1 openGauss openGauss是一款 关系型数据库管理系统 —RDBMS。关系型数据库是指采用了关系模型来组织数据的数据库, 以行和列的形式存储数据 。 openGauss的数据库节点负责存储数据,其 存储介质是磁盘

    2024年02月09日
    浏览(37)
  • Kotlin系列一(快速入门,kotlin的数据类型)

    kontlin可以写脚本 创建一个\\\"script.kts\\\"文件 编写脚本内容 使用 kotlinc -script script.kts 命令运行kotlin脚本 创建一个文件\\\"HelloWorld.kt\\\" 编写内容 使用 kotlinc HelloWorld.kt 编译kotlin代码 使用 kotlin HelloWorld Kt运行编译后的字节码 使用\\\"var\\\"定义变量,变量定义后值可以改变,且可以在定义

    2024年02月03日
    浏览(42)
  • 【RabbitMQ】快速入门及基本使用

    Ⅰ、什么是消息队列?         消息队列是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的数据,包含发生的时间,输入设备的种类,以及

    2024年01月20日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包