Thiago Miranda
Thiago Miranda

Reputation: 15

Problem with an infinite loop in Memory Chip implementation (Nand2Tetris)

I have two almost identical Memory chip implementations, except that one works and the other, when I test in the hardware simulator with the Memory.tst, give an infinite loop when the program expects me to press Y key.

The implementation that WORKS is:

 CHIP Memory {
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    // RAM
    // [00]0 0000 0000 0000
    // [01]1 1111 1111 1111
    // Screen
    // [10]0 0000 0000 0000
    // [10]0 1111 1111 1111
    // Keyboard
    // [11]0 0000 0000 0000
    DMux4Way(in=load, sel=address[13..14], a=ram1, b=ram2, c=loadScreen, d=ignored);
    Or(a=ram1, b=ram2, out=loadRam);
    
    RAM16K(in=in, load=loadRam, address=address[0..13], out=outRam);
    Screen(in=in, load=loadScreen, address=address[0..12], out=outScreen);

    And(a=address[13], b=address[14], out=canBeKbd);
    Or8Way(in=address[0..7], out=anyOne07);
    Or8Way(in=address[5..12], out=anyOne512);
    Or(a=anyOne07, b=anyOne512, out=anyOne012);
    Not(in=anyOne012, out=allZero012);
    And(a=canBeKbd, b=allZero012, out=isKbd);
    Keyboard(out=kdb);
    Mux16(a=false, b=kdb, sel=isKbd, out=outKbd);

    Mux4Way16(a=outRam, b=outRam, c=outScreen, d=outKbd, sel=address[13..14], out=out);
}

And the implementation that DON'T work is:

 CHIP Memory {
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    // RAM
    // [00]0 0000 0000 0000
    // [01]1 1111 1111 1111
    // Screen
    // [10]0 0000 0000 0000
    // [10]0 1111 1111 1111
    // Keyboard
    // [11]0 0000 0000 0000
    DMux4Way(in=load, sel=address[13..14], a=ram1, b=ram2, c=loadScreen, d=canBeKbd);
    Or(a=ram1, b=ram2, out=loadRam);
    
    RAM16K(in=in, load=loadRam, address=address[0..13], out=outRam);
    Screen(in=in, load=loadScreen, address=address[0..12], out=outScreen);

    Or8Way(in=address[0..7], out=anyOne07);
    Or8Way(in=address[5..12], out=anyOne512);
    Or(a=anyOne07, b=anyOne512, out=anyOne012);
    Not(in=anyOne012, out=allZero012);
    And(a=canBeKbd, b=allZero012, out=isKbd);
    Keyboard(out=kdb);
    Mux16(a=false, b=kdb, sel=isKbd, out=outKbd);

    Mux4Way16(a=outRam, b=outRam, c=outScreen, d=outKbd, sel=address[13..14], out=out);
}

The only diference that the second implementation has is that I get the canBeKbd from the first DMux. That SHOULD work, but it doesn't. I would be happy with anyone could tell me why.

Other implementation that pass the given test would be:

CHIP Memory {
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    // RAM
    // [00]0 0000 0000 0000
    // [01]1 1111 1111 1111
    // Screen
    // [10]0 0000 0000 0000
    // [10]0 1111 1111 1111
    // Keyboard
    // [11]0 0000 0000 0000
    DMux4Way(in=load, sel=address[13..14], a=ram1, b=ram2, c=loadScreen, d=loadKbd);
    Or(a=ram1, b=ram2, out=loadRam);
    
    RAM16K(in=in, load=loadRam, address=address[0..13], out=outRam);
    Screen(in=in, load=loadScreen, address=address[0..12], out=outScreen);
    Keyboard(out=outKbd);

    Mux4Way16(a=outRam, b=outRam, c=outScreen, d=outKbd, sel=address[13..14], out=out);
}

But I can't use the third implementation because I wouldn't test that all first 12 bits is 0. Because the keyboard memory location is 0011 0000 0000 0000 (0x6000) only.

Upvotes: 0

Views: 585

Answers (1)

Trebor the MadOverlord
Trebor the MadOverlord

Reputation: 1289

Looking at the difference between the two implementations, two questions come to mind that you should consider.

  1. Is the implementation of DMux4Way correctly producing output d?

  2. How does Mux4Way16 respond if outRam, outScreen and outKbd are all false? Because at a glance, it looks like this can happen if you give it an address in the 0x6nnn range that is not 0x6000.

Good luck!

Upvotes: 0

Related Questions