World's worst video card gets better?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
i'm working on hooking up this homemade video card to this homemade computer and in this video i'm actually going to bring it all together and get it working so that we can actually write some software for this computer that will output some sort of image to a standard vga monitor and by the way if you're interested in following along with this project you can now get a kit with all the parts for the video card over my website eater.net vga you can also get a kit for the 6502 based computer eprom programmer and anything else you'll need in order to recreate and experiment with this project yourself there's also schematics and other things there so check out eater.net vga for more all right so where we are is we've got this video card that is it's being driven by a 10 megahertz crystal oscillator that is driving these counters we've got a set of counters that are counting the horizontal position and then those are rolling over to a set of counters that are counting the vertical position and that's so that we're essentially scanning line by line here each scan line and going through every pixel on the screen all the way down to the bottom and then those counters reset back to zero zero for the next frame and previously the way we had that hooked up is we had the horizontal counters and the vertical counters all fed into the address lines of a rom chip and that rom chip was pre-programmed with the pixel data for a particular image and then the output of that rom chip the the data lines were connected to the series of resistors that would break out different voltages for red green and blue to give us 64 colors to actually send that image data to the monitor in the last video we removed that rom chip because we don't want to just have a single pre-programmed image we want to be able to control what's displayed on the monitor through the the computer and so we remove this rom chip and hook those counter lines up to a couple buffer chips and these buffer chips in turn are connecting it through to the address bus of the computer except that we've tied a couple address lines to fixed values so address 15 is tied to ground address 14 is tied to ground address 13 is tied to 5 volts and then addresses 12 all the way down through address zero are connected to those counters and so you can see that here so address uh 13 is is high 14 and 15 are tied to ground and what that does is that it ensures that those address lines whenever the video card is putting an address onto the computer bus it ensures that those first three bits are zero zero one which means that the resulting address whatever the rest of these things are is going to be somewhere in the range of two zero zero zero through three fff and that ensures that when the video card puts that address onto the computer's bus it's you know addressing something in the computer's ram so that way it will actually read the the pixel data from from the computer's ram which means that the computer of course can write whatever it wants into that same ram area to to have something show up on the monitor so when the video card puts one of these addresses on the bus and puts that on the ram then the ram chip is going to in turn put whatever is is in that ram value onto the data bus and that's coming back to the video card through these connections here and hook to to this buffer here and so this is the data bus and it's only six bits because the video card currently only supports 64 colors so we only need six bits for that but we've got six bits from the the data bus connected through this uh this series of buffers going to these these resistors and those resistors convert that six bit value into three different voltage levels for red green and blue to give a particular color and actually there's still a bunch of extra wires here from when we used to have these resistors connected to that rom chip so i'm going to go ahead and remove those right now just to clean this up a bit so there we go you can see the output of the data bus is going through these buffers and just into those resistor dividers which go out to the the actual vga monitor and then the reason we have these buffer chips in here is it gives us the ability to enable and disable them so that we can either attach or isolate the vga card from the the system bus because if the vga card were always putting an address out onto the address bus then the cpu on the computer wouldn't be able to do anything with the address bus or data bus and likewise if we were always reading whatever was on the data bus and putting that out to the vga monitor then we'd be putting garbage out to the vga monitor during the blanking intervals because remember there's this display time but then when you get to the end of a scan line there's a blanking interval where the vga monitor expects us to just be sending black to it and then same thing at the bottom of the frame so at the end of the frame here it expects some period of time where we're just sending black so we need to be able to not just send whatever happens to be on the computer's bus so we have a buffer for that as well that we can disable and this is also part of our strategy for actually making this all work in the first place because in order to share the bus we need some period of time where the vga card is able to access the bus and therefore memory and that's this display time and then we need some time for the computer or the cpu to be able to access the bus and we're actually going to do that during this blanking time this is not the most efficient use of time because this display time is is something like 71 percent of the time so 71 of the time the cpu won't actually be able to do anything but i think that's the simplest way to get this working so that's what we need to do now is we need to build all the logic that flips all the right switches so that the vga card has access to the bus during this display time and the cpu has access to the bus during the blanking time and in particular what that is is we've got the enable pins here for these buffers so whether these buffers are enabled we also have the bus enable pin here on the cpu which which tells the cpu whether it's able to access the bus or if it's isolated from the bus then we have the ready pin which will pause the cpu so that when the video card needs to access the bus the cpu will be paused and not trying to access it at the same time so how do we get all those control signals flipped at the right times well here's the schematic for the video card and we've got the horizontal circuitry here the vertical circuitry here and those are already generating these horizontal blanking signals and vertical blanking signals which will tell us when we're in the horizontal blanking interval or the vertical blanking interval and it's when we're in these intervals that we want to flip things around so that the cpu can operate and these are both active low logic that's what the bar over over the top is so when we're in the horizontal blanking period this will go low when we're in the vertical blanking period this will go low or another way to think of it is when we're not in horizontal blanking this will be high when we're not in vertical blanking this will be high so if both of them are high then that will mean that we're not in horizontal or vertical blanking and that of course means that we must be in this display time here so just ending these two together will give us a signal that tells us whether we're in the display interval here where the vga card should be active and when the vga card is active that's when we want these address lines to flow through to the address bus so these counters we want those to go into the computer's address bus and we want to be reading data from the data bus and using that to send the pixel data out to the vga monitor so we want to end these two together but then what we want to do with that once we've added them together is use them for this chip enable to enable these buffers and this is an active low this chip enable that's what the little bubble here means so actually we need to add them together and then invert them and of course easy way to do that is a nand gate we add a nand gate here and we connect the horizontal blanking although we don't actually necessarily want to only activate this when we're outside of the vertical blanking interval because remember the vertical blanking is just this blanking time at the bottom but because we didn't have quite enough ram in our in our computer you know we dropped one of these uh these address bits here so we're not using one of the address bits so our vertical counter is only able to count up to 64. so instead of having you know 100 pixel by 75 pixel resolution we've got 100 pixel by 64 pixel resolution so actually we maybe want to hand control back over to the cpu once we get to row 64 and that'll actually give us a little bit of extra processing time here at the bottom of the screen so rather than looking at that you know vertical blanking signal what we could do is look at this high order bit because once this counts up to 64 you know these first six bits get to 64. it'll roll over and this bit will go high and that bit will stay high you know for those last 11 pixels of the screen as well as during the entire blanking time until the entire counter resets back to zero so we should actually look at this q9 here instead of the vertical blanking signal that we already have because that'll tell us you know when we're in any any of that interval the only problem of course is we need to invert it and actually since we're already using nand gates rather than using an inverter we can add a nand gate here and just tie both of the inputs together and that will act as an inverter because either both of them are high in which case the output will be low or both of them are low in which case the output will be inverted and will be high so this here will give us a signal that will go low anytime we're in that display interval so when this goes low we want to start putting the address data out on the bus we want to start reading data in from the actually from the from the data bus from the computer you want to start reading that data in and feeding that through this uh this set of buffers so we can hook this up to the chip enable pin coming out of here so here's chip enable so we could hook this up over here like that we can also hook it up to the chip enable here for putting the the address out on the address bus though actually i don't want to hook it up directly there because this is a little bit more timing sensitive and what i mean by timing sensitive is that we've got something a little bit tricky going on here which is we have two different clocks we have a 10 megahertz clock that's sort of running the video card and then we have one megahertz clock that's providing the cpu clock for the computer and so in particular the thing we need to worry about is that this 10 megahertz clock is just sort of running independently of what's going on with the computer and this 10 mega clock is what's going to kind of determine when it is we get into these blanking intervals and so when we would need to switch from the video card being in control of the bus to the cpu being in control of the bus or vice versa so if the video card is trying to take control of the of the bus away from the cpu it's just going to kind of do that whenever it gets to that blanking or whenever it gets to the end of the blanking interval and into the display time then it's going to say like nope i'm taking control of the bus now and the problem with that is that because this is running completely on its own with its own clock that could happen in the middle of an instruction with the cpu and so if we just hook this up uh like this to the chip enable line then these buffers would enable and we would just be putting whatever um coming from the video card onto the bus perhaps you know in the middle of an instruction which could interrupt something that's going on here it could even interrupt a write so if the cpu was writing to ram and we just go flipping the address to something else we could end up writing to some other part of ram or you'd have the you know the cpu potentially conflicting so we need to make sure that when we switch control of the bus from the video card to the cpu or from the cpu to the video card we need to make sure we do that during at a fixed time during the clock cycle of the cpu which means that somehow in this switching logic we need to incorporate the cpu's clock and the way to do that is to use a latch so what we can do is we can take this uh and run it into basically a d-latch and then take the output of the d-latch and run that into this chip enable like that and then the latch will be controlled by the cpu clock in this way when that blanking signal changes it just changes the input to this latch and then the output of the latch doesn't then change until the next clock cycle from the cpu that way this output is changing only on the rising edge of the clock cycle and so this sort of works to synchronize that flipping of of who has control of the bus you know it synchronizes that with the cpu clock and here's a basically a redrawn version of that that's a little bit easier to see but we're taking this last bit from the vertical counter inverting it through this nand gate and then nanding it with the horizontal blanking interval and then this output here will go low any time we're in the display interval so whenever the the vga card ought to be controlling the bus and that's going directly into the enable pin with chip enable pin here for this set of buffers that's reading from the data bus and outputting to the vga port because it's okay to read from the bus anytime you know and we want this to be you know in sync with the clock on the video card so that the vga gets the right timings and everything but then we're also taking that same signal and we're running it through this d flip flop and the d flip flop will just take whatever comes in the d pin and put it out the q pin but it'll be gated by the cpu clock coming in the clock pin here and so this is the schematic for the the completed video card and so you can see how it interfaces with the rest of the computer you've got the cpu clock coming in here you've got the you know the address bus going out you've got the data bus going in we've got those hooked up already and then there's also this what i'm calling dma pin dma stands for direct memory access and that's a pretty common term for when you have some peripheral in this case a video card that has direct access to the memory so it doesn't have to communicate with the cpu in order to read or write from system memory and of course that's exactly what we're doing because we're directly on the bus and we can directly talk to the memory so this dma signal in addition to enabling these buffers to to give the video card access to the bus we're also using this dma signal then to go back to the cpu to uh this will this will go to that halt pin on the cpu or the ready pin rather on the cpu and it'll go to the bus enable pin on the cpu as well to tell the cpu that it no longer has access to the bus so let's start building this well first i'll hook up these nand gates and kind of running out of room here but i think i can squeeze a chip in over here somewhere and this is just a quad nand gate chip that's the same one i was using for the eeprom to do the control signal decode before we got that we'll hook up power and ground to it and i believe that last bit of the vertical counter is right in here on this on this third counter chip i think it's right there so we'll hook that up to the uh one of the inputs here and then connect the two inputs of the nand gate together and then on pin three here we'll get the inverted version of that coming out so we basically just built an inverter with an and gate so that's this guy here and then i guess we can then feed the output of that into the input of the next nand gate so we'll just connect pin three to pin four connect pin three to pin four there we go and then the second input of that next nand gate will go to the horizontal blanking which is coming off of this other nand gate right here and so now pin six coming out of this nand gate is this signal here and this signal of course is going to go to the the chip enable for the the data bust buffers and then we're also going to want to feed it into this latch so let me start by wiring up the latch so this is a 74 hct 74 which is a a dual d flip flop here we can adjust a little bit to get things to fit better maybe close enough there we go getting a little tight in here and so the input for this d flip flop is pin two so hook uh pin two up to the output of the nand king of the second nand gate down here so that's our input and then the output is on pin five so pin five here goes to the chip enable for our buffers and then the clock is pin three so we'll have to connect that over to our system clock over here so pin three goes to the clock on the cpu and this is just going to be part of the interface between these two and finally the enable for the data bus buffers is coming directly out of that nand gate down here so that's just this pin here going up to the chip enable of the data buffer right there so this is maybe getting a little bit messy but i think that's okay because we're pretty much done with the video card in fact i think there's only one last piece of interface between the video card and the rest of the computer which is that dma signal so remember we have this dma signal which you know signals to the computer that there's a peripheral that wants direct memory access and that's the signal that we're using to enable the the address bus access so when that when that pin goes low then the video card immediately starts taking control of the of the address bus and so it can start addressing whatever it wants and getting whatever data it wants from from the other parts of the computer but that dma signal also needs to tell the cpu to halt and to relinquish control of the bus and that should be straightforward enough because we can just connect this signal this is the dma signal over to our bus enable and ready signals and let me not tie that high anymore we don't want that so now that bus enable which is i think print pin 36 there and the ready pin which is pin two there when those are low the cpu will halt and it will relinquish control of the bus which means that the video card then is able to take control of the address bus and it means the cpu won't be doing anything with the data bus so that if the video card puts an address on the bus that starts talking to the memory the memory can put data on the bus and the video card can read it the other thing that the bus enable pin does is in addition to disabling the address bus and the data bus it also disables the the read write pin so pin 34 on the cpu is the read write pin and that tells that's that's the cpu saying whether it's reading or writing from the bus because the cpu of course can read from memory or write from memory and it uses that pin to indicate whether it's reading or writing when the video card takes control of the bus it now also needs to set that pin either high or low to indicate whether it's reading or writing but in the case of the video card it's always reading it's it's never writings the video card is never putting anything into memory it's only ever reading memory so we can do is add a resistor to pull that high and what this will do is if nothing is asserting the read write pin either high or low then the resistor will just pull it high which means that when the cpu has control the cpu will be setting it either high or low but when the cpu gives up control because the video card is taking control a resistor will pull it high and so the whole bus will just be set to reading because whenever the video card's active all we want to ever want to do is read so i think that's pretty much everything we need we've got our whole sort of bus mastering scheme figured out here so that either the cpu is going to be the bus master or the vga card is going to the bus master based on whether we're in the display interval or not and if we're in that display interval then we're going to detect that and both set the you know us to read from the data bus as well as in sync with the system clock trigger the uh the address bus so the video card can can write out an address to the bus to read from memory um i guess actually we are missing a couple things so the the flip flop here this d flip flop has got a couple extra pins that we need to hook up so it's got a clear pin that we need to tie high so that it doesn't you know go clearing itself and that's pin one and then pin four is a reset pin or excuse me pin four is a set pin so pin pin one's the reset pin pin four is the set pin so those those can override without waiting for the clock we're not going to use those we need to tie those high but i think with that everything else should be pretty much set up so i'll go ahead and power everything up and i could power the computer and the video card separately or we could just connect power but in either case we want to connect a common ground across them but i'll just power them both with the same same power here and plug that in reset the computer and so the computer should be running now let's try plugging in the video card and see what happens oh the monitor is coming live and well that's that's certainly interesting so we're getting something so obviously we're getting something on the monitor and it looks like garbage which i guess is what we'd expect right because we're just reading from memory and we don't have a program running that puts anything useful in memory so it's just going to be filled with whatever garbage happens to just randomly be in that area of memory i also see this interesting artifacting with sort of these weird lines and stuff going on and this stuff over here at the edge i think i have some idea what's going on there but we can take a look at that a little bit closer and then of course you see at the bottom uh the last section of the screen is black and that's because when we get to 64 pixels we switch over and give control back to the cpu so this is essentially that extra processing time that we got so it looks like this is sort of working but it is hard to tell because we're not really sure what we're supposed to see because we don't know what's in memory so let's go ahead and write a quick program to just fill memory with something known so we have some idea of what we're looking at okay so i'm going to write a program that's going to run from rom and our rom starts at address 800 then we have to have our reset vector up at address f ffa and then we also have our irq and nmi vectors and i'll just point all those to the same label which is reset and then reset here will be where we start the program so basically what i want to do is just have a loop that goes through and fills up video memory with something distinctive and so what i'll do is i'll start with initializing this variable vib page to the video memory which starts at address two zero zero zero and we'll use this variable as we go through our loop and fill up video memory with with some data and then vid page itself is just a variable name um and it'll be stored in ram and i'll just store it in ram at address zero just right at the beginning of ram and that's a two byte variable basically the way i'm going to loop through video memory is with two counters one is the x register which will uh just count down from hex to zero all the way down to zero and that will sort of count which page we're in in video memory because we start at sort of address two zero zero zero and go through three fffs there are in hex there are two zero hex pages of 256 bytes each and so x will just count down from two zero all the way down to zero and then y will use to count up as we fill each page with with some data and then the a register will just keep track of what color the pixel is that we're putting into memory and we'll increment that or do something with that as we go and if we do this store a video page comma y this will uh store to the the address of the video page which you know starts out at two zero zero zero plus whatever value is in y so if we increment y we can go through the page and then when we get to the next page we'll increment the the actual base address that's in the vidpage variable so after we write each pixel we'll increment the a register so that the next pixel is a different color now we'll increment the y register so we're pointing to the next value in memory and as long as the y register didn't roll over so we'll just loop back up to this page label and and we'll just keep writing incrementing the color and incrementing the the address each time when we do get to the end of the page we're going to fall through this branch not equal so in that case we'll increment the video page and actually we're incrementing the second byte of the video page so a video page started out as 2000 in that in that variable and this will increment it so now it's it'll be 2 1 0 0 2 2 0 0 and so on and then each time we do that we'll decrement x and remember x started at 2 0 so as long as that hasn't gotten to zero then we haven't gotten all the way through video memory yet so then we can just loop back up to this page and and continue writing to to memory so now we've basically got two loops we've got one loop with the y register that's going through each address and then one loop with the video page where we're decrementing the x register that's going through all of the pages and then once we're done with that we can just jump back up to the top and go through this whole loop again so i'll just jump right back up here and this will just continually fill video memory with some data that'll should look like something so let's save this and then i'll go ahead and assemble it and then we'll program the eprom so we have a 28c 256 type eprom we're going to write the output of that to that eprom and there we go i'll put the eprom back in our computer here and power up see what we got reset and okay so we're getting these colored bars which is kind of what i'd expect it seems like there's some other stuff going on for sure but what i would expect is nice clean colored bars and we're not exactly getting that there's a lot going on here and you do see the colored bars but but one thing i noticed is that on some of the scan lines here the transition from one colored bar to the next seems to be delayed that's why i think you see these little stripes that go left to right so you see it's you know maybe transitioning from one color to the next on that scan line and it you know on some scan lines it's just delayed for some reason so it suggests that there's maybe some kind of timing issue going on so what could be causing something like that you know we've spent a lot of time looking at the control logic and hooking all that up you know did we miss anything um i think one area maybe we haven't looked too closely at is what exactly is going on with the cpu when we're just pausing it and unpausing it and is there anything you know that we missed over here because we've got this basically this one signal this dma signal that comes in from the video card in the video card i'll search this to say i need to read from ram right now and you know we're using that to pause the cpu and and give up control of the bus and uh let's let's take a closer look at what exactly this thing is hooked to so we took to the bus enable pin and the ready pin and then really the only other thing we did with the computer is we have this pull up resistor on the read write pin so if we look at the schematic that dma signal is going into this bus enable pin here and which is no longer tied high and it's also going into the ready pin here which is also no longer tied high through this resistor so that's all gone and these two are tied together and this goes into that you know that dma that dma signal and that's an active low signal so that comes in and when that goes low what that says is it says to pause the cpu so it brings ready low and it also says to disable the bus so bus enable when that goes low that tells the cpu don't put anything on the data bus don't put anything on the address bus it also says don't put anything on this read write pin and so that read write pin you'll remember we also added a resistor tying that high and so once that dma signal goes low the video card ought to be able to read from ram just fine right because it it can then put whatever it wants on the address bus the cpu is not going to be doing anything with the address bus and it can read whatever comes out of the ram chip on the data bus and the ram chip because this uh read write pin is tied high and the cpu is not asserting that that read write pin um is this right enable pin on the on the ram chip and so that's tied high and so right enable is active low so it won't be active so so it'll be reading so whatever address goes in from the video card we're going to get the appropriate data coming out so that all seems fine right well we do have some other control signals here so this output enable we want that to be active we want that to be low because that's active low well that's tied to address 14. so as long as we're you know reading from an address where address line 14 is low then then that ought to be fine and and we will be right so address 2 0 0 0 through 3 f fff those those all have address line 14 low so that's that's no problem and then we also have chip select we want that to be low and that's coming through some of this address decode logic but in theory you know address line 15 is also going to be low if the video card is reading because the video card's setting all of these all these address lines so it'll be setting that low and if that's low then this is basically just inverting it and so as long as both of these inputs are high this output will be low and chip select will be active so what's this other input because that's got to be low as well so where's that coming from so if we follow that around that is coming from the clock and that is potentially a problem in fact it is a problem because what's happening is even if the video card has asserted this dma and brought that low and it's putting an appropriate address including you know address line 15 being low so that it's trying to read from the the ram if this pin ever goes low then the ram chip will be disabled and whatever's coming out will you know basically be garbage and this pin is going to be going high and low with this with the computer's clock so it's just going to be arbitrarily just like toggling high and low and so sometimes it'll be high and this will work fine and sometimes it'll be low and and it won't work and so that seems like it's going to be a problem and you know we can't get rid of this because we we still need this here uh for when the cpu has got control of all of this because you know if we're writing to ram remember we needed this this extra logic here so that the write happens on the first half of the clock and then this chip select goes inactive uh prior to the address changing so that you know during the write we don't corrupt ram or anything you can watch previous videos to see exactly how that works but we do need this here but we need some way to say that when this dma is active active low that is when when the video card wants to read from ram you know we don't want to be toggling uh the chip the ram chip on and off based on this clock here we want to get that out of the out of the loop here so what we could do is we could add an and gate in here and take the output of this go into the and gate and then the other input is this dma signal same same signal as we've we've got here and what this will say is that when the video card is not active that is this this dma signal is high because it's active low so when this is high then you know this and gate basically is transparent so whatever we would normally have we we we send through and and the chip select works the way that it needs to work when when the cpu is active but when the video card is active this dma goes low then the output of this and gate will will always be will always be low and so anytime this dma is active and low then this chip select will be will be low meaning that the ram is active and so i think if we add something like this that will clear up at least some of the problems that we're seeing so let's do that okay so that chip select pin is pin 20 here and that's this yellow wire here that's coming from the nand gate over there so let's get that out of the way because we want to basically have this coming from an and gate instead so i'll pull this out of there and then i'll add some and gate so this is a 74 hct-08 that's a quad end gate and we're only going to be using one of the and gates on there i'll connect up power and ground to this chip but it's the output now of one of these and gates that's going to be the input to the chip select pin on our ram chip but let's connect that up we're going to go from pin 20 which is our chip select pin on the ram and this should make it around to the output here of one of these and gates and then one of the inputs of that and gate is going to be the output of this nand gate here so this is where we were connected before so if we just hook that up like that if the other input of this and gate were always high then this and gate would be doing nothing and we'd essentially have exactly what we started with but instead i'm going to hook the other input of that and gate up to this dma pin that's coming in from the video card so that way when the video card wants control of the bus and it wants to be able to read from ram it can bring this pin low and then the output of this and gate will always be low which means the chip select for the ram will always be low when when the dma pin is active which then means that the ram will always be active whenever the dma pin is active meaning that the the video card will be able to read from ram whenever it needs to and then it's always a good practice to tie the unused pins of these these gates that we're not using high so that those inputs aren't fluctuating so that the gates aren't switching needlessly and drawing current and increasing power fluctuations okay so let's give this a try we'll power it up reset and here we go oh okay so this looks better um you definitely see the the stripes much more clearly you don't have that fuzzy stuff that was going on there but it looks like there still is some weird stuff going on here we've got these sort of random pixels popping up there's this weird sort of thing where it redraws or it gets out of sync or something it's not clear what's going on there and then there's this fuzzy stuff over on the left side of the screen so what what else might be going on well this is kind of a tricky one but i think it's related to the same issue i was talking about before as to why we have the clock going through this nand gate to control exactly when chip select is is enabled um when the when the cpu is running because i think what's happening is the ram is actually getting corrupted that certainly would explain the random pixels that we're seeing if just a byte in memory just gets randomly corrupted and it might even explain that sort of jumping because remember we have that one variable that's in ram which is the memory page so if that got corrupted we could maybe get out of sync with where we're filling the video memory and jump to somewhere else so that might explain some of the things we're seeing if what's happening is this ram is getting corrupted somehow and so i think that could happen if we had some address uh some random address here and the right enable pin were to go low at the same time that the chip select pin were low and normally we prevent the chip select and write enable pins going low at the same time before the address is stabilized by having this logic in here that says that the chip select pin can only go low on the second half of the clock cycle so that way we know that the address is stabilized but now we have this other condition that happens which is when the video card takes control it immediately sets this chip select low as soon as it takes control and i think what's happening is if we're in a write cycle which you know our program is certainly doing a lot of writing to ram so that could happen quite a lot but if we're in a write cycle when the video card takes control of ram it could be the case that we would um you know accidentally write some junk that's on the data bus to whatever address happened to be on the address bus at that moment that the video card takes control so that's my my hypothesis of what's what's going on here now a potential solution would be just to ensure that this chip select never goes low on the first half of the clock cycle and there's actually a pretty easy way to do that because we actually do have some control over when this dma pin gets asserted because it's coming from the video cards the video card is sort of jumping in and saying hey i need control of the of the ram right now but it can't do that whenever it wants it is gated by the system clock right now it's gated by the rising edge of the clock but i i think what we could do is if we gated it on the falling edge of the clock then when it takes control of ram it would take control in the middle of the clock cycle i think that might tend to avoid that situation where right enable and chip select are both active at the same time when we don't want them to be so i guess in order to switch this over so that instead of being gated by the rising edge of the system clock the the video card is gated by the falling edge of the system clock really we just need to invert the system clock we just need to invert this signal and conveniently we have an extra nand gate here and we can always easily configure a nand gate to be an inverter so let's let's do that so i'll disconnect these two inputs that we're just tying time high and then we'll just run the clock into one of the inputs of the nand gate and then connect the two inputs together and that way if both of those inputs are high then the output will be low if both of the inputs are low the output will be high and so now we've inverted our our clock so now we have an inverted copy of the clock here and so now this dma pin instead of activating on the rising edge of the clock it'll be active it'll it'll transition i guess on the falling edge of the clock so it'll transition in the middle of the clock cycle instead of the beginning of the clock cycle and hopefully that'll ensure that we don't ever get into that little race condition where the the ram might accidentally get corrupted so let's give this a try power it up reset and wow that looks a lot better we don't have any of those random pixels showing up and it's nice and stable the only weird thing we've got now is just this fuzzy stuff along along the left edge here and that actually makes a lot of sense because the video card is is grabbing and then relinquishing control only during this display time and so when it gets to the end of a scan line it then releases control back to the cpu and the cpu is able to do some processing but then when it gets to the end of this blanking time that's when the the video card then says hey i need control of the bus and everything but that of course is gated still on the cpu's uh clock that's that's what we were just hooking up there and so what happens is um the video card wants control of the bus but the cpu has to finish its current clock cycle before it actually gets it but the video card is is going to just keep on going and grab whatever happens to be on the bus and put that on the on the screen and so the first part of each scan line is really just this last bit of sort of uh processing if you want to think of it that way that the cpu was doing and so that's just kind of a little bit of an artifact of the way that we've designed this is is that there's a little bit of a delay built in when we start each scan line and so each scan line is not exactly starting on time and you can actually visibly see that now we could work around that by changing the timing for the the horizontal blanking right because this horizontal blank signal that we've got that we're using um is just coming off these counters that we've got and the counters are just counting the horizontal position so we've got 100 pixels across and you know between i think it's a 64 pixels then of of blanking interval so we've got these counters when we get to 100 then we are in the horizontal blank and we flip this flip-flop and we get to 164 then we flip it the other way around well if we look at the screen it looks like this margin that we're that we're working with here is maybe five pixels something like that so maybe try adjusting where that horizontal blank interval uh ends by five pixels and and maybe get rid of that you know end it a little bit early to give us some time to wait for that clock cycle so that's maybe something you could try i'm not going to do that in this video the other thing we could do is we could actually just change it so that instead of allowing the cpu to work at all during the horizontal blanking we only let it work in the vertical blanking that's actually a much easier change to make because we can just not and in that extra blanking interval and so now we're not doing any processing in the horizontal blanking interval we're only doing it in the vertical blanking interval and actually if you look closely you can see we still have that problem at the end of the vertical blanking interval so the very first scan line you can you can see the same issue but overall everything looks a lot cleaner so this might be a an easier solution but of course it does come with a processing cost because we're no longer letting the cpu run at the end of every scan line we're only letting it run at the end of every frame so so that's a trade-off so i'll put that back like that for now but i guess the last thing i want to do is this image still isn't doing anything that interesting you know we're just writing these colors to ram and and because the counter we're using to determine what color we're putting in into memory is is basically staying in sync with with what column we're in uh we just get bars nothing interesting is happening so let's modify the program to you know try to do something a little bit more interesting so i'm going to make a couple changes to our program one is that right now we increment the a register and we also increment the y register at the same time and the a register is the color and the y register is the index into memory and because we're always incrementing the color and the index at the same time they stay in sync and so we just end up with those color bars that don't seem to do anything interesting so right after we store the a register to memory that we've got the the color in the a register i'm going to end it with 7f so basically once we get to 127 colors which the video card only has 64 colors so basically once we cycle through the colors twice then i want to sort of do do something a little bit different to get things out of sync otherwise i'm just going to branch down here to where we increment the color but if we have gotten through that cycle then what i'll do is increment the color which because i'm incrementing it again means we're going to increment it twice and so by incrementing the color twice you know once through that cycle that'll kind of get the color counter a little bit out of sync with the with the memory counter and so we should see a little bit more of an interesting pattern than just bars and then the other change i'll make is that instead of always starting with color zero at the beginning of each frame i'll start with a different color each time so that'll be this variable start color that'll just be a one byte variable that's in memory and i'll put it in memory location address 2 right after vid page which is which is two bytes and that'll be a one byte variable and we'll initialize it to zero but then each time through our loop i'll increment it so that each frame starts with a you know a slightly different color than the last frame and so this should cause some sort of activity on the screen uh you know with each frame so so that should give us something a little bit more interesting to to look at so go ahead and save this assemble it and program it onto the eeprom and i'll put the eeprom back in and let's power it up and see what happens reset and there we go look at that so we don't have the columns anymore because we have a little bit of an offset and so that sort of creates this um more of diagonal sort of thing um which gives us something a little more interesting to look at and because each time we re um refill memory with this with this image we offset everything and so that's why you see it sort of shifting and then the actual like you can see it painting um and that's that's not the the monitor painting that's actually the time it takes for the processor to run our program and fill memory so you're actually you know seeing how slow the computer is i guess which i think gives you some some serious respect for people who wrote high performance graphics back in the day with these one megahertz processors of course we are only getting about 70 percent of the efficiency because the processor halted for 70 percent of the time um but but still it's not a complicated program as you know we're literally just going through a couple loops incrementing some counters and filling memory the other neat thing about this is because now we have a little bit of an animation that shows us how you know how fast our processor is running if we make that adjustment to to no longer uh use the the horizontal blanking interval and only use the vertical blanking interval you can see it slows down quite a bit that gives you a very visual indication of what we get out of using the the very end of each individual scan line for processing so i'll leave this here for now and hopefully this gives you a good sense of how a simple video card like this might work and of course there are a ton of different approaches to something like this that i could have taken and of course many ways of improving on on this not to mention you know all those sorts of things you could do with software and to make it do something a bit more interesting so i would definitely encourage you to see this as more of a starting point for exploring and of course to help you with that you know go check out eater.net vga where i'll post all the schematics for this and where you can find parts lists or kits and other useful links and things like that and finally as always i want to say thank you to all my patrons who helped make this video and all my videos possible so thank you you
Info
Channel: Ben Eater
Views: 803,813
Rating: undefined out of 5
Keywords:
Id: BUTHtNrpwiI
Channel Id: undefined
Length: 44min 25sec (2665 seconds)
Published: Sat Dec 05 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.