woai3c / nand2tetris

计算机系统要素-从零开始构建现代计算机
MIT License
2.65k stars 441 forks source link

终于找到答案了./... #1

Closed plh97 closed 5 years ago

plh97 commented 5 years ago

CPU.hdl

woai3c commented 5 years ago

一共12章所有项目答案都有

plh97 commented 5 years ago

...但是我没看懂, 有没有什么技巧,可以让我能够看懂,完全没有思路去如何实现一个CPU


CHIP CPU {

    IN  inM[16],         // M value input  (M = contents of RAM[A])
        instruction[16], // Instruction for execution
        reset;           // Signals whether to re-start the current
                         // program (reset==1) or continue executing
                         // the current program (reset==0).

    OUT outM[16],        // M value output
        writeM,          // Write to M? 
        addressM[15],    // Address in data memory (of M)
        pc[15];          // address of next instruction

    PARTS:
    // 指令的最大地址位 如果为1则是C指令 为0则是A指令
    Not(in = instruction[15], out = isA);
    // 对isC再次取返 判断是否C指令 读者可以自行用1或0代入想像一下 isC实际上就是instruction[15]的值
    Not(in = isA, out = isC);

    // 如果是C指令并且指令指定ALU输出存到AR 则将ALU的输出 输入到AR 否则将指令输入到AR
    And(a = isC, b = instruction[5], out = isLoadAluOut);
    Mux16(a = instruction, b = outALU, sel = isLoadAluOut, out = inAR);

    // 如果为A指令或指令指定输出到A处理器 则将AR的load位置1
    Or(a = isA, b = instruction[5], out = isLoadAR);
    ARegister(in = inAR, load = isLoadAR, out = outAR, out[0..14] = addressM);

    // 根据指令中的a位域判断将AR的输出或者inM输入到ALU
    Mux16(a = outAR, b = inM, sel = instruction[12], out = outAM);

    // 如果是C指令并且规定写入到M
    And(a = isC, b = instruction[3], out = writeM);

    // 如果是C指令并且规定写入到DR
    And(a = instruction[4], b = isC, out = isLoadDR); 
    DRegister(in = outALU, load = isLoadDR, out = outDR);

    And(a = isC, b = instruction[6], out = no);
    And(a = isC, b = instruction[7], out = f);
    And(a = isC, b = instruction[8], out = ny);
    And(a = isC, b = instruction[9], out = zy);
    And(a = isC, b = instruction[10], out = nx);
    And(a = isC, b = instruction[11], out = zx);

    ALU(x = outDR, y = outAM, zx = zx, nx = nx, zy = zy, ny = ny, f = f, no = no, out = outALU, out = outM, zr=zr, ng=ng);

    // 根据j位域和ALU的zr、ng位来判断跳转
    And(a = isC, b = instruction[0], out = isGT);
    And(a = isC, b = instruction[1], out = isEQ);
    And(a = isC, b = instruction[2], out = isLT);

    And(a = ng, b = isLT, out = isLtJump);
    And(a = zr, b = isEQ, out = isEqJump);

    // 输出是否大于0
    Not(in = ng, out = notNg);
    Not(in = zr, out = notZr);
    And(a = notNg, b = notZr, out = isOutGt);

    And(a = isOutGt, b = isGT, out = isGtJump);

    Or(a = isLtJump, b = isEqJump, out = isJump);
    Or(a = isJump, b = isGtJump, out = jump);

    PC(in = outAR, load = jump, inc = true, reset = reset, out[0..14] = pc);
}