so i built this video card thing that's
able to output a vga signal
and display a picture on a monitor and
it's pretty terrible so the
the display resolution is 100 pixels by
75 pixels 64 colors
and you know normally you'd expect a
video card to be connected to a computer
but this one just has a read-only memory
that's just hard-coded
with a single image so it only ever
shows the one image
but you know i also built this computer
it's got a 6502 microprocessor
and right now it's just got a couple
text line display here but wouldn't it
be cool
if we hooked this computer up through
the video card to the monitor
to actually display some more
interesting graphics well maybe
remember this video card is is pretty
terrible but hey let's give it a try i
mean
how bad could it really be 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 at 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
okay so what we've got here so far is
we're just generating a static image
and the way this works is we've got some
circuitry here that's generating the
horizontal
uh timing and everything we've got some
other circuitry here that's generating
the vertical timing
all of that together if we look at just
kind of a high level is this schematic
here and if you want more details
on all of that all these schematics are
on my website or obviously check out the
previous videos
but if we look at sort of at a high
level we've got this horizontal
component here we've got this vertical
component each of them has a binary
counter
that's just counting what pixel we're on
so the horizontal
will count from 0 to 100 because we've
got 100 pixels across
so if we look we started 0 up to 100 and
actually it'll count a little bit beyond
that it'll count up to 132
because there's this little extra
blanking time here at the end of each
line
and then when it gets to the end it'll
go ahead and re and increment the
vertical counter
and the vertical counter is just going
to count from top to bottom from 0 to
75 pixels down and actually it counts a
little bit beyond that to 78 or so
before it resets back up to 0 0 at the
top left
and each of those counters the
horizontal counter and the vertical
counter
are counting in binary so if you put all
those binary bits together you get this
14-bit binary value that goes in here
and that forms the address
for the the rom and so whatever is
programmed in the rom at that particular
14-bit address
will spit out some 8-bit value which you
know we just look at six bits of it
and run it through these resistor
divider things that generate
four different voltages per color which
gives us 64 different colors we've got
red green and blue
as for what's actually programmed in
here so basically what pixel you get out
based on what address you put in
that's programmed ahead of time with
with one of these programmers and we
can't change it
and that's what we'd like to fix because
we've got a computer here this computer
can
change stuff in ram but it can't change
stuff in rom rom is read only
so seems like what we need to do is we
need to swap this rom out for some ram
makes sense if you ever look at the
specs of a modern video card you know
the manufacturer is very quick to tell
you it has so many gigabytes of ram
and you know part of that ram of course
would be for storing this what we call
the frame buffer
but in a modern video card a lot of the
ram is used for other processing
so for high-end 3d graphics you know
rather than having the cpu
itself you know come up with every pixel
and fill the frame buffer by itself
the computer will send mathematical
descriptions of 3d objects
surfaces lighting and camera positions
and everything it'll send all that to
the graphics card
and then the gpu on the graphics card
will actually use that to compute the
actual pixel values and fill up the
frame buffer
and that's great because it offloads a
lot of the work from the computer cpu
but
you know we're not going to do anything
fancy like that we just need some ram to
replace this eprom
and hold the frame buffer the trick
though is that the
the video circuitry here needs to be
able to read from the ram
and output the right pixels and
everything and the
cpu needs to be able to write to the ram
uh to update it
you know to change what's being
displayed and those two things need to
happen
without any sort of conflicts and you
know
we actually do already have 16k of ram
in our in our computer
and the cpu of course can already read
and write for from that
ram just fine but what we need is a way
to also allow this video circuitry to
read from the ram
at this you know sort of the same time
and
and that turns out to be kind of tricky
but that is the approach i want to go
with is to share the system memory
that's already on the computer
and put the video frame buffer in that
memory but how do we get the video card
to
share that memory with the rest of the
computer well a big innovation in the
mid 1980s and used throughout the 90s
was dual ported ram and that's what this
uh monstrous chip is here and it's ram
that has
basically two sets of address lines and
two sets of of i o lines
for for data so that two things can
access it at the same time
and this is how a lot of video cards
used to work back then
but nowadays these are becoming more and
more rare in fact this this one chip
that i was able to find
only has ten address lines so it
actually wouldn't even be big enough
it's only a 1k memory chip so it's not
even big enough for our frame buffer let
alone anything else we might want the
computer to do
so nowadays most memory you see is ddr
sdram
and sdram is synchronous dynamic ram
which you know synchronous means that
it's operating with a clock
so reads and writes are happening on
each clock cycle
but the ddr means that it's a double
data rate
so you actually are able to read and
write multiple times
per clock cycle and and being able to do
multiple reads or writes per clock cycle
means that the cpu can still read and
write as fast as it wants to you know up
to
you know once every clock cycle and then
something else like a video card
would also be able to read from memory
at you know nearly the same time
but the memory we've got in our computer
already is not dual ported certainly not
ddr sdram or anything like that
it's uh it's just asynchronous static
ram which makes it very easy to
interface with it's it's you know if you
watch the videos on on how i built this
computer you'll see it's like
not too bad to interface with but it
does make it tricky to try to figure out
how to share it with the video card
and i suppose what we could do is we
could go back and look at some of the
timing diagrams
and try to find you know somewhere in
this timing diagram find enough
room to perhaps read the pixel data that
we need to to
to feed to the video card and then like
maybe buffer that somewhere
so we probably could build some fairly
involved circuitry to to do that
to be able to share this ram
simultaneously but that would be a ton
of extra work and i'm not 100 sure that
it's possible though
i think you know running this processor
as slow as we are at 1 megahertz
should give us time to do that but i'm
not going to i'm not going to take that
approach
instead i'm going to do something much
more blunt
something something fairly terrible so
if we look at what the video hardware is
doing
remember we've got these counters that
are going across and anytime we're
you know in this region here we want to
be reading from memory and sending some
data out to the
vga port and so whenever we're doing
that we need to make sure that the
the video hardware has access to the
memory but then we get over into this
region here this blanking interval
where we're actually not outputting
anything there's some sync pulses and
things like that going on
but but we're not actually outputting
anything to the to the to the vga
monitor
and so actually during this period it's
it's okay for the processor to access
memory
because the video card doesn't need to
but then as soon as we get back to the
next scan line
well then the the video card has got to
be reading from memory again
until we get to the end here and then
the processor has a little bit of time
to access the memory
and so we can kind of keep doing that
until we get to the very bottom and then
of course at the bottom
once we're done displaying the image
there's some blanking time at the bottom
of the frame
where again we could let the processor
access memory during any of this time
so so that's basically the plan is we're
going to say that anytime
that we're actually displaying the image
then the video card has access to the
memory
and then anytime we're in this blanking
interval where the video card doesn't
need access to the ram
well that's when the cpu gets access to
it so how do we
tell the cpu when it's okay to access
the memory you know in this blanking
time
versus when it's not okay when the cpu
can't use the memory
well if we look at the data sheet for
the cpu there's this pin two
which is the ready pin and if we look at
what the ready pin does
the data sheet tells us it says a low
input logic level on the ready pin will
halt the microprocessor in its current
state
and then returning ready to the high
state allows the microprocessor to
continue operation following the next
clock cycle so right now pin two
we've just tied it high all the time so
that just means that the processor is
always going to run
but we could pull this pin low and it
would halt the microprocessor which
means that it
you know if it's halted it's not doing
anything and that would include
accessing memory
so we could halt the microprocessor and
then while it's halted we could let the
video card access the memory
and then when the video card's done
accessing the memory we could uh unhaul
the cpu
and you know bring this ready pin high
again let the cpu run for a little bit
and then you know when it gets to the uh
when it gets to the end of
end of this little blanking interval
then we can halt the cpu again
unhaul the cpu and so forth that would
allow us to share the ram
between the video hardware and and the
cpu
and and you might be thinking like isn't
that going to be
bad for performance if the cpu is halted
this entire time because this is this
ends up being 71
of the time and so if we've halted the
cpu 71
of the time isn't isn't whatever code
we're trying to run going to run 71
slower well you know that is how it's
going to work
and you know maybe 71 cpu overhead is
not
usually a feature you look for in a
video card but uh you know i never
claimed this was the world's best video
card so what do you want from me
um it should be pretty straightforward
to implement and uh it'll work well
enough
so how do we implement this well we've
got the ready pin which is pin two here
we currently have that tied high but if
we bring that low that'll halt the cpu
temporarily which will let us access the
ram
except that the cpu may still depending
on when it's halted it may still be
putting stuff
out on the address bus and it may even
be putting stuff on the data bus
or it might be putting something on the
address bus that's causing some other
thing here to be putting something on
the data bus so
we need to not only halt the cpu we also
need to tell the cpu to
stop doing anything with the bus
fortunately there's another pin that
lets us do that
and that's this bus enable pin on pin 36
and you can see we've also got that tied
high right now
but if we bring that low in addition to
halting the cpu we bring the bus enable
low that will tell the cpu don't put
anything out on the bus it'll put the
bus into
a high impedance state so that the the
cpu won't be
putting anything on the address bus it
won't be putting anything on the data
bus it won't be putting anything on the
read write pin
that tells us whether we're reading or
writing and that will allow the video
card then to
basically take complete control of the
bus so that it can talk to the memory so
that's what we want to do
so instead of tying the ready pin and
the bus enable pin
let me connect them together because you
know anytime we want to take control of
the bus we want to we want to toggle
both of those low
so i'll connect those together and then
i'll leave them at least temporarily
i'll leave them connected high
but eventually when the video card comes
in whenever it needs to take control of
of the ram which means it needs to take
control of the whole bus and pause the
cpu
then it can bring both of those pins low
together and it's very convenient that
the 6502 that we're using
has that bus enable pin the original
6502 didn't have that
so it's very convenient that we have
that because we can just disable that
that whole bus
to to allow for the uh the video card to
access the bus
because if we didn't have that then we
would you know we would need to add some
buffers or something and it
which makes this a little bit more
complicated unfortunately though on
the video card side we don't have
anything like that and we do need to add
some buffers
that will allow us to control whether
the video card has access to the bus at
any point in time
and the buffers that i'm going to use
are the 74 i'm actually going to use 74
hct
245s but it's the same basic layout here
and these are you know a bus transceiver
so as the name indicates it's designed
to be able to transmit and receive
off from a bus and basically what you've
got in here is if you've got eight
uh buffers and you've got eight bits so
a
a1 through a8 and those are connected to
b1 through b8 over here
and it's bidirectional right you can
transmit or receive that's why it's
called a transceiver
and you've got a direction line and the
direction line basically just enables
one set of gates you know going one way
or if you flip the direction line it
enables the the set of gates going the
other way
so you can enable it either way and then
there's also an enable line which if you
if you bring that high
then it completely disables it in either
direction which isolates
whatever's on the one side from the
other side and so this is essentially
what's kind of happening
inside the 6502 when we when we take
that bus enable line and we bring it low
is it's disabling the sort of internal
bus transceiver that it has in here
but we need to do something similar for
the video card so that when the video
card
it is connected to the computer bus we
have the ability to enable or disable it
so that when the computer's running
it's disabled and then when the computer
is paused and the video card is
accessing memory then it's enabled
so i'm going to add a couple of the 74
hct 245 chips here
that we're going to use for the address
bus and we've got a 16 bit address bus
on the computer so i'm going to use
two of these because each of these is
eight bits and i'll go ahead and connect
ground and power
for each of these and then the enable
pin is pin 19 so i'll just connect both
of those together
because these are the buffers for the
16-bit address bus so it's either
all on or all off so we want them both
enabled or disabled at the same time
and then the direction pin is pin one
and that tells us whether
we're you know reading or writing or
which direction we're going with these
things
and in the case of the the video card
the video card is always going to be
setting the address of the ram it's
never reading the address
so we're always going to be i guess
writing the address out to the bus
so we can actually hard code that
direction in in one direction
and so if we're going let's say from a
to b
so bus a to data bus b is going to be
direction is going to be high so we'll
set pin one
to high and that'll set that direction
for us pin one here is high
i'll do that for both of these and then
each of these chips can buffer eight
signals so together we can buffer 16
signals
so i'll go ahead and connect those up to
the the address bus
on the computer and i mentioned that
these buffer chips that i'm hooking up
here are 74 hct 245's
and that's because the rest of the chips
on the video card are 74 ls series which
you know i think are a little bit easier
to work with they're a little more
forgiving less static sensitive than all
the rest
whereas the the cpu and everything on
the computer is is cmos level logic
and so the 74 hct series is nice because
it can interface between both of those
so that's what i'm going to use for
anything that sort of
needs to talk to both the video card and
the and the computer
but anyway and this idea of hooking up
multiple things to the same
bus each of which can control the bus at
different times
is sometimes called bus mastering the
idea is that they're at any
you know single point in time there's
one thing that is you know sort of quote
unquote the bus master
which means that it controls whatever's
happening on the bus but then we'll have
some
mechanism in our case you know figuring
out whether we're in the display
interval or the blanking interval
that switches what the bus master is so
that during the display interval the vga
card is going to be the bus master
and during the blanking interval the cpu
will be the bus master
and so adding these buffers and
connecting the buses gives us a way to
switch each of those on or off and then
we'll just need to have some logic that
figures out when the right time to do
that is
but when it's switched around so that
the video card is is controlling the bus
we've got all 16 address lines hooked up
so the video card could actually talk to
anything on the bus it can talk to ram
it can talk to rom it could even talk to
the i o
it can do anything so what addresses do
we actually want it talking to
because we look at the way that it's
currently hooked up these counter lines
are hooked up to the address lines of
this rom and so there are actually 14
address lines and these counters all
start at zero so it starts counting at
address zero
and goes up through you know the 14
address lines here to pull
uh the the pixel data out of the rom
but of course you know we've got to map
these 14 address lines
into the 16 address lines that are that
our computer bus uses
and we don't necessarily want it to
start at address zero so so where do we
want it to go
well if we look at the memory map for
the way the computer is set up now
this is how how the memory is laid out
so we have 16 address lines and
basically each of the rows on this paper
is
is an is a range of addresses so for
example you can see if the top two bits
are zeros
for our address then we're going to be
somewhere in ram um
if the top bits are 0 1 1 0 then we're
in we're in the i o range which means
we're talking to this chip
and then if the top bit is a 1 then
we're talking to rom
which is the the rom chip here so
actually most of our address space right
now is taken up by rom
we have a little bit of ram here we
would like to
you know obviously put our frame buffer
in the ram
and so you might think well okay great
you know we can just map this the same
way we had it mapped here we started at
address zero
we were using 14 bits uh so so if we
just map those 14 bits straight through
then that'll that'll cover that whole
ram area we'll be able to pull
whatever's
in ram and put it on the display but i
don't know that we want to do that for
for a couple reasons so so one
you know i don't want to use all of ram
just for the frame buffer i want to have
some ram left over for for some other
things
and also the the first part of ram
starting at address 0 is is
used by the 6502 for some special
purposes we have the zero page and the
stack and things like that
so ideally our frame buffer wouldn't
start at address zero it would start
somewhere else
so what i'm going to do is i'm going to
start at address
2000 and run through 3fff
and so that would mean that any time
that the the video card is talking to
to ram it's got to set those first three
bits of 0 0 1
and then the rest of the bits it has to
play with the the problem with that of
course though is that there's only
13 more bits left and if we look at how
the video card works
remember it actually is using 14 bits
coming off of these two counters to
address a particular xy
position on the screen to get the pixel
value out of that so somehow we're going
to give up one of these bits
and i think we can actually do that so
if we just drop this top bit here
then that will mean that instead of this
vertical counter being able to count
from 0 to 75 which is what it currently
does because our resolution on the
screen is 100 pixels by 75 pixels
if we drop that top bit we'll we'll
almost be able to count to 75
we'll we'll be able to count to 64 which
is you know it's close
but it'll free up that bit so that top
bit we can we can just ignore
the other uh i don't know i guess you
could maybe call it an advantage
is if our display range here only goes
to 64 pixels
then we're actually gonna have a little
bit of extra blanking time here at the
bottom which uh remember that we had
that trade off so
a little bit more blanking time a couple
extra blank pixels you know 11 more
pixels here where we're not displaying
anything we could actually recover that
and use that for processing
so that's what i'm going to do i'm going
to hook these counter lines up except
for that top bit
and then whenever the video card is
active i'll just hard code the top three
bits of the address
to zero zero one and that'll make sure
that whatever other
address it's it's putting out there is
within this range of two zero zero
zero to three fff uh which will make
sure that it's it's in ram and it's just
in that top part of ram
so we have some additional ram left over
to actually run our program
so to hard code those top three bits of
zero zero one
what i'll do is i'll just tie them
directly to you know zero zero one here
coming into our buffer so that whenever
our buffer is active
those uh top three pins are going to be
zero zero one and then the rest of these
pins
i'll hook up to the the address lines
that are coming in or really the counter
lines
that are coming in that form our address
which i guess means now is the time
where our
our eprom goes away so this has got our
image in it but we we won't need that
anymore
so now let me hook up those address
lines and instead of re-running all
these wires i'm just going to
jumper from where the rom used to be
since i already know what all those pins
are
and i guess another approach that i
could have taken instead of cutting my
resolution from 100 by 75 to 100
by 64 is you know i could have sort of
redone the address map of the computer
right because right now half of the
computer's address space is taken up by
rom and
i don't know that i'll ever actually use
that so maybe it would have made more
sense initially to
to set up you know half of the address
space for ram and then a smaller amount
for rom
but you know seeing as i've got it set
up the way that i have it i'm just going
to roll with it the way it is
okay so now when these buffers are
enabled they will pass an
address from these counters these xy
counters from the video card
it'll pass that on to the address bus
which then goes into these you know
these green wires here the address bus
and it will pass through an address that
is going to be somewhere in ram
between address 2 0 0 0 and 3 ff
which will be you know in ram and it'll
correspond to a particular pixel
value to display the ram will then put
that pixel value out on the data bus
which are these blue wires
and we need to get that pixel value back
over to the video card
so that we can you know feed it into
these this resistor divider network here
so that we can actually put out a
different voltage for red green and blue
to to allow the the pixel to be
displayed on the monitor
so before we do that i'm actually going
to get rid of some of this stuff here
because this
uh nand gate up here was being used for
for part of the control logic to figure
out whether the eprom needed to be
enabled or not
and of course now that we don't have the
eprom anymore we don't we don't need
that control logic
yeah we'll need to add some additional
control logic for what we're doing now
but but for now we'll just get rid of
this
and so similar to what we did with the
address bus i'm going to use another one
of these 74 htt 245
buffers for the data bus and then i'll
move these power and ground jumpers to
the right pins
and i guess since we're only using six
bits of data for the color anyway
because we're
it's only support 64 colors i'll just
hook up six of the bits
and actually in this case you know the
reason we're using this buffer
is a little bit different than the
reason we were using them for the
for the address bus because for the
address bus we need to make sure that
the video card's not putting anything
out on the address bus when it shouldn't
be
but in the case of the data bus the
video card is actually just reading from
the data bus it's not ever going to be
writing anything to the data bus
so we don't need the buffer to ensure
that the video card
is isolated from the data bus because
it's only ever reading
the reason we need it is that during the
blanking interval we need to make sure
we're not outputting any
random pixel data you know the vga
monitor just expects black
during during those blanking interval
times
but if that's the time where the cpu
gets to actually do stuff
then there's going to be all kinds of
you know sort of random data flicking
around on the data bus
so we can use this buffer to just shut
that off and essentially disconnect the
data bus from the red green and blue
resistor network that we've got so like
i mentioned you know this is going to be
uh
input now into the video card um and so
here where we have this
these direction bits pin one we had
those tied high in this case we want the
direction bit tied low
so i'll tie that to ground here because
in this case the direction is going the
other way
and then you know we'll have our enable
bit we'll need to make sure that's
enabled at the right point in time but
we'll get to that later but now we need
to hook up you know when that data when
that pixel data
comes in we want the we want those bits
to be hooked up to these resistors
so that we generate the right voltages
for red green and blue
so now we'll hook up the six data bits
coming out of this buffer to these
resistors
and the resistors like i talked about in
a previous video each
pair of resistors is taking two bits of
data
and converting that into uh four
different voltage levels
so that gives four different voltage
levels for each of the three colors
which is how we get to 64 colors and so
there we are the video card can now put
an address out on the bus
and that address will address something
in ram and then the data coming out of
ram
can go back to the video card and be
turned into a pixel value that will
generate the right voltages
to go out to the vga monitor so at this
point the missing piece
is just the control logic to decide
whether it's the video card or the cpu
that gets access to the bus at any
particular point in time
because if we're in the display portion
of the frame then we want the video card
to be active and we can do that we can
have the counters go out on the bus we
can receive the pixel data back we can
display it no problem
but then we're in the blanking interval
we want to hand control over to the cpu
so the cpu gets access to the bus for
however long it's able to and then
when we go back to the display interval
then the video card needs to take
control again
and we we have you know the way to do
that we have our ready pin we have our
bus enable pin here we have our enable
pins on our buffers over here we just
need to build
a couple little bit of glue logic to to
get that so that we can
toggle that at just the right times and
that's what i'll do in the next video
i'll hook up all the control logic so
the vga monitor will display what's in
the computer's ram
and i'll write a program or two to
display something interesting on the
screen
and again in the meantime if you're
interested in following along with this
project
check out eater.net vga for kits and
more
and be sure you're subscribed to my
channel so you don't miss the next part
where i get it working sort of
and of course as always thanks to all my
patrons for making this and all my
videos possible