Skip to content

第六章 - 寄存器与寄存器传输

约 5689 个字 预计阅读时间 19 分钟

在数字系统中,数据通路和控制单元通常在设计的较高层次上出现。数据通路 (datapath) 包括数据处理逻辑和一组用于执行数据处理的寄存器。控制单元 (control unit) 由一些逻辑单元构成,它决定着数据通路处理数据过程中各种操作的顺序。

寄存器传输记号描述了基本数据处理行为,也称作微操作 (microoperation)。寄存器传输 (register transfer) 是指在寄存器之间、寄存器与存储器之间以及用过数据处理逻辑传输信息,由专门的传输硬件和称作总线 (bus) 的共享传输硬件一起实现。

寄存器与加载使能

一个寄存器包含一组触发器,由于每一个触发器可以保存一位信息,因此由 \(n\) 个触发器组成的 \(n\) 位寄存器就可以保存 \(n\) 位的二进制信息。一般而言,寄存器是指一组用于完成特定数据处理任务的触发器以及附加的组合门电路。其中,触发器用于锁存数据,而门电路则用于决定输入触发器的数据是还是经过转换的。

计数器 (counter) 是指在时钟脉冲的激励下,能遍历预先规定好的状态序列的一种寄存器。计数器中按某种方式连接起来的逻辑门使得计数器能够生成规定顺序的二进制状态序列。

Note

尽管计数器也算是一种特殊类型的寄存器,但一般而言,我们将其和寄存器区别对待。

将新信息传送至寄存器称作寄存器的加载 (loading) 操作。如果寄存器中所有位都是在公用时钟脉冲下同时加载的,那么我们称这种加载为并行加载。

我们以下图中的 4 位寄存器为例:

这个 4 位寄存器仅包含 4 个 D 触发器,没有额外的门电路。公用的 Clock 信号在每个脉冲的上升沿触发所有的触发器,此时二进制数据经过 4 个 \(D\) 输入端存入 4 位寄存器中,4 个 \(Q\) 输出端输出存在寄存器中的二进制数据。Clear 信号则用于异步地将寄存器清零。

并行加载寄存器

一般来说,时钟脉冲会经过所有的寄存器。但多数时候我们不希望所有寄存器的内容,在每一个时钟脉冲下都改变,因此一个常用的方法是阻止时钟到达寄存器的时钟输入端。

具体来说,我们用一个单独的控制信号 Load 来控制时钟脉冲对寄存器有影响的时钟周期,当不希望寄存器的内容改变时,就阻止时钟脉冲到达寄存器。在前文的 4 位寄存器中,就满足表达式

\[C\ \text{Input} = \overline{\text{Load}} + \text{Clock}\]

为了使电路正常工作,Load 必须在 Clock 为 \(0\) 期间稳定在正确值 \(0\)\(1\)。一种实现方法是使 Load 信号来自于时钟上升沿触发的触发器,系统中所有触发器都用时钟上升沿来触发。由于使在寄存器 \(C\) 输入利用逻辑门来控制始终开关,因此这种技术称作门控时钟 (clock gating)。

在时钟脉冲路径上通常存在其它门,这会导致在带有门控时钟和不带有门控时钟的触发器的 Clock 和输入之间产生不同的传输延时。如果时钟信号到达不同触发器或寄存器的时间不同,就会存在时钟偏移 (clock skew)。但是为了得到一个真正的同步系统,必须保证所有时钟脉冲同时到达,以保证所有触发器能同时触发。

一个带并行加载的 4 位寄存器如下所示:

可见,我们利用带有使能的 D 触发器,实现了「加载」这一功能。同时在这个电路中,所有触发器都是在同一个时钟的上升沿实现了数据从输入到寄存器的传输,这样做避免了时钟偏差,是优于传统的门控时钟方法的。

寄存器传输

在大多数数字系统设计中,我们将系统划分为两种模块:数据通路 (datapath) 和控制单元 (control unit),前者完成数据处理操作,后者决定这些操作的执行顺序。它们间的基本关系如下:

其中,控制信号 (control signal) 是二进制信号,用于激活各种各样的数据处理操作。为使这些操作按照顺序执行,控制单元传送正确的控制信号序列给数据通路。桶式控制单元接受来自数据通路的状态信息,这些状态信息描述了数据通路当前状态的各个方面,控制单元用状态信息来决定下一步执行的操作。

数据通路由一组寄存器以及对寄存器中所存储的二进制数的操作所定义。寄存器操作包括数据的装载、清除、移位和基数。寄存器是数字系统的基本单元。对寄存器中存储的数据进行移动和处理定义为寄存器传输操作 (register transfer operation)。

一个寄存器可以完成一个或多个基本操作 (elementary operation),比如加载、计数、加法、减法和移位。对寄存器存储数据执行的基本操作称为微操作 (microoperation)。

寄存器传输操作

我们先给出通常的记号。一般地,用大写字母(有时也带数字)来表示寄存器的功能,例如 \(AR\) 表示地址寄存器、\(PC\) 表示程序计数器。\(n\) 位寄存器中的单个触发器通常从 \(0\)\(n - 1\) 进行编号,从最低位 \(0\) 位向最高位递增。\(0\) 位位于最右端的编号称作小端 (little-endian) 格式存储;反之 \(0\) 位位于最左端的编号称作大端 (big-endian) 格式存储。寄存器的框图如下:

将数据从一个寄存器传输到另一个寄存器用符号 \(\gets\) 表示。语句 \(R2 \gets R1\) 表示将寄存器 \(R1\) 的内容传输到寄存器 \(R2\),此时称 \(R1\) (source) 寄存器,\(R2\)目的 (destination) 寄存器。传输的结果只会改变目的寄存器 \(R2\) 的内容,而不会改变源寄存器 \(R1\) 的内容。

对于有条件的的寄存器传输操作,可以用 if-then 形式的条件语句进行定义,其一般形式为 \(\text{if } (K_{1} = 1) \text{ then } (R2 \gets R1)\),此时称 \(K_{1}\) 为控制单元产生的控制信号。上述语句也可以简写为 \(K_{1}: R2 \gets R1\),表示只有当 \(K_{1} = 1\) 时传输操作才会被执行。

我们假设所有的传输操作都出现在时钟发生跳变的情况下,也就是说尽管控制条件可能在两次时钟发生跳变间就被激活,但实际的传输操作是在触发器被时钟的下一个上升沿才发生的。

我们给出全部寄存器传输使用的基本符号:

符号 含义 示例
字母(可带有数字) 代表一个寄存器 \(AR, R2, DR, IR\)
圆括号 代表寄存器的一部分 \(R2(1), R2(7:0), AR(L)\)
箭头 代表数据的传输 \(R1 \gets R2\)
逗号 隔开同时进行的传输操作 \(R1 \gets R2, R2 \gets R1\)
方括号 定义存储器的地址 \(DR \gets M[AR]\)

微操作

微操作是指对寄存器或存储器中的数据进行基本的操作。数字系统中常见的微操作可分为 4 种类型:

  1. 传输微操作:将二进制数据从一个寄存器传输到另一个寄存器
  2. 算术微操作:对寄存器中的数据进行算术操作
  3. 逻辑微操作:对寄存器中的数据进行位操作
  4. 移位微操作:对寄存器中的数据进行移位
Note

一个位操作可能不只属于一种微操作类型,例如,求反操作既是算术微操作,也是逻辑微操作。

算数微操作

可以注意到,我们没有直接定义减法运算的微操作,而是用加补码的方式定义减法运算。

逻辑微操作

移位微操作

移位微操作用于数据的横向移动。源寄存器的内容可以向右或向左移位,左移 (left shift) 是向高位移位,右移 (right shift) 是向低位移位。

对单个寄存器的微操作

由于一个存储单元与微操作联系紧密,我们将实现微操作的组合逻辑当作寄存器的一部分,称作寄存器专用逻辑 (dedicatedd logic)。而针对目的寄存器组来实现微操作的组合逻辑称作共享逻辑 (shared logic)。

基于多路复用器的传输

在某些电路中,寄存器能够在不同时刻接受来自两个甚至多个不同源的数据。此时我们一般用 if-then-else 这样的条件语句进行表示,例如:

\[\text{if } (K_{1} = 1) \text{ then } (R0 \leftarrow R1) \text{ else if } (K_{2}) = 1 \text{ then } (R0 \leftarrow R2)\]

这等价于

\[K_{1}: R0 \leftarrow R1, \overline{K_{1}} K_{2}: R0 \leftarrow R2\]

这一传输一般使用多路复用器实现,其对应的电路框图为:

显然这样的设计可以扩展到具有 \(n\) 个源的多路复用器。

移位寄存器

具有单向或双向移动存储数据功能的寄存器称作移位寄存器 (shift register)。一个移位寄存器有一系列的触发器组成,每一个触发器的输出连接下一触发器的输入,所有触发器使用相同的时钟脉冲输入来触发移位操作。

下图是一个最简单的移位寄存器:

在该移位寄存器中,每一触发器的输出都直接连接到其右端下一触发器输入 \(D\) 上,串行输入 (serial input) 信号 \(SI\) 连接到最左端的触发器输入上,串行输出 (serial output) 信号 \(SO\) 从最右端的触发器的输出端上引出。

具有并行加载功能的移位寄存器

如果一个移位寄存器的所有触发器输出都是可访问的,那么通过串行移位操作进入的信息就可以从触发器的输出端并行读出。如果一个移位寄存器具有并行加载功能,那么并行进入的数据同样能够串行地是移位输出。因而,具有可访问的触发器输出以及并行加载的移位寄存器能够用于实现并行输入数据到串行输出数据的转换,反之亦然。

下图是一个具有并行加载功能的 4 位移位寄存器的逻辑图以及符号表示:

根据电路图,不难得到该寄存器可执行的操作为:

Shift Load 操作
0 0 没有变化(保持)
0 1 加载并行数据
1 × 按从 \(Q_{0}\)\(Q_{3}\) 的顺序左移

用语句定义即为:

\[\text{Shift}: Q \leftarrow \text{sl } Q \\ \overline{\text{Shift}} \cdot \text{Load}: Q \leftarrow D\]

双向移位寄存器

只具有单向移位功能的寄存器称作单向移位寄存器 (unidirectional shift register),具有双向移位功能的寄存器称作双向移位寄存器 (bidirectional shift register)。

下图是双向移位寄存器中某一集的逻辑图以及符号表示:

根据电路图,不难得到该寄存器可执行的操作为:

\(S_{1}\) $$S_{0} 操作
0 0 保持不变
0 1 向左移位
1 0 向右移位
1 1 并行加载

用语句定义即为:

\[\overline{S_{1}} \cdot S_{0}: Q \leftarrow \text{sl } Q \\ S_{1} \cdot \overline{S_{0}}: Q \leftarrow \text{sr } Q \\ S_{1} \cdot S_{0}: Q \leftarrow D\]

计数器

能够在输入脉冲序列的激励下遍历指定状态序列的寄存器称作计数器 (counter)。计数器可分为两种类型:行波计数器和同步计数器。在行波计数器中,某些触发器输出值的跳变可以改变其他一些触发器中的值。也就是说,加载到某些触发器 \(C\) 输入端的值不是公用的时钟脉冲,而是其它触发器的输出信号。而在同步计数器中,所有触发器的 \(C\) 输入端都是加载的公用时钟脉冲,并且计数器下一状态的值取决于其当前所处的状态。

行波计数器

下图是一个 4 位的二进制行波计数器。

据图可以看出,该计数器由 4 位 \(D\) 触发器串联组合而成,每一个触发器在其 \(C\) 输入信号的上升沿改变自身的状态。触发器的反向输出连接到下一个触发器的 \(C\) 输入,而处于最低位触发器的 \(C\) 输入则加载输入的时钟脉冲。加载到触发器 \(R\) 输入的复位信号为 \(1\) 时,触发器将异步清零。

行波计数器的优点是硬件实现简单。但遗憾的是,它是一种异步时序电路,当逻辑级增加时,将增大电路的时延,并将增加电路操作的不稳定性,这在那些从计数器输出到计数器输入存在反馈路径的逻辑电路中体现得尤为明显。同时,信号在电路中以行波方式前进需要很长时间,这使得位数较多的行波计数器的工作频率会很慢。因此,同步计数器在几乎所有方面都较行波计数器有优势。唯一的例外是行波计数器相较同步计数器功耗更低。

同步计数器

与行波计数器不同,同步计数器在所有触发器的 \(C\) 输入端口都加载公用的时钟信号。这样,同一个时钟脉冲将同时触发所有的触发器,不同于行波计数器中那样每次仅触发一个触发器。

下图是 4 位同步二进制计数器的逻辑图与符号表示:

一般来说,同步计数器有两种设计方式,即为图中的串行和并行。

在图 a 中,一条二输入与门链用于为计数器中的每一级提供其前一级的状态信息这与行波进位加法器中的进位逻辑类似。使用这种逻辑的计数器称作带有串行门控 (serial gating) 功能,因此其也称为串行计数器 (serial counter)。

由于与行波进位加法器相似,这意味着串行计数器中可能存在有类似于先行进位加法器的计数器逻辑。这种逻辑可以通过简化先行进位加法器得到,其结果即为图 b 所示。这种设计称作计数器中的并行门控 (parallel gating),对应的计数器就称作并行计数器 (parallel counter)。这种设计的优势在于信号时延减小,可以使计数器以更快的速度工作。

通过将若干并行计数器连接,即可得到更多位数的并行计数器。通过这种方法,可以扩展产生任意长度的计数器。

具有并行加载功能的计数器

数字系统中的计数器一般需要具有并行数据加载功能,用于在正式开始计数之前加载计数初始值。下图即为具有并行加载功能的 4 位二进制计数器。

其它类型计数器

自然地,通过设置并行加载的载入值和载入条件,即可得到一定范围内的循环计数器。如果不满足于从 0 开始的计数方式,也可以通过推到状态表进行修改。因此更一般地说,基于以上基本的计数器结构,并利用时序电路的设计方式,即可得到任意计数序列的计数器。

寄存器单元设计

将一位的迭代组合电路单元与一个触发器连接起来就构成一个具有两个状态的时序电路,称之为寄存器单元 (register cell)。

根据触发器的输出是否作为其迭代电路的输入信号,寄存器单元的下一状态可由其当前状态和输入信号共同决定,或仅仅由输入信号决定。如果仅由输入信号决定,那么可以先直接设计迭代组合电路然后将它与触发器相连即可。但是,如果触发器的状态输出作为反馈连接到了迭代电路单元的输入,那么也可以采用时序设计的方法对寄存器进行设计。

基于多路复用器和总线的多寄存器传输

一个典型的数字系统中包含有多个寄存器,在不同的寄存器之间必然存在着传输数据的通路。如果每个寄存器都使用专用的多路复用器,那么逻辑电路的大小和连线数量将十分的巨大。在不同寄存器之间传输数据更为有效的方案是使用一种称为总线 (bus) 的共享传输通路。总线的特征在于它是一组通用连线,每根连线由选择逻辑来驱动。在每一个传输时钟周期中,选择逻辑的控制信号会为总线选择一个源器件和一个或多个目的器件。

构造总线主要有两种形式:多路复用器总线和三态总线。

多路复用器总线

采用多路复用器和具有并行加载功能的寄存器可以实现具有多个来源的寄存器传输操作。传统的电路需要为每个寄存器提供一个专用的多路复用器,但如果使用一个公共通路使得多路复用器的输出为多个寄存器所共享,那么这些输出线就称作总线。下图即展示了两者架构的差别:

同时,我们给出该电路采用总线时的寄存器传输:

可以看到,使用单总线代替专用多路复用器,会降低硬件开销,但同时限制了并行传输操作的实现。

高阻态输出

另一种构建总线的方法是采用称为三态缓冲器 (three-state buffer) 的一类逻辑门,它提供称作高阻态 (high-impedane state) 的第三种输出值,用 Hi-Z 或者简单地用 Z 或 z 表示。

带有 Hi-Z 输出能力的门有两个重要的性质。首先,Hi-Z 输出可以互联,但不允许有两个或两个以上的门在同一时刻输出逻辑 0 和逻辑 1 两个相反的值。与此相反,只能输出逻辑 0 和逻辑 1 的门不能将它们的输出连在一起。其次,处在 Hi-Z 状态的输出端相当于开路,可以连接一个输入到电路内部,所以 Hi-Z 输出既可以作为输入又可以作为输出,称之为双向输入 / 输出。

三状态逻辑输出三种不同的状态,其中两种状态时常见的逻辑 1 和逻辑 0,第三个状态是高组织,称作高阻态。三态缓冲器的图形符号和真值表如下图所示:

由真值表可知,当 EN\(1\) 时,OUTIN 一致,三态缓冲器和普通缓冲器作用一致。但当 EN\(0\) 时,输出结果总为高阻态。

三态总线

在构建总线时,我们也可以使用三态缓冲器来取代原本所使用的多路复用器,以潜在地进一步减少连接的数量。一个示例如下图:

可以发现,多个三态缓冲器的输出可以连接在一起形成一位总线,而这个总线可以仅通过一级逻辑门实现。同时,对多路复用器而言,大量的数据源意味着很高的或门扇入系数,而这就需要多级的或门驱动,从而导致需要消耗更多的逻辑资源和更长的信号时延。与此相反三态缓冲器提供了一个更为实际的方式来构建具有多数据源的快速总线。更重要的是,三态总线上的信号是可以双向传输的。因此,三态总线可以通过相同的连接将信号引入或者引出逻辑电路。

寄存器传输控制

一个常用的数据通路和控制单元的设计过程,是对数据通路和控制单元的行为都采用状态机图或者状态机图加寄存器传输列表的组合方式进行描述。具体来说,这需要遵循如下步骤:

  1. 写出一个详细的系统说明书。
  2. 定义所有的外部数据和控制输入信号,所有数据、控制和状态输出信号,以及数据通路和控制单元中的寄存器。
  3. 画出系统的状态机图,其中包括数据通路和控制单元的寄存器传输情况。
  4. 定义内部控制和状态信号。使用这些信号将输出状态和输出行为以及寄存器传输从状态流程图中分开,再以表格的形式进行描述。
  5. 画一个包含了所有控制和状态输人、状态输出的数据通路的模块图。如果系统中包含有寄存器传输硬件,再画一个控制单元的模块图。
  6. 设计控制和数据通路两者专门的寄存器传输逻辑。
  7. 设计控制单元逻辑。
  8. 核实数据通路和控制单元结合在一起后系统操作的正确性。如果发现错误,则排除故障后重新进行核实。