Nand2Tetris Memory芯片实现无限循环问题排查求助
问题分析:Memory芯片键盘读取失效的原因
你第二个实现的核心问题,是把**“地址是否属于键盘区域”和“是否要向键盘写入”**这两个完全无关的信号搞混了,导致读取键盘时永远拿不到正确的输入,触发了测试中的无限循环。
先看正确逻辑里的canBeKbd
在第一个能正常工作的实现中,canBeKbd是这么生成的:
And(a=address[13], b=address[14], out=canBeKbd);
这个信号的唯一作用是判断当前访问的地址是不是键盘的专属地址——键盘的基地址是0x6000(二进制1100000000000000),对应地址的第13、14位(从0开始计数)都是1。这个判断只和地址有关,和load信号完全没关系,因为键盘是只读设备,读取它根本不需要load。
再看你错误实现的问题
你在第二个实现里,把DMux4Way的d输出直接赋值给了canBeKbd:
DMux4Way(in=load, sel=address[13..14], a=ram1, b=ram2, c=loadScreen, d=canBeKbd);
DMux4Way的作用是根据地址最高两位,把load信号分配给不同的存储设备:只有当地址最高两位是11(键盘区域)且load为1时,d输出才是1,其他情况都是0。
但问题来了:
- 测试中读取键盘的时候,
load信号是0(因为是读操作,不是写),这时候d输出就是0,导致后续的isKbd(And(a=canBeKbd, b=allZero012))永远为0。 - 最后那个
Mux16就会选择false(全0)作为outKbd,而不是实际的键盘输入值。程序一直读不到Y键的输入,自然就陷入无限循环了。
正确的做法总结
canBeKbd必须由地址的最高两位做与运算得到,只用来判断地址是否属于键盘区域,和load无关;DMux4Way的d端口应该是一个被忽略的信号(比如命名为ignored,像第一个实现那样),因为键盘是只读的,永远不需要执行写入操作。
内容的提问来源于stack exchange,提问作者Thiago Miranda




