数字逻辑

寄存器(register)

可以把寄存器想成芯片内部的一块小白板——宽度刚好够写下一个数,而且整排数字一笔就能改写完。单个触发器只能记住一个比特,而寄存器把 N 个触发器并排排好,让它们一起存住一个 N 位的值:8 位寄存器存一个字节,32 位寄存器存一个典型的机器字。它是芯片的短期记忆——一个值从被算出来、到被下游某处取走之间,就暂住在这里。

寄存器之所以不只是一把散落的触发器,是因为它们共用同一个时钟。在每个有效时钟边沿,每一位都(名义上)在同一瞬间抓取自己的输入,并一直保持稳定到下一个边沿,于是整个字一起更新——你绝不会看到一半旧、一半新的比特,前提是每个输入在该边沿前后的建立-保持窗口内都保持稳定。两次边沿之间,输入可以随意地穿过周围的组合逻辑来回摆动;只有边沿那一刻呈现的值才会被抓取。正是这种干净利落的「每拍采样一次、然后冻结」的行为,才让流水线能每个周期向前推进一级数据,而各级之间互不绊脚。

实践中你很少手工实例化触发器。在 RTL 里,你通过在一个时钟驱动的进程内对信号赋值来描述一个寄存器,综合工具会替你推断出触发器。真实的寄存器通常还带几样额外功能:一个复位信号,用来强制一个已知的起始值(可以是同步复位,在时钟边沿生效;也可以是异步复位,立即生效);往往还有一个时钟使能,让寄存器在你不想让它载入的周期里保持当前值——使设计的其余部分得以暂停或跳过,而不扰动已存下的内容。

// 8-bit register with synchronous reset and clock-enable
module reg8 (
  input        clk,
  input        rst,   // synchronous, active-high
  input        en,    // clock-enable
  input  [7:0] d,
  output reg [7:0] q
);
  always @(posedge clk)
    if (rst)      q <= 8'd0;   // clear to a known value
    else if (en)  q <= d;      // load d, otherwise hold q
endmodule

一个 8 位寄存器——在每个时钟上升沿,它要么清零、要么载入新数据、要么保持当前值。

别把这种硬件寄存器和有名字的 CPU 寄存器(比如程序员看到的 `R0`–`R31`)搞混,也别把它和你从软件里去读写的内存映射「控制寄存器」混为一谈——那些都是用这种寄存器搭建出来的体系结构概念,而不是门级那一排触发器本身。

又称
registerhardware registerdata registerparallel register寄存器暫存器