admin管理员组

文章数量:1291395

I am trying to implement CPU architecture in the NAND2Tetris Project5, but I don't understand why the D register output always remains 0. On the visualization tab I can clearly see Register D value updating betweeen clocks but that does not reflect on difference table. I am using the NAND2Tetris Online hardware simulator; the A register value is is being updated as expected only D register is having issues.

Here is the code I used:

// This file is part of www.nand2tetris
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/5/CPU.hdl
/**
 * The Hack Central Processing unit (CPU).
 * Parses the binary code in the instruction input and executes it according to the
 * Hack machine language specification. In the case of a C-instruction, computes the
 * function specified by the instruction. If the instruction specifies to read a memory
 * value, the inM input is expected to contain this value. If the instruction specifies
 * to write a value to the memory, sets the outM output to this value, sets the addressM
 * output to the target address, and asserts the writeM output (when writeM = 0, any
 * value may appear in outM).
 * If the reset input is 0, computes the address of the next instruction and sets the
 * pc output to that value. If the reset input is 1, sets pc to 0.
 * Note: The outM and writeM outputs are combinational: they are affected by the
 * instruction's execution during the current cycle. The addressM and pc outputs are
 * clocked: although they are affected by the instruction's execution, they commit to
 * their new values only in the next cycle.
 */
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:
    //// Replace this comment with your code.
    //A contents: if A-instruction, A reg--> instruction i.e @32, else A reg=computation(cmp) A=xxx;
    Mux16(a=instruction, b= ALUtoMux16output, sel=instruction[15], out=ALuoutputorInstselect);
    //load control bit logic for A-register:e.g @32 needs inst[15]=0(A-inst), A=D-M, needs bit d1 to be enabled
    //reg a is loaded always except when whe have c instruction, and d=0 (A=1, D=0 -->load=0)
    Nand(a=instruction[15], b=notd1, out=loadAregister); 
    //A register
    Register(in=ALuoutputorInstselect, load=loadAregister, out=AregistertoMux16output,
     out=Aregisteroutput2, out[0..14]=addressM, out=AregistertoPCoutput);
    /*to select between A and M inst must be a C-instruction first, then a bit
     selects betweeen A and M (else A register content will be selected)*/
    And(a=instruction[15], b=instruction[12], out=aAndm);
    Mux16(a=AregistertoMux16output, b=inM, sel=aAndm, out=AorMselect); //e.g D=A-D or D=A-M
    /*D-register: 
        to load  D reg, inst must b=C-inst(A=1) and d2 enabled*/
    And(a=instruction[15], b=instruction[4], out=Dregisterload);  
    Register(in=ALUtoDregisteroutput, load=Dregisterload, out=Dregisteroutput); 

    ALU(x=Dregisteroutput, y=AorMselect,zx=instruction[11], nx=instruction[10],
                 zy=instruction[9], ny=instruction[8], 
                f=instruction[7],no=instruction[6],
                out=ALUtoMux16output, out=ALUtoDregisteroutput, out=outM,
                 zr=ALUzr, zr=ALUzrtojeq, zr=ALUzrtojle,
                ng=ALUng, ng=ALUngtojlt);
    //jump logic
    Not(in=ALUng, out=notALUngtojgt, out=notALUngtojeq);
    Not(in=ALUzr, out=notALUzrtojgt, out=notALUzrtojne);
    Not(in=instruction[5], out=notd1);
    Not(in=instruction[15], out=nota); //detecting a instruction
    Not(in=instruction[2], out=notj1temp1, out=notj1temp2);
    Not(in=instruction[1], out=notj2temp1, out=notj2temp2);
    Not(in=instruction[0], out=notj3temp1, out=notj3temp2,
                            out=notj3temp3, out=notj3temp4,
                            out=notj3temp5);
    //no jump: inst logic( j1=0, j2=0, j3=0, zr=don't care(x), ng=don't care(x))
    //not that its opposite = JMP(unconditional jump--> with j1=1, j2=1, j3=1)
    And(a=notj1temp1, b=notj2temp1, out=notj1notj2temp1, out=notj1notj2temp2);
    And(a=notj3temp1, b=notj1notj2temp1, out=notj1notj2notj3temp1);
    //outputnaming-->desiredjumpcondition
    Not(in=notj1notj2notj3temp1, out=nullOrjmp);
    //JGT: inst logic( j1=0, j2=0, j3=1, zr=(0), ng=(0))
    And(a=notj1notj2temp2, b=notj3temp2, out=notj1notj2notj3);
    And(a=notj1notj2notj3, b=notALUzrtojgt, out=notj1notj2notj3notALUzr);
    And(a=notj1notj2notj3notALUzr, b=notALUngtojgt, out=jgt);
    //JEQ: inst logic( j1=0, j2=1, j3=0, zr=(1), ng=(0))
    And(a=notj1temp2, b=instruction[1], out=notj1j2temp1, out=notj1j2temp2);
    And(a=notj1j2temp1, b=notj3temp3, out=notj1j2notj3);
    And(a=notj1j2notj3, b=ALUzrtojeq, out=notj1j2notj3ALUzrtojeq);
    And(a=notj1j2notj3ALUzrtojeq, b=notALUngtojeq, out=jeq);
    //JGE: inst logic( j1=0, j2=1, j3=0, zr=(x), ng=(1))
    And(a=notj1j2temp2, b=instruction[0], out=notj1j2j3);
    And(a=notj1j2j3, b=ALUng, out=jge);
    //JLT: inst logic( j1=1, j2=0, j3=0, zr=(x), ng=(1))
    And(a=instruction[2], b=notj2temp2, out=j1notj2temp1, out=j1notj2temp2);
    And(a=j1notj2temp1, b=notj3temp4, out=j1notj2notj3);
    And(a=j1notj2notj3, b=ALUngtojlt, out=jlt);
    //JNE: inst logic( j1=1, j2=0, j3=1, zr=(0), ng=(x))
    And(a=j1notj2temp2, b=instruction[0], out=j1notj2j3);
    And(a=j1notj2j3, b=notALUzrtojne, out=jne);
    //JLE: inst logic( j1=1, j2=0, j3=1, zr=(1), ng=(x))
    And(a=instruction[3], b=instruction[2], out=j1j2);
    And(a=j1j2, b=notj3temp5, out=j1j2notj3);
    And(a=j1j2notj3, b=ALUzrtojle, out=jle);

    /*
        make pc load next address according to jump logic
        if it's an A instruction, the pc will not be loaded with address of instruction regardless of 
        regardless of the jumpo condition
    */
    Or8Way(in[0]=nullOrjmp, in[1]=jgt, in[2]=jeq, in[3]=jge,
            in[4]=jlt, in[5]=jne, in[6]=jle,out=pcjump);
    And(a=instruction[15], b=pcjump, out=pcload);
    
    PC(in=AregistertoPCoutput, load=pcload, inc=true, reset=reset, out[0..14]=pc);
    //write memory? control bit is d3: if d3=0 -- write=no(0) else write=yes(1)
    //if A instruction, writeM=no(0)
    And(a=instruction[15], b=instruction[3], out=writeM);
}

I have tried setting load to equal true always, and even tried setting instruction as the input to D register, but the Output & Difference table is always showing value of D register as 0.

本文标签: