Learning Objectives
- 說出 UC8 資料路徑上每個零件存什麼、資料怎麼在它們之間移動
- 用暫存器轉移表示法(例如 ACC ← ACC + MDR)描述一拍做的事
- 自己按控制訊號,把兩個記憶體裡的數相加並存回記憶體
- 說明同一拍兩個來源上匯流排為什麼不行,以及單一匯流排的取捨
零件都有了,資料要怎麼走
記憶體第 4 格放著 12,第 5 格放著 30。你想把它們相加,結果存進第 6 格。
前面幾課你已經做過會加法的 ALU、記得住值的暫存器,也知道記憶體是一張用位址選列的表。可是這些零件各自獨立:ALU 的輸入怎麼拿到記憶體裡的 12?算完的結果又怎麼回到記憶體?
把存放資料與運送資料的零件接起來,就叫資料路徑(datapath)。這一課和接下來兩課都用 UC8:這條課程自己設計的教學用處理器,8 位元、32 格記憶體、10 條指令,不是市面上任何一顆真實的處理器。它的資料路徑有這些零件:
| 零件 | 存什麼 |
|---|---|
| PC(程式計數器) | 下一條指令的位址 |
| IR(指令暫存器) | 正在執行的指令;前 3 位元是運算碼,後 5 位元是位址 |
| MAR(記憶體位址暫存器) | 接下來要存取記憶體的哪一格 |
| MDR(記憶體資料暫存器) | 從記憶體讀來的值,或準備寫出去的值 |
| ACC(累加器) | 計算的結果 |
| ALU | 不存東西。輸入固定接 ACC 和 MDR,算出加法或減法 |
這一課起不再一條一條接線。 模擬器換成暫存器轉移層級(register transfer level,RTL),只看「這一拍哪個暫存器的值移到哪裡」,不模擬裡面的閘。原因很實際:8 位元的資料路徑要接幾百條線,手接的話,你會花所有時間在對線,看不到資料的流動。最後一個練習會回到閘級,讓你接匯流排的其中 1 個位元,確認每一條線其實都是前面學過的東西。
匯流排與控制訊號
UC8 的暫存器不是兩兩相連,而是全部接到同一組線上,這組線叫匯流排(bus)。每個暫存器有兩個開關:
- 送上匯流排:把自己的值放到線上
- 接收:下一個時脈上升緣,把線上的值存進來
這些開關就是控制訊號(control signal)。控制訊號決定這一拍誰說話、誰聽。同樣的硬體,開不同的訊號就做不同的事。
描述一拍做了什麼,有一種簡潔的寫法叫暫存器轉移表示法:
MAR ← PC PC 送上匯流排,MAR 接收
MDR ← 記憶體[MAR] 記憶體把 MAR 指的那一格送到 MDR
ACC ← ACC + MDR ALU 把結果送上匯流排,ACC 接收
箭頭的意思是「這一拍結束時的時脈邊緣,左邊的暫存器存進右邊的值」。第三行的 ACC 同時出現在兩邊,看起來像是繞了一圈,但暫存器是正反器,只在上升緣取樣一次,所以 ACC 只會加一次,不會加了又加。如果 ACC 是栓鎖(第 7 課),透明期間結果會立刻繞回 ALU,這一行就不能這樣設計。
同一拍的轉移,右邊讀到的都是舊值
所有暫存器在同一個時脈邊緣更新,所以同一拍可以寫兩個轉移,右邊讀到的都是這一拍之前的值。Python 的賦值是一行一行做的,要用兩個步驟才模擬得出來。注意中間「一個一個改」為什麼會出錯。
為什麼同一拍只能有一個來源
剛才模擬擋下了那一拍。擋下的理由是物理上的:同一條線上,如果一個輸出推 1、另一個輸出推 0,就等於短路。電流會直接從電源流到地,線上的電壓不確定,零件也可能損壞。
真實的匯流排有兩種常見做法:
- 三態輸出(tri-state):輸出除了 0 和 1,還可以斷開。沒輪到的暫存器全部斷開,線上只有一個人在推。
- 多工器:所有來源都接到一個大多工器,由選擇訊號決定誰的值接到匯流排。這樣在硬體上根本不可能兩個一起上,晶片內部常用這種做法。
反過來,同一拍可以有很多接收者:一個值可以同時存進好幾個暫存器。而 PC 加 1 有自己的計數線路、記憶體讀取走 MDR 的專用線,都不佔匯流排,所以 IR ← MDR 和 PC ← PC + 1 可以同一拍做。
單一匯流排的取捨:線少、零件少,代價是一拍只能搬一筆資料。LDA 要先把位址搬到 MAR,再讀記憶體,再把值搬到 ACC,這三件事排隊做。如果有第二條匯流排,有些步驟就能併成一拍,一條指令的拍數變少,但線路和多工器都要多一份。真實處理器內部的路徑遠比 UC8 多,用面積換速度。
回到閘級看 1 個位元
RTL 是為了看得清楚,不是因為裡面有魔法。把匯流排的其中 1 個位元拆開來,只用前面學過的兩種零件:
- 選來源:多工器(第 4 課),
SEL決定 A 還是 B 的值接到匯流排 - 收資料:D 正反器前面接一個多工器(第 8 課)。
LOAD是 1 時,正反器存匯流排的值;LOAD是 0 時,把自己的 Q 接回 D,值就維持不變
SEL 和 LOAD 就是控制訊號。把這一片複製 8 份、控制訊號接在一起,就是 8 位元的匯流排與暫存器。
確認一下
這一拍開了「ACC 送上匯流排」和「MDR 接收」。寫成暫存器轉移是?
MAR 是 6、MDR 是 42、ACC 是 12。這一拍只開「MDR 寫進記憶體」,結束後第 6 格是多少?
ACC ← ACC + MDR 這一拍,ACC 為什麼只加一次?
有人提議把 MDR 和 ACC 同時送上匯流排,由接收端自己決定要誰。這樣會發生什麼?
把 UC8 的單一匯流排改成兩條,主要的好處和代價是?
重點整理
- 資料路徑是存資料與運送資料的零件接起來的結果;UC8 用一條匯流排連接 PC、IR、MAR、MDR、ACC 與 ALU。
- 控制訊號決定這一拍誰送上匯流排、誰接收。硬體不變,開不同的訊號就做不同的事。
- 暫存器轉移表示法描述一拍做的事;所有暫存器在同一個時脈邊緣更新,右邊讀到的都是舊值。
- 同一拍只能有一個來源,但可以有多個接收者;單一匯流排省線路,代價是一拍只搬一筆資料。
- 每一條線還是閘與正反器:RTL 只是讓人看得清楚的描述方式。
剛才每一拍都是你在開訊號,還要自己讀 IR 判斷下一步。下一課把這件事交給電路:控制單元。