Chisel 教程翻译 之 第五章:组合逻辑电路 of《Digital Design with Chisel》

6 篇文章 0 订阅
6 篇文章 1 订阅

5 Combinational Building Blocks 43
5.1 Combinational Circuits . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.2 Decoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  45
5.3 Encoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47
5.4 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48


5 Combinational Building Blocks
5 构建组合逻辑电路

In this chapter, we explore various combinational circuits, 
basic building blocks that we can use to construct more complex systems. 
本章我们将会深入研究几个组合逻辑电路,和基本的构建模块的方法,这些方法我们可以用在更加复杂的系统里面。

In principle, all combinational circuits can be described with Boolean equations. 
从原理上讲,所有的 组合逻辑电路都可以由布尔表达式来描写。

However, more often, a description in the form of a table is more efficient. 
然而,更加常见的,用真值表来描述电路时更加高效的。

We let the synthesize tool extract and minimize the Boolean equations. 
我们允许综合工具提取并化简布尔表达式。

Two basic circuits, best described in a table form, are a decoder and an encoder.
两个真值表描述得最好的基本电路,分别是解码器和编码器。

5.1 Combinational Circuits
5.1 组合逻辑电路

Before describing some standard combinational building blocks, 
we will explore how combinational circuits can be expressed in Chisel. 
在描述一些标准的组合构建块之前,我们将会探讨Chisel可以怎么样来表示一个组合逻辑电路。

The simplest form is a Boolean expression, which can be assigned a name:
表示组合逻辑电路的一个最简单的形式是使用一个布尔代数表达式,而且给这个表达式赋一个值。

val e = (a & b) | c

The Boolean expression is given a name (e) by assigning it to a Scala value. 
通过把表达式赋值给一个Scala常变量的方式,给它取了一名字。

The expression can be reused in other expressions:
这个表达式可以在其他表达式中重用,例如:

val f = ~e

Such an expression is considered fixed. 
这样的一个表示方式时固定的。

A reassignment to e with = would result in a Scala compiler error: reassignment to val. 
如果使用= 对e重新赋值,将会导致要给Scala编译器错误:reassiignment to val。


A try with the Chisel operator :=, as shown below,
如果使用Chisel的操作符 :=重新赋值,像如下这样:

e := c & b

results in a runtime exception: Cannot reassign to read-only.
将会导致一个运行时异常: Cannot reassign to read-only.

Chisel also supports describing combinational circuits with conditional updates. 
Chisel也支持表述基于条件更新的组合逻辑电路。

Such a circuit is declared as a Wire. 
这样的电路会被声明为一个Wire。

Then you uses conditional operations, such as when, to describe the logic of the circuit. 
然后你可以使用条件操作符,例如when,来表述电路的逻辑。
The following code declares a Wire w of type UInt and assigns a default value of 0. 
下面的代码声明了一个Wire类型的w变量,而且是UInt型的,将0作为默认赋值。

The when block takes a Chisel Bool and reassigns 3 to w if cond is true.B.
这个电路将会通过判断一个Chisel Bool来判断是否应该给w赋值为3.

val w = Wire(UInt())
w := 0.U
when (cond) {
w := 3.U
}

The logic of the circuit is a multiplexer, 
where the two inputs are the constants 0 and 3 and the condition cond the select signal. 
这个电路的逻辑功能是一个多路器,
两个输入是常量0和3,而且条件cond作为选择信号。

Keep in mind that we describe hardware circuits and not a software program with conditional execution.
需要绷住的一根弦儿是,我们用条件语句来描述硬件电路,而不是做软件编程。

The Chisel condition construct when also has a form of else, it is called otherwise.
Chisel条件语句除了when,还有else形式,他被称之为otherwise。

With assigning a value under any condition we can omit the default value assignment:
通过在任何情况下都可以赋一个值的方式,我们可以省略默认赋值。

val w = Wire(UInt())
    when (cond) {
        w := 1.U
    } otherwise {
        w := 2.U
    }

Chisel also supports a chain of conditionals (a if/elseif/else chain) with .elsewhen:
Chisel也支持条件链,一个if/elseif/else链,用.elsewhen实现,如下:


val w = Wire(UInt())
when (cond) {
    w := 1.U
} .elsewhen (cond2) {
    w := 2.U
} otherwise {
    w := 3.U
}

Note the ‘.’ in .elsewhen that is needed to chain methods in Scala. 
注意.elsewhen中的那个‘.’,他是为了构成Scala中的链方法。

Those .elsewhen branches can be arbitrary long. 
其中的.eslewhen分支可以由无限多个。

However, if the chain of conditions depends on a single signal, it is better to use the switch statement, 
which is introduced in the following subsection with a decoder circuit.
然而,如果一个条件链依赖于一个单独的信号,那么最好使用switch表达式,switch表达式将会用一个解码器电路在下面内容中介绍。

For more complex combinational circuits it might be practical to assign a default value to a Wire. 
对于更多的复杂组合电路,给要给Wire夫一个默认值应该是一种更实际的做法。

A default assignment can be combined with the wire declaration with WireDefault.
一个默认赋值可以与声明合写在一起,用WireDefault()函数来表示:

val w = WireDefault(0.U)

Figure 5.1: A 2-bit to 4-bit decoder.

Table 5.1: Truth table for a 2 to 4 decoder.


when (cond) {
w := 3.U
}

// ... and some more complex conditional assignments

One might question why using when, .elsewhen, and otherwise when Scala has if, else if, and else? 
可能会问,既然Scala中由if,else if,和else,为什么还要使用when,.elsewhen,以及otherwise呢?

Those statements are for conditional execution of Scala code, not generating Chisel (multiplexer) hardware. 
这些表达式是为条件地执行Scala代码而设计的,不是为生成Chisel多路器而设计的。

Those Scala conditionals have their use in Chisel when we write circuit generators, 
which take parameters to conditionally generate different hardware instances.
这些Scala条件表达式在用Chisel编写电路生成器时由他们自己的用处,可以通过参数来生成不同的硬件实例。

5.2 Decoder
5.2 解码器

A decoder converts a binary number of n bits to an m-bit signal, where m ≤ 2n. 
要给解码器把一个n位二进制数转换成要给mbite的信号,其中m<=2的n次幂。

The output is one-hot encoded (where exactly one bit is one).
输出值是独热码的。


Figure 5.1 shows a 2-bit to 4-bit decoder. 


We can describe the function of the decoder with a truth table, such as Table 5.2.
我们可以用一个真值表来描述这个解码器的功能,如表5.2.

A Chisel switch statement describes the logic as a truth table. 
Chisel的switch表达式可以描述这个真值表。

The switch statement is not part of the core Chisel language. 
switch表达式并不是Chisel语言核心的一部分。

Therefore, we need to include the elements of the package chisel.util._
所以,我们需要导入Chisel.util._才行。

import chisel3.util._

The following code introduces the switch statement of Chisel to describe a decoder:
下面代码表述了要给的解码器:

result := 0.U
switch(sel) {
    is (0.U) { result := 1.U}
    is (1.U) { result := 2.U}
    is (2.U) { result := 4.U}
    is (3.U) { result := 8.U}
}

The above switch statement lists all possible values of the sel signal 
and assigns the decoded value to the result signal. 
上面的switch表达式列出了sel的所有可能值,并且把对应的值赋值给了输出信号。

Note that even if we enumerate all possible input values,
 Chisel still needs us to assign a default value, as we do by assigning 0 to result.
注意,即使我们给出了输入的所有可能sel的值,Chisel仍然需要我们给输出事先赋一个默认值,就像我们赋了0给result。 
 
This assignment will never be active and therefore optimized away by the backend tool.
这个赋值将不起作用,因此它会被后端工具优化掉。
It is intended to avoid situations with incomplete assignments for combinational circuits (in Chisel a Wire) 
that will result in unintended latches in hardware description languages such as VHDL and Verilog. 
这是为了避免在组合逻辑电路赋值不完全的情形,这将导致违背初衷的意见锁存。
Chisel does not allow incomplete assignments.
所以,Chisel是不允许不完全赋值的。
In the example before we used unsigned integers for the signals. 
在之前的例子中,我们使用了无符号整数给信号赋值。
Maybe a clearer representation of an encode circuit uses the binary notation:
或许一个解码器电路可以用二进制数更清楚地表示成如下格式:

switch (sel) {
    is ("b00".U) { result := "b0001".U}
    is ("b01".U) { result := "b0010".U}
    is ("b10".U) { result := "b0100".U}
    is ("b11".U) { result := "b1000".U}
}

A table gives a very readable representation of the decoder function but is also a little bit verbose. 
真值表给出了解码器功能的很易读的表达方式,但是还是有一点啰嗦。

When examining the table, we see a regular structure: a 1 is shifted left by the number represented by sel. 
当检查表格时,我们看到了数据中的规律,每个值是把1向左以为了sel次。

Therefore, we can express a decoder with the Chisel shift operation <<.
所以,我们可以用左移操作符来表示这个解码器,如下所示:

result := 1.U << sel


Decoders are used as a building block for a multiplexer 
by using the output as an enable with an AND gate for the multiplexer data input. 
解码器可以用来构建多路器,把解码器的输出作为使能信号,跟多路器的数据输入共同作为与门的输入。

However, in Chisel, we do not need to construct a multiplexer, as a Mux is available in the core library. 
然而,在Chisel中我们不需要动手构建多路器,在核心库中有一个Mux可以声明多路器。

Decoders can also be used for address decoding, and then the outputs are used as select signals, e.g.,
different IO devices connected to a microprocessor.
解码器也可以用于地址译码,而且输出是作为选择信号的,例如,由不同的一些IO设备连接到了微处理器上。

5.3 Encoder
5.3 编码器

Figure 5.2: A 4-bit to 2-bit encoder.


Table 5.2: Truth table for a 4 to 2 encoder.

An encoder converts a one-hot encoded input signal into a binary encoded output signal.
一个编码器把一个独热码的输入转换成一个二进制编码的输出信号。

The encoder does the inverse operation of a decoder.
编码器是解码器的逆操作。

Figure 5.2 shows a 4-bit one-hot input to a 2-bit binary output encoder, 
and Table 5.3 shows the truth table of the encode function. 
图5.2显示了4比特独热码到2比特二进制的输出编码器,表5.3展示了编码函数的真值表。

However, an encoder works only as expected when the input signal is one-hot coded. 
然而,一个编码器只有在输入信号位独热码时才能够按照期待工作。

For all other input values, the output is undefined. 
对于其他所有的值,输出结果都是未定义的。

As we cannot describe a function with undefined outputs, 
we use a default assignment that catches all undefined input patterns.
因为我们无法描述一个输出未定义的功能,所以,我们使用默认的赋值,这样它会捕捉左右的未定义输入模式。

The following Chisel code assigns a default value of 00 and then uses the switch statement for the legal input values.
下面的Chisel代码给结果输出赋了一个默认的00值,并且用switch表达式来处理其他合法输入。

b := "b00".U
switch (a) {
    is ("b0001".U) { b := "b00".U}
    is ("b0010".U) { b := "b01".U}
    is ("b0100".U) { b := "b10".U}
    is ("b1000".U) { b := "b11".U}
}

5.4 Exercise
5.4 练习

Describe a combinational circuit to convert a 4-bit binary input to the encoding of a 7- segment display. 
描述一个组合电路,把4位二进制输入,编码成7段码显示。

You can either define the codes for the decimal digits, 
which was the initial usage of a 7-segment display or additionally, 
define encodings for the remaining bit pattern to be able to display all 16 values of a single digit in hexadecimal. 
你可以把4位输入定义成一个十进制数,这是7段码显示的最初用途,或者定义其余的比特模式编码,以便能够显式全部16个数字。

When you have an FPGA board with a 7-segment display, 
connect 4 switches or buttons to the input of your circuit and the output to the 7-segment display
如果你搞到了一个带有7段码显示器的FPGA板子,把4个开关或按钮连接到输入上,并且把输出连接到7段码显示器上。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值