当前位置:网站首页>吃透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里面还提供了更多的组件和控制抽象,能让我们在描述一个组合电路的时候更优雅,相关内容后面详细说!
边栏推荐
猜你喜欢
德明利深交所上市:市值31亿 为李虎与田华夫妻档
安装trinity、解决报错
Interviewer: what is the internal implementation of hash data type in redis?
博士申请 | 西湖大学学习与推理系统实验室招收博后/博士/研究实习等
ViewBinding和DataBinding的理解和区别
JVM 内存布局详解,图文并茂,写得太好了!
When MDK uses precompiler in header file, ifdef is invalid
Understanding and difference between viewbinding and databinding
中邮科技冲刺科创板:年营收20.58亿 邮政集团是大股东
免费、好用、强大的轻量级笔记软件评测:Drafts、Apple 备忘录、Flomo、Keep、FlowUs、Agenda、SideNote、Workflowy
随机推荐
国内酒店交易DDD应用与实践——代码篇
C语言宿舍管理查询软件
unity不识别rider的其中一种解决方法
Haproxy high availability solution
Optional values and functions of the itemized contenttype parameter in the request header
舔狗舔到最后一无所有(状态机)
Variable promotion and function promotion in JS
C语言程序设计选题参考
Getting started with microservices
【R语言数据科学】:交叉验证再回首
One of the solutions for unity not recognizing riders
C语言课程设计题
Introduction to XML II
C language Dormitory Management Query Software
DGraph: 大规模动态图数据集
锐成芯微冲刺科创板:年营收3.67亿拟募资13亿 大唐电信是股东
C foundation in-depth learning II
2022 hoisting machinery command examination simulation 100 questions simulation examination platform operation
2022年起重机械指挥考试模拟100题模拟考试平台操作
In 2022, it will be es2022 soon. Do you only know the new features of ES6?