Reading on in the From NAND to Tetris textbook.
I realized I have a problem. One RAM chip only has one address but will have to be connected to three other parties. The reason this doesn’t work is that the three parties might want to read three different addresses of RAM, and (unless you use dual/triple port ram) the RAM doesn’t like that. It only allows reading from one address at a time.
So I came up with the idea to use a copy RAM that would alternate between copying RAM and letting the screen access it (the CPU has a clock, which alternates between a “low” voltage, and a “high” voltage, at a steady rate. The CPU and the screen only do things when the clock “ticks” (goes from low to high). So we can copy RAM when the clock “tocks” (goes from high to low)).
But wait, what about the keyboard? It turns out that only the CPU needs to access the entire RAM, the screen and the keyboard only need to access a few parts of it. So we can have both a single RAM chip for the CPU to access, and two separate RAM chips (the screen and the keyboard) for the screen and the keyboard to access. We can use the copying scheme from before for the screen, but what about the keyboard?
Here’s the solution I came up with: when the CPU is about to access the keyboard data, we write the updated keyboard data to RAM. This works, but what if we’re “too late” and wrote after the CPU is already done accessing the keyboard? Ok, here’s a thing: the keyboard RAM is just a register. The keyboard only needs to access one specific address in RAM. So, what if we set it up so that the CPU accesses RAM normally, but if it wants to access the keyboard data, it just reads from the keyboard register? We don’t have the same problem as before, where the CPU wants to access one address and the keyboard another, because there’s just one address. So, that’s the solution, right?…
…no. Here’s the last problem: most RAM chips have 1 byte of data per address. The Hack CPU (and also the screen and keyboard), however, expects 2 bytes of data for each address. The solution I came up with is just to use two chips of RAM hooked to the same address: one chip holds 1 byte of data, the other one holds the other byte. Then the CPU can simply read from both when trying to access 2 bytes.