当前位置:网站首页>吃透Chisel语言.05.Chisel基础(二)——组合电路与运算符
吃透Chisel语言.05.Chisel基础(二)——组合电路与运算符
2022-07-04 12:49:00 【github-3rr0r】
Chisel基础(二)——组合电路与运算符
组合逻辑电路从数学的角度来讲,就是用布尔代数的操作符来描述的数字逻辑电路,也就是一系列布尔代数运算符的组合。Chisel中,这些布尔代数的操作符跟C、Java、Scala以及其他编程语言中定义的是类似的,比如,&
是按位与操作符,|
是按位或操作符。这一部分就详细介绍Chisel中基本的位运算符、算术运算符、逻辑运算符、比较运算符等,以及Chisel中的一个高阶组合电路运算符——多路选择器。
一个简单组合逻辑电路的例子
下面这一行代码,定义了一个组合电路,它用一个与门连接信号a
和b
,然后把这个与门的输出和信号c
用或门连接在一起:
val logic = (a & b) | c
这个表达式对应的电路示意图如下:
可以看到基础语法是很简单的,需要注意的是,这个电路中与门和或门的输入信号可以是单个比特,也可以是比特向量。
Chisel中的位运算符
下面的例子分别演示了四种基本的位运算,用的是Scala中的标准运算符,他们的操作数可以是UInt
、SInt
和Bool
:
val and = a & b // 按位与
val or = a | b // 按位或
val xor = a ^ b // 按位异或
val not = ~a // 按位取反
这几种基本的位运算都很基础,还有两个移位操作,他们的操作数可以是UInt
或SInt
:
val shiftleft = a << b
val shiftright = a >> b
需要注意的是,对于SInt
类型的操作数,右移或会进行符号拓展,即算术右移。
总结Chisel中的位运算符如下:
操作符 | 描述 | 数据类型 |
---|---|---|
& | 按位与 | UInt 、SInt 、Bool |
` | ` | 按位或 |
^ | 按位异或 | UInt 、SInt 、Bool |
~ | 按位取反 | UInt 、SInt 、Bool |
<< | 左移 | UInt 、SInt |
>> | 对于UInt 是逻辑右移,对于SInt 是算术右移 | UInt 、SInt |
Chisel中的算术运算符
下面是Chisel中使用Scala标准运算符进行的算术运算,他们的操作数可以是UInt
或SInt
:
val add = a + b // 加法
val sub = a - b // 减法
val neg = -a // 取相反数
val mul = a * b // 乘法
val div = a / b // 除法
val mod = a % b // 取余
需要注意这里的位宽推断:
- 对于加减法,结果宽度为操作数中最宽的那个宽度;
- 对于乘法,结果宽度为操作数的宽度之和;
- 对于除法和取余,结果宽度通常为被除数的宽度;
另外,对于加法和减法,还可以指定是否进行位宽拓展保留进位,在+
或-
后加上%
就是不进行位宽拓展,加上&
就是不保留进位,默认是不进行位宽拓展。
总结Chisel中的算术运算符如下:
操作符 | 描述 | 数据类型 |
---|---|---|
+ 或+% | 加(不保留进位) | UInt 、SInt |
+& | 加(保留进位) | UInt 、SInt |
- 或-% | 减(不保留进位) | UInt 、SInt |
-& | 减(保留进位) | UInt 、SInt |
* | 乘 | UInt 、SInt |
/ | 除 | UInt 、SInt |
% | 取余 | UInt 、SInt |
Chisel中的逻辑运算符
逻辑运算符是针对Bool
类型的值进行运算的,有逻辑与、逻辑或和逻辑非这三种,和Scala以及其他编程语言是类似的:
操作符 | 描述 | 数据类型 |
---|---|---|
&& | 逻辑与 | Bool |
` | ` | |
! | 逻辑非 | Bool |
Chisel中的比较运算符
对于小于、小于等于、大于和大于等于,Chisel和Scala是一致的,但在等于和不等于上表示不一样。比较运算符的操作数为UInt
或SInt
,总结如下:
操作符 | 描述 | 数据类型 |
---|---|---|
> | 大于 | UInt 、SInt ,返回Bool |
>= | 大于等于 | UInt 、SInt ,返回Bool |
< | 小于 | UInt 、SInt ,返回Bool |
<= | 小于等于 | UInt 、SInt ,返回Bool |
=== | 等于 | UInt 、SInt ,返回Bool |
=/= | 不等于 | UInt 、SInt ,返回Bool |
虽然这里的===
和=/=
看起来很奇怪,但千万不能弄错,设计者表示这么做是为了让Scala中原有的==
和!=
仍然可用。
Chisel中的规约运算符
这是Chisel中比较好用的运算符,操作数为SInt
或UInt
,对操作数的每一位进行规约运算,返回值为Bool
类型,三个规约运算符如下:
操作符 | 描述 | 数据类型 |
---|---|---|
.andR | 与规约 | UInt 、SInt ,返回Bool |
.orR | 或规约 | UInt 、SInt ,返回Bool |
.xorR | 异或规约 | UInt 、SInt ,返回Bool |
用法如下:
val allSet = x.andR // 与规约
val anySet = x.orR // 或规约
val parity = x.xorR // 异或规约
Chisel中的位字段操作符
我们前面提到UInt
和SInt
都是位向量,因此应该有一些对向量的位字段进行操作的操作符,上一部分的规约操作符就属于这类。Chisel中还有其他的位字段操作符:
比如从位向量中提取单个比特,操作符为(n)
,表示提取第n位,最低有效位LSB索引为0:
val xLSB = x(0) // 提取x的最低位
也可以提取一个位段,操作符为(end, start)
,表示提取第start
位到第end
位之间的字段,这个start
和end
是包括在内的,返回值是个UInt
:
val xTopNibble = x(15, 12) // 假设x是16位的,提取x的高4位
还可以把一个位向量复制多次,操作符为Fill(n, x)
,n
为复制次数,x
为被复制的位向量,只可以是或UInt
,返回值也是UInt
:
val usDebt = Fill(3, "hA".U) // "hAAA".U
最后是可以拼接多个位向量的操作,操作符为##
或Cat
,和Verilog中的{}
类似,示例如下:
val float = Cat(sign, exponent, mantissa) // 拼接三个向量,或者
val float = sign ## exponent ## mantissa
不过需要注意的是,拼接操作的操作数两边类型必须一样,而返回值为UInt
,因此,如果在多个操作数上用##
进行拼接的时候需要注意,比如对三个SInt
进行拼接就会报错,而对两个SInt
和一个UInt
进行拼接就不会报错,而使用Cat
就不会有这个问题。
另外还有个需要注意的是,虽然##
和Cat
功能是类似的,但是生成的Verilog会有所不同,比如:
a := -1.S ## -2.S
会生成:
assign a = {1'sh1,2'sh2};
而:
a := Cat(-1.S, -2.S)
会生成:
assign a = 3'h6;
一般来说使用Cat
进行拼接是更好的。
总结如下:
操作符 | 描述 | 数据类型 |
---|---|---|
x(n) | 提取第n 位 | UInt 、SInt ,返回Bool |
x(end, start) | 提取第start 到第end 位 | UInt 、SInt ,返回UInt |
Fill(n, x) | 位向量x 复制n 次 | UInt ,返回UInt |
a ## b | 位向量拼接 | UInt 、SInt ,返回UInt |
Cat(a, b, ...) | 位向量拼接 | UInt 、SInt ,返回UInt |
关于Chisel操作符的优先级
Chisel操作符的优先级并没有作为Chisel语言的一部分直接定义出来,而是取决于电路的赋值顺序,自然地遵循Scala的运算符优先级。如果实在拿不准的话,那就使用括号来表达运算优先级。
题外话,Chisel和Scala的运算符优先级和Java/C相似但不同,而Verilog和C是一样的,但是VHDL直接就是没有这个特性的。在VHDL里面,所有的运算符优先级相同,按照从左到右的顺序进行计算。
Chisel中的2-1多路选择器
多路选择器(multiplexer)是在多个输入中选择一个作为输出的组合电路,其最基本的形式就是2-1多路选择器,即二选一。下图就是一个2-1多路选择器,或者简称为Mux:
根据选择信号sel
的值,输出y
会表示输入信号a
或b
。当然,我们用逻辑门也是可以实现这个Mux的,但是Chisel标准库里面就提供了Mux
作为标准的操作符,示例如下:
val y = Mux(sel, a, b)
当sel
是个Chisel中的Bool
类型值,为true
的时候选择输出a
,否则选择输出b
。这里a
和b
可以是任意的Chisel基本类型或聚合类(比如bundle或vector,后面会详细讲),只要它俩的类型是一样的就行。
结语
有了上面的基本算术、逻辑操作和这里的多路选择器,那就可以描述所有的组合电路了。但是,硬用这些来描述显然不够优雅,比如我要实现一个3-8译码器,我总不能使用8个Mux吧?那代码可读性也太差了!而Chisel里面还提供了更多的组件和控制抽象,能让我们在描述一个组合电路的时候更优雅,相关内容后面详细说!
边栏推荐
- MySQL version 8 installation Free Tutorial
- SQL language
- 一次 Keepalived 高可用的事故,让我重学了一遍它
- Fisher信息量检测对抗样本代码详解
- C language staff management system
- E-week finance | Q1 the number of active people in the insurance industry was 86.8867 million, and the licenses of 19 Payment institutions were cancelled
- BLOB,TEXT GEOMETRY or JSON column 'xxx' can't have a default value query 问题
- WS2818M是CPC8封装,是三通道LED驱动控制专用电路外置IC全彩双信号5V32灯可编程led灯带户外工程
- 舔狗舔到最后一无所有(状态机)
- How to choose a technology stack for web applications in 2022
猜你喜欢
随机推荐
remount of the / superblock failed: Permission denied
#yyds干货盘点# 解决名企真题:连续最大和
华昊中天冲刺科创板:年亏2.8亿拟募资15亿 贝达药业是股东
Dgraph: large scale dynamic graph dataset
字节面试算法题
安装trinity、解决报错
2022 hoisting machinery command examination simulation 100 questions simulation examination platform operation
The only core indicator of high-quality software architecture
Byte interview algorithm question
2022危险化学品经营单位主要负责人练习题及模拟考试
Qt如何实现打包,实现EXE分享
Web knowledge supplement
go vendor 项目迁移到 mod 项目
Xilinx/system-controller-c/boardui/ unable to connect to the development board, the solution of jamming after arbitrary operation
Flet教程之 03 FilledButton基础入门(教程含源码)(教程含源码)
分布式BASE理论
【R语言数据科学】:交叉验证再回首
MySQL8版本免安装步骤教程
JVM系列——栈与堆、方法区day1-2
.NET 使用 redis