 So, I decided to hook up the logic analyzer to the hold, hold, act, and IAQ lines of the processor because I woke up last night in cold sweat. As sometimes happens, my subconscious was chewing on data while I was asleep, and it came up with a red flag. A quick review. I can ask the processor to stop when I assert the hold signal, which in this case is active low. The processor acknowledges that it has stopped by asserting its hold act signal. Also, the processor's IAQ signal indicates that it is reading an instruction from memory. IAQ stands for Instruction Acquire. Okay, I hit step a few times. Let's zoom into one instance and see what woke me up at night. Well, that's no good. That's no good at all. That's like an 11 step, not a single step. The reason is that my AVR-powered pseudorom is too slow. Remember that's a single step, I want to release the processor just long enough for it to execute one instruction, then stop it. Executing a single instruction could take as little as under a microsecond, and my pseudorom takes something like 12 microseconds to react. And if we look at the very first step after reset, we can see another problem. The processor said it was running, but it took quite a long time for it to go fetch the first instruction. That's just how long the processor takes to come out of reset. The original plan was to assert hold as soon as the processor said it was running, but clearly that's not going to work in this case. I have to assert hold after the processor says it has fetched an instruction. So that's two problems. Yay, subconscious. Alright, so here is a timing diagram of what we want to see now. So I have a hold signal here. This is actually a positive active signal, unlike the one that actually goes into the processor, which is active low. The reason that I did that is just because it's easier for me to keep track of the fact that this is positive logic instead of negative logic, so I'm just not getting confused anyway. So the idea is that we start off in the state where the processor is being held. So it stopped, it's not doing anything. Hold is high, and hold acknowledge of course is also high, and the processor is not executing any instructions. Now, we flick the step switch, and when that happens, we unassert hold, and eventually the processor acknowledges that by starting to run. And when it runs, it executes an instruction. So now the idea is that when we detect that an instruction is being fetched and executed, we immediately assert hold again. And eventually, when the processor finishes executing its instruction, it will acknowledge that hold. Now the processor is stopped. Now if we were to flick the run switch, then what we want to do is unassert hold again, and of course the processor will unassert hold acknowledge to signal that it's running, and it goes and fetches instructions and executes them and keeps going, until we press the step button, which is now also a stop button. When we hit that, we want to hold the processor. The processor will, maybe it's in the middle of executing an instruction, maybe it's in the middle of fetching an instruction. It doesn't matter. The point is that when it's done, it will acknowledge hold, and at that point we can say yes, the processor is stopped. And after the processor is stopped, we're back in this state in the beginning. All right, so let's draw that out as a state machine and see what we get. All right, and that's easy enough to do. We will just start in state zero. That's going to be here. And we're going to say, all right, we will flick the step switch. Now the step switch goes up, and at that point we want to wait for the step switch to come back down. So the step switch comes back down. At that point we want to unhold the processor. So what I'm going to do is I'm going to put a little arrow here saying hold goes to zero. Okay, so at that point hold acknowledge goes low, but we don't care because we want to know when the next instruction starts getting executed. So what we're going to do is we're just going to wait for IAQ to go either high or low. In this case, we're just going to let it wait until it goes low, and at that point we want to set hold equal to one. And when hold equals to one, what we want to do is simply wait until that hold is acknowledged. So hold goes, sorry, hold acknowledge goes high, and then we go back to the beginning because now we're back in the state where the processor has stopped and we're waiting for either step or run to be hit. Great. Now what happens if run is hit? Well, what are we on state for? So this is run goes high, and we want to wait for run to come back down, okay? When run comes back down, we want to set hold to zero, and basically we just want to see that instructions are being executed. So we're going to say IAQ goes low, and when IAQ goes low, now all we're doing is we're basically waiting for the step switch to be hit. We don't care if the run switch is hit because we're already running. So we'll go to state six, we'll say step needs to go high, state seven, step needs to go low. And when step goes low, we want to wait for hold acknowledge to go high, and that means that we can make it go to step three because we also want to set hold to one. And that's it. That's the state machine. Now we'll just fill out the rest of the hold signals. So here, of course, we're not doing anything, so we're holding at zero, holding at zero. Here we're hold is one, here hold is one, and here hold is one, and that's it. So that's basically the state machine, eight states. So we're going to implement this as a state machine with three bits for the state. So state is three bits, and we've got a number of inputs. We've obviously got step, and we've got run. We've also got hold acknowledge. We've also got IAQ. And the one thing that I didn't show in the state machine is that there should be some sort of a reset signal, which will set the state machine to state zero. So we want a reset signal. And so that's the input, and the output is going to be the next state, which is also three bits, and also the hold signal. And that's one bit. So in the input, how many bits do we have, eight bits of input? And for the output, how many bits? Four bits. So that's a 256 by four prom. And again, such things do not exist anymore. They used to, but now they don't. So of course we're not going to use our pseudo ROM because we know that our pseudo ROM is too slow. So we're going to use something else. So the ROM that we're going to use is this Atmel 8k by 8 parallel electrically erasable prom. It is, believe it or not, the smallest prom that has parallel output. Most, well actually all, of the smaller proms are basically used for things like configuring FPGAs. They're usually little eight pin guys, and they are serial output. So they output one bit at a time. And they're also serial input in terms of address. So that's absolutely no good. We want to be able to, in parallel, put an address in, and in parallel, get eight bits out, or four bits, but in this case, there's nothing smaller. So we're stuck with this huge dealio. Okay, so that leads to another problem, which is this thing right over here, the access time. What that means is, if we look at this timing diagram over here, is that when the address is presented to the chip, it must be stable for 150 nanoseconds before the output becomes valid. So if the address is changing, well, the data is going to change. And even if the address is not changing for say, 50 nanoseconds or 100 nanoseconds, the internal components and circuitry may not settle on their final value, which means that the data is just going to be all over the place. So it's only 150 nanoseconds after the address has been presented and is stable to the chip that the output will be valid. This is the chip enable line. It's active low. We're going to keep it low. This is the output enable line. It's also active low and we're going to keep it low. So the time from chip enable to data and the time from output enable to data doesn't actually matter. So the only thing that matters is this access time. So that's 150 nanoseconds. Now the thing is that we are essentially clocking, here is the inverted phase two clock. Remember that there are four phases, they're staggered, and we're using the positive edge of the negative phase two clock in order to clock the next state into our register. And at the same time, what we're going to do is we're going to clock all of the input signals to the ROM chip so that the input can remain stable until we evaluate it and get the output and then the output is going to be stable and we latch the output and that's the next state. So let's put together a ROM, load it with data and add a register that will register the inputs and the outputs and see what happens. So here it is. I have hooked up the ROM in the breadboard right over here and next to it is an 8-bit register, which I use to register all of my input signals like the reset step and run line. The hold acknowledge and IAQ lines actually don't need to be registered by us because that is registered by the CPU already. And the next state is also being registered as well as the hold signal. Great. Single step actually seems to work and I can run the processor and stop it and single step it and that's pretty good. Let's take a look at the logic analyzer. Okay, so we can see I've stepped a few times and then I hit run and after I hit run I also stopped the processor and stepped it a couple of times. So let's take a look at one of these signals. We can zoom in and see what happens and make sure that only a single instruction gets executed and yeah it looks like a single instruction is executed. So when we hit step we release hold and the processor acknowledges that so it starts running and this is the first time after reset so it takes a little while before the first instruction actually gets executed and that's normal for this processor it just takes a little while. Once the instruction starts executing we assert hold and after the instruction is finished executing the CPU acknowledges hold so that seems to work pretty well. Let's take a look at the next instance of the single step and here we can see that we release the processor after the step button is released and the processor acknowledges that and starts running it executes a single instruction pretty quickly this time and then we hold the processor and it acknowledges so that works pretty well. Now in the case of letting the processor run I don't show the run signal but you can imagine that I've pressed the button we release hold the processor runs and it starts executing an instruction and another instruction and a whole bunch of instructions and then finally I hit the step button and then release it whoa there's a whole lot of scruff on that release I wonder what's going on there maybe there's a bounce that I didn't take care of well anyway eventually the hold signal is activated and the processor acknowledges hold and that's really all there is to it so that seems to work pretty well here is another step after I've stopped the processor to show that yes after we stop the processor in single step we execute one instruction well hopefully I can get a good night's sleep now I hope you enjoyed that and maybe I should start working on the front panel and maybe adding some RAM to this thing since I seem to have single step working pretty well until next time see ya