CPU.hdl
// Parses the binary code in the instruction input and executes it according to the
// Hack machine language specification.
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:
//The first thing to figure out is whether the instruction is an A instruction or a C instruction.
//A instruction: instruction[15] == 0
//C instruction: instruction[15] == 1
Not(in= instruction[15], out= isAInstruction);
And(a= instruction[15], b= true, out= isCInstruction);
//The A register has two possible inputs.
//If we are dealing with an A instruction, the instruction itself becomes the new value.
//If we are dealing with a C instruction, the ALU output can become the new value.
Mux16(a= aluOut, b= instruction, sel= isAInstruction, out= aRegisterInput);
//The A register should load if this is an A instruction.
//It should also load if this is a C instruction and the A destination bit is turned on.
And(a= isCInstruction, b= instruction[5], out= cInstructionLoadsA);
Or(a= isAInstruction, b= cInstructionLoadsA, out= loadARegister);
ARegister(in= aRegisterInput, load= loadARegister, out= aRegisterOut, out[0..14]= addressM);
//The D register should only load if this is a C instruction and the D destination bit is turned on.
And(a= isCInstruction, b= instruction[4], out= loadDRegister);
DRegister(in= aluOut, load= loadDRegister, out= dRegisterOut);
//The ALU's second input is either A or M.
//The a-bit in the instruction chooses which one.
Mux16(a= aRegisterOut, b= inM, sel= instruction[12], out= aOrM);
//The ALU does the actual C instruction computation.
ALU(x= dRegisterOut, y= aOrM,
zx= instruction[11],
nx= instruction[10],
zy= instruction[9],
ny= instruction[8],
f= instruction[7],
no= instruction[6],
out= aluOut,
out= outM,
zr= zr,
ng= ng);
//The M destination bit controls whether we write the ALU output to memory.
And(a= isCInstruction, b= instruction[3], out= writeM);
//For jump logic we need to know whether the ALU output is positive, zero, or negative.
Not(in= zr, out= notZero);
Not(in= ng, out= notNegative);
And(a= notZero, b= notNegative, out= positive);
//The jump bits are JLT, JEQ, JGT.
//instruction[2] says jump if negative.
//instruction[1] says jump if zero.
//instruction[0] says jump if positive.
And(a= instruction[2], b= ng, out= jumpIfNegative);
And(a= instruction[1], b= zr, out= jumpIfZero);
And(a= instruction[0], b= positive, out= jumpIfPositive);
Or(a= jumpIfNegative, b= jumpIfZero, out= jumpOne);
Or(a= jumpOne, b= jumpIfPositive, out= jumpTwo);
And(a= isCInstruction, b= jumpTwo, out= loadPC);
//If loadPC is true, PC becomes A.
//Otherwise it increments.
//If reset is true, PC handles that internally and becomes 0.
PC(in= aRegisterOut, load= loadPC, inc= true, reset= reset, out[0..14]= pc);
}
Memory and I/O
Memory.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/5/Memory.hdl
/**
* The complete address space of the Hack computer's memory,
* including RAM and memory-mapped I/O.
* The chip facilitates read and write operations, as follows:
* Read: out(t) = Memory[address(t)](t)
* Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1)
* In words: the chip always outputs the value stored at the memory
* location specified by address. If load=1, the in value is loaded
* into the memory location specified by address. This value becomes
* available through the out output from the next time step onward.
* Address space rules:
* Only the upper 16K+8K+1 words of the Memory chip are used.
* Access to address>0x6000 is invalid and reads 0. Access to any address
* in the range 0x4000-0x5FFF results in accessing the screen memory
* map. Access to address 0x6000 results in accessing the keyboard
* memory map. The behavior in these addresses is described in the Screen
* and Keyboard chip specifications given in the lectures and the book.
*/
CHIP Memory {
IN in[16], load, address[15];
OUT out[16];
PARTS:
DMux4Way(in= load, sel= address[13..14], a= ramLoadOne, b= ramLoadTwo, c= screenLoad, d= keyboardLoad);
Or(a= ramLoadOne, b= ramLoadTwo, out= ramLoad);
//24577-32,768 = 110000000000001
//24576 = 110000000000000
Keyboard(out= keyboardOut);
//16384-24575 = 100000000000000-101111111111111
Screen(in= in, load= screenLoad, address=address[0..12], out= screenOut);
//0-16383 = 000000000000000-011111111111111
RAM16K(in= in, load= ramLoad, address=address[0..13], out= ramOut);
//00:a, 01:b, 10:c, 11:d
Mux4Way16(a= ramOut, b= ramOut, c= screenOut, d= keyboardOut, sel= address[13..14], out= out);
}
RAM16K.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/b/RAM16K.hdl
/**
* Memory of 16K 16-bit registers.
* If load is asserted, the value of the register selected by
* address is set to in; Otherwise, the value does not change.
* The value of the selected register is emitted by out.
*/
CHIP RAM16K {
IN in[16], load, address[14];
OUT out[16];
PARTS:
//Take the load bit and assign it to the correct output via address
DMux(in= load, sel=address[1] , a= o1, b= o2);
DMux(in= o1, sel= address[0], a= oo1, b= oo2);
DMux(in= o2, sel= address[0], a= oo3, b= oo4);
//Create the RAM. The correct RAM will recieve the load bit.
RAM4K(in= in, load= oo1, address= address[2..13], out= ob1);
RAM4K(in= in, load= oo2, address= address[2..13], out= ob2);
RAM4K(in= in, load= oo3, address= address[2..13], out= ob3);
RAM4K(in= in, load= oo4, address= address[2..13], out= ob4);
//The output register will be based on the address.
Mux4Way16(a= ob1, b= ob2, c= ob3, d= ob4, sel= address[0..1], out= out);
}
RAM4K.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/b/RAM4K.hdl
/**
* Memory of 4K 16-bit registers.
* If load is asserted, the value of the register selected by
* address is set to in; Otherwise, the value does not change.
* The value of the selected register is emitted by out.
*/
CHIP RAM4K {
IN in[16], load, address[12];
OUT out[16];
PARTS:
//Take the load bit and assign it to the correct output via address
DMux(in= load, sel=address[2] , a= o1, b= o2);
DMux(in= o1, sel= address[1], a= o3, b= o4);
DMux(in= o2, sel= address[1], a= o5, b= o6);
DMux(in= o3, sel= address[0], a= oo1, b= oo2);
DMux(in= o4, sel= address[0], a= oo3, b= oo4);
DMux(in= o5, sel= address[0], a= oo5, b= oo6);
DMux(in= o6, sel= address[0], a= oo7, b= oo8);
//Create the RAM. The correct RAM will recieve the load bit.
RAM512(in= in, load= oo1, address= address[3..11], out= ob1);
RAM512(in= in, load= oo2, address= address[3..11], out= ob2);
RAM512(in= in, load= oo3, address= address[3..11], out= ob3);
RAM512(in= in, load= oo4, address= address[3..11], out= ob4);
RAM512(in= in, load= oo5, address= address[3..11], out= ob5);
RAM512(in= in, load= oo6, address= address[3..11], out= ob6);
RAM512(in= in, load= oo7, address= address[3..11], out= ob7);
RAM512(in= in, load= oo8, address= address[3..11], out= ob8);
//The output register will be based on the address.
Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address[0..2], out= out);
}
RAM512.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/b/RAM512.hdl
/**
* Memory of 512 16-bit registers.
* If load is asserted, the value of the register selected by
* address is set to in; Otherwise, the value does not change.
* The value of the selected register is emitted by out.
*/
CHIP RAM512 {
IN in[16], load, address[9];
OUT out[16];
PARTS:
//Take the load bit and assign it to the correct output via address
DMux(in= load, sel=address[2] , a= o1, b= o2);
DMux(in= o1, sel= address[1], a= o3, b= o4);
DMux(in= o2, sel= address[1], a= o5, b= o6);
DMux(in= o3, sel= address[0], a= oo1, b= oo2);
DMux(in= o4, sel= address[0], a= oo3, b= oo4);
DMux(in= o5, sel= address[0], a= oo5, b= oo6);
DMux(in= o6, sel= address[0], a= oo7, b= oo8);
//Create the RAM. The correct RAM will recieve the load bit.
RAM64(in= in, load= oo1, address= address[3..8], out= ob1);
RAM64(in= in, load= oo2, address= address[3..8], out= ob2);
RAM64(in= in, load= oo3, address= address[3..8], out= ob3);
RAM64(in= in, load= oo4, address= address[3..8], out= ob4);
RAM64(in= in, load= oo5, address= address[3..8], out= ob5);
RAM64(in= in, load= oo6, address= address[3..8], out= ob6);
RAM64(in= in, load= oo7, address= address[3..8], out= ob7);
RAM64(in= in, load= oo8, address= address[3..8], out= ob8);
//The output register will be based on the address.
Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address[0..2], out= out);
}
RAM64.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/RAM64.hdl
/**
* Memory of sixty four 16-bit registers.
* If load is asserted, the value of the register selected by
* address is set to in; Otherwise, the value does not change.
* The value of the selected register is emitted by out.
*/
CHIP RAM64 {
IN in[16], load, address[6];
OUT out[16];
PARTS:
//Take the load bit and assign it to the correct output via address
DMux(in= load, sel=address[2] , a= o1, b= o2);
DMux(in= o1, sel= address[1], a= o3, b= o4);
DMux(in= o2, sel= address[1], a= o5, b= o6);
DMux(in= o3, sel= address[0], a= oo1, b= oo2);
DMux(in= o4, sel= address[0], a= oo3, b= oo4);
DMux(in= o5, sel= address[0], a= oo5, b= oo6);
DMux(in= o6, sel= address[0], a= oo7, b= oo8);
//Create the RAM. The correct RAM will recieve the load bit.
RAM8(in= in, load= oo1, address= address[3..5], out= ob1);
RAM8(in= in, load= oo2, address= address[3..5], out= ob2);
RAM8(in= in, load= oo3, address= address[3..5], out= ob3);
RAM8(in= in, load= oo4, address= address[3..5], out= ob4);
RAM8(in= in, load= oo5, address= address[3..5], out= ob5);
RAM8(in= in, load= oo6, address= address[3..5], out= ob6);
RAM8(in= in, load= oo7, address= address[3..5], out= ob7);
RAM8(in= in, load= oo8, address= address[3..5], out= ob8);
//The output register will be based on the address.
Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address[0..2], out= out);
}
RAM8.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/RAM8.hdl
/**
* Memory of eight 16-bit registers.
* If load is asserted, the value of the register selected by
* address is set to in; Otherwise, the value does not change.
* The value of the selected register is emitted by out.
*/
CHIP RAM8 {
IN in[16], load, address[3];
OUT out[16];
PARTS:
//Take the load bit and assign it to the correct output via address
DMux(in= load, sel=address[2] , a= o1, b= o2);
DMux(in= o1, sel= address[1], a= o3, b= o4);
DMux(in= o2, sel= address[1], a= o5, b= o6);
DMux(in= o3, sel= address[0], a= oo1, b= oo2);
DMux(in= o4, sel= address[0], a= oo3, b= oo4);
DMux(in= o5, sel= address[0], a= oo5, b= oo6);
DMux(in= o6, sel= address[0], a= oo7, b= oo8);
//Create the registers. The correct register will recieve the load bit.
Register(in= in, load= oo1, out= ob1);
Register(in= in, load= oo2, out= ob2);
Register(in= in, load= oo3, out= ob3);
Register(in= in, load= oo4, out= ob4);
Register(in= in, load= oo5, out= ob5);
Register(in= in, load= oo6, out= ob6);
Register(in= in, load= oo7, out= ob7);
Register(in= in, load= oo8, out= ob8);
//The output register will be based on the address.
Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address, out= out);
}
Register.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/Register.hdl
/**
* 16-bit register:
* If load is asserted, the register's value is set to in;
* Otherwise, the register maintains its current value:
* if (load(t)) out(t+1) = int(t), else out(t+1) = out(t)
*/
CHIP Register {
IN in[16], load;
OUT out[16];
PARTS:
/*
Similar to the bit chip, the description doesn't specify the case in which garbage is returned.
*/
Bit(in= in[0], load= load, out= out[0]);
Bit(in= in[1], load= load, out= out[1]);
Bit(in= in[2], load= load, out= out[2]);
Bit(in= in[3], load= load, out= out[3]);
Bit(in= in[4], load= load, out= out[4]);
Bit(in= in[5], load= load, out= out[5]);
Bit(in= in[6], load= load, out= out[6]);
Bit(in= in[7], load= load, out= out[7]);
Bit(in= in[8], load= load, out= out[8]);
Bit(in= in[9], load= load, out= out[9]);
Bit(in= in[10], load= load, out= out[10]);
Bit(in= in[11], load= load, out= out[11]);
Bit(in= in[12], load= load, out= out[12]);
Bit(in= in[13], load= load, out= out[13]);
Bit(in= in[14], load= load, out= out[14]);
Bit(in= in[15], load= load, out= out[15]);
}
Bit.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/Bit.hdl
/**
* 1-bit register:
* If load is asserted, the register's value is set to in;
* Otherwise, the register maintains its current value:
* if (load(t)) out(t+1) = in(t), else out(t+1) = out(t)
*/
CHIP Bit {
IN in, load;
OUT out;
PARTS:
//Very simple.
//if load:
// return input
//if not load:
// if DFF contains prior value:
// return prior value
// else:
// return garbage
//The value is either the prior value (captured via DFF)
Mux(a= o1, b= in, sel= load, out= o2);
DFF(in= o2, out= out, out= o1);
}
ALU
ALU.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/ALU.hdl
/**
* ALU (Arithmetic Logic Unit):
* Computes out = one of the following functions:
* 0, 1, -1,
* x, y, !x, !y, -x, -y,
* x + 1, y + 1, x - 1, y - 1,
* x + y, x - y, y - x,
* x & y, x | y
* on the 16-bit inputs x, y,
* according to the input bits zx, nx, zy, ny, f, no.
* In addition, computes the two output bits:
* if (out == 0) zr = 1, else zr = 0
* if (out < 0) ng = 1, else ng = 0
*/
// Implementation: Manipulates the x and y inputs
// and operates on the resulting values, as follows:
// if (zx == 1) sets x = 0 // 16-bit constant
// if (nx == 1) sets x = !x // bitwise not
// if (zy == 1) sets y = 0 // 16-bit constant
// if (ny == 1) sets y = !y // bitwise not
// if (f == 1) sets out = x + y // integer 2's complement addition
// if (f == 0) sets out = x & y // bitwise and
// if (no == 1) sets out = !out // bitwise not
CHIP ALU {
IN
x[16], y[16], // 16-bit inputs
zx, // zero the x input?
nx, // negate the x input?
zy, // zero the y input?
ny, // negate the y input?
f, // compute (out = x + y) or (out = x & y)?
no; // negate the out output?
OUT
out[16], // 16-bit output
zr, // if (out == 0) equals 1, else 0
ng; // if (out < 0) equals 1, else 0
PARTS:
//zx
Mux16(a= x, b= false, sel= zx, out= outZX);
//nx
Not16(in= outZX, out= notX);
Mux16(a= outZX, b= notX, sel= nx, out= outNX);
//zy
Mux16(a= y, b= false, sel= zy, out= outZY);
//ny
Not16(in= outZY, out= notY);
Mux16(a= outZY, b= notY, sel= ny, out= outNY);
//f
Add16(a= outNX, b= outNY, out= outF1);
And16(a= outNX, b= outNY, out= outF2);
Mux16(a= outF2, b= outF1, sel= f, out= outF);
//no
Not16(in= outF, out= outNO1);
Mux16(a= outF, b= outNO1, sel= no, out= out, out[15]= mostSignificantBit,
out[0]=o0,
out[1]=o1,
out[2]=o2,
out[3]=o3,
out[4]=o4,
out[5]=o5,
out[6]=o6,
out[7]=o7,
out[8]=o8,
out[9]=o9,
out[10]=o10,
out[11]=o11,
out[12]=o12,
out[13]=o13,
out[14]=o14,
out[15]=o15
);
//zr
//what logic gate can we use to check if both are zero
//Not 16
//If 1, then 0, if 0 then 1.
Or(a= o0, b= false, out= or0);
Or(a= o1, b= or0, out= or1);
Or(a= o2, b= or1, out= or2);
Or(a= o3, b= or2, out= or3);
Or(a= o4, b= or3, out= or4);
Or(a= o5, b= or4, out= or5);
Or(a= o6, b= or5, out= or6);
Or(a= o7, b= or6, out= or7);
Or(a= o8, b= or7, out= or8);
Or(a= o9, b= or8, out= or9);
Or(a= o10, b= or9, out= or10);
Or(a= o11, b= or10, out= or11);
Or(a= o12, b= or11, out= or12);
Or(a= o13, b= or12, out= or13);
Or(a= o14, b= or13, out= or14);
Or(a= o15, b= or14, out= or15);
Mux(a= true, b= false, sel= or15, out= zr);
//ng
Mux(a= false, b= true, sel= mostSignificantBit, out= ng);
}
Arithmetic
Inc16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/Inc16.hdl
/**
* 16-bit incrementer:
* out = in + 1
*/
CHIP Inc16 {
IN in[16];
OUT out[16];
PARTS:
Add16(a= in[0..15], b[0]= true, b[1..15]=false, out=out );
//// Replace this comment with your code.
}
Add16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/Add16.hdl
/**
* 16-bit adder: Adds two 16-bit two's complement values.
* The most significant carry bit is ignored.
*/
CHIP Add16 {
IN a[16], b[16];
OUT out[16];
PARTS:
HalfAdder(a= a[0], b= b[0], sum= out[0], carry= c0);
FullAdder(a= a[1], b= b[1], c= c0, sum= out[1], carry= c1);
FullAdder(a= a[2], b= b[2], c= c1, sum= out[2], carry= c2);
FullAdder(a= a[3], b= b[3], c= c2, sum= out[3], carry= c3);
FullAdder(a= a[4], b= b[4], c= c3, sum= out[4], carry= c4);
FullAdder(a= a[5], b= b[5], c= c4, sum= out[5], carry= c5);
FullAdder(a= a[6], b= b[6], c= c5, sum= out[6], carry= c6);
FullAdder(a= a[7], b= b[7], c= c6, sum= out[7], carry= c7);
FullAdder(a= a[8], b= b[8], c= c7, sum= out[8], carry= c8);
FullAdder(a= a[9], b= b[9], c= c8, sum= out[9], carry= c9);
FullAdder(a= a[10], b= b[10], c= c9, sum= out[10], carry= c10);
FullAdder(a= a[11], b= b[11], c= c10, sum= out[11], carry= c11);
FullAdder(a= a[12], b= b[12], c= c11, sum= out[12], carry= c12);
FullAdder(a= a[13], b= b[13], c= c12, sum= out[13], carry= c13);
FullAdder(a= a[14], b= b[14], c= c13, sum= out[14], carry= c14);
FullAdder(a= a[15], b= b[15], c= c14, sum= out[15], carry= c15);
}
FullAdder.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/FullAdder.hdl
/**
* Computes the sum of three bits.
*/
CHIP FullAdder {
IN a, b, c; // 1-bit inputs
OUT sum, // Right bit of a + b + c
carry; // Left bit of a + b + c
PARTS:
/*
| a | b |sum|car|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| a | b | c |sum|carry|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 |
*/
HalfAdder(a= b, b= c, sum= sum1 , carry= carry1);
Not(in=sum1 , out= sum2);
//if a == 0 SAME
//if a == 1 -> SUM GETS INVERTED
//if a == 1 -> CARRY IS 1 IF NOT SAME
Xor(a= b, b= c, out= o1);
And(a= b, b= c, out= o2);
Or(a= o1, b= o2, out= carry2);
//How do we "glue" another half adder to get this functionality.
//We can use AND OR NOT XOR MUX ETC
//We can use MUX with A as SEL
//If A is Zero then we route half adder
Mux(a=sum1 , b=sum2 , sel=a, out=sum );
Mux(a=carry1 , b=carry2 , sel=a , out=carry );
}
HalfAdder.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/HalfAdder.hdl
/**
* Computes the sum of two bits.
*/
CHIP HalfAdder {
IN a, b; // 1-bit inputs
OUT sum, // Right bit of a + b
carry; // Left bit of a + b
PARTS:
//// Replace this comment with your code.
Xor(a= a, b= b, out=sum);
And(a= a, b=b , out=carry);
}
16-bit Logic
Mux8Way16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux8Way16.hdl
/**
* 8-way 16-bit multiplexor:
* out = a if sel = 000
* b if sel = 001
* c if sel = 010
* d if sel = 011
* e if sel = 100
* f if sel = 101
* g if sel = 110
* h if sel = 111
*/
CHIP Mux8Way16 {
IN a[16], b[16], c[16], d[16],
e[16], f[16], g[16], h[16],
sel[3];
OUT out[16];
PARTS:
//// Replace this comment with your code.
Mux4Way16(a= a[0..15], b= b[0..15], c= c[0..15], d= d[0..15], sel= sel[0..1], out= o1);
Mux4Way16(a= e[0..15], b= f[0..15], c= g[0..15], d= h[0..15], sel= sel[0..1], out= o2);
Mux16(a= o1, b= o2, sel= sel[2], out= out);
}
Mux4Way16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux4Way16.hdl
/**
* 4-way 16-bit multiplexor:
* out = a if sel = 00
* b if sel = 01
* c if sel = 10
* d if sel = 11
*/
CHIP Mux4Way16 {
IN a[16], b[16], c[16], d[16], sel[2];
OUT out[16];
PARTS:
//a if sel[1] is 0 b if sel[1] is 1
Mux16(a= a[0..15], b= b[0..15], sel= sel[0], out= o1);
//c if sel[1] is 0 d if sel[1] is 1
Mux16(a= c[0..15], b= d[0..15], sel=sel[0], out= o2);
//o1 if sel[0] is 0 o2 if sel[0] is 1
Mux16(a= o1, b= o2, sel=sel[1], out=out);
}
Mux16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux16.hdl
/**
* 16-bit multiplexor:
* for i = 0, ..., 15:
* if (sel = 0) out[i] = a[i], else out[i] = b[i]
*/
CHIP Mux16 {
IN a[16], b[16], sel;
OUT out[16];
PARTS:
Mux(a= a[0], b=b[0], sel=sel, out=out[0]);
Mux(a= a[1], b=b[1], sel=sel, out=out[1]);
Mux(a= a[2], b=b[2], sel=sel, out=out[2]);
Mux(a= a[3], b=b[3], sel=sel, out=out[3]);
Mux(a= a[4], b=b[4], sel=sel, out=out[4]);
Mux(a= a[5], b=b[5], sel=sel, out=out[5]);
Mux(a= a[6], b=b[6], sel=sel, out=out[6]);
Mux(a= a[7], b=b[7], sel=sel, out=out[7]);
Mux(a= a[8], b=b[8], sel=sel, out=out[8]);
Mux(a= a[9], b=b[9], sel=sel, out=out[9]);
Mux(a= a[10], b=b[10], sel=sel, out=out[10]);
Mux(a= a[11], b=b[11], sel=sel, out=out[11]);
Mux(a= a[12], b=b[12], sel=sel, out=out[12]);
Mux(a= a[13], b=b[13], sel=sel, out=out[13]);
Mux(a= a[14], b=b[14], sel=sel, out=out[14]);
Mux(a= a[15], b=b[15], sel=sel, out=out[15]);
}
Or8Way.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Or8Way.hdl
/**
* 8-way Or gate:
* out = in[0] Or in[1] Or ... Or in[7]
*/
CHIP Or8Way {
IN in[8];
OUT out;
PARTS:
Or(a= in[0], b= in[1], out= o1);
Or(a= o1, b= in[2], out= o2);
Or(a= o2, b= in[3], out= o3);
Or(a= o3, b= in[4], out= o4);
Or(a= o4, b= in[5], out= o5);
Or(a= o5, b= in[6], out= o6);
Or(a= o6, b= in[7], out= out);
}
Or16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Or16.hdl
/**
* 16-bit Or gate:
* for i = 0, ..., 15:
* out[i] = a[i] Or b[i]
*/
CHIP Or16 {
IN a[16], b[16];
OUT out[16];
PARTS:
Or(a= a[0], b=b[0], out=out[0]);
Or(a= a[1], b=b[1], out=out[1]);
Or(a= a[2], b=b[2], out=out[2]);
Or(a= a[3], b=b[3], out=out[3]);
Or(a= a[4], b=b[4], out=out[4]);
Or(a= a[5], b=b[5], out=out[5]);
Or(a= a[6], b=b[6], out=out[6]);
Or(a= a[7], b=b[7], out=out[7]);
Or(a= a[8], b=b[8], out=out[8]);
Or(a= a[9], b=b[9], out=out[9]);
Or(a= a[10], b=b[10], out=out[10]);
Or(a= a[11], b=b[11], out=out[11]);
Or(a= a[12], b=b[12], out=out[12]);
Or(a= a[13], b=b[13], out=out[13]);
Or(a= a[14], b=b[14], out=out[14]);
Or(a= a[15], b=b[15], out=out[15]);
}
And16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/And16.hdl
/**
* 16-bit And gate:
* for i = 0, ..., 15:
* out[i] = a[i] And b[i]
*/
CHIP And16 {
IN a[16], b[16];
OUT out[16];
PARTS:
And(a= a[0], b=b[0], out=out[0]);
And(a= a[1], b=b[1], out=out[1]);
And(a= a[2], b=b[2], out=out[2]);
And(a= a[3], b=b[3], out=out[3]);
And(a= a[4], b=b[4], out=out[4]);
And(a= a[5], b=b[5], out=out[5]);
And(a= a[6], b=b[6], out=out[6]);
And(a= a[7], b=b[7], out=out[7]);
And(a= a[8], b=b[8], out=out[8]);
And(a= a[9], b=b[9], out=out[9]);
And(a= a[10], b=b[10], out=out[10]);
And(a= a[11], b=b[11], out=out[11]);
And(a= a[12], b=b[12], out=out[12]);
And(a= a[13], b=b[13], out=out[13]);
And(a= a[14], b=b[14], out=out[14]);
And(a= a[15], b=b[15], out=out[15]);
}
Not16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Not16.hdl
/**
* 16-bit Not gate:
* for i = 0, ..., 15:
* out[i] = Not(a[i])
*/
CHIP Not16 {
IN in[16];
OUT out[16];
PARTS:
Not(in=in[0], out= out[0]);
Not(in=in[1], out= out[1]);
Not(in=in[2], out= out[2]);
Not(in=in[3], out= out[3]);
Not(in=in[4], out= out[4]);
Not(in=in[5], out= out[5]);
Not(in=in[6], out= out[6]);
Not(in=in[7], out= out[7]);
Not(in=in[8], out= out[8]);
Not(in=in[9], out= out[9]);
Not(in=in[10], out= out[10]);
Not(in=in[11], out= out[11]);
Not(in=in[12], out= out[12]);
Not(in=in[13], out= out[13]);
Not(in=in[14], out= out[14]);
Not(in=in[15], out= out[15]);
}
Single-bit Logic
DMux8Way.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/DMux8Way.hdl
/**
* 8-way demultiplexor:
* [a, b, c, d, e, f, g, h] = [in, 0, 0, 0, 0, 0, 0, 0] if sel = 000
* [0, in, 0, 0, 0, 0, 0, 0] if sel = 001
* [0, 0, in, 0, 0, 0, 0, 0] if sel = 010
* [0, 0, 0, in, 0, 0, 0, 0] if sel = 011
* [0, 0, 0, 0, in, 0, 0, 0] if sel = 100
* [0, 0, 0, 0, 0, in, 0, 0] if sel = 101
* [0, 0, 0, 0, 0, 0, in, 0] if sel = 110
* [0, 0, 0, 0, 0, 0, 0, in] if sel = 111
*/
CHIP DMux8Way {
IN in, sel[3];
OUT a, b, c, d, e, f, g, h;
PARTS:
DMux4Way(in= o1, sel= sel[0..1], a= a, b= b, c= c, d= d);
DMux4Way(in= o2, sel= sel[0..1], a= e, b= f, c= g, d= h);
DMux(in= in, sel= sel[2], a= o1, b= o2);
}
DMux4Way.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/DMux4Way.hdl
/**
* 4-way demultiplexor:
* [a, b, c, d] = [in, 0, 0, 0] if sel = 00
* [0, in, 0, 0] if sel = 01
* [0, 0, in, 0] if sel = 10
* [0, 0, 0, in] if sel = 11
*/
CHIP DMux4Way {
IN in, sel[2];
OUT a, b, c, d;
PARTS:
/*
|in | sel | a | b | c | d |
| 0 | 00 | 0 | 0 | 0 | 0 |
| 0 | 01 | 0 | 0 | 0 | 0 |
| 0 | 10 | 0 | 0 | 0 | 0 |
| 0 | 11 | 0 | 0 | 0 | 0 |
| 1 | 00 | 1 | 0 | 0 | 0 |
| 1 | 01 | 0 | 1 | 0 | 0 |
| 1 | 10 | 0 | 0 | 1 | 0 |
| 1 | 11 | 0 | 0 | 0 | 1 |
*/
DMux(in= o1, sel= sel[0], a= a, b= b);
DMux(in= o2, sel= sel[0], a= c, b= d);
DMux(in= in, sel= sel[1], a= o1, b= o2);
}
DMux.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/DMux.hdl
/**
* Demultiplexor:
* [a, b] = [in, 0] if sel = 0
* [0, in] if sel = 1
*/
CHIP DMux {
IN in, sel;
OUT a, b;
PARTS:
//|in |sel| a | b |
//| 0 | 0 | 0 | 0 |
//| 0 | 1 | 0 | 0 |
//| 1 | 0 | 1 | 0 |
//| 1 | 1 | 0 | 1 |
Not(in= sel, out= notSel);
And(a= in, b= notSel, out=a);
And(a= in, b= sel, out=b);
}
Mux.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux.hdl
/**
* Multiplexor:
* if (sel = 0) out = a, else out = b
*/
/*
*/
CHIP Mux {
IN a, b, sel;
OUT out;
PARTS:
Not(in= a, out= notA);
Not(in= b, out= notB);
Not(in= sel, out= notSel);
And(a= a, b= b, out= aAndB);
And(a= notA, b= b, out= notAAndB);
And(a= a, b= notB, out= aAndNotB);
//| 0 | 1 | 0 | 0 |
And(a= notAAndB, b= notSel, out= notAAndBAndNotSel);
//| 0 | 1 | 1 | 1 |
And(a= notAAndB, b= sel, out= notAAndBAndSel);
//| 1 | 0 | 0 | 1 |
And(a= aAndNotB, b= notSel, out= aAndNotBAndNotSel);
//| 1 | 1 | 0 | 1 |
And(a= aAndB, b= notSel, out= aAndBAndNotSel);
//| 1 | 1 | 1 | 1 |
And(a= aAndB, b= sel, out= aAndBAndSel);
Or(a= notAAndBAndSel, b= notAAndBAndSel, out= o3);
Or(a= o3, b= aAndNotBAndNotSel, out= o4);
Or(a= o4, b= aAndBAndNotSel, out= o6);
Or(a= o6, b= aAndBAndSel, out= out);
}
Xor.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Xor.hdl
/**
* Exclusive-or gate:
* if ((a and Not(b)) or (Not(a) and b)) out = 1, else out = 0
*/
CHIP Xor {
IN a, b;
OUT out;
PARTS:
Not(in= a, out= notA);
And(a= notA, b= b, out= notAAndB);
Not(in= b, out= notB);
And(a= a, b= notB, out= aAndNotB);
Or(a= notAAndB, b= aAndNotB, out= out);
}
Or.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Or.hdl
/**
* Or gate:
* if (a or b) out = 1, else out = 0
*/
CHIP Or {
IN a, b;
OUT out;
PARTS:
Not(in= a, out= o1);
Not(in= b, out= o2);
Nand(a= o1, b= o2, out= out);
}
And.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/And.hdl
/**
* And gate:
* if (a and b) out = 1, else out = 0
*/
CHIP And {
IN a, b;
OUT out;
PARTS:
Nand(a= a, b= b, out= o1);
Not(in= o1, out= out);
}
Not.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Not.hdl
/**
* Not gate:
* if (in) out = 0, else out = 1
*/
CHIP Not {
IN in;
OUT out;
PARTS:
Nand(a= in, b= in, out= out);
}