Memopak : bad RAM chips ?

Discussions about Sinclair ZX80 and ZX81 Hardware
Rishi
Posts: 107
Joined: Mon Jun 08, 2015 6:57 pm
Location: Amsterdam

Re: Memopak : bad RAM chips ?

Post by Rishi »

Anyway, what i don't get is that my IO-port can disable the SRAM via !CE (if the A2-A15 are high and !MI and !(!MEMRQ) ) so the SRAM gets disabled for addresses FFFCh-FFFFh but when i do that for just A15 and !MI and !(!MEMRQ) then something goes wrong. Of course i have to keep disabling it in case of IO-port request, so i used another OR-gate, but if i have the other input of that low on one of the SRAM's and high on the other, it's fine.. both chips are fine, the extra OR-gate doesn't slow it down to much (or the IO-port would cause an issue) so anyway, how come what works one way, doesn't work the other way :D
32K SRAM WRX compatible, 32Bit IO-Port, ROM Ghost, ZX-Printer.
User avatar
1024MAK
Posts: 5103
Joined: Mon Sep 26, 2011 10:56 am
Location: Looking forward to summer in Somerset, UK...

Re: Memopak : bad RAM chips ?

Post by 1024MAK »

The display system needs the RAM that contains the display file to respond when A15 is both low and when it is high...
The display system needs to "execute" (/M1 low) the display file (with A15 high). High memory can still exist at addresses with A15 high, but should only respond when /M1 is high.

If there is no shadowing of the RAM that contains the display file (in your case because you have disabled the chip), the system will be unable to process the display code, so will crash.

Mark

Edited to correct a typo.
Last edited by 1024MAK on Sun Oct 04, 2015 6:49 pm, edited 1 time in total.
ZX81 Variations
ZX81 Chip Pin-outs
ZX81 Video Transistor Buffer Amp

:!: Standby alert :!:
There are four lights!
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :!:
Looking forward to summer later in the year.
Rishi
Posts: 107
Joined: Mon Jun 08, 2015 6:57 pm
Location: Amsterdam

Re: Memopak : bad RAM chips ?

Post by Rishi »

Ah, maybe i've found a way around (and my earlier mistake) let me see if i understand; if !MI is low, the part of RAM that is addressed should actually always be 4000h - 8000h (regardless of A15) since that is where the D-file is. In other words, the chip should only be disabled(and the other disabled) if !MI is high and A15 is high, i'm fairly sure i actually tried that though, but not with understanding... :D
32K SRAM WRX compatible, 32Bit IO-Port, ROM Ghost, ZX-Printer.
User avatar
RetroTechie
Posts: 379
Joined: Tue Nov 01, 2011 12:16 am
Location: Hengelo, NL
Contact:

Re: Memopak : bad RAM chips ?

Post by RetroTechie »

You're beginning to "get it"... :D
Rishi wrote:let me see if i understand; if !MI is low, the part of RAM that is addressed should actually always be 4000h - 8000h (regardless of A15) since that is where the D-file is.
More exactly: if /MREQ, /RD and /M1 are low, and A14/A15 both high (= a Z80 instruction fetch from C000-FFFFh area), then the RAM memory location that is actually read from, must be the same as if reading from 4000-7FFFh (since that's the DFILE-containing area mirrored in C000-FFFFh). How that's done, is up to you as circuit designer.

You don't have to decode all those signals to handle the special case, only those signals that are different from a normal read. Much depends on how you want the RAM to be 'mapped' into the 64K Z80 address space, and where you want to be able to execute Z80 code.

To explain that last bit: For deciding between regular reads/instruction fetches and 'DFILE execution', the ZX81 ULA doesn't use A14, only A15 (and a few other signals). That means the ULA can detect 'DFILE execution' in the entire 8000-FFFFh range, even though the RAM area that holds the DFILE is mirrored in C000-FFFFh only (8000-BFFFh has a mirror of the ROM). So it's possible to execute regular Z80 code in 8000-BFFFh range by looking at both A14/A15. If you don't need that option you can leave A14 out of the [DFILE execution-or-not] equation.

For example with a 32K*8 SRAM:

1st half in 4000-7FFFh, 2nd half in C000-FFFFh, Z80 code executable in 4000-7FFFh only.
Continuous RAM from 4000-BFFFh, Z80 code executable in 4000-7FFFh range only.
Continuous RAM from 4000-BFFFh, Z80 code executable in that entire range.
Continuous RAM from 2000-9FFFh, Z80 code executable in 2000-7FFFh range only.
Continuous RAM from 2000-9FFFh, Z80 code executable in that entire range.

Each of those requires a different signal decoding circuit (some options simpler, some options more complex). And that's ignoring the question whether RAM locations are mirrored elsewhere and if so, where/how. Occupying more of a CPU's address space often simplifies decoding (especially with a single RAM chip), so consider bringing in a 128K*8 SRAM, and use half of that to slap a full 64K (ehm.. make that 56K?) RAM onto your ZX81.

A simple (internal) 32KB circuit is here: www.zx81.de/english/32k-rame.htm. Shouldn't be hard to get that working on the expansion connector.

I've had a good look at Rishi's circuit above, and spotted several problems:

* If you put all possible states of A14 and /M1, and the signal on the SRAM's A14 input in a table, then think about what exactly is happening in each case, you will find that the results just don't make sense. My gut feeling says you need A15 there rather than A14, and possibly you can do with a single AND gate (but don't trust my gut... :lol: work it out!).

* /ROMCS is pulled high (ROM disabled) whenever /MREQ and any of A13/A14/A15 are low. That is: a refresh cycle, or memory access in 2000-FFFFh range. So far so good. But the ROM is enabled at ALL other times, and that is NOT good. :evil: This might work if at ANY time there is either ROM, or RAM access happening. But that's not the case: there's Z80 I/O cycles, interrupt acknowledge cycles (and perhaps other types I forgot), in which /ROMCS is low (ROM output enabled), while BOTH RAM and ROM should be disabled at that time. Obviously you can expect this to cause problems.
A better method is to force /ROMCS low for cases where it's clear the ROM must respond, and pull /ROMCS high at all other times. Or perhaps easier to decode: force /ROMCS high for cases where the ROM isn't needed, and leave /ROMCS alone in other cases. This may require an IC with tri-state output, transistor or some resistor-diode circuit.

* There's a signal going into an OR gate on both /OE and /WE pin of the SRAM, while its /CE is permanently pulled low (active). Much better: put the signal that goes into those OR gates on /CE, and tie Z80 /RD and /WR directly to the SRAM's /OE and /WE pins. That way the circuit becomes slightly faster, and 2 OR gates can go.
Rishi
Posts: 107
Joined: Mon Jun 08, 2015 6:57 pm
Location: Amsterdam

Re: Memopak : bad RAM chips ?

Post by Rishi »

RetroTechie wrote:You're beginning to "get it"... :D
Sometimes i do and sometimes i don't, sometimes my info seems a tad incomplete
Rishi wrote:let me see if i understand; if !MI is low, the part of RAM that is addressed should actually always be 4000h - 8000h (regardless of A15) since that is where the D-file is.
RetroTechie wrote: More exactly: if /MREQ, /RD and /M1 are low, and A14/A15 both high (= a Z80 instruction fetch from C000-FFFFh area), then the RAM memory location that is actually read from, must be the same as if reading from 4000-7FFFh (since that's the DFILE-containing area mirrored in C000-FFFFh). How that's done, is up to you as circuit designer.

You see there is one thing that A14 needs to be taken into account as well, mind you i figured if i connect all Address pins and Data pins it should pick the proper area as long as i make A15 irrelevant when /MI is low.
RetroTechie wrote: To explain that last bit: For deciding between regular reads/instruction fetches and 'DFILE execution', the ZX81 ULA doesn't use A14, only A15 (and a few other signals). That means the ULA can detect 'DFILE execution' in the entire 8000-FFFFh range, even though the RAM area that holds the DFILE is mirrored in C000-FFFFh only (8000-BFFFh has a mirror of the ROM). So it's possible to execute regular Z80 code in 8000-BFFFh range by looking at both A14/A15. If you don't need that option you can leave A14 out of the [DFILE execution-or-not] equation.

For example with a 32K*8 SRAM:

1st half in 4000-7FFFh, 2nd half in C000-FFFFh, Z80 code executable in 4000-7FFFh only.
Continuous RAM from 4000-BFFFh, Z80 code executable in 4000-7FFFh range only.
Continuous RAM from 4000-BFFFh, Z80 code executable in that entire range.
Continuous RAM from 2000-9FFFh, Z80 code executable in 2000-7FFFh range only.
Continuous RAM from 2000-9FFFh, Z80 code executable in that entire range.
The schematic in this post isn't actually the latest version, this is :
Image
Which gives me continuous RAM 0000h-7FFFh (all Z80 executable) mirrored 8000h-FFFFh where the 0000h-1FFFh area is switchable,
like this i can copy the ROM into 8000h-9FFFh, flick the switch, and have the it all running from the RAM (where there is a ghost of the ROM) and i can modify and experiment. I had to have the /REFSN back at the switch again, since my RAM wasn't UDG ready (still working on that)

RetroTechie wrote:Each of those requires a different signal decoding circuit (some options simpler, some options more complex). And that's ignoring the question whether RAM locations are mirrored elsewhere and if so, where/how. Occupying more of a CPU's address space often simplifies decoding (especially with a single RAM chip), so consider bringing in a 128K*8 SRAM, and use half of that to slap a full 64K (ehm.. make that 56K?) RAM onto your ZX81.
I'll probably do that for the next version, but for now that is not really an option. :D
RetroTechie wrote:I've had a good look at Rishi's circuit above, and spotted several problems:

* If you put all possible states of A14 and /M1, and the signal on the SRAM's A14 input in a table, then think about what exactly is happening in each case, you will find that the results just don't make sense. My gut feeling says you need A15 there rather than A14, and possibly you can do with a single AND gate (but don't trust my gut... :lol: work it out!).
That is where i think the trouble is, and i am going to have really good look there to see if i can do it differently somehow and what the exact consequences are, I got a bit of a headache from it last night, since it can be so hard to see just by looking at it, and a simple logic-gate truth program would be really helpful, i actually suspect that when i fiddle /MI and A15 into the equation, the pin that we are talking about now accidently gets inverted (i tried what mark suggested and it's got to be something like that)
RetroTechie wrote:* /ROMCS is pulled high (ROM disabled) whenever /MREQ and any of A13/A14/A15 are low. That is: a refresh cycle, or memory access in 2000-FFFFh range. So far so good. But the ROM is enabled at ALL other times, and that is NOT good. :evil: This might work if at ANY time there is either ROM, or RAM access happening. But that's not the case: there's Z80 I/O cycles, interrupt acknowledge cycles (and perhaps other types I forgot), in which /ROMCS is low (ROM output enabled), while BOTH RAM and ROM should be disabled at that time. Obviously you can expect this to cause problems.
??? All i am doing is removing the ROM mirror's from memory, and that only while it is replaced by RAM, /ROMCS on the Edge is not the same as /ROMCS on the actual ROM (i read that somewhere, i think WILF's site on his topic of UDG)
RetroTechie wrote:* There's a signal going into an OR gate on both /OE and /WE pin of the SRAM, while its /CE is permanently pulled low (active). Much better: put the signal that goes into those OR gates on /CE, and tie Z80 /RD and /WR directly to the SRAM's /OE and /WE pins. That way the circuit becomes slightly faster, and 2 OR gates can go.
Karl made a similar mention about that, earlier on, but i actually understand now. (didn't quiet get it the first time) /CE is not actually pulled low anymore, since the IO-port pulls it high when it's being addressed (FFFBh-FFFFh), so that would speed things up anymore, unfortunately and only save 1 OR-gate, it seemed a more obvious way to do it, and given the length of the cycles (as provided by Mark) and the speed of the RAM, i am not so stressed for time, Both work.

Ok so now i am thinking how can i simplify this, and keep my ROM-ghost, 'cause the obvious thing to do would be to connect A15 and /MI to the A14-RAM pin, but then how can i write to 0000h-2000h ? the original idea was to have this mirror and write into it (actually i changed the setup because i wanted continuous 4000h-AFFFh memory for HiRes, but also there i think something does not quite go right), and then enable the second half, disabling the mirror. And once the ROM is turned off (sort of) i can write to it of course.

Thank you very much Retro (or Techie, do they call you that at home ? :? ) I might seem a little thick, but this is quite tricky stuff, and i only really got into electronics about a year and a half ago, all these double inverted denials... out of my own experience (both ways) it turns out also a lot harder to explain something to someone how doesn't understand yet, than to someone who understands already. :idea:
32K SRAM WRX compatible, 32Bit IO-Port, ROM Ghost, ZX-Printer.
User avatar
RetroTechie
Posts: 379
Joined: Tue Nov 01, 2011 12:16 am
Location: Hengelo, NL
Contact:

Re: Memopak : bad RAM chips ?

Post by RetroTechie »

Rishi wrote:The schematic in this post isn't actually the latest version, this is :
Thx for that... and ouch! I won't even try to figure out what that circuit does! :mrgreen:
Which gives me continuous RAM 0000h-7FFFh (all Z80 executable) mirrored 8000h-FFFFh where the 0000h-1FFFh area is switchable,
like this i can copy the ROM into 8000h-9FFFh, flick the switch, and have the it all running from the RAM (where there is a ghost of the ROM) and i can modify and experiment.
Yes, I've been thinking about doing that too, very fun to try ROM modifications or alternative ROMs on the fly (and on real hardware!). Options I have considered for this:
  • A (byte-writeable) EEPROM (8 KB? 32 KB?) in place of the ROM.
  • A (sector-writeable) Flash EPROM (1 Mbit or so) in place of the ROM. Of course with a nice selection of alternative ROMs pre-programmed.
  • An FRAM in place of the internal RAM. Copy ROM contents over, remove ROM and change circuit so that you have a 3-IC ZX81 (Z80, ULA, FRAM). Unfortunately these FRAM IC's are hard to find, 3.3V devices (especially anything >32K*8), smd-IC or other non pin-compatible package, and kinda expensive. :( Cypress seems to be the only manufacturer of these devices currently, look here for example.
  • A battery-backed RAM, possibly used in a similar way.
Pro's and con's for each of those options. Choices, choices.... :?
That is where i think the trouble is, and i am going to have really good look there to see if i can do it differently somehow and what the exact consequences are, I got a bit of a headache from it last night, since it can be so hard to see just by looking at it, and a simple logic-gate truth program would be really helpful, (..)
Tables are your friend... Put all combinations of the 'signals of interest' under each other, leave a few columns for output signals needed, and after you've gone through a bunch it usually becomes obvious what the logic should do. A Notepad-like editor, or good old paper & pen are my tools of choice for this. Spreadsheet may work too.
After you have a circuit you think should work, it's back to datasheets to check timing diagrams & think about how that works out with the circuit as designed. Only when that is deemed okay, it's solder time for me - not just solder something together and try if it works somehow. :evil: Understand first, build later.
i actually suspect that when i fiddle /MI and A15 into the equation, the pin that we are talking about now accidently gets inverted (i tried what mark suggested and it's got to be something like that)
Well one thing is for sure: for [Z80 instruction fetch from 4000-7FFFh] and [instruction fetch from C000-FFFFh] A14 is the same (1 in both cases), but the ULA responds very different when fetch takes place in 8000-FFFFh range. So if DFILE execution (-> image on screen) is to work, somehow A15 must be part of what goes into the SRAM's upper address lines (unless 4000-7FFF and C000-FFFFh are always the same RAM locations like in a basic 16K RAM expansion).
Perhaps making code executable in 8000-BFFFh is a bridge too far, and you'd do better to aim for RAM that's R/W in some mirror ranges, but executable only for <8000h range (A15 low).
/ROMCS on the Edge is not the same as /ROMCS on the actual ROM
The ULA's /ROMCS signal goes via a series resistor (R28, 680 Ohm) to the internal ROM. This series resistor is what allows you to override /ROMCS without shorting out the ULA output. The non-ULA side of that signal, /ROMCS' (note the added ' character) is what's on the -internal- ROM's /CE and edge connector. Electrically the same point. Don't touch that signal, and the ULA controls it. Pull it to +5V, and the -internal- ROM is disabled no matter what the ULA does. Pull it to 0V, and the -internal- ROM is enabled & outputting data (again, no matter what the ULA does). Even when you do that at times where the ROM shouldn't output data.
Same story for /RAMCS.
??? All i am doing is removing the ROM mirror's from memory, and that only while it is replaced by RAM, (..)
That's what I thought as well at first look. But it's not the case: /ROMCS' is activated whenever the external RAM's /OE and /WE inputs are held high. Including times where neither ROM or RAM should be doing anything. Btw. you've got /RAMCS' on the edge connector hardwired to +5V, right?

When the Z80 executes this code:

Code: Select all

     IN A,(n)
/MREQ will be high, /IORQ goes low, port number "n" goes onto A0..A7, aaaaannnd the contents of A register goes onto A8...A15. For I/O instructions that use register(s):

Code: Select all

     IN r,(C)
     INI
     INIR
     IND
     INDR
it's C that goes onto A0..A7, and B register that goes onto A8..A15.
Similar story for Z80 OUT/OUTI/OTIR/OUTD/OTDR instructions. What's on A8..A15 during I/O instructions, is perhaps not-so-well-known among programmers, but documented Z80 behavior (see "INPUT AND OUTPUT GROUP" in instruction set description).
Now work out what the circuit above does in these cases, and you'll find that /ROMCS' may be activated (and thus, the internal ROM outputting data) depending on a few bits from A or B register - which may come from random application software. Even though the internal ROM shouldn't do anything during I/O cycles (as is the case when ULA controls the ROM).
At best, things still work and/or R7..R14 (see ZX81 schematic) prevent damage. At worst, you get a short circuit between ROM output and external hardware.

The thinking error here is that you have a memory IC outputting data at all times, and you only have to decide between internal ROM or external RAM. That is simply not true, you have:
  • ROM access (usually, only attempts to read)
  • RAM access (read & write)
  • Refresh cycles
  • I/O cycles (read & write)
  • Interrupt Acknowledge
  • ??? (perhaps something I forgot)
The circuit above deals with the first 3 cases, but ignores/responds incorrectly to bold-printed events below it.
/CE is not actually pulled low anymore, since the IO-port pulls it high when it's being addressed (FFFBh-FFFFh), so that would speed things up anymore, unfortunately and only save 1 OR-gate, it seemed a more obvious way to do it, and given the length of the cycles (as provided by Mark) and the speed of the RAM, i am not so stressed for time, Both work.
??? Don't understand what you're trying to say here. :?
Ok so now i am thinking how can i simplify this, and keep my ROM-ghost, 'cause the obvious thing to do would be to connect A15 and /MI to the A14-RAM pin, but then how can i write to 0000h-2000h ?
Well in principle there isn't a problem with having your RAM 'absorb' data written to 0000-1FFFh (or 2000-3FFFh), even though a programmer might expect ROM there. As long as /ROMCS' is pulled high during that time.
No idea what would be the simplest circuit, or easiest way to switch ROM -> shadow RAM. "Anything goes" 8-) as long as at most one IC outputs data at any point in time.
Thank you very much Retro (or Techie, do they call you that at home ? :? )
I wish... :lol: family & friends know me as Alwin.
I might seem a little thick, but this is quite tricky stuff, and i only really got into electronics about a year and a half ago,
To be fair, a ZX81 is far from easy to understand. Low in "gate count", but quite difficult to understand how it works. For example most MSX computers have more, and more complex IC's on board. But both from programmer and hardware-designer's point-of-view, it's much easier to understand how they work. For Z80 systems, a ZX Spectrum sits somewhere in between (still a lot simpler than a ZX81).
out of my own experience (both ways) it turns out also a lot harder to explain something to someone how doesn't understand yet, than to someone who understands already.
Like everyone, you build 'on top' of existing knowledge. Kind of like discovering new territory: you look around, observe, think, then take a few steps in the direction that seems most promising or interesting. But in order to find London (or tell other people what the place is like), you first need to have a general idea where the UK is... :D
Rishi
Posts: 107
Joined: Mon Jun 08, 2015 6:57 pm
Location: Amsterdam

Re: Memopak : bad RAM chips ?

Post by Rishi »

RetroTechie wrote:
Rishi wrote:The schematic in this post isn't actually the latest version, this is :
Thx for that... and ouch! I won't even try to figure out what that circuit does! :mrgreen:
It's not all that different from the other one, just /REFSN making sure that the characterset is available from the ROM
RetroTechie wrote:
??? All i am doing is removing the ROM mirror's from memory, and that only while it is replaced by RAM, (..)
That's what I thought as well at first look. But it's not the case: /ROMCS' is activated whenever the external RAM's /OE and /WE inputs are held high. Including times where neither ROM or RAM should be doing anything. Btw. you've got /RAMCS' on the edge connector hardwired to +5V, right?

When the Z80 executes this code:

Code: Select all

     IN A,(n)
/MREQ will be high, /IORQ goes low, port number "n" goes onto A0..A7, aaaaannnd the contents of A register goes onto A8...A15. For I/O instructions that use register(s):

Code: Select all

     IN r,(C)
     INI
     INIR
     IND
     INDR
it's C that goes onto A0..A7, and B register that goes onto A8..A15.
Similar story for Z80 OUT/OUTI/OTIR/OUTD/OTDR instructions. What's on A8..A15 during I/O instructions, is perhaps not-so-well-known among programmers, but documented Z80 behavior (see "INPUT AND OUTPUT GROUP" in instruction set description).
Now work out what the circuit above does in these cases, and you'll find that /ROMCS' may be activated (and thus, the internal ROM outputting data) depending on a few bits from A or B register - which may come from random application software. Even though the internal ROM shouldn't do anything during I/O cycles (as is the case when ULA controls the ROM).
At best, things still work and/or R7..R14 (see ZX81 schematic) prevent damage. At worst, you get a short circuit between ROM output and external hardware.

The thinking error here is that you have a memory IC outputting data at all times, and you only have to decide between internal ROM or external RAM. That is simply not true, you have:
  • ROM access (usually, only attempts to read)
  • RAM access (read & write)
  • Refresh cycles
  • I/O cycles (read & write)
  • Interrupt Acknowledge
  • ??? (perhaps something I forgot)
The circuit above deals with the first 3 cases, but ignores/responds incorrectly to bold-printed events below it.
That is not true, /ROMCS only goes high when /MEMRQ goes low ! (i did have a version where i tapped onto the circuit before the OR-gate with /MEMRQ, but that didn't work, for exactly the reasons you you mention now)
RetroTechie wrote:
/CE is not actually pulled low anymore, since the IO-port pulls it high when it's being addressed (FFFBh-FFFFh), so that would speed things up anymore, unfortunately and only save 1 OR-gate, it seemed a more obvious way to do it, and given the length of the cycles (as provided by Mark) and the speed of the RAM, i am not so stressed for time, Both work.
??? Don't understand what you're trying to say here. :?
I'm saying 2 things, 1- since the IO-port (which is 4 Addresses) disables the RAM for given addresses using /CE has to keep doing that, also when i connect /MEMRQ to /CE the gain of nr. of Gates is only 1. 2-the speed of the gates combined with the speed of the RAM is such that either way it would take about 100ns to complete the whole thing, and since the cycle last 300ns time should be plenty, this is simplifying things, i was concerned about it, but one of the things to keep in mind is that for the pins on the chip that respond to a downward edge, is that the edge only occurs once, eg the address pins go to their state first, /RD & /WR get their state, only then does /MEMRQ go low, that is why i chose this option to begin with, i didn't know that after /CE goes low (i should have know, it triggers internal line drivers i guess) /CO & /CI have a state change.
RetroTechie wrote:
Ok so now i am thinking how can i simplify this, and keep my ROM-ghost, 'cause the obvious thing to do would be to connect A15 and /MI to the A14-RAM pin, but then how can i write to 0000h-2000h ?
Well in principle there isn't a problem with having your RAM 'absorb' data written to 0000-1FFFh (or 2000-3FFFh), even though a programmer might expect ROM there. As long as /ROMCS' is pulled high during that time.
No idea what would be the simplest circuit, or easiest way to switch ROM -> shadow RAM. "Anything goes" 8-) as long as at most one IC outputs data at any point in time.
Oh that is a great idea, that is definitely better then any other solution i've come up with so far with 64K present, it would change the schematics terribly though, but that will probably any happen, to get 64K to work. For now i've decided to focus on gettig the UDG to work first and then look at the 64K again, or first get a USB adapter to my IO-port (parts came in for that as well, an Arduino-nano clone, cheap, small and multi-platform) and keep my magic box closed for a while so that some programming can happen.
Thanks again Alwin, 2 see more then 1
32K SRAM WRX compatible, 32Bit IO-Port, ROM Ghost, ZX-Printer.
Post Reply