building a simple computer based on the
6502 processor and in previous videos we
got it working and actually displaying
some text but then we tried to simplify
the code to use subroutines it stopped
working and it's not working because
when the computer jumps into a
subroutine it pushes the return address
onto the stack which is in memory and at
the end of the subroutine it pulls that
return address off the stack so it can
jump back from where it came our problem
is that our computer didn't actually
have any RAM in it so in the last video
I started hooking up this Ram chip here
and I've got the 15 address lines as a
green wires here hooked up to the
address bus the eight data lines the
blue here hooked up to the data bus and
the right enable pin which is this
yellow wire underneath here that goes
all the way over hooked up to the
read/write pin on the microprocessor and
so that's hooked up pretty much like
this we've got the 15 address lines
we've got the eight data lines and we've
got the read/write or a right enable
signal hooked up here but then the RAM
chips got a couple of control signals
here as well to enable it and for that
we said well we can hook those up to
address 14 and 15 so that when both of
those are low the ram is enabled and
that'll ensure that the ram is enabled
anytime the address is between 0 0 0 0
and 3 FFF which is the range we want to
use for the RAM but then in the last
video we took a closer look at the
timing diagram for the RAM to take a
closer look at the timing requirements
for interfacing with it and then we
looked at the timing diagram for the
microprocessor as well it's kind of the
interaction between these two and so
that was those in the last video and
what we found is that this wouldn't
actually work quite like this instead
we'd have to add a little bit of logic
here and this is to ensure that the chip
select signal doesn't go low until all
of the address lines are set and
stabilized and then the chip select
signal would go high before any of the
address lines change any time we're
doing a read or write particularly a
write to the RAM and so that's what this
additional logic here does and in my
last video I went over exactly why we
needed this so in this video let's hook
this this extra logic up and see if we
can get the RAM working I'll start with
address 14 and hook that around to the
output enable so address 14 is this pin
here and we're gonna hook that to output
enable over here and so this will ensure
that the RAM is not going to output
anything unless address 14 is low which
it has to be if we're addressing
anything in that 0 through 3 ffff
address range then we need to hook up
the chip select and the chip select is
going through these logic gates now
conveniently we already have one of the
logic gates hooked up already because we
have this address 15 being inverted
through a NAND gate like this that we
already did for the chip select for the
the ROM and so address 15 is is coming
down here and this is actually address
15 here and it's connected and if you
can see it's connected to both inputs of
one of these NAND gates and then the
output here is is going back up around
to chip select for the ROM but we can
reuse that to go to one of the inputs of
this other NAND gate so I'll just hook
from the output of that first NAND gate
to one of the inputs of
the next NAND gate with just a little
tiny jumper there so that's that
connection there and then this NAND gate
the output of that will go to the chip
select of the RAM so that's going to be
the output of this NAND gate here has
got to go all the way around to the chip
select input of the RAM and I've got a
nicely measured wire that I need to
somehow feed through here and there we
go so we've got one of the inputs going
into this NAND gate and then we've got
the output going around to the chip
select over here and then the other
input is going to be our clock signal
and I've already got the clock signal
hooked up here coming from the clock pin
of the processor around to the clock
input down here of the interface adapter
and what I'm going to do is I'm actually
to pull this this longer wire out and
replace it with two shorter wires so we
can drop it in to this NAND gate input
here as well I'll pull that clock wire
out and will come from the processor
down to that input on the NAND gate and
then I'll have another shorter wire that
goes from that input of the NAND gate
around to the interface adapter clock so
there we go so that restores that same
connection we had before but now we've
also have a clock input going into the
NAND gate there so now I'm using three
of these NAND gates and I'm not planning
to use the fourth NAND gate and it's a
good practice when you're not using
inputs to tie them you know either high
or low so they're not floating and and
potentially you know hovering between
high and low and causing the chip to
switch on and off and which could
introduce noise and such into into the
rest of the circuit so it's just a good
practice to tie those unused inputs high
so
go ahead and do that but with that you
know we've got let's see we've got
address 14 now hooked to output enable
we've got address 15 already was being
inverted by this first man gate and now
that's going into the second NAND gate
as well as the clock going to the second
NAND gate and then the output of that
NAND gate is coming all the way around
here to chip select so with that we
should now have RAM in our computer
which also means we should now have a
stack in our computer so let's let's go
ahead and try to power it up and see if
our program works because if we have a
stack our program ought to work so I'll
plug this in and see our clock is
running a little reset and yeah there we
go our program is working and I haven't
changed the the program in the ROM so
it's using the jump to subroutine
instruction and and obviously the return
from subroutine instruction which is
what wasn't working before and it
appears to be working now which which is
great so yeah let's take a closer look
at that look let's get this out of the
way and I will hook the Arduino back up
so we can actually monitor step by step
and see that stack operation again but
this time actually see it work so I'll
power this off get the Arduino back here
and I'll hook the Arduino up again to
monitor everything so like before I'll
start by hooking up all 16 of the
address lines to 16 inputs of the
Arduino and then we'll hook up another 8
inputs of the Arduino to eight of the
data lines and then we'll hook up the
read write signal from the processor to
to another input and of course hook up
the clock to another input on the
Arduino - to trigger it and then finally
we need a common ground alright so
that's all hooked up and it's pretty
annoying to hook up I have to say but in
any event I will hook up the Arduino to
the computer and power up the computer
other computer reset here and our
program is running but I'm going to hold
down reset and stop the clock
that way we'll be able to single step
through this and see what's going on so
here's the output of the Arduino serial
monitor and I'll go ahead and clear that
and this Arduino program that I'm
running will actually let us see what's
on the data and address buses for each
clock cycle and you can check out a
previous video where I talk
more about how it works anyway I'll step
through the first seven o'clock cycles
to let the processor initialize itself
and then the next two clock cycles
reading fffc and FFT that reads the
reset vector which is eight zero zero
zero and we'll jump to eight zero zero
zero and we'll start reading
instructions so a2 is the load X and
then F F so that loads F F into the X
register and this is initializing the
stack pointers because the next
instruction is going to be our transfer
X 2's and that's nine a is the opcode
for that and then we get to a nine which
is load a and actually we see this
repeated because really what's happening
here is the transfer excess takes two
clock cycles so this first clock cycle
where it looks like it's reading a nine
from address eight zero zero three that
is what happens to be on the bus but I
think it's still executing the transfer
next s instruction on that clock cycle
and it's on this next clock cycle where
it's actually reading the load a because
then it's going to follow up with load
AF F which is actually the next
instruction then we have eight D which
is store a and it's store a six zero
zero two which is the address for DDR B
so this is all just part of the
initialization so I'm gonna go through
this pretty quickly just to get to the
point where we're actually calling and
returning from the subroutine since I've
already shown a lot of this in previous
videos but anyway we're next we're gonna
have a well this is actually the right
so it's actually writing the FF to edit
or 6 or 0 to a now we're gonna read load
a ez row and then store a 6 0 0 3 and so
now it's going to store the ez row at
address 6 0 0 3 then we have a load a
3/8 so that's the first instruction that
we're actually going to send to the LCD
so the next instruction now is going to
be the the jump subroutine opcode to 0
is jump to subroutine and then the
address of that is going to be 8 0 6 0
or no it's not 8 0 6 0 this actually
kind of fooled me because the 6 0 it's
reading from you know address 8 0 1 0
that is going to be part of the address
that we're jumping to but you can see
this 8 0 is actually being read from 1 0
1 FF and that is going to be the bottom
of our stack because the FF remember
that is our stack pointer and so
actually what we should be doing is now
that we're pointing at that stack
we should be writing yes eight zero one
one into the bottom two positions of the
stack so 0 1 FF and 0 1 F E and now
we're reading from 8 0 1 1 and so that 8
0 6 0 is in fact the address that we're
jumping to for the subroutine it's just
that by a pure coincidence the address 0
1 FF happened to have 8 0 in it and so
that kind of fooled me there for a
minute there's a little bit confusing
because there's two things going on here
I talked about this in the last video
but you know we're jumping to subroutine
so this to 0 is the instruction to jump
to subroutine and then it it needs to
read the address that were jumping to so
it reads from the next address 8 0 1 0
so that the instruction was in 8 0 0 F
so then it reads from 8 0 1 0 + 8 0 1 1
it reads the address that we're jumping
to and so that's 8 0 6 0
I was thrown off here because it's also
has to write the address that we're
jumping from which is 8 0 1 1 and it's
writing that to 0 1 F F and 0 1 F V so
it's pushing those on to the stack and
then there's this extra clock cycle in
here where the bus is not being used
you know something internally going on
in the processor because you know the
jump to subroutine takes an extra clock
cycle for whatever reason internally so
the processor is not really reading this
value 8 0 from the bottom of the stack
it just happens to set the address lines
to that value and this happens happen to
be what was in memory which which
confused me there for a minute but any
rate we've got our return address pushed
onto the stack
8 0 1 1 and we've read the address that
we're jumping to you know 8 0 6 0 so we
should now jump to eight zero six zero
and there we are we're at age address
aid 0 6 0 and we're reading 8 D and
that's because we're down in the LCD
instruction subroutine and 8 D is the
the first opcode for for store a so I'll
just go through this pretty quickly so
we have a store a6000 which is port b so
there it is storing the 38 into port b
and we have a load a 0 0 and so this is
to clear that register select read/write
and enable bits and then store a 6 0 0 1
which is port a and there goes storing 0
into port a so we have a load a 8 0
that's the enable bit and store a 6 0 0
1 again and there it is writing that out
too
6:01 so it's setting the enable bit and
then we have a load a zero zero to
clearly enable bit and store a six zero
zero one and there it is writing that
out again and then we get to our return
to subroutine instruction so six zero is
returned from subroutine and so at this
point it should read back those values
that it stored on the stack so it stored
the return value eight zero one one on
the stack at you know zero one FF and
zero one Fe so it should pull those back
off the stack so let's see here
so it jumps ahead to eight eight zero
seven three and again I think this is a
clock cycle that's being used internally
I don't think it's actually trying to
read this next instruction but now it
goes to zero one FD which is where the
stack pointer is pointing and then it
reads from zero one Fe and zero one FF
so again I think these two clock cycles
here the processor is not actually using
the bus it's just those clock cycles are
being used internally and this just
happens to be what's on the bus but
certainly for these two clock cycles
here we are reading the return address
eight zero one one and if you watch the
last video before we had the RAM
installed this is where things fell
apart because when we tried to read that
return address back well it wasn't
stored in the RAM because there was no
RAM and so the next instruction we
jumped off into some garbage address but
now we're reading the correct thing back
eight zero one one so we should see it
jump to eight zero one one and continue
executing and so here we are at eight
zero one one and notice that you know
jumps back to eat zero one one which is
not actually the next instruction this
is this is actually the last half of the
address that we jump to so we're not
quite at the next instruction which is
the load a that's going to be an eight
zero one two so if we keep going here we
are at eight zero one two so again I
think you know this is a little bit
confusing the way that this monitor
shows what's going on because it prints
out what's on the bus for each clock
cycle even if that clock cycle is not
actually transferring data on the bus
but nonetheless I think we can conclude
that this is working correctly because
now here we are at eight zero one two
which is in fact the next load a and so
we should see that load a zero e which
is the next LCD instruction that we want
to execute and then we should again see
another jump to subroutine to the LCD
which is going to be the eight zero six
zero and so there it is reading the
eight zero six zero and also pushing the
return address which this time is eight
zero one six and the bottom line is if
we let this run as we saw before it's
just going to work
because now we've got the RAM there and
because we have the RAM we have a stack
and because we have a stack or jump to
subroutine instruction is going to work
for us I think there are a few
improvements that we can make to our
hello world program before we're
completely done with this one of them
you can probably see right off the bat
here is that we're not clearing the
screen at the beginning you know before
it was working fine because when we
first plugged the computer in the screen
starts out cleared but here you know I
let the program run for a little bit and
we stop the clock and then I used the
reset to reset it and as part of our
reset sequence we don't actually clear
the screen so let's go ahead and add
that because that's a pretty
straightforward thing to add well if we
take a look at the data sheet for the
LCD module we can see there's an
instruction for clearing the display and
it's just all of the bits are zero
except for the last bit which is a 1 and
that's fairly straightforward to do just
go down here with all the other
instructions that we're sending to the
LCD and add another instruction to clear
the display and the instruction is just
all zeros except for a 1 and that clears
the display and once we load that
instruction into the a register we just
jump to the subroutine and that's it
that should clear the display before we
print our message so I'll save that and
I'll switch over to the terminal and run
our assembler to assemble that program
into binary and this will output a file
a dot out with the binary that we need
to put on the EEPROM and we can take a
look at what's on that binary if we want
there's our program and it's now we need
to do program that onto the EEPROM
that's buried in here so what I'm gonna
do is disconnect all of this is I don't
think I'm going to be using this monitor
again in this video so I'll get that out
of the way and then I can carefully
remove the EEPROM carefully and put it
in the EEPROM programmer being again
careful to put it in the right place in
the EEPROM Bergner and I'll go ahead and
write this to the pound and so it's
writing that to the EEPROM and there we
go it's done let's pull the EEPROM out
carefully put it back in our circuit
there we go and now let's power this up
yeah and we should get a hello world
message
reset hmm something's not working quite
right here what's going on and it looks
like my clock fell out how about that
look that back in and there it goes
and we could speed this up and if i
reset should clear and reprint it
beautiful
and so there we go we've got working
working RAM in our computer which means
we've got a working stack which means
that our program that uses subroutines
is working and as you can see it was
easier easy to add another instruction
at the LCD to get it to clear just by
adding another subroutine call so that
should make programming this thing a lot
easier and in fact there are some more
improvements I want to make to the
program for hello world so you know even
six videos in I'm still not done with
writing a basic hello world program but
you know what do you want for me I
assume if you've been watching the last
half-hour of timing diagrams you're
probably okay with the situation but
anyway in the next video I'm gonna add
some more improvements to the program
and also get rid of our clock module
here and replace it with our one
megahertz crystal oscillator clock so
that our computer will actually be
running at the speeds that we talked
about when we looked at the timing
diagrams and so there'll be a few more
interesting things that we'll have to
think about when we do that and remember
if you're interested in following along
with these videos you can get all the
parts I'm using over at my website Eater
dotnet slash 6502 I've got the base
computer kit as well as everything else
you need to follow along with these
videos so you can check that out at
either net slash 6502 and of course as
always I want to thank all my patrons
your support is a huge part of what
makes these videos possible so thank you
you