Altifigence Academy

3 / 24 · 實作

實作:八位元 ALU 參考模型

以獨立可執行程式檢查 ADD、SUB、AND、XOR、進位與借位。

讓數值契約可以執行

這個實作用 JavaScript 整數模擬組合 ALU。運算元範圍為 0 到 255,操作碼為 0 到 3。輸出 y 永遠可容納於八位元。旗標代表 ADD 進位或 SUB 借位,邏輯操作則為零。在此介面中,a 小於 b 時,借位為一。其他架構可能對減法旗標採用不同定義;我們的契約則明確指定。

建立本機資料夾,或在 Digital Design Studio 中手動建立空白專案並加入 alu-model.mjs。儲存下列檔案。在已安裝 Node.js 的終端機中,進入該資料夾並執行 node alu-model.mjs。在 DDS 中編輯檔案與執行 JavaScript 是兩個獨立動作。不需要安裝套件,也不需要自動匯入功能。

javascript
import assert from 'node:assert/strict';
function alu(a, b, op) {
  if (op === 0) {
    const wide = a + b;
    return { y: wide & 255, flag: Number(wide > 255) };
  }
  if (op === 1) return { y: (a - b) & 255, flag: Number(a < b) };
  if (op === 2) return { y: a & b, flag: 0 };
  if (op === 3) return { y: a ^ b, flag: 0 };
  throw new RangeError('operation');
}
assert.deepEqual(alu(250, 10, 0), { y: 4, flag: 1 });
assert.deepEqual(alu(3, 5, 1), { y: 254, flag: 1 });
assert.deepEqual(alu(170, 204, 2), { y: 136, flag: 0 });
assert.deepEqual(alu(170, 204, 3), { y: 102, flag: 0 });
let checks = 0;
for (let a = 0; a < 256; a++) {
  for (let b = 0; b < 256; b++) {
    const add = alu(a, b, 0), sub = alu(a, b, 1);
    assert.equal(add.y + 256 * add.flag, a + b);
    assert.equal(sub.y - 256 * sub.flag, a - b);
    assert.equal(alu(a, b, 2).y | alu(a, b, 3).y, a | b);
    checks += 3;
  }
}
console.log(`ALU PASS: ${checks} identities`);

對 250+10 而言,y=4 與 carry=1 可以重建 260。對 3-5 而言,y=254 與 borrow=1 可以重建 -2。170 的二進位表示是 10101010,204 是 11001100:AND 得到 136,XOR 得到 102。迴圈會遍歷全部 65536 組運算元配對,每組檢查三個恆等式。成功執行時會回報 196608 次檢查。

參考模型應採用與 RTL 不同的方法。若硬體從九位元加法器擷取進位,本模型便檢查數學範圍。這能減少共同實作錯誤。這些檢查不評估 HDL 的 X/Z 值、傳播時序或時脈行為。實作 RTL 時,應將這些測試向量重用於模擬器。除了資料,也要比較旗標;正確的回繞位元可能掩蓋錯誤的邊界旗標。

自己試試看

若 SUB 一律傳回 flag=0,哪個數值恆等式會失敗?手算 a=0、b=1,並還原正確實作。

查看解說

y 是 255。當 flag=0 時,y-256×flag 為 255,而非 -1,因此減法重建失敗。當 borrow=1 時,255-256=-1。只檢查 y 會漏掉這個錯誤。

Lesson files

alu-model.mjs ↓

此選擇適用於本瀏覽器,隨時可從頁尾變更。