So now that we went through the theory of sequential logic and time, we can go ahead and begin building the memory units that we need in order to build our computer. Before we do that, let's revisit the Von Neumann architecture. And observe that one of the major players of this architecture is something called memory. Now, when we say memory in computer hardware, we mean many different things. First of all there is main memory, which consists of the memory that resides actually inside the computer and hard-wired into the computer's motherboard. And this main memory also divides into several different categories of memories. The most famous one is called RAM or the Random Access Memory. And then there's secondary memory like hard-disks and memory sticks and and so on. And then there's also the distinction between volatile and non-volatile memory. For example, when you pull out the plug of the computer, the RAM is effectively erased. At the same time the information which is stored on the disks and on, on, flash memory and so on, persists even when the computer is not connected to a power supply. So, we have this distinction. The RAM is used to store both the data on which our programs operate as well as the instructions, which are the building blocks of the programs themselves. And we will talk about this duality later on in the course when we talk about the overall computer architecture. And finally, another comment that I want to make before we actually start this unit, is that like anything else when we talk about memory. We can talk about it from a physical perspective, how we actually build the memory, what kind of the technology do we, do we, do we use in order to realize the memory. And we can also talk about the logical organization of the memory. Now, in this unit, and in this course, in general, we always focus on logical considerations. And we focus in particular on the RAM unit, which is once again, the most important element of the computer's main memory. All right. Now, before we actually talk about the RAM, we have to step back and talk about the elementary building blocks from which memory is designed. So, the previous unit ended up with a description of how a single bit register works. And it doesn't take a big stretch of imagination to understand that you can take several such one bit register and put them one next to the other. And by doing this, you can create an abstraction of a 16-bit number. And we call this abstraction register. The width of the register, in general, is, is, is a parameter. We call it w. And in some computers it's 16-bit, in other computers it may be 32-bits or 64-bit. It turns out that its not a terribly interesting parameter because everything that they say in this lecture works for any width of, of memory that you might encounter. But from now on I'm going to use w equals 16 because we are building a 16-bit computer so we do this without loss of generality. Another thing that I'd like to say is that I'm going to use a lot the term register's state. And in fact, this term was introduced in the previous unit as well. State is the value which is currently stored, quote unquote, inside the register. To say it more precisely, this is the value which is currently being expressed by the internal circuits of, of, the register. This is a more, I think, accurate description of what's going on. It creates an illusion of, of storage if you will. All right, so here's the register. And let's take a user's perspective of this of this device. How do we read the value of this register? Well, it turns out that all we have to do is probe the out, output. Why? Because at any given point of time, the out, output simply emits the state of the register. So if we just look up the value that comes out from out, we know what is stored inside the register in this particular time cycle. Now let us talk about how we write a new value into the register. So, you know, we want to we want the register to remember the number 17 from now on. What do we do? Well, we set in to this new value, let's say 17, and we assert the load bit. When I say assert the load bit, I mean we set the load bit to 1. So here's what will happen. The register state becomes v. And from the next cycle onward, the output of the register will also start emitting this value v. So from the next cycle onward, the register will effectively store the new value 17. And it will keep on storing this value forever until we decide to change this value in the very same manner that I just described. All right, so we are now ready to give you an example of a register chip in action. And in order to do this, we will fire up the hardware simulator and show you how register chip works. So to get started I, I am going to load one of my built-in register chips. And in order to do it, I will select the nand2tetris folder. And within it I'm going to tools, and within tools I'm going to builtinChips. And by the way, everything that I do, you can do also on your computer. You know, all these folders are available to you also if of course if you have downloaded the nand2tetris suite to your computer. So I'm selecting the builtinChips directory and opening it. And I see that they have all sorts of built in chips available to me. And all these chips are part of the hack chip set. You know, these are chips that will come to play when we piece together the computer architecture. In one of these chips is called DRegister. So let us load the DRegister built in chip into the simulator. And if I look at the HDL code, I see that the HDL code is a little bit strange because it's a built in chip. You don't have to worry about it, because you don't have to build built in chips in, in this course. You have to build them in plain HDL. But this code here says that this chip is actually implemented by a Java class called DRegister which delivers the functionality of, of a 16-bit register. So it also says that this chip is clocked. Because, you know, it's, it's a register chip so it receives a clock input. And because the HDL includes the magical word clocked, we see that a clock icon has opened up in the control panel of the of the simulator. And this clock is used to simulate the progression of time within the computer, or more accurately, it simulates, it can be used to simulate a train. Of cycles. So each time I click this clock icon, I move one phase in the cycle. So, you know, this was a tick, this is a tock. Tick, tock, tick, tock, tick, tock. So I'm progressing the clock manually. And of course I can also write a test script that includes a command like while true, tick tock, which will cause the clock to to tick and tock forever. Or I can say something like repeat 10,000, tick tocks and so on. So but now we're going to do everything manually. And that's what you normally do when you build a chip and, and test it for the first time. So because this chip is implemented by a Java class, we, we added to the to these Java implementations all sorts of nice features. For example the D register has a GUI that it's a GUI side effect that shows what is the current state, or the current contents of this register. Happens to be 0, because this is the default. So let's go ahead and change the the contents of this register to something else. In particular, let's change the register to 17, my favorite number. So I'm changing the in input, which is a 16-bit value, into 17. And I will run the clock forward, and I see that actually, nothing seems to happen. The contents of the register remains 0, and so is the output of the register. Well, nothing happens because I forgot to assert the load bit. So let's go to the load bit and turn it into 1. And then we go back to the clock. We do a tick. And we see that the contents of the register changed to 17, which is very nice. But the output of the register is still 0. And that's because, you know, it takes a complete cycle for the register to actually stabilize and begin to emit the new state. So let's do a tock. And indeed, I see that once I move to the next cycle, the output of the register is also 17. And from now on the register is in a stable state, and the state is 17. And it will remain 17 until a point of time in which I will decide to change it into something else. Now, you know, one thing which I may want to do is set the the load bit to 0. And this will serve as a safety so that if inadvertently, you know, someone changes the value of this register nothing will happen until the load bit will be asserted. So, so let's go ahead and, and change the value of the register which is presently 17 to let's say 23, which is another one of my favorite numbers. So 23, and I set the load bit to 1. I do a tick. And I see that now the register is kind of an inconsistent state because the state of the register is 23, but the output is still 17. Once again, I have to complete the cycle in order to to get to the, the register into a stable state. So I do a tock. And now the register is 23. But both the state, the internal state of the register is 23. And also the, the register is itself has committed to this new value, and it emits the value 23 as well. So now I continue to click the clock, and the value of, of the register became 23. So, you know, this has been a demo of the typical behavior of the register. And let's continue with the lecture. So now that we understand how the basic building blocks of memory work, registers, we can begin to stack them together and build actual memory units. And the general architecture of of these units looks as follows. In fact, I can talk about it in, in terms of abstraction. The RAM abstraction, or the way we are used to think about memories, is we think about them as a sequence of addressable registers. It's as if every register has an address that ranges from 0 to n minus 1 in case of a, of a RAM device that consists of, of n registers. Now, there's one thing which is very important to emphasize, which makes this whole notion of RAM much easier to, to understand and to to comprehend. And this is the fact that irrespective of how many registers you have in this RAM unit, and it may well have millions of such registers, at any given point of time, only one register is selected and only one register is interesting. All the other registers don't take any part in the game, so to speak. So at any given point of time, we have to say which is the register on which we want to operate. Which is the register that we want to read, or which is the register whose value we want to change. So we have to make a selection. We have to determine this the address of this register. And we do it using an input, which we call address. So think about it. If we have to select one out of n possible registers using some sort of a binary code, how many bits do we need in order to create such a code? Well, it turns out that we need log of n such bits. For example, if we have eight registers we need three bits, right? Log of 8 in base 2 is 3. So register number 0 will be represented with a code 000. Repre, register number 7 will be represented with a code 111. And then we have all the possibilities in the middle. So the length of the address input, which we call k in this diagram equals log of n, the number of registers in this particular RAM device. And finally, we have this w, which as I said before is not terribly interesting. w, in our computer, happens to be 16. But if you want you, we can make this w equal some other number like 64. And everything that we say from now, now until the end of the unit would be just the same. So without loss of generality, w equals 16. Finally, I want to I want us all to remember that this is a sequential chip. It depends on a clock input, and that's why we have this little triangle in the diagram. And this means that it has a clocked behavior. And the behavior is defined as follows. If we use the label M to stand for the state of the selected register, then if load equals 1 M becomes in. And from the next cycle onward, the output of this register become M as well. And if load is not 1, the output of this register will be exactly as it was before, okay? So this is the basic functionality of of this RAM unit. Let us say a few words about how we read and write values using this RAM device. So, to read a particular register, we do two things. First of all, we set the address of the RAM unit to the desired register number or address, you know, register number five or something like this. And then we probe the out of the register we probe the out of the RAM unit. And the out of the RAM unit is built in such a way. I mean, the, the internal circuitry is built in such a way that the out always emits the state of the selected register. So in this case, it will emit the state of register number i. So that's how we read one register out of the millions of registers that may be present in this RAM device. What about writing? Well writing is slightly more involved. If we want to write something into register number five using the same example, we set the address to five. We set in to 17 for example. We assert the load bit and here is what will happen. The state of register number 5 will become 17. And from the next cycle onward, the RAM will start to output this value as well. And from now until further notice register number 5 will contain the value 17. Until we, we change it again using precisely the same procedure. So we know how to read and write individual registers from the given RAM device. Okay I would now to give you an example of a RAM chip in action. So once again, we're going to fire up the hardware simulator and we'll see some examples of, of how the values of the registers change over time. In this demo, we're going to illustrate how a RAM device operates using the how to simulator. So let's open our built in chip directory and look for some RAM device. We have several RAM devices in the hex chip set. Let's select the RAM8. So I load the chip and this is a built in chip. It comes a nice GUI side effect which we see here on the right-hand side. And I can use this GUI in order to put some values inside the RAM so let's do it. So I'm just putting some you know, random numbers really inside some of the registers. And we can leave some registers as zero. I'm just entering values. You know, nothing interesting here. And, and that's it. Now it should be understood that what I did here is is kind of cheating. That's not how you manipulate a RAM device in a low level fashion. So, so, so let's, let's go ahead and do it the right way so to speak. Let's decide that we want to read say, register number 5. How do I read the contents of register number 5? Well I go to the address input of the RAM device and I put the number 5 there, and then nothing seems to happen. But if I run the clock, I see that the out output of the RAM device begins to emit the value 8373, which happens to be the contents of the selected register or register number 5. If I want read another register, let's say register number 1. Well I change the address to number 1, I run the clock and I see that I get the contents of register number 1. What about changing the contents of some of these registers? Let's say they want to set the contents of register number 4 to 12. So I go to this address here to, to, I'm sorry I go to the address input of the RAM. I set the address to 4. I assert the load bit to enable the right operation. I set the value of the in input to the desired value which we decided is 12 and then I run the clock. So in the first tick, I see that the internal state of register number 4 became a 12. But the output of the RAM device is still something else. In order to commit the RAM to the new value, I have to complete the cycle. So I do it, and I see that now the RAM device is also emitting the value of the selected register which happens to be register number 4. So let's say that I want to change another register. Say register number 2. Let us set register number 2 to the number 17. So, I go to to the address input. I set it to 2. I go to the input. To the in input, I change it to 17. I run the clock. And I see that the register number 2 indeed changed to 17. And the out output of the RAM is now emitting this value as well. So, this has been a demonstration of how a RAM unit operates. Now, in this particular course, we are going to build a family of 16-bit RAM chips. All of them are going to have exactly the same generic architecture. But the details are going to be slightly different. So, here are the chips that we are actually going to build. We'll build a RAM8 consisting of 8 registers, and the length of the address bit is going to be log of 8, which is 3. Log to the base to 2 of 8. RAM64 contains 64 registers and 6 address bits. Then we'll create a RAM whose size is half k of registers and then we'll continue with a RAM4K and RAM16K. Which is what we finally need for our hack computer platform. So these are the five chips that we are going to build and the construction of these chips is going to be surprisingly simple as you will see in the next unit. Now a sensible question is why do we need these these five particular chips? And the answer is quite simply because that's what we need in order to build our Hack computer. And another interesting question that I side stepped until now is, why is this thing called RAM? To begin with. Well, RAM stands for random access memory. And I would like to note at the end of this unit, that maybe we didn't give this this chip the, the respect that, it actually deserves. Because something really remarkable happens with this chip, and here's what actually happens. Irrespective of the size of this chip, irre, irrespective of whether it has 8 registers or 8 million registers, I can select every register from this chip and apply an operation on it in exactly the same axis time which is truly remarkable. All I have to do is enter the address of this register into the address input and boom, this register is going to be selected and all the other registers are going to be ignored. Okay now there is no boom in reality, I'm doing it for dramatic effect. But actually it's quite dramatic because once again if I now want to select the register number of 5,000, all I have to do is enter 5,000 and boom, this register becomes irrelevant and register number 5,000 becomes active and, and it, it it kind of opens up for business. And it doesn't matter if I have 8 million registers or 8 billion registers. I have this basic ability to select at random any register in this configuration and either read it or write it in the same access time. So this is truly a remarkable functionality and later on in this week, you will actually build this functionality using HDL. But before we do so, we have one more chip that we need to describe. And this is the chip that implements accounting operation. And the chip is called counters. And counter, in singular, and this will be the subject of our next unit.