I recently made some changes (mostly corrections) to my design as I reported in my last blog update. Since then I did few more changes, in order to accommodate for the prototype of banked RAM I was making. I will explain in detail later on, but let me first introduce my banked RAM concept.
My banked RAM design is a simple solution with 128kB of static CMOS RAM chip WS628128LLPG-70, with address lines A14-A16 driven by 3 output ports (Q0, Q1 and Q2) of latch register 74LS374 to select 8 banks, 16 kB each.
That creates a simple output only port, which is at address $C000. Writing a value to that address, with older 5 bits masked out (zeroed) allows to select a bank # (0-7) of RAM in the range $8000-$BFFF.
This circuit will share a single board with my RTC circuit which also happens to be a battery sustained memory storage (some 200+ bytes available to store BIOS settings, short machine code or whatever). So it was logical IMO to put these two circuits on a single board (plus I save one bus slot by having one instead of 2 cards).
Now, about the changes I made to accommodate banked RAM:
Note the /BRAM signal that drives the chip select pin of the memory chip. This pin was in the original design driven by a local address decoder made out of 2 NAND gates. The problem however was that my RTC circuit also requires one NAND gate. Therefore if I wanted to use just one 74LS00 chip on this board I'd be one NAND gate short. On the other hand If I added a 2-nd 74LS00, I'd have inefficient design with 3 unused NAND gates. But, the good news was that I also happened to have 2 unused NAND gates on my CPU board. I only had to do some design change to make the /BRAM address decoding circuit out of these free CPU board NAND gates and also a change the CPU bus design to be able to get that signal out of the CPU board into the CPU bus to the banked RAM board. That I did and it worked. I saved one 74LS00 chip. I changed the designation of the pin A30 on CPU bus from GND to /BRAM signal. Just a bit of soldering work. Saving one 74LS00 chip may not sound that important, but it kind of bothered me that I had 2 unused NAND gates on CPU board and would have another 3 on the RTC+BRAM board.
I didn't even have to write any special software to test it initially. I used monitor built into M.O.S. (OS running on my computer) to select memory bank, modify RAM contents and verify my changes stick. Then I switched memory bank and did the same, then switched back to the previously modified banks and checked again if my memory modifications were there. It all seems to work just fine. I only see one problem here. The banked memory resides in $8000-$BFFF range. The next address after this range is $C000 which happens to be the I/O 0 port - a memory bank selection port. Writing a value to that port selects the bank. However it is also sensitive to reading from this address in this design. Reading from that port automatically switches the bank to bank #0. You must be aware of this issue if you have a loop that at some point crosses the boundary $BFFF-$C000 and read from $Cxxx range is performed. This will switch your current memory bank, not a desired outcome in most cases I think. I learned this when my initialize memory command in my monitor program didn't produce the expected result. That was because I issued a command to initialize range $8000-$C000, which caused just one read from $C000 address at the end of the loop. Command was fine if I used range $8000-$BFFF, but then the last memory location: $BFFF wasn't initialized to the value I wanted. The same side effect happens when I dump memory and the range of dumped memory happens to cross $BFFF-$C000 boundary. I will have to think about some hardware correction to this problem or live with it. I think that signal /WE needs to be involved in the circuit that drives CLK input of the latch register. The data from data bus should only be latched on the register's output during write cycles.
I am thinking about putting signal /WE from CPU bus on one of the NAND inputs (U22), the one that now has both inputs driven by /IO0 signal would be multiplied with /WE so only if /IO0 and /WE are active, the data shall be latched at the outpout. I am going to try this and report the results in my next update.
This is all I've got today.