 Greetings retro friends today we're going to talk about memory. We're finally going to add some memory to the 9900 CPU. So let's take a look at the data sheet first. So what are these things? They are 32K by 8 SRAM. So SRAM means it's static it's not dynamic it means that the circuitry is a lot easier to handle except it does take more power. So because these are 32K by 8 what I need is 32K by 16. I'm trying hard not to touch these because they are CMOS but my matte is grounded so hopefully nothing's gonna nothing bad is gonna happen to them. Anyway these are 32K by 8 each so if I put 1, 2 side by side that would be 32K by 16 and remember that the address space in 16 bit words of the 9900 is 32K. So we can see that it has an access time of 70 nanoseconds that means that when you present an address on the address lines then 70 nanoseconds later at most the data will appear on the output. Let me show you first a picture of the front panel that I want to put together so here is my idea of the memory section of the front panel so this thing over here is the Run Step button. The idea is that you're not going to be able to fiddle with memory unless you're in the stop position because obviously if you're running the CPU is the thing that's accessing memory not you so you would have to stop it and then you could use the memory side to read and write data. The idea is that we have two rows of two position switches these aren't toggle switches well they are they're on off switches basically. The address lines go from 15 to 1 and the data lines go from 15 to 0 and of course the reason that the address lines go from 15 to 1 is that in the 9900 CPU it doesn't actually have a least significant bit at 0. That is the reason why you have 32K words but in byte-oriented terminology it would be 64K so we leave off this last address. Addresses are always even in the 9900 CPU. We have a display of address and data these are our nice little hexadecimal displays over here and we also have two push switches these are these these switches where you can push them and it springs back to the initial position. This switch which I don't have a cap on is one position one position so that's going to be used to enter in bits. Anyway so this one is read and write or pre-increment read and pre-increment write. Okay so you enter an address on the address switches and then you press read and what will happen is the address will appear here and the data is read from the RAM and it appears in the data window. When you want to write to memory you flip the switches for the address, flip the switches for the data, flip write and the address and data that you've just written appear in the windows. A lot of front panels from the late 70s and early 80s have this other switch which will automatically increment the address for you from a starting position so the idea is that you can set up an address and flip read and it will show you what's in that address and then if you flip plus plus read what that does is it increments the address and then reads the data and shows you that so that way you can just flip through memory by going plus plus plus plus plus plus and so on. Same thing with write you set up your address and data over here and you flip write the address and data appear over here and then you can set up the data and just go plus plus write and that will write the data to the next address and then that will appear over here or for example if you wanted to load up a bunch of zeros for example or a bunch of Fs you could just set up the address, set up the data, flip write and then flip plus plus write and flip it several times in order to load that data into the address and always the last written or read address is going to be displayed in the address window and that's basically it so how do you think we're going to implement this? Yeah, it's a state machine. So, first let me talk about the circuitry that I want to build. We have this front panel data and front panel address and these are these switches they each have 16 lines well actually the address only has 15 lines but one of the lines is permanently connected to zero basically and we have the RAM on this side so this is 32K by 16 now the RAM has data and it has address lines it also has an output enable line which turns on and off the output data and a write enable line which allows you to write into the RAM and we'll talk about how that works in a moment but first what I want to do is talk about the buffers. So, these are tri-state buffers and the idea behind tri-state buffers is that when they're off they're effectively electrically disconnected from whatever their output is. If we disable this buffer over here then effectively this data line has nothing feeding it in this direction. This over here is the 8-bit register that we used before this is a 574 it's more convenient than other 8-bit registers because it has what's called a bus-oriented pinout which means that all the data lines are on one side and all the output lines are on another so that's why I like the 574. There would actually be two of them because they're 8 bits each and they feed the data display so the idea is that if we were to present an address to the RAM and output enable were enabled then the RAM would feed the data out this way and then you can clock the data in to this register and it would be displayed in the data window. Same thing with the address if you want to feed an address to the RAM you have to turn on this buffer over here and that will directly feed the output of the switches to the address lines on the RAM. So you can see that that's kind of how we can implement the read switch so you would set up the address lines you would turn on this buffer and then when you flip the read switch that basically clocks the data into the data register. We also have an address register over here which is capable of incrementing the address so you would also clock the data into this register and then that would enable the address to appear in the address window so that's the address window, that's the data window, great. So that's how read would work. In order to write data of course we have to feed the switches over to the RAM so you would turn on this buffer but the danger is that you cannot have the RAM outputting data at the same time as your outputting data on the bus because you will get bus contention so you have to be sure that only one device is talking at once so that's why the output enable line is there so that you can turn off the output and that puts the RAM effectively into not talking mode so the only thing that's talking would be this buffer. You set up your address on your data, you turn the output off on the RAM you turn these buffers on that allows the address and data to get to the RAM and then you pulse the write enable line and that writes the data into the RAM. The pre-increment modes basically clock is actually a counter register initially when you read or write that clocks the initial data into the address register but then when you do plus plus read and plus plus write you're not paying attention to the switches so you're turning this buffer off you're just clocking an increment into this register and then you need to turn this buffer over here on because now you're feeding the output of that result to the RAM so that basically very briefly is how the circuitry works again like I said before these registers over here are 574s you can't buy any of this stuff unlike Digi-Key so you have to look on eBay for these 574s the buffers are 541s you can get 8-bit buffers in the lower numbers which you can probably get in Digi-Key but I like the 541s because again they have a bus-oriented pinout which will make laying out the the circuitry very easy. 541s are 8-bit buffers 8-bit tri-state buffers so of course I need two of them here two of them here and two of them over here and then finally this thing over here is it is an 8-bit binary up-down counter with preset it's a 269 so with preset basically means that you can clock input data into the counter and it's bi-directional so you can actually count up or down so if I wanted to I suppose I could add also a pre-decrement read and write switch if I wanted to and that's basically all it is so 1, 2, 3, 4, 5, 6 of these chips 7, 8, 9, 10 of course because you need this to be 16-bit so that's 10 and then I'm not counting the RAM this is just going to be the the front circuitry so that's about 10 chips right there now I've already talked about how to read and write from the RAM so link down below for that okay you may notice a different sound quality because I've switched to another microphone anyway so here I've redrawn the circuit with all of its signals and let's draw out what we want to see for reading so that we can start designing the state machine so first of all we know that we have a read switch so here's read we know that we wanted to go up and then we want to go down again and that's when we actually start the read so when we turn on the read we want to send the front panel address over to the RAM address so we want Fp or AFp2 bus that's this signal to be enabled and let's see what also do we want we want to clock that address into the address register so that means that the address clock is going to go high now because this is a positive or edge triggered signal we want to make sure that the address is actually on the bus before we clock it in so we have to add a little bit of delay so that will be one state and let's see we also want the address load signal of course to go high at that point and when we drop the clock we can drop the address load signal now once we put the address onto the address lines we know that the RAM about 70 nanoseconds later which is definitely less than one clock cycle that we're going to use we know that the data lines are going to go active so what we want to do is we want to send that data down into the data register so we have the data clock and let's see it's probably going to be here the data clock again is edge triggered so this is the time that we send the address over to the RAM and this is the time that we read the data from the RAM so we can clock it in and we're done that's it so let's call this where everything is idle state zero now we're waiting for one of the switches to be pressed so in this case if the read switch is pressed we're going to go to state one which is going to wait for the read switch to be released and then in rapid succession we're going to go to state two where we're going to enable the address bus and start a load and then in state three we're going to clock everything in and then at that point we go straight back to state zero where everything is idle now while this is happening of course there there are these other signals so for example the data front panel to bus we definitely want to be always zero the address up down signal doesn't actually matter and this address to bus signal we also want to be zero because the only thing that should be talking to the address lines is this buffer that's how you do a read now let's look at something a little more complicated which is the read with pre increment so in this case we're going to look at the plus plus read switch we wanted to go up and we want to go down again again everything is idle in state zero we're waiting for a switch press to happen we're on state four so let's just call this state four and then whatever states going to be next is going to be state five okay so at this point the first thing that we want to do is pre is increment whatever is in the address register remember you have to do a read or a write in order to get the front panel address into the address register in the first place when you do a plus plus read or a plus plus write you're not paying attention to the address which is you're only using whatever is in the address register alright so we want load address load to be zero because we are going to do a an address up down operation so we want that to be one because if the up down signal is one you're going to count up if the up down signal is zero you're going to count down let's see we want to also once we set that up we want to clock that address in so there's the address clock okay actually we're not going to clock anything and we're just going to clock the up down operation so then the next thing that has to happen at at that point it can even happen over here is that we want to send the address that the register contains over to the address lines of the RAM so a to bus at that point is going to go hi now yes the address is going to be the former address at this point and the address is going to change somewhere during this state but that doesn't really matter because all we care about is that the address is eventually going to be sent so seventy nanoseconds later the RAM is going to read from its data lines which reminds me we also have to set output enable to one and write enable to zero in the state and I may as well write that down here output enable one write enable zero data front panel to bus is zero and address to bus we've already looked at and address front panel to bus we also turn off okay so where are we here so sometime after that we want to clock the data into the data register so this is data clock and that would be it so we also want to release the address bus at that point once we're done clocking it clocking the data in and the address up down line we can actually release after we've performed the operation so that's where that goes alright so let me draw some more dotted lines here to delineate the states and we've got state four five six state seven back to state zero alright so that's how you do the two reads let's talk about writes so for writing again we're going to wait for the switch to go up and wait for it to come back down we're up to state eight right now so let me stick a dotted line down here alright so output enable now here output enable was one we can actually set that here and drop it here okay the same thing here output enable is one we can enable it here and drop it there alright here output enable is always going to be zero so we're going to keep it at zero uh let's see for write we have the the address and the data being set up by the switches so of course we will want to send those over to the RAM and because the RAMs output enable is at zero that means that it is not sending data out it means that we can send data in so address front panel to bus and data front panel to bus should both be enabled so let's do that here address front panel to bus and data front panel to bus both go high we also want to clock whatever we have set in the switches into the respective registers so the address clock one state later is going to go high and is going to go low same thing with the data clock it's going to go high and then it's going to go low and then to write the data in uh it's basically the same we bring it high and then we bring it low and we're done so let's drop these lines drop these lines draw some dotted lines so we've got states nine ten and back to zero all right the final thing is the pre-increment right so this is going to be probably i will put it let's see how about here oh the address to bus is also zero because we're not sending the address register down to this the address up down doesn't actually matter so we're going to set it to zero the address load um oh we do have to set the address load don't we the address load needs to be set up here okay otherwise we wouldn't be able to clock anything in uh let's see data clock addressed most okay i've got all the signals great all right let's look at the final sequence all right so i said state 11 right state 11 and the next state will be state 12 all right so in this case again we want to increment whatever is in the address first so we've already done that sort of thing right over here so let's just copy that address load is zero address up down is going to go up and there's going to be one state and then it's going to come back down the address gets clocked in here or actually the address gets incremented there and then the address gets sent out over the bus here okay output enable is zero of course and once we've done that let's see uh we've also got the data that needs to be clocked in don't we so data clock we can clock it in whenever just clock it in over there just for the hell of it um it's the same thing as this we we could in fact move this data clock over to here if we wanted to because the data is present on the address on the data lines on the front panel data lines um so i guess just to be consistent let's put the pulse here when the address clock goes up okay so we don't actually want to enable write until we have finished the increment operation which means that write enable goes high at this point and then comes back down so uh that should be it address load of course is zero and we've already got address up down so let me just count up the signals to make sure we've taken care of everything we've got one two three four five six seven eight one two three four five six seven eight nine what am i missing what am i missing well here i'm missing the address up down signal which we want to be zero okay so that's nine signals one two three four five six seven eight nine one two three four five six seven eight nine and one two three four five six seven eight and i've missed probably these two buses um oh okay well i've certainly missed the data front panel two bus signal data front panel two bus that has to come let's see that has to be set up here okay so one two three four five six seven eight nine excellent all right let's draw some dotted lines the address to bus can be dropped at this point so we've got state 11 12 13 14 and back down to zero all right so i've set that up excellent uh so we have 15 states 15 states are going to take four state bits we've got nine output signals and we're going to have one reset input one reset input because of course we want to reset the entire state machine on power up or you know whenever and that will go back to state zero we have four switches so we have four switch inputs so in terms of outputs we have nine plus four is 13 and in terms of inputs we have four plus five is nine total number is 22 and then of course we have plus the state machine clock so the unfortunate thing about this is that there are 22 signals plus one state machine clock now if i wanted to use a 22 v 10 gal to implement this state machine well unfortunately one of those 22 i o lines has to be taken up by the clock which means that i would have to split this in two so maybe i could use you know two 16 v eights possibly uh because we have 13 outputs so you know say eight outputs would be on one and the rest would be on the other and in terms of inputs uh that's actually not going to work because we need all of the inputs in order to determine what state we want to go into next so we can't use 16 v eights because there would be eight outputs and eight inputs one of which would be the clock so that's only seven inputs so we have to go with two 22 v 10s if we have 13 outputs we could divide um let's see we could put six on one and five on the other and that would leave plenty of input uh input pin space for the 22 v 10s so that's how it's done that's how we've designed a state machine to operate this circuitry uh let's just uh put that into windcouple and see what happens so if you may have been yelling at the screen this data front panel two bus has to be put onto the bus before we clock the data in so this actually has to be high up here and then we release it over there so slight mistake but corrected before we actually did anything right so what i've done is i've taken the state machine and just converted it into a spreadsheet uh so i've divided the spreadsheet into two sections one section is basically how to get from one state to another so for example um obviously when you hit the reset signal no matter what state you're in you want to go to state zero great um if you press the read switch uh and of course none of the other switches are pressed uh then and you're in state zero then you want to go to state one uh if you hit the increment read switch then you want to go from state zero to state four and so on um the other thing is that uh what i don't have explicitly here in the table is that if none of these conditions are true then you always want to stay in the same state so for example um after you release the read switch uh and you're in state one you go to state two but of course as long as you're holding down the read switch you remain in state one now when you go to state two at that point all we're doing is outputting some patterns uh some logic patterns to control all the buffers and the chips and so on so it doesn't matter what we're doing we're going to go from state two to state three on the next clock same thing from state three to state zero on the next clock of course as long as reset isn't uh being asserted so that's what this uh first table is uh the second table is what uh what the outputs are depending on what the current state is so for example uh in state two the only signals that are asserted are the afp to bus address load and output enable um all the other signals are by default zero so that states zero to 14 okay now on the right side um what i have here is the dot pld file um a dot pld file is what wincouple takes this is the software that converts your logic equations to a fuse map that can be programmed into the gal um i have to split the state machine into two gals so i have front panel one and front panel two uh both of them are going to be 22 v10s uh so the first section of the pld file is uh just a bunch of annotations name date revision and device these are standard uh for the header uh the next section is you get to define what the names of the signals are uh and uh what pins they are associated with so for example pins 23 down to 20 are the next state q3 down to q0 and uh this is if you're looking at a pinout it's going to be in the upper right hand of the uh chip if you're looking at it with pin one on the upper left uh pin one is always clock that's just a limitation of the architecture of the chip uh and then you get the input pins so we've got pin two up to five are the current state d3 down to d0 and then we've got six seven eight nine and 10 are the five inputs the four switches and the reset button uh so you'll notice that i don't have any of the outputs on this chip uh that's because i put all the outputs on the second gal uh the purpose of the first gal is to uh determine what the next state is based on the switch signals and the reset of course and the purpose of the second gal is simply combinatorial so that's just going to output the signals according to the current state so the next section i am just defining some convenient fields and fields are just lists of signals that you can handle all at once so next state is defined as q3 down to q0 and current state d3 down to d0 now because i'm using the um the flip-flop block or the the macro cell of the gal um i have to define what the asynchronous reset for that flip-flop is so for all of the output signals i'm defining the asynchronous reset of course as the reset signal next i'm defining a bunch of constants uh you probably don't have to do this i believe that windcouple accepts possibly uh decimal values maybe even hex values nevertheless i just found this convenient so state zero is defined as binary zero zero zero zero and so on so i've defined that for every state so the next thing is uh now i'm going to code up state zero so here are a bunch of intermediate equations i'll get to those in a moment uh but what i want to show is the append statement now what this does is it basically is like or equals so we're just going to append this statement with any previous statement using an or so in other words next state dot d d being the input to the flip-flop will be this or this or this or this and so on and so on down through the rest of the file and this is a very convenient way of defining a state machine now i'm aware that uh there is a state machine syntax that windcouple accepts i decided not to use it because i just want things to be uh relatively clear and i i feel that this does make things clear so let's examine the first statement here uh the colon is basically an equals operator so here we're comparing the current state with state zero and condition zero one needs to be true now condition zero one here is the read signal is asserted but none of the other signals are asserted condition zero two is the increment read is asserted oh i've got a mistake here look at that okay um the increment read is asserted but none of the other signals are asserted condition three of course is the right signal and condition four is the increment right signal now because again you need to specify what happens if none of those conditions are true i need to define the negative of any of those conditions so that's what this is note that the pound sign is used as or in windcouple so uh if you look again at this statement you can see that we're comparing the current state to state zero and condition zero one is true now that is a single boolean value it's either true or false but we're anding it with state one which is a four-bit value what windcouple knows how to do is to basically broadcast that single boolean value across this operation so it's going to and every bit of state one with the single bit that is the result of this computation so this is the way that you basically write a state machine you define what happens on the next clock cycle by defining the dot d signal and then because the clock signal by default goes to every single flip-flop that will clock all the flip-flops simultaneously so one other thing that i want to show is this silly thing over here now you might say well if the asynchronous reset that i've defined up here will clear out all the flip-flops why do i need to define that state two only goes to state three if reset is not being asserted and why didn't i put that in any of these other equations the answer is windcouple it's legacy software it's not that smart apparently and it actually had problems with this equation when the not reset and was was not in there so just a comparison and a bit pattern apparently caused the software to die in a mysterious way so this was the only way to fix it and as i've said before and i will continue to say we really need an open hardware programmer with open source software so that we can solve all of these silly little problems okay so that's the first gal the second gal is just combinatorial so here i've defined the output signals so pins 23 down to pin 15 are all of the output signals there are nine of them now you'll notice that i have output enable and right enable with active high as i've defined my state machine you can define it as an active low output by just putting a bang in front of the symbol and the compiler will know to activate the inverter on the output so that's very convenient and the reason why we wanted active low is of course because the rams signal signals are active low so we have some inputs pins two through five just like in the first gal our d3 down to d0 and also just like in the first gal pin 10 i've defined as reset just to be consistent but that's all we need we don't need a clock because this is combinatorial logic and we don't need to output the next state because well that's what gal one is for so here are the definitions again and here are the definitions of the signals so afp2bus is simply not reset and any of these states so if you look at afp2bus over here you can see that it's only active during states two three nine or ten two three nine or ten and hopefully i got the rest of it correct but we'll test that anyway so the next thing to do is to fire up wincouple and compile these down to a fuse map or a jeddak file so let's take a look at that so here is wincouple the atmel version uh well it's actually microchip now because microchip bought atmel in 2016 uh the only thing that this supports are the atmel chips so that's nice um so let's open front panel one dot pld okay so it pulls it up in an editor and you can edit the uh you can edit the code here but um it's a kind of a silly text editor i prefer to just edit in my own editor and then reload the file so let's take a look at some of the options for the compiler so first of all it's very important that jeddak is checked the jeddak file is the file that the programmer needs in order to program the chip that is the fuse map and jeddak is the file format also there is a documentation file that wincouple can output which is very convenient it gives you the plot of all the fuses and also the minimized equations which is quite nice to look at it also gives you a pinout um in terms of minimization this is how it minimizes the logical equations that you've written um none is really bad um expresso is probably the best um expresso or actually espresso um i believe that is the actual name of the library and i think it's a an open source um boolean minimization library so that's nice uh i don't think we need to pay attention to optimization uh because that i think uh has to do with maybe some chips that uh aren't actually supported by atmel that's why keep xor equations is in there because that used to be some of the old gals and pals that are apparently not compiled into this version that's nice um general the jeddak the name of the jeddak file should be the name of the pld file so we're going to have front panel one dot jedd and front panel two dot jedd um i don't think we need any of this and library is um something pretty weird which is undocumented and who the hell knows what that is so um in terms of devices you can see that these are all the devices that are supported that's it that's all you get uh and in fact the 20 v8s aren't even being sold anymore so that's nice um i have a 22 v10c but in fact it doesn't really matter because there's this little checkbox down here device in file so what it will do is it will look at the device annotation and because it knows what a g22 v10 is uh because if you look at the devices you can see down here that for the 22 v10s um you can use p22 v10 or g22 v10 uh and you can do that for any of these so that's why i've put specifically g22 v10 down here in the device okay so all we have to do is compile it that's this button right here and we've got five warnings and zero errors now the warnings there are four warnings over here uh it says that there's no expression assigned to q0.sp now sp is the synchronous preset line for all of the flip flops there's also an asynchronous reset line which we've connected up to the reset input but we haven't set the synchronous preset to anything because there's no reason for us to preset any of the flip flops so it's just warning uh it's just warning us saying you know hey you might have forgotten to use a synchronous preset so there it is um what's the fifth warning missing header items it's probably just complaining that um there may be a missing header over here or a missing annotation that's actually not important it's just a warning as long as it's not an error we don't really care um okay that's front panel one now what the compilation did was it output a jeddak file and also a documentation file so here's the documentation file this is the end of the file let's go all the way up to the beginning and you can see that it's basically copied over some of the annotations um these are the expanded product terms or the minimized equations this is actually front panel two let me open front panel one sorry about that so front panel and the interesting thing is that it's in all caps why legacy software there we go so these are the expanded product terms so here's q zero and of course the asynchronous reset is the reset line there's q1 q2 and so on um this is nice because it shows you how many product terms you used and how many product terms are available for your chosen pin different pins have different numbers of product terms available so this is useful to know because you might say oh my product term actually has 14 uh i actually have 14 product terms but i assigned that to pin 21 which can't take 14 product terms so i'll just assign it to pin 20 instead so that's nice uh this is the fuse map and this is the pinout which is very very convenient so you can see exactly which pins are what so that's front panel one let's go ahead and compile front panel two so i open front panel two i don't need to set any options i just hit compile one warning what's the warning a missing header item that's okay at least one of the header statements is missing well which one is missing thanks for letting me know legacy software so now we're done with that um let's take a look at the result front panel two dot doc and there it is expanded product terms the this thing fuse plot and the chip diagram uh it's actually kind of nice to look at the chip diagram to make sure that you're that it actually ended up with 24 pins which is the number of pins in a 22 v 10 instead of a 16 v 8 which has i believe 18 pins so that's nice uh let's take a look at the jetik file as well um jetik is um a file format that is quite old so it'll look a little odd front panel dot jet so basically a great start of text um non printable characters that's okay um so again a bunch of headers uh and then it's got basically a bunch of commands this this tells the programmer how many total fuses there are i think the f zero line basically says this is the default value of a fuse if it's not specified and then you've got a bunch of lines starting from fuse number zero what the settings of the fuses are and so on um and you can i believe skip fuses because yeah here is a whole bunch of skips because you've defined or the compiler has defined the default setting of a fuse uh there's a checksum at the end and then i think that's a checksum for the entire file so that's basically what a jetik file looks like and the programmer software should accept that and program our chips which we're going to do now program our chips now i bought some atmel uh chips but i'm going to be using these lattice gals uh why well funny story so i bought this uh vp 598 well on programmer which claims to be able to program the atmel chips well it turns out that it doesn't um i actually did program one or two chips successfully but every time after that uh it just seemed to not pass checksum and it it just didn't work um and it even didn't work sometimes with some of these lattice chips which is quite surprising so uh stay away from this instead i'm going to use the mini pro programmer which also does not support the atmel chips but at least they say they don't support the atmel chips but they do support these lattice gals and you can get lattice gals off of ebay pretty easily there's um i guess millions of them out there so let's take a look at the software so uh what we're going to do is we are going to select an ic and specifically it's going to be a pld or gal it's going to be a lattice chip because they they only support the atf 16 v8 uh so here's the lattice uh section and i have a gal 22 v10 d so i'm just going to select that um i do not encrypt anything because i am an open sort of person that's the way i roll uh okay so the next thing that i need to do is open the jetec file so where are we front panel one dot jed open okay and you can see that here's the fuse map loaded all the way down to that very last fuse so now uh i'm just going to plug the mini pro in great um click that off again i don't know why it set that again and hardware interface yes it's tl 866 so i am just going to put the gal in like that and then i'm going to hit what program right programming chip yes code memory lock bit i have no idea i don't think i want to lock it so yeah because otherwise i couldn't rewrite it i guess without erasing it i don't know anyway program erasing programming verifying done okay so that's uh gal number one and of course now i have to remember that that's gal number one i could put a little label on it um which is probably a good idea but i'm not going to do that right now so here is going to be the second gal so i'm just going to open that front panel two dot jed okay and again it it tries to encrypt by default why um and then we just go ahead and program program erasing programming verifying done okay that's it so now i have gals one and two and i can test that which we will do now test those okay so here i have the circuit hooked up i have the two gals hooked up i've got four leds here for the states you can see that the next state goes to the current state using these jumpers and they get transferred over to the combinatorial gal on this side using these jumpers and i have four leds here i don't have enough leds to show all of the signals but this is just going to be an example so the first led here on the left is the address register to the bus so that goes from the counter that stores the address to the bus the next one is the address clock the next one is the address increment signal or the address up down signal and this one over here is the output enable for the chip for the for the ram so i'm just going to put this little piece of plastic over the leds because it makes it easier to see and this wire is hooked up to the increment read switch so basically i'm going to simulate the increment read switch using this wire and this button is the clock the idea is that the clock is continuously going at like you know two megahertz or four megahertz or whatever it is i'm just going to press this whenever i need to so okay so first we're at state zero and now i'm going to simulate pressing the switch i can keep clocking the state machine and of course we're not doing anything because we are waiting for the for the switch to be released this led over here is output enable it's a negative signal so you can see that it is not asserted so now i'm going to release the switch and in the next clock cycle we're at state five and output enable has gone low which means that we are now enabling read from the ram and the address increment has gone high so the next state is state six the address to bus has gone high so we are sending the address that's in the address register over to the ram so the address clock went high which basically says to the register okay increment your address and in the next state again the address to bus signal is high so we are still sending the now incremented address over to the ram notice that output enable is still enabled so and then we're back to zero now again i don't have any any extra leds to show the state of the data clock but if i had it would have shown that after incrementing the address there's one more cycle where we actually clock the data from the ram into the data register and now we're back in state zero and we are just waiting for another switch press so that actually works pretty well great now we have to breadboard the entire circuit so let's do that all right so here i've breadboarded eight bits out of the sixteen i don't really need to have more than eight bits just for testing this circuit will work for any number of bits okay so here's the display for the address and here's the display for the data so i've put leds on several of the signals i have leds on the buffer signals and i also have leds on output enable and write enable on the ram and the reason that i've done this is because i want to make sure that on power up when we are at state zero all of these leds are off and by the way i should mention that when i looked at the data sheets for the buffers i realized that the output enable for the buffers are active low so i quickly went into the pld file and basically i just negated those signals and reprogrammed the gal and i was good to go so anyway i've connected these leds actually backwards so when they are off that means that the output enable is unasserted so i want to make sure that all of these leds are off we're not writing to the chip we're not outputting from the chip and all of the buffers are off uh if one of these is on i guess that's okay but if two of them are on that means that two buffers are fighting for the same bus and that's really bad and then i will quickly turn off the circuit so let's go ahead and turn on my power supply and make sure that all of these leds are off yep okay all of the leds are off that's great um i can clock the state machine and nothing happens um the odd thing though is that the displays are off also and the reason for that is that i actually forgot to connect the power signals between the uh the state machine breadboard and these breadboards so let's do that right now so i'm just going to take uh two jumpers and i'm going to connect the positive to the positive and the negative to the negative and now i have to do my test all over again so power supply on excellent all right so here is the um so this is the address and this is the data uh the data is the address and the data should basically be random except for the top eight bits which i've hardcoded to zero um i don't have any address or data switches going into here so uh this is where the data lines would go in from the front panel and this is where the address lines would go in from the front panel uh i don't really know what they would be set to if they're just left unconnected so um i'm just going to do a read and see what happens so i'm going to clock once okay nothing happened because of course we're waiting for the switch to be released okay so here we have the output enable goes uh asserted for the ram and also uh this buffer which which is the address um lines from the front panel goes to the ram so in theory we're outputting some address over to the ram i guess it's going to be zero so i'm going to clock this in again okay so it's actually ff and then i'm going to clock again okay and these lines went low and presumably i've clocked something into the data and that's that okay uh that was interesting um let us change one of the address lines to a zero to make sure that we are actually properly clocking in the address so i'm just going to randomly change one of the addresses to zero and i'm going to press the read switch okay and now we are sending the address over to the bus which is the ram and also the uh register and also we are outputting the data and if i clock it once again we should latch the data and the address in okay so there we go fb and apparently at that address is three two and that's it so reading actually seems to work which is quite nice let's try writing so let's see we've got three two here um when we're reading from address fb so what i'm going to do is i'm going to change the high bit which i believe is or maybe it's the low bit well either the high or the low bit i'm not sure which one it is i'm going to change that to a one and now we're going to try to write so now very delicately i have to try to change my switch jumper over to the right signal and then make the read signal always low i don't want to disturb any of these delicate wires here okay so let's see if we can write so writing will result in the address and the data buffer is going high this um the address register should never be going on to the bus so let's see what happens okay release the switch okay great so the address and data buffers are now high meaning that they're both being the address and the data are now being sent to the rim um now i press again okay so we've clocked apparently ff in there and that's it okay so apparently we've written ff into the memory okay because none of the address none of the data lines were actually set um now let's go ahead and read i really need another jumper do i have another jumper here not conveniently close that's unfortunate okay well here maybe i'll use this long wire here or maybe this big green wire okay that's my read switch okay so i'm going to press the read switch now and i should be reading back ff instead of three two if right actually worked okay release the switch okay we're sending the address over to the ram we're outputting from the ram okay i think that is correct so let's see what happens when i increment read when i do an increment read so we should see the address go up and whatever is in the ram will be displayed so let me get an increment read jumper okay press the switch release the switch okay we're outputting uh-huh we just went from fb to fc and we're outputting whatever is in the register over to the bus that's good and apparently at that address was zero a done uh let's just do it again for fun because that was actually quite fun okay fd and there was an f0 for whatever reason at that address excellent now we are going to write to the data uh to the to the ram using increment write so i'm going to get one final jumper this is the last jumper the last switch so increment write means that we're going to take whatever is here and what i'm going to do is because i know that we're going to be writing an ff i'm going to change one of the lines to a zero so i think that's either going to be 7f or fe one of those depending on whether i got the high bit or the low bit uh okay so uh an fd so the first thing that should happen is this should go to fe then we're going to write that to the data to the to the ram okay so i press the switch okay now this is interesting uh this i don't think should have happened it looks like the data bus the the data lines have been put onto the data bus i have not yet released the switch so that's not great i will have to look at that um so now let me release the switch okay we went to fe we wrote an fe and we're going to run well we we latched an fe from the front panel we're writing to the ram and now we're done so now if i let's see which one is the read switch this one is the read switch if i read nothing should change well well okay so for some reason i got an fa and a three nine here that shouldn't have happened okay let me do another read okay um oh that's right of course well okay so the reason probably that the address um changed is that we're actually reading from the front panel when i did that and the front panel switches are basically not connected so i could get zeros and i could get ones so well all right in any case i'm pretty sure that everything worked uh the only question of course is the increment write so let me do that once again right that should not happen it should wait until i release the switch okay so this went to fb which is correct we are writing an fe and that works pretty well okay so everything is actually working with the exception of this one thing over here um that's not critical but i want to fix that and i will do that in a moment all right so i went ahead and changed the equations what actually happened was there was a bug in gal one where when i pressed the increment write switch it would go to state 12 instead of state 11 in other words it wasn't waiting for the switch to be released so i fixed that in the file and i ran it through wincouple and wincouple started giving me these mysterious program errors um it turns out that when i changed the optimization method from espresso to mccluskie quine those errors went away so i suspect that maybe they're using an older version of the espresso library that had a bug in it or something in any case uh when i changed the optimization method um the program compiled properly i reprogrammed the gal and stuck it in and now let us test that final thing so what i'm going to do is i'm going to do an increment write and this time when i press the button you can see that the buffer is not enabled and it will wait until the switch is released increment write done okay and that's the ram circuit well i hope you enjoyed that um this was a very very long um video but there was a lot of information to go through and i hope maybe you learned something possibly um there is one other thing which is test vectors you can actually put test vectors into a jetech file and what that will do is basically do what i did in hardware except in software um well okay not necessarily in software but when the gal is in the programmer after it's programmed it will be stimulated with your stimulus vectors and then um read back to make sure that it um it reads uh whatever you were supposed to output so that is actually a very convenient thing and i might have done that and that may have saved me a little bit of effort um but that's just something you should know that test vectors for jetech files do exist uh i guess that's it so i will hopefully see you on the next video