CHIP CPU {
IN inM[16],
instruction[16],
reset;
OUT outM[16],
writeM,
addressM[15],
pc[15];
PARTS:
Or(a=instruction[15], b=false, out=isCInstruction);
Not(in=instruction[15], out=isAInstruction);
And(a=isCInstruction, b=instruction[5], out=isCWriteA);
Or(a=isAInstruction, b=isCWriteA, out=loadA);
Mux16(a=instruction, b=outALU, sel=isCWriteA, out=inAReg);
ARegister(in=inAReg, load=loadA, out=outAreg, out[0..14]=addressM);
And(a=isCInstruction, b=instruction[4], out=loadD);
DRegister(in=outALU, load=loadD, out=outDReg);
Mux16(a=outAreg, b=inM, sel=instruction[12], out=outAorM);
ALU(
x=outDReg,
y=outAorM,
zx=instruction[11],
nx=instruction[10],
zy=instruction[9],
ny=instruction[8],
f=instruction[7],
no=instruction[6],
out=outALU,
out=outM,
zr=isZeroOut,
ng=isNegOut
);
Not(in=isNegOut, out=isNonNeg);
Not(in=isZeroOut, out=isNonZero);
And(a=isNonNeg, b=isNonZero, out=isPositive);
And(a=isCInstruction, b=instruction[3], out=writeM);
And(a=isPositive, b=instruction[0], out=JGT);
And(a=isZeroOut, b=instruction[1], out=JEQ);
And(a=isNegOut, b=instruction[2], out=JLT);
Or(a=JEQ, b=JLT, out=JLE);
Or(a=JLE, b=JGT, out=jumpToA);
And(a=isCInstruction, b=jumpToA, out=loadPC);
Not(in=loadPC, out=PCinc);
PC(
in=outAreg,
inc=PCinc,
load=loadPC,
reset=reset,
out[0..14]=pc
);
}
CHIP Memory { IN in[16], load, address[15]; OUT out[16];
PARTS:
DMux4Way(in=load, sel=address[13..14], a=selRam1, b=selRam2, c=selScreen, d=selKbd);
Or(a=selRam1, b=selRam2, out=selRam);
RAM16K(in=in, load=selRam, address=address[0..13], out=outRam);
Screen(in=in, load=selScreen, address=address[0..12], out=outScreen);
Keyboard(out=outKbd);
Mux4Way16(
a=outRam,
b=outRam,
c=outScreen,
d=outKbd,
sel=address[13..14],
out=out
);
}
CHIP Computer {
IN reset;
PARTS:
ROM32K(address=PC, out=instruction);
CPU(
inM=memOut,
instruction=instruction,
reset=reset,
outM=outM,
writeM=writeM,
addressM=addressM,
pc=PC
);
Memory(
in=outM,
load=writeM,
address=addressM,
out=memOut
);
}
CHIP Bit { IN in, load; OUT out;
PARTS:
Mux(a=dffOut, b=in, sel=load, out=muxOut);
DFF(in=muxOut, out=dffOut);
Or(a=false, b=dffOut, out=out); //
}
CHIP PC { IN in[16],load,inc,reset; OUT out[16];
PARTS:
Inc16(in=regOutput, out=regOutputInc);
Mux16(a=regOutput, b=regOutputInc, sel=inc, out=out1);
Mux16(a=out1, b=in, sel=load, out=out2);
Mux16(a=out2, b=false, sel=reset, out=regInput);
// load == load OR inc OR reset !!!
Or(a=load, b=inc, out=loadOrInc);
Or(a=loadOrInc, b=reset, out=loadOrIncOrReset);
Register(in=regInput, load=loadOrIncOrReset, out=regOutput);
Or16(a=false, b=regOutput, out=out); // dummy OR gate for output
}
CHIP RAM8 { IN in[16], load, address[3]; OUT out[16];
// 8 registers
PARTS:
DMux8Way(in=load, sel=address,
a=sel0,
b=sel1,
c=sel2,
d=sel3,
e=sel4,
f=sel5,
g=sel6,
h=sel7
);
Register(in=in, load=sel0, out=r0);
Register(in=in, load=sel1, out=r1);
Register(in=in, load=sel2, out=r2);
Register(in=in, load=sel3, out=r3);
Register(in=in, load=sel4, out=r4);
Register(in=in, load=sel5, out=r5);
Register(in=in, load=sel6, out=r6);
Register(in=in, load=sel7, out=r7);
Mux8Way16(
a=r0,
b=r1,
c=r2,
d=r3,
e=r4,
f=r5,
g=r6,
h=r7,
sel=address,
out=out);
}
CHIP RAM64 { IN in[16], load, address[6]; OUT out[16];
PARTS:
// 0..2 - low bits select the register, 3..5 select the bank (one of RAM8 chips)
DMux8Way(in=load, sel=address[3..5],
a=sel0,
b=sel1,
c=sel2,
d=sel3,
e=sel4,
f=sel5,
g=sel6,
h=sel7
);
RAM8(in=in, load=sel0, address=address[0..2], out=r0);
RAM8(in=in, load=sel1, address=address[0..2], out=r1);
RAM8(in=in, load=sel2, address=address[0..2], out=r2);
RAM8(in=in, load=sel3, address=address[0..2], out=r3);
RAM8(in=in, load=sel4, address=address[0..2], out=r4);
RAM8(in=in, load=sel5, address=address[0..2], out=r5);
RAM8(in=in, load=sel6, address=address[0..2], out=r6);
RAM8(in=in, load=sel7, address=address[0..2], out=r7);
Mux8Way16(
a=r0,
b=r1,
c=r2,
d=r3,
e=r4,
f=r5,
g=r6,
h=r7,
sel=address[3..5],
out=out);
}
CHIP Register { IN in[16], load; OUT out[16];
PARTS:
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]);
}
CHIP RAM4K { IN in[16], load, address[12]; OUT out[16];
PARTS:
DMux8Way(in=load, sel=address[9..11],
a=sel0,
b=sel1,
c=sel2,
d=sel3,
e=sel4,
f=sel5,
g=sel6,
h=sel7
);
RAM512(in=in, load=sel0, address=address[0..8], out=r0);
RAM512(in=in, load=sel1, address=address[0..8], out=r1);
RAM512(in=in, load=sel2, address=address[0..8], out=r2);
RAM512(in=in, load=sel3, address=address[0..8], out=r3);
RAM512(in=in, load=sel4, address=address[0..8], out=r4);
RAM512(in=in, load=sel5, address=address[0..8], out=r5);
RAM512(in=in, load=sel6, address=address[0..8], out=r6);
RAM512(in=in, load=sel7, address=address[0..8], out=r7);
Mux8Way16(
a=r0,
b=r1,
c=r2,
d=r3,
e=r4,
f=r5,
g=r6,
h=r7,
sel=address[9..11],
out=out);
}
CHIP RAM16K { IN in[16], load, address[14]; OUT out[16];
PARTS:
DMux4Way(in=load, sel=address[12..13],
a=sel0,
b=sel1,
c=sel2,
d=sel3
);
RAM4K(in=in, load=sel0, address=address[0..11], out=r0);
RAM4K(in=in, load=sel1, address=address[0..11], out=r1);
RAM4K(in=in, load=sel2, address=address[0..11], out=r2);
RAM4K(in=in, load=sel3, address=address[0..11], out=r3);
Mux4Way16(
a=r0,
b=r1,
c=r2,
d=r3,
sel=address[12..13],
out=out);
}
CHIP RAM512 { IN in[16], load, address[9]; OUT out[16];
PARTS:
DMux8Way(in=load, sel=address[6..8],
a=sel0,
b=sel1,
c=sel2,
d=sel3,
e=sel4,
f=sel5,
g=sel6,
h=sel7
);
RAM64(in=in, load=sel0, address=address[0..5], out=r0);
RAM64(in=in, load=sel1, address=address[0..5], out=r1);
RAM64(in=in, load=sel2, address=address[0..5], out=r2);
RAM64(in=in, load=sel3, address=address[0..5], out=r3);
RAM64(in=in, load=sel4, address=address[0..5], out=r4);
RAM64(in=in, load=sel5, address=address[0..5], out=r5);
RAM64(in=in, load=sel6, address=address[0..5], out=r6);
RAM64(in=in, load=sel7, address=address[0..5], out=r7);
Mux8Way16(
a=r0,
b=r1,
c=r2,
d=r3,
e=r4,
f=r5,
g=r6,
h=r7,
sel=address[6..8],
out=out);
}