數位邏輯
暫存器(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`)搞混,也別把它和你從軟體裡去讀寫的記憶體映射「控制暫存器」混為一談——那些都是用這種暫存器搭建出來的體系結構概念,而不是閘級那一排正反器本身。
又稱
另見