Altifigence Academy

3 / 24 · 实验

实验:八位 ALU 参考模型

在独立可执行程序中检查 ADD、SUB、AND、XOR、进位和借位。

让数值约定可以执行

本实验使用 JavaScript 整数建立组合 ALU 模型。操作数范围为 0 到 255,操作码为 0 到 3。输出 y 始终能用八位表示。flag 表示 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 ↓

你的选择适用于此浏览器,可随时在页脚更改。