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 是兩個獨立動作。不需要安裝套件,也不需要自動匯入功能。
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 會漏掉這個錯誤。