Z80 memory banking for 128K - MMU design - Page 1
Forum section: electronics / projects

author: nockieboy
author_rank: Super Contributor
timestamp: November 08, 2017, 04:19:53 pm
content: Hi everyone,Okay, I've been busy learning more assembly and writing CP/M software for my Z80 SBC these past few weeks and now I'm taking a break to finish off a couple of hardware tasks I'd like to complete on it.I'm having more than just a little trouble getting my head around designing an MMU for my Z80 that will allow it to use a 17-bit (128KB) address space.For those that are unaware of my lengthy previous post in these forums regarding Z80 fault finding, I'll just state that my software capability far outstrips my hardware and soldering skills. My Z80 currently resides on a breadboard, but is otherwise a fully-functioning computer with 64K SRAM, CTC, SIO/2, PIO and an Atmega328 micro-controller providing multiple speeds of system clock (2, 4 and 8 MHz selectable from CP/M 2.2 which runs just fine from the CompactFlash card.)It has a 128KB SRAM chip, though and I would really like to be able to give the Z80 access to the full 128KB of SRAM goodness. However, after much digging online and finding precious little regarding MMU designs for the Z80, I am resorting to asking here for a bit of a leg-up on the circuit design.Here's the design specs (or intended memory map, if you will):So as you can see, I want to divide the memory space into 4 blocks of 16KB:Area 0, the base 16KB of memory, will be fixed as this forms the ROM space when the computer first boots up and, when CP/M is running, this area is RAM and houses a lot of important CP/M vectors and the start of the TPA.Area 1is the second 16KB of RAM space and, if CP/M isn't running, houses a lot of important information for the ROM like the stack, command buffer etc.Area 2is the top 16KB of the TPA in CP/M and free memory - so this is the 16KB bank of RAM I'd like to be able to switch with one of the four 16KB banks in the upper 64KB of the SRAM.Area 3is the top 16KB of the 64KB addressable by the Z80 (the bottom half of the 128KB SRAM) and is where CP/M, CBIOS etc reside.So I'd like to be able to swap in any of four 16KB banks in the upper half of the 128KB SRAM into Areas 0, 1 or 2.So what have I tried so far?Well, aside from hunting out some not very helpful schematics online, like this onehttps://sites.google.com/site/oldcpusrus/home/simple-mmu-for-the-z80, which confuses rather than helps me (remember I'm not so hot on the electronics side), I came up with the beginnings of an MMU design on the back of a fag packet (or would have been if I smoked):So this allows me to swap Area 2 for Bank 1 or Bank 2 in the upper 64KB of SRAM. I think. BUT I can't work out how to finish the schematic so that ANY other 16KB bank in the upper 64KB can be mapped to Area 2 - at least not without the addition of lots of convoluted circuits and logic chips to force the values of A15 and A14 depending on the output from the 273... but then I don't want to mess with the addressing of normal, non-banked memory space.So, would anyone be kind enough to give me some explicit guidance on how I need to design the circuit (as simply and with as few chips as possible) so as to expand the address bus to 17 bits and allow me to map any of the 4 banks in the top half of the 128KB SRAM to Area 2 in the lower half of the memory space?UPDATE: (Edited to update requirements for CP/M 3 compatibility.)I've been reading through the CP/M 3 system guide (seems I should have done that before I decided the specifications for the MMU) and it appears that CP/M 3 wants the bottom three areas (0, 1 and 2) to be switchable, rather than just the one...So now I'm looking to have three switchable 16KB banks, Areas 0, 1 and 2, that I can switch the banks in the upper 64KB into and out of at will. I like the idea of being able to map any bank to any area in the memory space, so that's a key requirement for the MMU design now.

author: Mjolinor
author_rank: Frequent Contributor
timestamp: November 08, 2017, 04:33:52 pm
content: It has been a long time since I did any messing with Z80s, around 40 years if I had to guess.At that time I would probably have solved this problem with a UVEPROM that contained a look up table and used the data lines to drive the relevant address lines on the thing I wanted the data from.I hope that is enough to start your brain because specific would really tax me nowadays.

author: jm_araujo
author_rank: Regular Contributor
timestamp: November 08, 2017, 05:04:03 pm
content: I think you can solve it with a single 74HCT157 - Quad 2-input multiplexer. See attached schematic.I didn't redesign the parts already in your schematic. "Dn_Latch" are the outputs from the 74hct273 (with an extra D2), "1Y" is the same as yours (area 2 selected).If other area is selected A16=0, SRAM_A14/A15=CPU_A14/A15If area 2 is selected, A16=D0, A14=D1, A15=D2 (change as it best suits you, it was made in a rush).This way you can map any memory area to area 2, so be careful

author: bsudbrink
author_rank: Frequent Contributor
timestamp: November 08, 2017, 05:05:27 pm
content: Use something simple like a 7475 latch at a particular I/O address to drive some of the EPROM pins and give you software control over the banking.

author: glarsson
author_rank: Frequent Contributor
timestamp: November 08, 2017, 06:12:17 pm
content: The CP/M system I designed, built and used in the early eighties had a MMU designed using 74170 register file (SRAM). The 7417 is (was?) an odd thing with separate data and address lines for writing and reading. It has two address lines and four data lines (not a large RAM).The way to build a MMU from it to connect A14 and A15 (on the Z80 side) to the two address lines used for reading and the four data outputs to A14, A15, A16 and A17 (bus side). RE (read enable) is grounded. More 74170 can be used to address even more memory and/or address smaller segments. Note that the 74170 has open collectors on the data outputs and will need pull up resistors. The four data inputs connect to D0, D1, D2 and D3 on the Z80. The two address inputs connect to A0 and A1 on the Z80. The write enable (WE) connect to some decoding logic that decodes the port space and write signals from the Z80.The 74170 will now appear as four byte sized I/O ports (write only).After reset the content is unknown so you can not use anything on the bus side until the 74170 has been initialized. I did this by having the boot EPROM on the inside of the MMU. It had incomplete address decoding so it was replicated all over the 64k address space. When the Z80 started running at 0000 it jumped up to the same EPROM at 64k-4k. After initializing the 74170 it then copied itself over to RAM (the write signal went to the bus, the read signal to the EPROM). Then a flip/flop was set and the EPROM was removed from the address space.I ran CP/M 3.0 (also known as CP/M Plus) on this machine. This version of CP/M supported memory banks. The way I used my MMU was to have 16k at the bottom for CP/M variables and first part of the TPA and 16k at the top for the last part of the TPA. At the top was a very small bios used to switch bank and vector all CP/M calls to a different memory bank. The middle two 16k banks had three alternatives, 32k TPA, 32k disk buffers or 32k CP/M bios and bdos.The memory was 64 times 6116 CMOS RAM (2k-byte) for a total of 128k. All wire wrapped. The MMU used more than one 74170 to make expansion to 1MB possible, but that never happened. To expensive (both cost of RAM and wire wrapping time).

author: David Hess
author_rank: Super Contributor
timestamp: November 08, 2017, 08:35:27 pm
content: One trick I remember is to have separate banking control for reads and writes. Now banks may be configured to act like ROMs if necessary, ROMs may be copied into overlayed RAM which is then swapped, and copying from the current visible bank to a hidden bank at the same addresses becomes trivial.

author: nockieboy
author_rank: Super Contributor
timestamp: November 08, 2017, 08:42:59 pm
content: Okay, thanks guys - there's some good starters for 10 there. I've been reading through the CP/M 3 system guide (seems I should have done that before I decided the specifications for the MMU) and it appears that CP/M 3 wants the bottom three areas (0, 1 and 2) to be switchable, rather than just the one...So now I'm looking to have three switchable 16KB banks, Areas 0, 1 and 2, that I can switch the banks in the upper 64KB into and out of at will. I like the idea of being able to map any bank to any area in the memory space, so that's a key requirement for the MMU design now.If at all possible, I'd like to do it with discrete logic rather than more RAM or EEPROM chips (seems like overkill?)Quote from: jm_araujo on November 08, 2017, 05:04:03 pmThat sounds like the ideal solution so far - would it require much alteration to allow mapping to ANY area, not just Area 2?

author: C
author_rank: Super Contributor
timestamp: November 08, 2017, 08:44:31 pm
content: Need to get your head around memory management. It can be simple, your computer is doing it now.Area 0You now have a bit that is controlled by an z80 out instruction. This bit and Area 0 select enables one of two chips.You have a switch with output enabled by Area 0 select. The switch controls which chip select is enabled.If you add one more bit then you would have four different states. when combined with Area 0 could select one of four chips by using chip select. Area 0 would enable output of a 139With three bits, you could select one of eight chips. This would use a 138.So this is many chips swapped into one area.Now lets look at many areas of a chip swapped into one area.If the bit is connected to an address line of a chip, you could switch between two areas of the chip. So the Z80 would access Area 0 and the bit would select one of two blocks of memory on the chip.If you added one more bit(2), you would get 4 blocks from chip. With three bits you get 8 blocks.Now if you put both of above together you have a X-Y matrix of block. Some bits select what chip ( row ) and some bits select the block (column).Now this is all using Area 0 select, but you also have four areas to deal with. You want to use the blocks from one chip in the different areas. You get four layers in the Z direction when you add the area selects.To have the blocks work with four areas you need four sets of bits to select what block is used in each area. You also need a switch to select what set of bits is used.A 273 has 8 bits, so you could have two bits for each area. You would need a dual one of four data selector to do this. The output of data selector connects to chip address lines and selects one of four sets of bits on the input.Now if you add an additional 273 and dual 1 of 4 selector you could have four sets(area) of 4 bits(block). Do some numbers, Four Areas of 16k for Z80 & 16 blocks of 16k for memory(256k). So you have two 273 and two 153 to do this.Now ram/rom switch is included, Using this larger address space, Rom is addressed 0-128k and ram is addressed 128k-256k.With power up resetting the two 273's you have the the first block of Rom in each Area. With two Z80 output instructions you can have any block in any Area.Now that you have got this far, look at the 74LS670 again. Data sheet states it is a 4 x 4 register file. Four sets of bits with each set four bits wide.To work with this chip you would use 4 I/O addresses and write just 4 bits. The above using two 273's lets you use just two addresses and write two sets of four bits.Note that the special thing about the 74LS670 is that it has one set of pins to write to the chip and a second set that is used for read. The write set would be connected to Z80 I/O. The Read set address lines are connected to Z80 A14-A15 giving you four areas. The read data outputs are the expanded address A14-A17 address lines. You should note that on power up the data in the 74LS670 is unknown which will need more chips to correct so that Rom is in place on power up..------Think of a separate memory card. Rom responds to addresses of 0-128k and Ram responds to addresses 128k-256k.The A14-A17 address lines are connected to the outputs of the 153's.The A0-A13 address lines are connected to the Z80.The other lines are connected to Z80 like normal memory.The Inputs to 153's are connected to outputs of the 273.The two select lines(a0-a1) of 153 are connected to Z80 A14-A15The Strobe lines are tied low.With two 153's each being dual you have a 4 of 4 data selector.The two 273's are connected as Z80 output ports and the outputs are the four sets of four bits for input to 153'sThe 273's are reset on power on so that you get Rom on power up.Now the cement.You want four areas of 16k. This uses two bits to select area. If you only had two bits of data in the four sets, you would have four blocks that you could put in any of the four areas. This is four areas with four blocks. You need more bits in each set to expand. Each extra bit per sett doubles the number of blocks.If you understand how this works then you can expand even more. Each 153 adds two more expanded address lines and would need input data.Note that the data sits at inputs of the 153's so that the upper expanded address lines are delayed by 153's input select time.This is greater then what you asked for, but in the process uses few general chips and works with power on.

author: nockieboy
author_rank: Super Contributor
timestamp: November 09, 2017, 11:15:29 am
content: Quote from: jm_araujo on November 08, 2017, 05:04:03 pmWould an SN74HCT257N be a suitable replacement for the 74HCT157? I'm trying to avoid SMD if at all possible as my soldering skills are probably not up to it!

author: nockieboy
author_rank: Super Contributor
timestamp: November 09, 2017, 11:20:23 am
content: Quote from: C on November 08, 2017, 08:44:31 pmI'm going to have to go away and think about what you've written, C - for quite a while. Maybe even draw some diagrams before I can understand the premise.. there's a lot there!

author: jm_araujo
author_rank: Regular Contributor
timestamp: November 09, 2017, 11:45:39 am
content: Quote from: nockieboy on November 09, 2017, 11:15:29 amIn this case it will work the same.

author: C
author_rank: Super Contributor
timestamp: November 09, 2017, 08:13:40 pm
content: nockieboysorry looks like my cement was not good.Try making a picture.Large sheet of paper.1. On right side make a box an label it memory. Draw a line across this block as half is rom and other half is ram.2. On left side make a box an label it Z80.First questionHow many areas will Z80 memory be?When you have number of Z80 memory areas then you know what kind of switch you need.You stated 4 Z80 areas, so you need a 4 throw switch.3. Draw a 4 throw switch to right of center of drawing.With 4 Z80 areas you haveZ90A15 - A14 these are area select lines.A13-A0 these are address in the area & blockExpanded memoryEa17-Ea14 These are the block in expanded memoryEa13-Ea0 These are the address in the block.Back to your drawing4. Now to the left of center need to draw something for block address data.From switch side you have four boxes.From Z80 you have two boxes that are splitSo Two boxes wide & two boxes high with some white space separating the boxes5. now add some logic lines.a. each box of #4 will be connected to a switch input.b. the two horizontal boxes will be written by a Z80 out instruction.c. The switch position will be controlled by Z80 A14 & A15d. The remaining Z80 addresses are connected to memory box.On Power up you reset the 273's, so all bits are 0 in #4 boxes.So6. In memory box, Rom must be low address range of memory to match the 273 on reset.So you have the 4 boxes of #4 that the contents of a box is Ea17-Ea14 The extended memory block address for that Z80 area.The switch is selecting which box of data to use as extended address, the block address based on Z80 area.After two Z80 out instructions you could have this.Area Z80 extended memoryA15 A14 Ea17 Ea16 Ea15 Ea140 0 0 0 0 0 01 0 1 0 0 0 12 1 0 1 0 0 03 1 1 1 0 0 1Note that you are using two 273 to store the above data, one out instruction sets data for two areas.The data in above table statesZ80 area 0 0-16k = expanded memory block 0 = 0-16k = rom 0-16kZ80 area 1 16k-32k = expanded memory block 1 = 16k-32k = rom 16k-32kZ80 area 2 32k-48k = expanded memory block 8 = 128k- 144k = ram 0-16kZ80 area 3 28k-64k = expanded memory block 9 = 144k--160k = ram 16k-32kFrom the Z80 you have 32k of rom starting ar address 0 & followed by 32k of ramThis is the same as if you just had two 32k memory chips connected to Z80.To get to this state the Z80 did two Z80 Out instructions with the instructions in 0-16k if romOrg 0 H; do some initial boot stuff; then set up memoryout 273-0, 10h ; set area 1 bits to block 1 set area 0 bits to block 0out 273-1, 98h ; set area 3 bits to block 9 set area 2 bits to block 8: now you can set the SP and continue booting===============The switch in the drawing is letting you use two bits of Z80 to get 4 bits to be used as the high bits of the extended address.======Things to look atThe switch is doing the decoding of the Z80 area.Say you wanted0-16k to be rom always at same rom address48k-64k to be ram always at the same ram address.And want to switch the center two 16k blocks.You would need memory chips for the two fixed areas & more memory chips for the switched memory. You could use a two way switch in this case.If you want the fixed rom or ram to come from the memory chips in the switched memory chip area, you need to add at least one more switch position to get this to happen.Computers work in binary so a 3 position switch is hard to find, you would end up using a 4 throw switch. You could then strap the inputs of the 4 throw switch so that it gives the fixed address to get the above two fixed areas. And data at the other two switch inputs to select wanted block for that area.By adding just one 273 chip you have data for four switched areas. This is what you have in drawing.If you look at the boxes that hold the expanded address, you should see that a few bits can make a huge difference. Two more bits would let you have a 1M expanded address range.==========74LS670As stated in last post, you would have a power up problem using this chip. There is a pin on this chip that will make outputs go tri-state. You could control this pin by using one bit of a 273 that was cleared on power up.To get this to work you would need pull-up resistors on the outputs of the 74LS670 & need to put power up boot code in the highest block of memory.Ram would be address in 0-128k, Rom 128k -256k.The highest block of 16k would then be rom and you put boot code in this block.At power up Z80 would be running block F code with Z80 using addresses in 0-16k.With Z80 now running the first steps would be to write good data in the extended address blocks stored in the 74LS670 and then enable output of the 74LS670 by writing to 273Look at drawing againWhen you use 74LS670Rom and Ram areas are wwapped.The boxes that store extended address are now four tall and use four Z80 output instructions.The 74LS670 contains the switch and the data boxes.Using two 74LS670 would let you have a 4M expanded address range by using 4 output ports. You are probably thinking what would I use it for.One use would be to use memory that is shared or used by a different CPU.So memory management is simpleYou have something between the CPU and Memory that changes addresses that the CPU can control.If something does not make sense it could be an error in above.

author: nockieboy
author_rank: Super Contributor
timestamp: November 09, 2017, 10:19:38 pm
content: Yeah, I'm going to have to go away and think long and hard about what you've written, C - I'm finding it a little hard to follow.Here's what I've drawn up so far - it's more of a serious sketch of the original hand-drawn plans in my first post, but this one includes a slight improvement in terms of using a 74HCT257, thanks to jm_araujo's suggestion.The problem with this design is that it just answers my original question - i.e. making area 2 switchable with any bank in the upper 64KB of RAM. What I need to be able to do, having looked at the CP/M 3 System Guide, is to make areas 0, 1 and 2 switchable. This adds a layer of complexity that is far beyond my simple electronics knowledge and understanding, unfortunately.

author: glarsson
author_rank: Frequent Contributor
timestamp: November 09, 2017, 10:29:10 pm
content: Quote from: nockieboy on November 09, 2017, 10:19:38 pmUsing a 74140 or 74LS670 allows you to map any memory segment (e.g. 16k) to any e.g. 16k as seen by the Z80.

author: C
author_rank: Super Contributor
timestamp: November 10, 2017, 03:16:31 am
content: Look at your last design.You have more bits in the 273 & one more 1 of 2 switches.This one bit lets you have A17.When A17 = 0 rom is selected.When A17 = 1 ram is selected.You can get this to happen just by proper connection to rom & ram chips.You now have 8 banks you can swap in to area 2, 4 ram & 4 rom.This change is a step to removing all the other chips used to swap rom for ram.Your switch is a 2 throw switch & is selecting normal Z80 or Banked, but banked is only used for area 2 which needs extra logic to select.You can remove the logic that selects area 2 by using a 4 throw switch!Two 153 would let you do this. A 153 is a dual 1 of four switch.By connecting Z80 A14 & A15 to the 153's A & B inputs, the switch it's self will decode the area removing need for area2 select. For now just strap other inputs to proper levels for the fixed addresses like you have with the 257.Now if you look at 273 you have 4 bits not used. If you used these 4 bits to select the bank for area 0 you could remove all the other logic that selects rom/ram for system.Area 0 would point to 0-16k on power up and by writing the 4 bits can point to any block of ram or rom.This leaves 8 inputs to the 153 strapped to a level. By adding one 273 you have bits needed to change these pins and all areas can be banked as needed.So two 273's and two 153's give you four areas that are bank selectable & you get to remove current logic that selects rom or ram swap.You should note that CS for the rom & ram chips selects chip active or disabled/sleep.If A17 & Z80 MREQ is used for Chip select then Z80 RD & WR can be directly connected to these chips.Need to look at big picture when thinking about a change.You locked into changing only area 2 and not looking at total system and a change that would get a better result.

author: nockieboy
author_rank: Super Contributor
timestamp: November 10, 2017, 11:18:49 am
content: Quote from: C on November 10, 2017, 03:16:31 amOh yes, I like your thinking, C.It would be great to improve on Grant Searle's original ROM/RAM switching design with a reversible system. By default, his system allows you to switch the ROM 'off' when loading CP/M, but there's no way to switch it back in without doing a cold reset of the entire system. Being able to switch in any bank of the 128KB ROM would be nice too...Quote from: C on November 10, 2017, 03:16:31 amYes, well the whole Area 2 thing was just my initial thoughts on MMU design, partly because it seemed simple and a good idea at the time, and partly because I was unaware how CP/M 3 likes to have the whole bottom three areas switchable! I've updated the original post and memory map accordingly.Quote from: C on November 10, 2017, 03:16:31 amI like the sound of this.Will have to look at the 153 and spend some time thinking about what you've said here to make sure I understand how it fits together.Quote from: C on November 10, 2017, 03:16:31 amThis is going to require someon the breadboard (or at least de-wiring of logic chips for the existing RAM/ROM select circuit), but it sounds like a much more flexible and powerful system.Quote from: C on November 10, 2017, 03:16:31 amOkay, I think I already have a couple of 273's knocking about. Could I use74HCT253's in place of the 153's? I'm dippy about DIPs and want to stay away from SMD for as long as possible - plus the adapters are an added expense when prototyping on breadboard and I'm as likely to solder an SMD to my fingers as I am to the board.Quote from: C on November 10, 2017, 03:16:31 amConsider myself told off!Seriously though, thanks for that C - I feel I actually have the outlines of a plan now. I'm going to spend some time this weekend (hopefully) converting what you've written into a schematic that I'll post ASAP for feedback.

author: nockieboy
author_rank: Super Contributor
timestamp: November 10, 2017, 02:26:34 pm
content: Is this going along the right lines, C? I'm not sure this is even right, but going by your previous comments this as close as I can get. Not sure what to do with the Y1/Y2 outputs of the 253's, though - do they go to A15/A16 on the RAM/ROM? How do I select between RAM/ROM with this configuration?

author: C
author_rank: Super Contributor
timestamp: November 10, 2017, 02:43:22 pm
content: Just think of what you haveA 4 throw switchso the switch is area decode and you use two chips the get the expanded address buss width.the two latches arethe memory for the MMU, The storage of what bank in extended address to use for an areaso put bank decoder under area decoder in your drawing as both are arealabel four outputs of these as expanded address or extended addressYour data bus Area & bankthese inputs are Z80 I/O write to selected addressyou are writing two areas extended address data (bank) with one output.ADDEDThe output of Switch is A14, A15,A16,A17As they are not the same as direct Z80 it is a good idea to change the labelEA14-EA17Yes yes switch outputs go direct to memory are address lines.The big difference is that you have the ability to change the address mapping&The switch takes time to switch so these higher address lines change slower, need to check timing as this can effect memory read/write times

author: C
author_rank: Super Contributor
timestamp: November 10, 2017, 06:24:31 pm
content: You should note that all my posts here are same result.Two 273's and two dual 1 of 4 switches or mux.I just modified your drawing step by step.Speed of the switches is important. Faster gives you more time for memory.Normal Z80 Memory connection.Most memory chips do nothing when CS is inactive.Most expect address inputs to be stable when CS goes active.With CS inactive changes on RD and WR are not used or looked at.Your memory works like this.I say most as there are many ways to connect memory and types of memorySo Normal Z80 has RD & WR directly connected to memory. The selected chip will respond to memory cycle.Memory CS is a combination of Address Valid, which memory chip is to respond & Z80 MREQThe 138 is build just for this as you can connect one of the enables to Z80 MREQ and if you look at inside logic of chip, some of the enables just turn on the outputs of the chip. This hides all the random states as the address line inputs are changing.MREQ then will enable output at correct time, removes chip output glitches.So my good design practice it to use proper chips in correct place and really check the timing & time delays to try to prevent glitches that are very hard to find.So You have two 128k chips and need a decoder to select which chip based onEA17 & Z80 MREQPick a decoder chip and use it. You have many choices 138, 139 and many others.Now look at your memory timing.The data in the 273 is static, not changing on a memory cycle.The address buss from Z80 starts changing.The Switch takes time to switch inputs and get proper static output so this adds a delay.Then Z80 MREQ happens and gets sent to decoder chips.The decoder chip takes time so you have a delay here also.The output of decoder chips start the time clock on the memory CS time.So is address stable when CS of memory chip goes active?Now keep in mind that for Z80 address starts changing on one clock edge and MREQ is a different clock edge.It is not hard to add some delay to MREQ.Look at removing Grant's logic.Having a Cold reset & Warm reset is a great thing.U8 is not common in most designs I have seenWith most designs I have seen MREQ and IORQ are output enables of address decoder chips.Looking at the SIO the CE pin would go low(active) when proper address is valid and stable and IORQ is active. U5 is missing a IORQ input to enable pins to make this case.You could do some tests to verify that the following changes work step by step with the result of removing grant's logic.1. On U5 connect pin 5 (E0) to IORQ instead of A7Test computer all should work fine. You should be able to send/receive via SIO and you should be able to read and write to CF Card with out errors.2. With change 1 in place, you should be able to move connections to J1 piins 4 & 5 to connect to the Z80 RD & WR in place of U8c & U8D.Run tests of #1 again and you should see no problems.Starting change to add new Memory mapper.3 You will add a decoder chip and connect it to an un-used output of U5. You will use this I/o address range to control the MMU. When MMU is working properly you can then remove grant's ram/rom logic.Add a 138 or 139 chip. The U5 un-used output can be connected to an enable pin or an address input of decoder. One of the enables will be Z80 WR. Connect A0 & if possible A1,A2 to this chip.You now have outputs that are IO write that can be connected to 273 chips.4. A quick test of what you have to this point.connect one 273 to #3 and use a output of 273 to change input of U8D pin 12.heck/verify that a 0 output of 273 selects ROM chip.Add software in Z80 to change the bit in 273. leave old software for grant's in place.Run #1 tests. Should work for grant's logic or 273 output.Keep in mind that a MMU goes between CPU and Memory.This MMU uses a few I/O writes to control it's operation.You might want to put this circuit on a separate breadboard.A step by step change for memory is harder to do. You need all four chips connected properly with some changes to memory chip selects & software.5. with U6D connected to grant's logic, build MMU circuit.Do NOT connect switch outputs yet.You will need to write software for MMU. Do this by adding software leaving grant's software.On power up you will have all ROM so use software to make MMU select0-16k rom for area 0 and ram for other areas.Where software changes to all ram, add code to change MMU (the 273 data) for all ram. Leave grant's software in place.Check proper data is written to the two 273'sWill need to use scope to verify that Switch outputs is working.6. Now that you have this much working and tested as much as you can, change memory selects so that MREQ is used to control CS of memory chips and EA17 is also used. Rom = 0-128l Ram = 129k-256k when looking at the expanded address.If you need logic to do this I would use a decoder chip.Connect MMU outputs to memory.7. Test it.with proper software for MMU you should see no change from what you have now.8. Here you can remove Grant's logic that is not used.You should note that for CP/M3 & TurboDos you can start the computer running CP/M2 and run a command to change to new system.This makes testing the software changes needed for new OS easer.You can use the 74ls670 if you want to.The cmos versions of this chip are very slow, you need LS or faster.If you order this chip 74LS670, I would get 2 or more.You will also need pull-up resistors for outputs of chip.The basics are the same as using 4 chip MMUThe 74ls670 will use 4 Z80 out addresses instead of 2.Rom/Ram is swapped in extended memoryOne step that you might have trouble with is loading boot code into the highest 16k block of Ram.Something you might want to think about. The Z80 can program the ROM you are using.

author: jaycee
author_rank: Regular Contributor
timestamp: November 10, 2017, 08:19:07 pm
content: Worth looking at the design of the ZX Spectrum 128, which banks memory in the top page of the Z80's address range. It's quite a simple mechanism.

author: nockieboy
author_rank: Super Contributor
timestamp: November 10, 2017, 09:49:34 pm
content: Quote from: jaycee on November 10, 2017, 08:19:07 pmYeah, that's no good for me as I want to make my computer compatible with CP/M 3, which requires the bottom two thirds of RAM to be switchable. I noticed some interesting stuff going off with the AY sound chip in the 128's schematic though - looks like they control the keyboard and RS232 through the AY's IO ports..Quote from: C on November 10, 2017, 06:24:31 pmYes, Grant's design is missing the IORQ input to U5, but I've added it to mine so the 138 only responds to proper IO requests.

author: Jr460
author_rank: Regular Contributor
timestamp: November 10, 2017, 10:33:54 pm
content: I didn't read all the post in this thread in detail, so maybe I'm stating something already discussed, sorry.Many years ago, before CP/M 3.0, when 2.2 was king, I worked on a MP/M system. It was multi-user CP/M and if you wanted it work well you needed bank switched memory. Like 3.0 the top part of memory was not switched.(If think about it this is way most modern virtual memory OSes work. System space for the OS and devices is the top half of the virtual address space and process private is the lower half.)The system I worked on was S100 buss based and the memory cards were 48K each and had a dip switch that set the IO port number that the card would listen to to turn it on or off. It was up to MP/M to keep track and only have one card enabled at a time. One card in the system had a full 64K, and the lower 48 could be disabled again with an OUT command.Maybe look for old schematics of those S100 boards and see what they did. At least you know CP/M 3.0 will work with with that method of memory management.

author: nockieboy
author_rank: Super Contributor
timestamp: November 11, 2017, 04:01:03 pm
content: Okay, this is where I'm at with the schematic based on C's discussion above (ignore the labelling for ~AREA and ~BANK - they're just IO select lines from the '138.)I'm flying blind a little bit as I don't fully understand how this will work - or even if it WILL work - I've just thrown it all together based on C's posts. You don't want to hear excuses, but I've had a busy day with the family and now have a splitting headache, so I'm struggling to work out how and if this circuit works at switch-on.At power-on, the default state should be: ROM - 0000h-3FFFh, RAM - 4000h-FFFFh. The ROM should be able to be switched-out with an IO call so that the entire 64KB memory space is RAM, for CP/M to run. This is handled by EA17 in the schematic.Now bearing in mind I don't really know how this is supposed to work - aren't I going to have to set a default value in the latches to ensure the above default ROM/RAM memory state is enforced?If no banking is enabled, how does A14 and A15 get passed through to the RAM/ROM? Do I need to connect A14/A15 to 1C0/2C0 on the 253 that outputs EA14 and EA15? This circuit just feels incomplete...Quote from: Jr460 on November 10, 2017, 10:33:54 pmNo need to apologise! Welcome to the discussion, Jr460!Quote from: Jr460 on November 10, 2017, 10:33:54 pmI'll have a hunt for S100-related schematics then - there seems to be a couple of sites relating to S100 computers that I've come across previously. I feel I'm getting somewhere with my current design, though and if I can complete it, it'll be extremely versatile as it will allow me to map ANY 16KB bank of memory space to ANY 16KB bank in physical RAM or ROM.

author: Ian.M
author_rank: Super Contributor
timestamp: November 11, 2017, 05:08:50 pm
content: At powerup, after /RESET is released, both latches will have '0' on all outputs. A14 and A15 will therefore be ignored and the low 16K of the ROM will be mapped to the whole address space, repeating four times. By writing to the latches you can map any bank of RAM or ROM at any 16K page in the address space. However you would do well to rearrange the input lines to the multiplexors so EA14-EA17 for a single page are controlled by four bits on the same latch, otherwise it will be difficult to switch mappings without smashing the mapping for the page that is currently executing.However this seems over-complex. Personally, I'd use a 74HC670 4x4 addressable register file to expand the addressing. It does *NEARLY* everything the above circuit does in one chip. That would give you a separate port write to control each page, with two bits in the data selecting the page and four bits selecting the bank, but would need the addition of a flipflop driving its /RE pin (that controls its output tristate capability) set by /Reset and cleared by an unused data bit decoded at the port address+ 10K pullup or pulldown resistors to set the default powerup mapping.

author: nockieboy
author_rank: Super Contributor
timestamp: November 11, 2017, 08:06:55 pm
content: Quote from: Ian.M on November 11, 2017, 05:08:50 pmAh, right - how should I rearrange the multiplexer input lines to achieve that?Quote from: Ian.M on November 11, 2017, 05:08:50 pmOkay, I'm nearly persuaded - I'll see if I can get a basic understanding of how it works from the datasheet and throw a schematic together to see if I can pull this off.

author: C
author_rank: Super Contributor
timestamp: November 11, 2017, 08:21:57 pm
content: You are getting there keep up good work.An MMU enables lining to CPU about where the memory data actually is.Remember that it takes time to do this. Here the 153 is delaying address data from A15,A14 to EA15,EA14The 153 must select the input pin and the data on that pin then needs to get to output of 153.An example of this MMU in use.Your 128k rom has 8 blocks of 16k.One block needs to be the Z80 power up boot code.This boot code could ask you to pick 1 thing from the 7 other blocks.Block 1 your system monitor programBlock 2 Grant's basicblock 3 microsoft's basic...Block 7 something.All these different programs could be assembled to ORG 0HThe power up boot code when it gets an answer,Sets area 0 to the proper blockjumps to address 0HIf you selected 1 then you are running the monitor.selecting 2 gives you grant's basic.This is just very simple use of this MMU.=====As Ian.M pointed out and in my posts aboveThe Area bits should be together in one 273.Each 273 will hold two areas.So two bits of 273 area go to one 153 and the other two go to other 153.The data stored in the 273 for an area is EA17-EA14 used to address memory.The Switches (the 153) selects 1 of 4 sets of data based on Z80 A15-A14.So if both Z80 A15,A14 are low, The switches select area 0 data The expanded address EA17-EA14 which then goes to your memory chips.Your two 273 chips make up a 2 x 8 bit memory chip.The Reset/clear inputs lets you force contents of the 2 x 8 memory chip to all 0.Being able to set memory data to 0 like this is not normal for memory. You Ram memory chip when power is connected will have random data.Now the 153 switches is using this 2 x 8 memory as if it is a 4 x 4 memory chip.Think of your current ram chipIt has one set of data pins. You use these pins for both read & write.The two 273's is like a 2 x 8 memory chip. It has data pins for Write & a set of data pins for read.The 273 based memory has a data port for write and a data port for read.You are using a 1 of 4 switch on the output of the 273 memory.Your current ram chip has a built in 1 of 128k switch to select data.A normal memory chip stores data, your 273's stores data.A normal memory chip has a data selector, the 153's are data selectors.A normal memory chip has no reset input, the 273's does.Most normal memory chips have one data port, the 273's + 153's have two data ports.Now look at the 74LS670.It is a 4 X 4 memory chip.It has a data & address port for writing data.it has a data & address port for reading data.It has NO reset input.It has a tri-state output for read data port.This chip does all most the same thing as the two 273's & two 153'sWould use 4 outputs addresses of 4 bits.It is a RAM memory, So you have random un-known data in the 74LS670 at power up.To get valid data on output pins at power up,You connect pull-up resistors to the Read data port that is connected to memory, when you enable tri-state mode the resistors will supply a 1 to memory address line.When the 74LS670 read port is tr-stated your ram and rom chips will see an address of EA17-EA14 all being 1.By tri-stating read port at power up, The Z80 when reset will ask for address 0h, The memory will respond with data fromEA17-EA14 = 1 + Z80 A13-A0 = 0.The Z80 is reading the top 16k of memory but thinks it is the first 16k of Z80 memory.Your Z80 boot program is running and can now put initial data into the 74LS670. When that is done the Z80 can then turn-off the 74LS670 tri-state and start using the data in the 74LS670 for EA17-EA14.SoAn MMU is put between the CPU & Memory.It allows lining to CPU about where the memory data is in the actual memory.The CPU has a way to change the LIEThe computer you are using to look at this will probably have an MMU.The OS can use the MMU to keep one user of program from messing with another user or program.If a user or program can not access something then it can NOT make changes.A computer can run more programs or data then will fit in memory, if it can store the memory contents for a while in mass storage, This is called Virtual memory.Your mmu is using 16k blocks & has 4 areas.Some systems use much smaller area blocks. One system I worked with used 512 byte blocks.To change your MMU you may need to change 4 sets of 4 bits.Using the same total memory(256k) and same 64k CPU memory the MMU using 512bytes could need to change 128 sets of 10 bits.If you changed the MMU to use 4 sets of 8 bits then the total memory would increase to 4m.This would be two sets of 4 chips or 2 74LS670'sKeep in mind what you might want to do in the future.The 512k dip memory I found was in a 32 pin package.The Z80 being able to access a lot of memory space is a powerful thing.Memory does not have to be memory.Some CPU's have I/O in memory space.The extra memory space could be connected to other processors.

author: C
author_rank: Super Contributor
timestamp: November 11, 2017, 09:23:19 pm
content: Little steps trying to use what you know.You are using grant's logic to do Ram/RomRemove some of this and use a 273U7 C & D is a FFA 273 is 8 FF with a reset/clear inputTo use a 273 you need a signal to drive the clock input.You want to clock this input with a Z80 out instruction.You need IORQ & WR & a valid write address.With IORQ connected to U5 you have part of this.You can use an additional 138 or 139 to get what is missing.Lets use a 138 as it is easer to understand.The 138 has three enable inputs.One needs to be connected to U5One needs to be connected to WRA0 connects to A inputA1 to B inputA2 to C inputYou how have 8 outputs that are Z80 I/O write to a address.You can connect up to 8 273'sYou can connect other types of chips to these outputs.So you can connect one 273 and get the reset on power up of grants logic needs by using one output of the 273.A zero on output of 273 needs to select ROM.To get the 74LS670 to workYou need one output from the 273 connected so that a 0 makes the 74LS670 output goes tri-state.ORYou keep using grant's logic and have ROMDisabled connected to 74LS670 tri-state input pin 11.Wa & Wb connect to Z80 A0 & A1Gw ineeds to be Z80 out for a range of 4 addresses.U5 is I/O for a range of 8. Need to add WR to thisWith a 138 you would not connect A0 & A1 so that each output of 138 gives a 4 address ramge.With 139 you only have one enable.Connect WR to one half's enable.Need to use one of the address input pins to connect to U5.By connecting A0 to other address input pinYou get Y0 and Y1 as a valid Z80 output select.Y2 & Y3 are no connects.You can connect two 273's to the valid outputs.When connected to U6even address writes to 1 273, Odd address writes to other 273for 74LS670 with 139You connect A2 to address inputYou get four outputs that are a range of 4 output addresses.The 139 is dual so you could wire it up and connectTwo 273's&Up to Four things that need a 4 address range like the 74LS670You would need different outputs of U5 for each 139 halfWith this you can co I/O write to 4 chip MMU or 74LS670 based MMUNo other logic is needed for 4 chip MMU or 74LS670Note my quick look at data sheets for 74HC670 & 74LS670 suggests you want the 74LS670 for the speed.Parts count4 chip MMU1 138 or 1392 2732 15374LS670 MMU1 1391 2731 or more 74LS670Pull-UP resistors for outputs of 74LS670'sA resistor back would work great.

author: nockieboy
author_rank: Super Contributor
timestamp: November 11, 2017, 09:39:22 pm
content: Okay, preliminary schematic for an MMU using the 670 chip:I'm a bit lost with this one - one minute I'm getting my head around using 273's and 253's, now I'm looking at a 670 and wondering how I connect it up...Okay, so I know I have to add pull-up / pull-down resistors as appropriate to set initial startup values when the 670 is tri-stated during power-up - I need the bottom 16K of the ROM to be available to the Z80 in the bottom 16K of memory space on startup (0000h-3FFFh) - so I have a couple of questions regarding this circuit:1) How do I finish connecting it up to the address bus / control line/s. Do A14/A15 go toboththe read and write address inputs on the 670?2) I assume the IO select lines go to ~WE and ~RE?3) Have I connected up the Qn outputs correctly to the address lines on the RAM/ROM?4) The pull-up/pull-down resistors go in the data lines (D1-D4)?5) Where does the flip-flop go?Quote from: C on November 11, 2017, 08:21:57 pmThanks C - though it's causing me some headaches now!Quote from: C on November 11, 2017, 08:21:57 pmYes and because of that (and my keep-it-simple mantra) I think I'm going to develop the 670 idea from here. I just have a really poor understanding of how it works (or how to get it to work.)Quote from: C on November 11, 2017, 08:21:57 pmErm.. where? Are you talking about D1-D3 on the schematic?Quote from: C on November 11, 2017, 08:21:57 pmAt the moment I'll be ecstatic if I can just get an MMU working with the 128KB I've got in the SRAM and ROM! I'm not likely to want to expand the memory further - at least not for the foreseeable future and if I do, I can presumably add another 670 without major upheaval.I understand the concept of an MMU, the difference between memory space and physical memory etc, I'm just struggling at the moment with the specific technical details of how the 670 works to give the Z80 extra address lines. Ian.M mentioned the 670 would also require a flip-flop - I do have a 74HCT74, would that be suitable? Where and how would I need to wire it into the MMU circuit above?Sorry about all the questions - I'm happy to work my way towards designing this MMU myself, but my understanding of the chips we're talking about (and some of the concepts) is virtually non-existent.

author: Ian.M
author_rank: Super Contributor
timestamp: November 11, 2017, 10:42:40 pm
content: Now connect RA0 to Z80 A14 and RA1 to A15. Connect WA0 to Z80 D4 and WA1 to D5. Connect /RE to flipflop Q, flipflop D to D7 and flipflop /SET to Z80 /Reset. Drive '670 /WE and flipflop CLK in parallel from your port address decode logic which should include Z80 /WR.Now what happens depends on the byte you write to the single control port:B7 B6 B5 B4 B3 B2 B1 B0Boot -- S15 S14 EA17 EA16 EA15 EA14The MMU effectively matches S14-S15 against Z80 A14-A15 to give you four pages (each a 16K block of Z80 address space). Your ROM extends from EAddr 0x00000 to 0x1FFFF, and RAM from 0X20000 to 0x3FFFF. You can map any of the four pages to any bank (16K block of RAM or ROM), so to set up a usable memory map, in BOOT mode, with the '690 outputs disabled and EA17-EA14 set by the pullups/pulldowns:Code:LD B, high(PORT) ; assuming full IO address decodingLD C, low(PORT)LD A, $80 ; High bit set to stay in BOOT modeOUT (C),A ; set page 0 to bank 0 - the first 16K block of ROM.LD A, $99OUT (C),A ; set page 1 to bank 9 - the second 16K block of RAMLD A, $AAOUT (C),A ; set page 2 to bank 10 - the third 16K block of RAMLD A, $3B ; High bit clear to leave BOOT modeOUT (C),A ; set page 3 to bank 11 - the fourth 16K block of RAMOnce execution is transferred to RAM, you can remap page 0 to RAM as well. Because you want to keep the '690 enabled keep bit 7 clear:Code:LD B, high(PORT) ; assuming full IO address decodingLD C, low(PORT)LD A, $08OUT (C),A ; set page 0 to bank 8 - the first 16K block of RAM

author: C
author_rank: Super Contributor
timestamp: November 11, 2017, 11:08:33 pm
content: First a good rule for TTL logicTTL uses higher current to make a logic 0 then logic 1Good idea to use Pull-Up resistors for TTLUsing Pull-UP resistors requires boot rom code to be at highest address block.ian.M is putting all MMU control on one I/O output port.Saves I/O ports at some possible cost of slower software to control MMUMy setup uses 4 I/O output ports for 74LS670 and one output port for boot.One for Boot where only 1 bit is used leaving you 7 bits you can use.4 addresses that you only write B3 to B0 fromB7 B6 B5 B4 B3 B2 B1 B0X X X X EA17 EA16 EA15 EA14If you add one more 74LS670 to get 4M range this becomesB7 B6 B5 B4 B3 B2 B1 B0EA21 EA20 EA19 EA18 EA17 EA16 EA15 EA14With pull up resistors connected to outputs of 74LS670, just put the power up boot program in the highest 16k block of ram and have ram at top of memory.When you disconnect A14 & A150000h-3FFFh the Z80 is asking for becomes??00 0000 & ??11 1111 for high byte of addressThe 74LS670 4 outputs are pulled to 11111 from 74ls670 and 00 0000 from Z80 to1111 from 74ls670 and 11 1111 from Z80This gives3C000-3FFF range in expanded memory the highest 16 k blockYou need the Z80 to see 0-16k as boot program. with the outputs of 74LS670 this is the high 16k of memory.1. A14/A15 go to the read data port address lines Ra & Rb2. A0 A1 go to Wa Wb with the D1-D4 connected to Z80 data linesGw is connected to Z80 output write for a range of 4 addresses.3. Yes these are the highest address lines for ROM/RAM.4. Pull-UP connect to Qn5. Read my last post. Rom disable for grant's logic or bit of a 2736. Grants logic is a FF, one bit of 273 is a FFKeep in mind that both circuits do the same thing with minor changes.Tried to step you through the 4 chip logicYou understand the 4 chip version then you are very close to the 74LS670Quoteon 74LS670 pin GR(11) controls the tri-state of Qn outputs.74LS670Think you understand your current ram chip.You could think of the 74ls670 as two ram chips.One ram chip is write only.One chip is read only.When you use write only chip to write a location say address 1 you can only read the data using the read only chip using address 1The 74LS670 is like two ram chips but with only one storage location inside for an address.Think you want to play and learn hardware using Z80Z80 is also not bad learning software on.For software side you can get more done using nice powerful tools.For hardware side good hardware design is what makes it easer.Grant's just a working computer with few chips. not a great hardware design.Parts of design is for other microprocessers, still works with Z80 just not great.MMUsimple conceptA circuit that lies about the address it uses.Here the MMU only stores address data used for the Lie.It can an often does store other data like.is this area accessableis this area writable.has this area been changedThe CPU asks for something by address.the MMU uses this address to access it memory. from this memory it gets the actual address to use with memoryThis takes time but can make a computer very powerful.Even at the cost on having to add wait states for memory.Think of what CP/M3 can try to do.that old slow floppy disk drive that is using 1024 byte sectors.CP/M programs want a 128 byte sector.CP/M can read that 1024 byte sector from that slow floppy and put data in extra memoryKeep track of what changed and then write back to floppy if needed.Many many things possible with more memory

author: Ian.M
author_rank: Super Contributor
timestamp: November 11, 2017, 11:44:30 pm
content: Personally, I wouldn't use two '690 chips to map 4MB down to 64KB. The benefit of the '690 is it allows a very simple MMU to be built to map 256KB down to 64KB in 16K pages. However its relatively slow so if you want to clock a modern Z80 clone as fast as possible it isn't a great choice.I cant conceive of needing more than 1MB address space for a Z80 systemIn the topic I linked to in theO.P.s earlier Z80 thread, I contributed the concept of using a '486 era fast cache SRAM to do the mapping. The spec was to map 1MB into the Z80 64KB in 4KB blocks. Propagation delay was solely dependent on the SRAM used, possibly as low as 10ns.The smaller block size is far more versatile, and specifically makes it easier to work on large data sets, or implement a fast ROMDISK and RAMDISK, without any speed penalty, as the design could store 256 maps and, once a mapping was set up, you could select it or flip to another mapping with a single OUT instruction. It mapped reads and writes separately for ease of copying ROM to RAM, and also to permit write protection of RAM.

author: C
author_rank: Super Contributor
timestamp: November 12, 2017, 02:27:01 am
content: nockieboy is trying to understand a MMUI started with 4 simple chipsThe storage chip(273) have a reset or clear input.As reset/clear causes data to be 0, ROM is first and boot rom code is at 0-16kRam starts at 128kThe change from this to using an 74LS670 isUsing 4 I/O output addresses in place of two.And a change from having a reset/clear input to using pull-ups and tri-state disabled outputs.Disabled outputs with pull-ups causes output bits = 1This change causes the boot rom to be at the highest block in memory.The addition of a second 74LS670 becomes a simple step then when using 4 I/O output ports.The benefit is a 4M address space when using 16k blocks, an upgrade from 256kThis shows that a few added bits can make a huge change in expended memory.The logic of how these steps work is an important part to understanding an MMU.nockieboyGrab a some paper and then work through this posthttps://www.eevblog.com/forum/projects/z80-memory-banking-for-128k-mmu-design/msg1345498/#msg1345498The drawing you create should be a big help in understanding both the 4 chip MMU and the 74ls670 version.Think it will help a lot.Next look at datasheet for 74LS670http://www.ti.com/lit/ds/sdls193/sdls193.pdfAt top of page two is a logic drawingLets fix that drawing so that it makes sense as used in a MMURa & Rb put these on right side inline with Wa & WbGr put on right side inline with GwYou now have two address pins at topa Ck input on left & a tri-state enable on rightData pins at bottom.Left side of chip is now Z80 I/O write inputsDn = data Z80 Data D3-D0W? = Address A1,A0Gw = Ck for write and = Address + IORQ + WRthese pins are connected as a z80 output,four i/o output addresses usedData written is high expanded address to be used for the four 16k blocksThis data will become EA17,EA16,EA15,EA14Right side is now MMU pinsQn is expanded address to memory. EA17,EA16,EA15,EA14Rn is high address from Z80 A15, A14Gr is output enable active low. When high Qn are in tri-state mode.How it worksZ80 starts a memory cycleZ80 puts address on address bussThis causes Rn to select 1 of the four data stores( the 16k area)The data in store appears on Qn, this data is used as high part of expanded address.How Z80 controlsThe Z80 writes 4 bits of data into one of the four output addresses( an area)The four addresses are area0 to area3On power upGarbage is in storage.On power-up, Qn is disabled by using Gr input, A high level.With no output on Qn, pull-up resisters makes these pins = 1.Write good dataenable Qn output so data can be used, A low level on Gr.On power-up with Qn disabled( and resistors pulling high each pin, each area is accessingFromMMU Z80 MMU Z800b1111 00000000000000 to 0b1111 11111111111111 a 16k areaThe expanded address range of 0x3C000 to 0x3FFFFwith output disabled it is same as if Z80 wrote F in each of 4 locations0-7 = Ram blocks8-F = Rom blocksBlock F = Boot ROM code The highest 16k block.The 4 chip version of MMU has0-7 = Rom blocks8-F = Ram blocksBlock 0 = Boot ROM code The lowest 16k block.

author: nockieboy
author_rank: Super Contributor
timestamp: November 12, 2017, 11:57:37 am
content: Quote from: Ian.M on November 11, 2017, 11:44:30 pmCrikey, I'd forgotten all about that thread! That was a long time ago.. (well, it feels like it!)Okay, I think I'm making progress with this 2-chip MMU design, following Ian.M's suggestions so far:I have really only two questions regarding this circuit now:1) Where do those pull-up/downs go to selectROM bank 0(lowest 16K in ROM) forArea 0(lowest 16K in memory space) andRAM bank 1(16-32K in RAM) forArea 1(16-32K in memory space) on power-up?? (That's the minimum requirement to get the monitor running - once running, it can set up the memory as it likes.)2) Ian.M - you state:Quote from: Ian.M on November 11, 2017, 10:42:40 pmMy IO port address decode logic currently looks like this:So I'm going to have to AND the Z80's ~WR line with the appropriate IO address select line from the 138 before it goes to the 670 ~WE and 7474 CLK?Also, on a tangent, I think I'm going to have to add another 138 to decode some more addresses - I'm running low on IO lines! (only 2 left..)Although this MMU design would free up the IO line used currently to switch the ROM out in Grant's design...Quote from: C on November 12, 2017, 02:27:01 amI got this, I'll break the crayons out and be right back...The honest problem is I don't have 15 minutes to sit and focus on this at the moment (and it requires aLOTof focus due to my limited understanding) - I'm hoping to get some time during the week to work on getting my head around how to get the 670 doing what I want it to.

author: nockieboy
author_rank: Super Contributor
timestamp: November 12, 2017, 12:07:48 pm
content: Quote from: C on November 11, 2017, 09:23:19 pmJust noticed this, C, and your comment about needing the 74LS670 as it would be quicker. Would the LS version work okay with the rest of my chips which are all HCT components?Also - the comment re: the 273. I've not got a 273 in the current MMU design (see post above) - would the current design do what I need it to do and switch the ROM so I can remove Grant's ROM switching circuit?

author: C
author_rank: Super Contributor
timestamp: November 12, 2017, 12:40:32 pm
content: The 74HC670 looks to be slower then the 74LS670.So both would work an slow Z80 clock speeds.As you increase the Z80 clock speed, you have less time from when the Z80 address lines are changing and then MREQ going active.So at some Z80 CK speed slower stops working correctly. Faster gets you higher clock speedsI have not added up the times but I think 2 & 4 meg should be okAt some point, you would need to add a time delay to MREQ to go higher.Two inverters are a time delay.The 74LS670 is not for a 16-20 meg z80 clock if you want fast computer.Think you will be fine and rememver easy to change on breadboard.HCT is a TTL level CHIP the 74LS670 will be fine here.If you have two 273's and 2 253's you have what you need.A change to 74LS670 is very small. need 74LS670 and pull-ups.A 273 and inverter will work to control tri-stateGrant's rom disable would work.Some clean up of grant's would make playing with hardware easer.More quick

author: C
author_rank: Super Contributor
timestamp: November 12, 2017, 12:46:27 pm
content: Good morning nockieboySee if I can make it betterYour last drawing is the 74ls670Note that you need the LS not the HCThe Gr pin of 74ls670 is like the EO pin of the 253 in your previous drawingRa & Rb are the select inputs of the 253For the 74LS670 the 253's data inputs do not show. But both are connected to storage.74LS670 Qn outputs are same as 253 outputs. With just 2 outputs ber 253, need two to get four outputs.So 253 pins match 74LS670 With storage connection shown for 253 and hidden inside for 74LS670To get the 273 to match it's four 273's but only 4 input & output bits.74LS670 Dn inputs are the 273 data inputsThe 74LS670 has part of address decoder you need to connect to get 4 273's workingThis is one half of a 139 decoder.74ls670 Wa,Wb are decoder inputs of 139The 139 decoder has an enable pin, the 273 have a Ck pin, These are all connected together and are these become Gr input of 74LS670Just noticedSee Gw & Gr in some data sheets and Ew & Er in others they are same pins.So The four chip version lets you see some of what is inside the 74LS670If you do not use the clear input to 273 and use the tri-state output of 253 you have a 74LS670

author: C
author_rank: Super Contributor
timestamp: November 12, 2017, 12:53:21 pm
content: PULL-UP- resistorsThe Pull-up resistors put a valid logic level on inputs of memory chips isstead of letting them flop around.Connect to Output of MMUQn on 74LS670Outputs of 253 for that versionConnect to address inputs of your memory chips

author: Ian.M
author_rank: Super Contributor
timestamp: November 12, 2017, 01:02:23 pm
content: Q1: The pullups/pulldowns go on the four extended address bits EA14-EA17 on the physical memory side of the MMU circuit. If all the memory chips and logic that has those lines as inputs have normal CMOS input thresholds (20%, 80%) you can use pullups and pulldowns to set the default value of that nibble freely. However if any of them have TTL compatible input thresholds you should *ONLY* use pullups, which forces you to put the ROM at the top of the memory map and the boot block at the top of the ROM as 'C' has been recommending. Because the extended address bus is inactive from /RESET until your code enables it, the pullups/pulldowns can be a relatively high value as their lines are static until enabled. 10K should work nicely.N.B the effect of switching back to BOOT mode on a screaming fast Z80 system would be unpredictable. 10K might not pull the lines to the correct level in time for the next /M1 instruction fetch. Don't do that unless you are already executing from the BOOT block mapped in page 0.Q2: Propagation delay in the I/O address decoder is a bitch. Personally, I'd start with a pair of 74AC138*chips totally decoding the high nibble of the 8 bit I/O address (A4-A7), + /IORQ (to /E1). Connect A7 to /E2 of the first chip and E3 of the second. Don't include /M1. Its only active with /IORQ in IM2 interrupt acknowledge cycles, with /RD and /WR inactive. That will give you 16 active low lines that each correspond to 16 consecutive I/O addresses. Within each 16 address block, you can then decode right down to single address level and include /RD or /WR with another '138.On speed of 74xx670 chips - they aren't that fast - if you are building a screaming fast system using a Z80 clone possibly with interleaved video memory access you need to use something much better. That's what drove the topic I originally pointed you at towards '486 era cache SRAM to do the MMU mapping, in spite of the complexity of it only having a single address bus and data bus. There was just no other way of getting the MMU propagation delay down to 10ns while retaining 5V logic.If you need to interface Z80 peripheral chips that directly take /IORQ, /RD and /WR, the above doesn't give enough setup time for /CS because /IORQ was included in the first decode. A single '138 directly on the address bus lets you decode 6 bits, with the constraint that one must be high and two low, and will support eight Z80 peripheral chips, with A0 and A1 passed through to the chip for register selection.Take care to avoid address conflicts between the raw I/O decoded addresses and addresses decoded for Z80 peripheral chips.* 74AC series parts have brutally fast edges on their outputs. 6ns is typical. Use a ground plane and make sure each package has good local decoupling. You may need to add source termination and RC load termination of long lines to reduce reflections and control EMI.

author: C
author_rank: Super Contributor
timestamp: November 12, 2017, 01:12:56 pm
content: Quote from: nockieboy on November 12, 2017, 11:57:37 amYou only get ROM at low address range if you use pull-DOWN resistors.Pull-Down not a good idea when using LS or HCTDo thismake two versions of your power up boot programPut one copy at 0-16k in your ROMHave it stat "From Low Rom Area"Put a second copy in your Rom at the highest 16K areaJust changet "From Low Rom Area"to"From HI Rom Area"your Boot ROM is now good if your code is good.Will work with Grant'sWill work with Expanded 0-16kWill work with Expanded 256-16k to 256k the highest blockThe code is the same only the message changed.

author: C
author_rank: Super Contributor
timestamp: November 12, 2017, 03:13:49 pm
content: Address decodersTo keep math easy need some numbers, these ARE MADE UP.When data changes on a bus, any buss, it is a BIG MESS.First you have the device trying to change the data not changing it at same time.Then you have differences in signal paths, load on pins, and a whole bunch of other things.Safe thing to thinkBuss has stable data.When bus starts to change, the data goes to crap, IT is UN-KNOWN.Some time later the data lines get to a stable state, but NOT at same time.If you have a decoder chip looking at the buss, many of the outputs will bounce up and down. With out careful design of decoder some outputs could take less time to decode then others.The decoder chips like the 138 are built to handle this problem but needs a signal stating that BUSS is now stable.For Z80 this is MREQ or IORQ for address buss.Now at a slow Z80 clock speed the address buss should become stable a long time before MREQ or IORQIt is not hard to delay MREQ or IORQ, but you can not make these happen before they do.Now if you KNOW that MREQ or IORQ happens before the address buss is stable, it is not a problem if you add the correct delay to fix this.If you look at Z80 Datasheet, At high Z80 clock speeds the 20m Z80 does this.What you want is a nice clean change on the CS pin of your SIO or memory chip.To get this MREQ or IORQ should enable the outputs of the decoder chip that is connected to the SIO or memory chip.Look at the Z80 peripheral chips, they want CS to be a range of 4 I/O addresses.SoA0 & A1 goes to Z80 peripheral chipFor full address decode A2,A3<A4 goes to 138The final output enable should connect to IORQThis leaves A5,A6,A7 not decoded yet for full address decode.Lets use some simple numbers to make the picture clearLets say that it takes 15 Ns for output to change based on A2-A4.and it takes 10 ns IORQ change to get to outputs to enable themAs long as IORQ happens 5 ns after the addresses have stopped changing you get no glitches on the output. A glitch is the output going low and back high in this case before the stable low level.Now to get full address decode you need a second 138 for A5,A6,A7With the output of this chip going to one of the first enables you have the followingA5,A6,A7 take 15 ns to change first 138 output then 10 Ns enable time of second 138.with this logic A5,A6,A7 need to be stable 25 ns before output to SIO.This is 15 ns before IORQ.If you connect IORQ to A5,A6,A7 you create a problemoutput of this decoder is 10 ns after IORQ & another 10 ns delay happens with second decoder. The CS of the SIO is now delayed 20 ns instead of 10 nsNow some chips when used for OUTPUT also need WRChips like 273 need this.The 74LS670 needs this.Connecting a AND gate to combine WR AND the address + IORQ above will add the AND gate delay time to the signal.If you can connect WR to the decoder you can save this time.So when designing a computer it is not just getting the logic correct.It is getting the Logic correct with out GLITCHES.It is getting the timing correct to prevent glitches and making the connected chip happy.AND Z80 happy with the connected circuit.Note that I used 10 ns and 15 Ns above, You always want some stable time and not run on ragged edge of times.Now if you have a need for just IORQ enabled chip selects and IORQ + /wr chip selects, you might want to run parallel decoders to do this.Going parallel means that the Z80 has to drive more chips which slows changes but can save having to go through more levels of decode.The Z80 has a limit on what it can driveRemember that time is not just hardware.Good hardware lets you use less software to get the job done.Less software = faster computer.Now in past I talked about softwareLast I saw your SIO init code it had data values embedded in the code.lan.M's example code does this.It is easer to show details when doing this, but you can not easy have program change the data.The data is all over the place when you need a change and often this means you need to run the assembler again.This is where having data tables is your friend.For your SIO init codeLoad register with address of a table of bytes to be sent to SIO.Load a register with What SIOYou can now have a common sub that will INIT any SIO.For MMU this can also be handyThe same sub could handle part of the inital load to MMUAnd same sub could then be used when areas need to be changed.If what CP/M3 wants does not match what your MMU needs then the table can handle most of the problems.So for MMUFirst thing is get ONE MMU working. This is the big step.After that it is small change for the different versions of MMU.You could have software that will work with any version with out software change.When you look at the old ways, try to understand then in the time when used.Is there a better way using todays chips.An examplemy first ram memory board used 2kx1 chips and cost a lot.A simple 8k memory board was 2kx1 X 8 X 4 That is 32 chips. This board ran HOT, it was almost a bread toaster.When the 2k x 8 chip came out, that board saved a lot of chips and a lot of power.So when you used 128k chips it was a smart move and saved you money. Now if you think about it 512k could be better yet.The 48k bank select was a way to got old computers to work with few changes.Big thing was Many boards with only a 16 bit address bus and no easy way to add more address lines.Having 4 16k areas lets you look like you have 48k banks and use the huge memory chips of today. That old hardware will becomes a mess when connected to huge memory of today.

author: nockieboy
author_rank: Super Contributor
timestamp: November 12, 2017, 10:42:42 pm
content: Okay, here's the updated schematic with the 74LS670:Are the pull-ups correct? They should make the very top 16KB bank of the 128KB ROM appear in Area 0 (bottom 0-16K page of memory space) on power-up.The issue I can see is how do I set the default power-on state of Q4 (the RAM/~ROM select line) - technically it should be pulled low, but apparently that's a 'bad thing'TM?Let me know what changes I need to make to the MMU circuit above (if any), then I'll start looking at the IO decoder circuit as I'm going to have to make changes there also.

author: C
author_rank: Super Contributor
timestamp: November 13, 2017, 01:28:42 am
content: Resistors on all four pins Q1-Q4The pull up on Q4 should enable ROM.=====Gr is High for tri-state so at power up reset the FF output connected should a 1 HIGHHere you have a lot of options using the 74Would be nice when you write to this port for D7 to be low normally so when clocked by I/O write you will get a state on the two outputs. Here you want a low level onD7 low on I/O write which makes Gr = 0 The Q output.At power UP you then write the first 4 times with D7 high.Then turn on MMU by a write with D7 lowSo with this being what you want for normal, you have a choice of preseting this chip on power up or clearing this chip on power up.So if I am thinking correct Power Up preset Sets the FF to cause Q= 1 -> Gr which tri-states 74LS670 outputs.So if your RESET goes Low at power up and is connected to preset you are good.This matches lam.MFrom what I see in drawing add the Q4 resistorYou match lan.M post for port use.======In place of 74Now If you are going to have a 273 that is reset at power up you could use a bit there in place of 74 FF. BUT the 273 only resets to 0 so you would need and inverter between 273 bit and Gr.And to be complete you could use grant's existing logic to do this. Not my choice unless you want to use it while making the change.Would suggest you put this on separate breadboard or on memory breadboard.You could leave the Q1-Q4 disconnected from memory and do some tests to verify you have built this correctly.========Decoderremember that you do not have to use all outputs.If you have nothing connected then nothing will respond to that address.You could build a new decoder and slowly move outputs from U5 to new.In the future, think you would like a decoder forOne address I/O Write (273,374 & lan.M MMU )One address I/O ReadFour address I/O for (SIO, CTC PIO)Then I think the CF card is using 8 addresses. Would need to look in the software to verify it is using 8 and not less.You could OR two 4 address outputs, but Need to test to see if it works with added delay of OR gate.Need to keep track of what is connected and how much load each thing adds to Z80 output. Z80 has limited output.

author: Ian.M
author_rank: Super Contributor
timestamp: November 13, 2017, 04:53:45 am
content: No. the ROM has /CE and the RAM has CE2. Pulling up EA17 (aka Q4, RAM/ROM_SELECT) would select the RAM at booot - pretty pointless.However the RAM and ROM *PROBABLY* have CMOS input thresholds. If so, a pulldown is legitimate.If they have TTL thresholds, (or worse there is an actual bipolar TTL gate input on that line), then stick a pullup on Q4 and follow it with a CMOS inverter to drive the ROM /CE and RAM CE2. That would also swap the positions of the ROM and RAM in the memory map.If you go with my suggestion for decoders, you get at the top level 16 address blocks, so no problem hooking up a CF card with three address lines. However a CF card has TWO chip select lines, that select different register sets so you still need to combine A3 with the 16 address block /CS from the top level '138.

author: nockieboy
author_rank: Super Contributor
timestamp: November 13, 2017, 06:25:52 pm
content: Quote from: Ian.M on November 13, 2017, 04:53:45 amYeah, that was my concern. Could always use an inverter, but I'd be miffed if I have to add another chip to useoneinverter on it...Quote from: Ian.M on November 13, 2017, 04:53:45 amOkay well, this sounds like it could make a huge difference - I'm going to pour over the datasheets for the RAM and ROM tonight to see if I can work out if they're CMOS or not. Will it say 'CMOS/TTL-level inputs', or am I looking for something in particular?Quote from: Ian.M on November 13, 2017, 04:53:45 amI was a little befuddled by the decoder explanation, I'll admit - I think the considerations around potential timing issues are worrying and distracting me - but I'm not giving that much thought at the moment as I want to pin down the MMU function and design first, then I'll turn my full attention to modifying the IO decoder.Quote from: C on November 13, 2017, 01:28:42 amSorry C, I'm struggling with the English in this one. So you're saying that at power-up, ideally I want the 74 flip-flop to be outputting HIGH to tri-state the 670's outputs? Then I guess the pull-ups will work their magic and the top bank in ROM will appear in the first area of memory space?(How) can I preset the output of the 7474? The design only uses D0-D5 currently - how would I implement your suggestion about using D7 to enable/disable the 670?Quote from: C on November 13, 2017, 01:28:42 amNo, I'm going with this design currently so I won't be touching any 273's.Quote from: C on November 13, 2017, 01:28:42 amAbsolutely - sounds like a good idea.Quote from: C on November 13, 2017, 01:28:42 amAnother good idea re: building a new decoder and swapping lines over to it from U5 one by one. I'm running out of space though!Currently I've got the ROM/RAM select circuit, SIO/2, CTC, PIO and CompactFlash running from the 138 IO decoder. I'll be adding the AY PSG after the MMU, so that's two more things to add. These select lines are all driven by the 138, though - the Z80 (it's CMOS - Z84C008) itself drives the address and data buses and a handful of HCT logic chips, but I hear you loud and clear. I have plans to add buffers to the address and data buses, but won't these add a delay into the circuit?

author: nockieboy
author_rank: Super Contributor
timestamp: November 13, 2017, 07:04:17 pm
content: Quote from: Ian.M on November 13, 2017, 04:53:45 amErrr... okay, both the datasheets for the ROM and RAM mention TTL IO compatibility... not sure if that is a definite no to the question of whether they have CMOS input thresholds, as I don't know what I'm looking for. Here's the relevant datasheets, anyway:ROM:39SF010A EEPROMRAM:AS6C1008-55PCN SRAM

author: Ian.M
author_rank: Super Contributor
timestamp: November 13, 2017, 07:11:18 pm
content: TTL thresholds, and the RAM's logic 0 threshold is only 0.6V, so you *should* use an inverter. You can use any inverting gate with its inputs strapped together. If you try to use a resistor it will probably be unreliable.

author: nockieboy
author_rank: Super Contributor
timestamp: November 13, 2017, 11:23:15 pm
content: Okay, so this is how the MMU is looking now:Can I just confirm what the memory map now looks like and that the IO addressing is the same as you previously stated, Ian.M?So RAM is now 0-128KB and ROM effectively now occupies 128-256KB in physical memory space? On power-on, the Z80 will see the top 16KB bank (112-128K) of ROM as area 0 (0-16K) in memory space?

author: C
author_rank: Super Contributor
timestamp: November 14, 2017, 12:08:38 am
content: YesA14 & A15 connect to 74LS670.Output of 74LS670 is disabled. (rri-state)Resistors supply high address lines levels.So At power up Z80 sees four copies of the top 16k bankYou write good data in to 74LS670 with it still disabled.You then enable 74ls670Z80 A14 & A15 noiw controls what is on the 4 address lines via 74LS670

author: C
author_rank: Super Contributor
timestamp: November 14, 2017, 12:42:42 pm
content: You could have a lable on Q4 EA17Might make it easer for some one to understand. Q4 is an expanded address line, here used as ram/rom select.How you doing understanding a MMU?Now some things you might not have noticed.There is JEDEC Standard for a – 32-pin PDIPPart of standard covers the pins, part software for non tam/rom , parts like flash eeprom.The datasheet for your flash rom table 4 shows this for a 32 pin socket. If you were planning a PC board, with some care, it could be used with many sizes of chips.Note the software steps for your Flash Rom to write data again part of JEDECSo table 4 gives you a list of pins to check how the use of pins change with sizepin 30, pin 1 , pinI would wire up pin 31 to both chips so in the future you can write to flash using Z80.You are using a inverter here. If you had more 128k chips, you should use a decoder like 138.Older memory chips do not support the way these chips are used and you would have MREQ connected to decoder enable instead of where MREQ is connected now.

author: Ian.M
author_rank: Super Contributor
timestamp: November 14, 2017, 01:28:10 pm
content: A cheap and easy way of adding more FLASH ROM would be to connect the remaining unused data bit at the MMU port address to the other half of the boot mode flipflop chip, in exactly the same way. Then instead of the inverter between EA17 and the /CS line to the ROM, take the Q and /Q from the new flipflop, each to one input of a pair of NAND gates, with their other inputs from EA17. That gives you two ROM /CS signals, each suitable for a 128K chip without increasing your glue logic chip count. At boot, the flipflop would be set, so the NAND fed with Q would generate the active /CS.It would have the limitation that you cant map blocks from both ROMs simultaneously, and when you switch that bit, *ALL* ROM mapped pages flip to the other ROM chip, but that can be handled by *either* duplicating the critical boot block and BIOS in both chips, leaving you with 224K free, *or* copying the BIOS to RAM, giving you 240K free. Both give enough space for a CP/M Plus system + selected utilities on ROMdisk.

author: nockieboy
author_rank: Super Contributor
timestamp: November 14, 2017, 03:45:16 pm
content: Okay, I've skipped ahead a little and started thinking about the IO decode circuit, as below, before I read the last two comments from C and Ian.M.Above is how Ithinkthe 138 should be wired? Is that right? Should I remove ~M1 and/or ~IORQ from the 138? (Thinking about timings..)Quote from: Ian.M on November 14, 2017, 01:28:10 pmInteresting point - something I might think about later, but at the moment I can't see a use for an additional 128K ROM... Though, yes I know, that might change.Quote from: C on November 14, 2017, 12:42:42 pmWon't have time to sit down and the sketch out the MMU picture into later in the week. Until then I'm grabbing spare time where I can to update the MMU / IO decode schematics with the progress in this forum.Quote from: C on November 14, 2017, 12:42:42 pmYes, I was aware of the JEDEC standard and the possibility that the EEPROM could be in-circuit programmed, but it's something I've never gotten round to looking at. To be honest, I've thought of it as a lot of work just to remove the minor annoyance of removing the EEPROM from the ZIF and putting it into my EEPROM programmer, then swapping it back afterwards. However, as and when (and if) I get round to putting this onto a proper PCB, then in-circuit programming would remove the need for a ZIF on the PCB and allow me to just pop the EEPROM into a DIL holder and leave it there, but carry on development. Nice idea - something I'll add to the end of my wish-list.

author: C
author_rank: Super Contributor
timestamp: November 14, 2017, 04:10:05 pm
content: A list\IORQ & RD = i/o read inputIORQ & WR = I/O write outputIORQ & M1 = Interrupt ackThe second item is uniqueThe Z80 never makes WR & RD active at same time.Remove M1Now an optionConnect WR to 138 and you have a Z80 I/O OUTPUT decoder.You could then connect MMU directly to an output pin.You could also connect 7 other 273 or 374 chips for more output bits.With RD connected to decoder you have signal needed to read a 374 when connected to 374 OESo think a bitA 138 decodes 8 addresses.The MMU and other chips need WR added to write dataThe output of your U1 is 8 addresses.If U3 is a 138 you would have 8 one address outputs. You could use one for MMU and have 7 more just waiting to be connected for more output chips..

author: C
author_rank: Super Contributor
timestamp: November 14, 2017, 04:28:32 pm
content: You have been working with Grat's software for a while now.Have you seen Grant's code use any thing other thanOUT to address 0H with some data value?If this is true then you can connect the second 138 tothe original U5 pin 13 and still leave Grants logic connected to second 138 pin 15.You now have 7 more outputs on second 138 that could connect to MMU.This would let you run as you are now with added 138.You could then start adding MMU circuit and test it with a working computer.On software side you would leave grant's code in place and start adding for the MMU.When all tests are completeChange memory connections from Grant's logic to MMU logic.With software in place this will work.When working clean-up and remove some of Grant's logic.

author: nockieboy
author_rank: Super Contributor
timestamp: November 14, 2017, 11:27:44 pm
content: Quote from: C on November 14, 2017, 04:28:32 pmIt uses:Code:LD A,01OUT (38h),Aexclusively to switch the ROM off. There's no way to switch it back on in Grant's circuit, so it doesn't matter value is subsequently written to 38h afterwards.Quote from: C on November 14, 2017, 04:10:05 pmOkay, so I just need to remove M1 then. I'll post the updated decoder schematic tomorrow. IORQ and M1 were added to the 138 as a result of this discussion here about adding the AY sound chip -Z80 Homebrew Computer - fault finding.Turns out the schematic I've been using for the IO decoder here isn't 100% accurate. Below is what the decoder looks like in my current setup:I'll get this updated and posted here tomorrow with M1 removed - unless anyone can head me off at the pass and let me know if there's going to be any problems running the MMU from Y7?

author: C
author_rank: Super Contributor
timestamp: November 15, 2017, 12:00:05 am
content: Let me put it this wayM1 is not needed when you follow Z80 rules.What are Z80 rules?IORQ & RD is an I/O read.IORQ & WR is an I/O writeWhen you have something that does not follow the rules you can have a problemNot Z80 rulesIORQ & not RD this is not a valid select for a Z80 I/O writeIORQ & not WR this is not a valid select for a Z80 I/O readM1 will not hurt any thing just that If needed it is a sign of some poor interface.AY sound could need M1 so leave it connectedSuggest that you connect a new 138A0 -> A pin 1A1 -> B pin 2A2 -> C pin 3Wr -> E3 pin 5pull-up E1 pin 6current 138 Y7 pin 7 38-3F to new 138 E2 pin 4Grants that was connected to current 138 Y7 move to new 138 Y0 pin 15You have 7 outputs that will work for MMU pick one.In summary:you have removed connections to grant's U5 Y7 pin 7 and moved these connections to a new 138 Y0 pin 15You have connected grant's U5 Y7 pin 7 to new 138 E2 pin 4New 138 decodes 8 addresses 38 - 3F as single address outputsNew 138 Y0 is output @ 38hIn your last post U1 = grant's U5Every thing connected still works.

author: nctnico
author_rank: Super Contributor
timestamp: November 15, 2017, 12:27:24 am
content: The Z80 based MSX2 computer had a memory exentension system:http://msx.hansotten.com/do-it-yourself/memory-mappers-slots/

author: C
author_rank: Super Contributor
timestamp: November 15, 2017, 12:37:51 am
content: You are trying to have many areas from the two main memory chips Used at many Z80 addresses.the MSX2 is differentIt has memory in side the computer &More memory in side cartridge.The switch choice becomes INSIDE or Cartridge.Need more info or is this enough?

author: nockieboy
author_rank: Super Contributor
timestamp: November 15, 2017, 03:01:37 pm
content: Quote from: C on November 15, 2017, 12:00:05 amYes, I'm pretty sure I added it in due to some good reasoning by grumpydoc.Quote from: C on November 15, 2017, 12:00:05 amHmm.. okay, well I've diverted from your suggestion only slightly, in that I've removed ~M1 fromU5(and also the OR that was gating A6 & A7 as an active-low enable pin was freed up) and kept the MMU select line on U5. Instead, I've passed ~Y1 to pin 5 of U13 (a second 138 as you've suggested) which, along with ~M1 on pin 4 and A0-A2 on pins 1-3, will provide another 8 select lines (at least one of which I can use for the PSG.)The reason I've done it this way and not your suggested way is because I didn't want the MMU's select line sitting behind another 138 (with the associated additional propagation delay that would introduce) and it would still be sitting behind the ~M1 line which would still be attached to U5.Here's the updated decoder circuit - note that U13 won't be built in to the SBC until I finish the MMU entirely and move on to getting the PSG back on-board:

author: C
author_rank: Super Contributor
timestamp: November 15, 2017, 05:56:44 pm
content: QuoteThink a second on critical pathMMU is used for memoryThe critical time path is Z80 A14 & A15 to Q1-Q4so A0 -A13 go directA14 & A15 in the form of Qn are delayed by 74LS670Read time is the critical path.Z80 I/O write you have a lot of time.So MMU being connected to U13 makes no difference for a memory cycle.Think of 74LS670 being a memory chipRead mode is used during the memory cycle.RA & RB are address pins usedQn is data outputs usedGr is the OEWhen updating the map you use write modeWA &WB are address pins usedDn is data inputGw is write, chip select and address select input.If you were using a cache memory chipA14 & A15 & memory read time to data output is critical time.the CS & OE are active all the time except for I/O write.The other address inputs to this memory chip can be strapped to a level and you would have one map like the 74LS670If you connected other address inputs to the output of a chip, these are still static for memory cycle. But if you change output of chip in a I/O output you can switch between many different maps with just ONE i/o out.So looking at your lastY7 connection works fine with both chips.When connected to U13 the MMU uses one output address a savings of 7.So drawing looks OKThink you know that U5 is working now.so only changes are U12 & U13To help with future logic designs, not to change what you have now.U12 version with WR could be a 138 like I stated.You could still have your special U12 that adds M1 connected to a different outputNow if you were trying for max speed, you would need to look again at the Z80 I/o chips. CS for these chips is only address select.For PIOQuoteNote the PIO has no WR pinThe chip gets the Z80 clock and by using the other inputs from Z80 can build an internal copy of what the missing Z80 pins would do.the WR is an internal PIO creation.the WR is an internal SIO creation.the WR is an internal CTC creation.These chips use a directly connected IORQ to qualify the address.So if you want to plan for the future and higher Z80 clock speedYou want an address only decoder for all the Z80 I/O chips.Each use 4 addressesA2-A4 connected to 138 gives thisA4 when connected to E2 then gives a Low address A4 block of I/OA4 when connected to E1 then gives a High address A4 block of I/OThen by how you connect A5,A6 & A7 determines if you have one block or many mirrors of the blocks in I/O address space.Back in the old days, You would have many boards connected to a buss. Each board would have it's decoder chips.Most had jumpers that you strapped to set the boards addressA 138 could be connected to A5,A6 & A7 and you would connect one output of this decoder to one of the inputs of the four address decoder.A real pain in the ____.Better designs used a MAGNITUDE COMPARATOR like 74xx85This change lets board designer put a dip switch on the edge of the board to set the board's address range.The next step up from this is plug & playThere were many different versionsSome were based on what slot board was connected to. You could think that each slot had a output of a 138. The problem with this is some boards need a lot of addresses an some one or two addresses.Then it would be nice if the CPU could know what was plugged into a slot.Today a version of SPI is used to find out what is connected and to configure it.So you need to make baby steps while thinking of future paths this might go.The MMU is as simple as it can be for what you have.In future it can be replaced or added to supporting your needs.Like wise your decoder can be used as drawn or some changes for future.The most important thing is TIMEYour RAM or ROM must have the proper data when Z80 reads it and must capture the Z80 data on write properly.To check this you match data times then work back in time to see if some time is too short.At some Z80 clock speed your circuit and memory will be too slow unless you add wait states.And you should note that wait states is not a cure for every thing.Wait states for example do not change time from when the data outputs of a device turn tri-state and when Z80 uses data buss for output.Keep in mind that the Z80 does not have to run at an even MHZ. A Z80 can be faster with a little slower clock if memory changes from 1 wait state to 0 wait state.A wait state is a step in time.

author: nockieboy
author_rank: Super Contributor
timestamp: November 15, 2017, 09:59:10 pm
content: Quote from: C on November 15, 2017, 05:56:44 pmOkay, so that leads me on to a (vaguely) related question - is there such a thing as a programmable oscillator or frequency divider? The reason I ask is that I can ch7ange the frequency of my SBC in software between 2, 4 or 8MHz, but I need a fixed 2MHz signal for the PSG, so whenever I change the system clock frequency, I'd like to be able to maintain a 2MHz frequency for the PSG. I'm guessing a separate, dedicated 2MHz oscillator is probably the simplest and cheapest option...EDIT: ... except a separate oscillator will mean the PSG is running out of sync with the SBC's system clock, which could cause timing problems of its own. I've just done a quick search for 'programmable oscillator' - the cheapest I could find was like £50 (~$70?) Ouch!Ah, 74LS294 - programmable frequency divider?

author: C
author_rank: Super Contributor
timestamp: November 15, 2017, 11:41:23 pm
content: Stage 1 is not worry about clock muchMy thinking is that you are doing this to learn, and Z80 is not bad to learn on.So a 4 Mhz machine or even a 2 Mhz is fine to learn on.I would not try to use any Z80 chips with a clock greater then datasheet specifications.The reason I mentioned time is you should be keeping track of what you have and looking for problems.So when thinking critical paths need numbers to know if it is critical.Stage 2work the numbers for what you have.You could do this on paper but in long run a spreadsheet should be better.Should not take you long to compute how fast the Z80 could run with your existing memory.Then it should be a small step to see what the limit is with this MMUDo the same for I/OWith the numbers you should then be able to tell how much margin you have a X z80 clock speed.Then to make things more fun you should note that when the Z80 clock is less than max for that CPU you do not have to use a square wave to drive the chip.So do your math's and get some numbers.This is an important part of learning a CPU like Z80Until this is on a PC board you should not try to get close to limits due to the use of breadboards.spend some time to really understand the MMUA lot will be handled by proper driver in CP/M3 but it would be good idea to think how the Z80 will work with this.On software sidewould be good idea to be able to run the CP/M3's relocating assembler for the bios code.

author: nockieboy
author_rank: Super Contributor
timestamp: November 19, 2017, 10:19:01 pm
content: Quick update now that I've started building the MMU. I've discovered an error in the IO manager's design - it now looks like this:I'd previously used an AND gate to combine ~WR and ~Y7 to form the select line for the MMU - this clearly was the wrong gate to use, so I've swapped it for an OR gate instead. I think ~IORQ was previously going into E3, which is the HIGH enable for the 138, so I've moved it to E2 which is a LOW enable.

author: David Hess
author_rank: Super Contributor
timestamp: November 20, 2017, 12:19:50 am
content: Quote from: nockieboy on November 15, 2017, 09:59:10 pmAs you identified, the clocks need to be synchronous unless special precautions are taken.A synchronous counter can produce all of the needed clocks simultaneously and then a multiplexer can select which one is used. Special precautions may be necessary to prevent glitches and clock violations.

author: nockieboy
author_rank: Super Contributor
timestamp: November 20, 2017, 09:26:47 am
content: Quote from: David Hess on November 20, 2017, 12:19:50 amAh, thank you - hadn't thought about using a counter to divide the clock rate!(I'm pretty new at this electronics stuff!)So - would something like a74LS163Abe suitable? I'm guessing I'd only need a 4-bit counter, rather than a decade counter, as I only have to get 2MHz from an 8, 4 or 2MHz system clock speed? Unless I completely misunderstand the principle, a 4-bit counter would give me 4, 2, 1MHz and 500KHz from an 8MHz input clock, halving down accordingly with lower (4 or 2MHz) system clock speeds?

author: C
author_rank: Super Contributor
timestamp: November 20, 2017, 07:12:24 pm
content: Are you missing the first question?Why change the Z80 clock speed?If you have a good scope, running the Z80 at some divide by 2 ratio does not help much in testing.What helps is changing the high & low times of the clock by a small amount.Using a counter, you could decode the count and then have a multiplexer select that output. You could then reset the counter for next cycle.Using a shift register gives you outputs that are counts. This removes decode glitches.Using a 20Mhz master clock gives 50ns steps.To keep glitches from Z80 clock, it is a good idea to use the output of a FF.So a 20Mhz master clock gives a 10Mhz square wave clock to Z80.50ns high, 50ns low = 10Mhz square wave100ns high,50ns low = 7.5Mhz100ns high, 100ns low = 5Mhz square wave150ns high, 100ns low =but you could have150ns high & 50ns lowThe non square wave lets you adjust address valid to MREQ valid for example.These are still huge steps. Using a delay line would let you get smaller steps.You need to remember also that you do not know what the Z80 is doing until after a delay when some Z80 pin changes.A delay line gives more options but needs more chips.A timer output from a microcontroller is an option if it has the controls needed and speed.Easy thing to do is build your computer. Then use your scope to check signals to see how much faster it could run and get an oscillator that is just a little slower.

author: nockieboy
author_rank: Super Contributor
timestamp: November 21, 2017, 10:09:30 am
content: The Z80's clockiscurrently provided by a micro-controller - an Atmega328 running at 16MHz. I can divide the clock by 2 for 8, 4, 2, 1 etc clock speeds. It supplies an 8, 4 or 2 MHz clock to the SBC based on what the Z80 requests, defaulting to 4MHz at power-on, for no reason other than it was easy to add to the system and I learned a bit about changing the clock on the Atmega328 and adjusting for different clock speeds in software for the SIO and CTC (well, I'm still working on the CTC's timing!)But because the clock is variable, I was doing some research to see if there was an easy way to generate a constant 2MHz clock for the PSG. I think a synchronous dual FF and multiplexer is the way to go (or just fix the system clock at xMHz.)

author: David Hess
author_rank: Super Contributor
timestamp: November 21, 2017, 03:56:57 pm
content: Quote from: nockieboy on November 20, 2017, 09:26:47 amSome variation of the 74163 would be my first choice but it would be difficult to go wrong with any synchronous counter. Using a synchronous counter can make things easier since all of the outputs change simultaneously relaxing the timing requirements of the logic which selects which output is used.

author: nockieboy
author_rank: Super Contributor
timestamp: November 22, 2017, 09:47:20 pm
content: C - I've got my head around how the 670 works as the key component in the MMU now, thanks for taking the time to explain that to me.I have a question about timings, though, which I'm not sure I can work out myself due to lack of experience and no idea where to start. I'm still waiting for a 74LS670 to turn up in the post, so in the meantime I thought I'd throw the MMU together with a 74HCT670 for the fun of it, really and to see if it would work. It doesn't.Now, I haven't had time to start searching for problems yet (so it could be a dodgy connection) but I thought I'd ask the obvious one before I break out the multimeter and vat of coffee; namely, is thereanychance the HCT version of the 670 would work at 4MHz, or is it just too slow and that's the reason my SBC isn't booting? I note that it's roughly half as fast as the LS version, but am not sure how that stacks with the ~M1 / ~RD timings etc.

author: Ian.M
author_rank: Super Contributor
timestamp: November 22, 2017, 10:06:33 pm
content: Drop your system clock to 1MHz - if that doesn't fix it you've got a design or wiring problem or a bad chip. The worst case propagation delay from the 74HCT670 in the A4:15 to EA14:17 path is under 50ns. You'd have to sit down with Z80 timing diagrams for memory read and write and M1 opcode fetch + the specs for your memory chips to see how fast you can push the cycle time without wait states. Don't forget to allow for propagation delays in any bus buffers.

author: nockieboy
author_rank: Super Contributor
timestamp: November 23, 2017, 02:09:38 pm
content: Okay, the 74LS670's arrived in the post this morning and I've swapped the HCT 670 out for an LS version. The SBC still won't boot, even when I drop the clock to 2MHz (the current minimum without tweaking the Arduino's software) I'm getting nothing but a blank console. So I've started with basic fault-finding - found a D0 line that had become disconnected from the SIO/2 whilst I was removing some of the old (Grant's design) RAM/ROM select lines, but other than that I can't see anything else obviously wrong with the connections (it still won't boot.) The next step is go through the schematics and make sure that every wire connects everything it should to everything else it should.Before I started that, however, I thought I'd check the output of Q4 on the 670 to see if it was selecting the ROM as it should at boot. Q4 shows 0v, which means the ROM will be disabled (the select line goes through an inverter, remember) and the Z80 will just see 64K of SRAM (and its associated random contents.) 1Q from the 74HCT74 FF is low, which is a good start. I've done a little more cursory fault-checking with the 670 and found its supply voltage to be 4.2V - that's a bit on the low side for it to work, methinks?My multi-meter isn't exactly the mutt's genitals, though and my skill using it and interpreting the results is about at the same level. My USB volt meter widget is showing 5.00v at 0.17A, which seems reasonable to me.

author: Ian.M
author_rank: Super Contributor
timestamp: November 23, 2017, 02:40:59 pm
content: Back to classic minimal Z80 fault finding - disable all memory by disconnecting their chip selects and strapping them inactive, and put 8x 10K pulldowns on the data bus so the Z80 only fetches NOP instructions. It will cycle through all 64K of the address space in order, in under eight seconds at 2MHz. Then its a matter of fun with a scope and/or logic analyser.If all you've got is a logic probe or DMM, you'll have to customise your Arduino clock generator to let you run it for N clock pulses from release from reset (N=0 to 262144), then let you slow clock it or even toggle the clock manually, or the critical transitons will wizz past before you can study them.

author: C
author_rank: Super Contributor
timestamp: November 23, 2017, 03:13:13 pm
content: From what I am reading, guess you did not do slow changes with verify steps to see each part is working.SoOn power up 670 read output should be tristateQn pull-up resistors make these pins high.Think of ways to test thisThe 670 Gr pin high for example.If you leave pull-up resistors connected to connected to memory &disconnect Qn from memory, Z80 should see High 16k block of ROM,Note that with all ROM the Z80 STACK is not working.The Z80 boot software should be able to start and send a message to serial even with out STACK working.Now if the MAD Software creator happened to write some code.The code could write some values to the 670 and let you test the 670Even with out the STACK working a JP will work.At boot Z80 A14 & A15 = 0If boot code jumps to the different areas what is on A14 & A15 will changeSo code is running in area 0do a jump where A14 & A15 change to area 1 with the lower bits set for instruction after the jumpWith the boot code showing in all four areas, the Z80 could jump between the areas and stay in that area a while by doing a loop.While looping you could output a message to serial.The Z80 could try to write to memory & read memory.Note that the ROM write has a software safety lock so even with ROM's WR pin connected, Rom should be un-changed.You could get real fancy and do a software memory test on each area.Think of thisRead a locationWrite something differentRead the location againWrite back first read of locationIf both reads match you have ROMIf Write value and following read value you have a RAM fault or ROMERROR in above line or not clearIf you write a value to memory you should read back same value if it is RAMNote that you should use many different values to test RAM00H followed by FFh changes all bits so you could have some shorts between data lines.AAh followed by 55h is not badCrap meter should read close to same value for same voltage.If you measure USB Voltage with crap meter then you should get very close to same value every where for 5v.

author: nockieboy
author_rank: Super Contributor
timestamp: November 23, 2017, 04:17:14 pm
content: Quote from: C on November 23, 2017, 03:13:13 pmEeeerr...Noooo... I DID wire it all up with just the Qn connections disconnected and the memory select lines intact and it worked, but that doesn't really prove a lot I guess.EDIT: Oh, I made the modifications to the 138 IO manager and it all worked fine there too, before building the rest of the MMU.Quote from: C on November 23, 2017, 03:13:13 pmYes, that did concern me a little when I was modifying the boot code for the ROM. At startup, there's an army of EQUates and DSs reserving space for variables, but they're little more than labels the assembler uses for memory addresses to store values, so with an all-ROM memory they shouldn't cause any problems, right?After the EQU's and DSs, at the start of the ROM effectively, the code does this:Code:;------------------------------------------------------------------------------; START OF MONITOR ROM;------------------------------------------------------------------------------MON.ORG$0000; MONITOR ROM RESET VECTOR;------------------------------------------------------------------------------; Reset;------------------------------------------------------------------------------RST00DI; Disable INTerruptsJPMINIT; Initialize Hardware and goSo it jumps to MINIT, which does this:Code:MINIT:; Initialise MMULDC,MMU_IO; Set C to IO port of MMULDA,$8F; MMU disabled, Page 0 = Bank 0FOUT(C),ALDA,$91; MMU disabled, Page 1 = Bank 01OUT(C),ALDA,$A2; MMU disabled, Page 2 = Bank 02OUT(C),ALDA,$33; MMU enabled, Page 3 = Bank 03OUT(C),ALDA,$3; Set MMU_Lock byte so that Areas 0 and 1 are lockedLD(MMU_Lock),A; from inadvertant re-mapping by the BANK commandLDSP,MSTACK; Set the Stack PointerLDHL,serABuf; Set up Serial A bufferLD(serAInPtr),HL; with In and Read pointersLD(serARdPtr),HLLDHL,serBBuf; Ditto for Serial BLD(serBInPtr),HLLD(serBRdPtr),HLXORA; 0 to accumulatorLD(serABufUsed),A; Set both buffer sizes to zeroLD(serBBufUsed),ASo the first commands to execute, aside from the initial JP, are to set up the MMU and memory space, so the rest of the monitor code will run normally (and starts by setting up the stack area in a newly-assigned RAM bank.) That's the idea, anyway.Is that all okay to run without a stack?Quote from: C on November 23, 2017, 03:13:13 pmOkay, sounds like a plan.Quote from: C on November 23, 2017, 03:13:13 pmYeah, I'm not sure about the issue there. If there really is only 4.2V at the 670, that could be a problem. I'll look into it (along with the software edits you've mentioned) later this week when I have some time. Thanks.

author: C
author_rank: Super Contributor
timestamp: November 23, 2017, 06:43:30 pm
content: I do not see a problem with your codeInterrupt code will not work with out a stack in ram just so you know.You can use the SIO with out interrupts be enabled.One handy thing to have in software is a string output.The C language uses a zero byte at end of string to determine the string length, but this prevents output of a zero byteOther languages put a byte or word at the beginning that has number of characters/bytes to send. This way a Zero is a valid byte in string.If you look at code for SIO init you could have a stream of bytes.SIO_INITA:; init channel Alength, register, value, register, valueSIO_INITB:; init channel Blength, register, value, register, valuemain code would doLoad I/O address in Z80 registerLoad address of length byte in a Z80 registerCall stream_outNow you see a problem, With no stack at this time calls do not work!But this is a problem only during boot & no stackBoot with no stack could use the followingSIO_INITA:; init channel Alength, register, value, register, valueReturn_addressSIO_INITB:; init channel Alength, register, value, register, valueReturn_addressand instead of a RET instruction do aLd HL ,(address of return_address data)JP (HL)And this address just happens to be in a register. You used the register to access the table of data.Now some trick codeCall InLine_stream_outDb lengthDS "This it message output."; More code here the sub will return hereThe sub InLine_stream_outpops the return address off the stack and uses it as a data pointer to read Length and streamread lengthloop outputting bytea until length = 0Pushes address back on stack. At this time it should be pointing at address of :more codeRET : This takes back to running code starting one byte after last stream bytelook at instruction OTIR

author: nockieboy
author_rank: Super Contributor
timestamp: November 23, 2017, 10:23:52 pm
content: That's what I find fascinating about assembly - it can be streamlined and optimised in ways that almost look like black magic to the uninitiated! There's some good advice there, C - thanks very much!My plan is as follows:1. Sanity-check all connections to the MMU and from MMU to memory.2. Check that I've got no stray signals from Grant's old ROM (de)select circuitry causing problems.3. Clarify the voltage reading I'm getting on pin 1 of the LS670. It should be higher than 4.2V.4. Edit the ROM assembly to stop execution before the ROM is mapped to just Area 0 (this way I can test to make sure Q4 is actually low in error, rather than low because the Z80 has randomly executed some code and the ROM is not being accessed when I test with my multimeter.)Can I just stick a HALT at the start of MINIT: to do this?5. Include some code to see if I can get any text out of the SIO/2 as part of step 3 above.(Thanks for the suggestion, C!)6. If all the above fails, spend a couple of weeks learning how to do timing charts for the Z80 and work out if the Z80 needs any WAIT states for the MMU to keep up.

author: C
author_rank: Super Contributor
timestamp: November 24, 2017, 12:53:50 am
content: Can think of a couple of problems areas.With the memory mode you are running the memory in, you need U8:A & U8:B wired like grant's drawing. Pins 3 & 6 connect to ram/rom grant's way.Pin 3 to ram WRpin 6 to RAM & ROM OEAll Ram/rom address/data lines go to Z80Except for A14 and higher.Did you get the High 16k area of ROM programmed properly?It should match first 16K except for those bytes in the message.If not sureFrom What I know you were running 16K ROM with reaming RAM until all ram.If so with only first 16K programmed you could strap A14,A15,A16 low only at ROMQ4 would still do rom/ram but rom would act like a 16k rombefore step 4 I wouldPatch/strap the 670 so it stays in tri-state output mode.Remove connection to Pin 11Gr and pull high or strap highdoes mot matter what Z80 does Q1-Q4 should remain high and connected memory pins high with ROM selectedIf this is correct then output of 670 is probably correct.If not and you have a second ROM, put 00h in all locations.Z80 will do nop and A0-A13 of memory should count.A volt meter is not a good way to troubleshoot a running computer.job for scope.Can I just stick a HALT at the start of MINIT: to do this? should work

author: nockieboy
author_rank: Super Contributor
timestamp: November 24, 2017, 10:21:28 pm
content: Quote from: C on November 24, 2017, 12:53:50 amYep, that's all in place still.Quote from: C on November 24, 2017, 12:53:50 amA14 & A15 from the Z80 go straight to the MMU (670). The Z80's A14 & A15 are now only connected to the rest of the address bus via the MMU.Quote from: C on November 24, 2017, 12:53:50 amYes, I've actually copied the monitor code into all 8 banks of the ROM earlier this evening (00000h, 04000h, 08000h, 0C000h 10000h, 14000h, 18000h and 1C000h) - so whichever ROM bank is selected, the SBC should boot. It still doesn't, so this tells me that the ROM isn't selected at all by the MMU (which backs up the multimeter reading I took yesterday on Q4 being low.) When I get more than 5 minutes to work on the issue, I'll get the oscilloscope out so don't worry, I won't be using the multimeter anymore.So, I've had little time today to look at the issue but Iwasable to program the ROM with monitor code in each of its 8 banks and try the SBC again. It still doesn't boot, so this backs up my earlier observation that Q4 was low and thus the MMU wasn't selecting the ROM properly for boot. I'll take a closer look at the MMU this weekend and check the voltages and signals to the 670.

author: C
author_rank: Super Contributor
timestamp: November 25, 2017, 05:49:19 am
content: My first thoughts on last post.Use a 138 NOW to select the ROM & RAM chips.So if you connect the address input of 138 to Q4 and can swap connections, could be a quick get computer working step with a better future.This still has all RAM or ROM and needs 670 to add the other.You only need one address input to select between the ROM & RAM chips.And the BIG one, you can swap connections between Y0 & Y1.AND Know that only one output will be enabled at a time.Some day I am guessing that you will want to do something and need a memory space to do it in.You will have two more address lines you can use for future memory expansion.You will have three inputs you could use to disable memory in future. This is a powerful thing. Take a glance at Mouser 9 different parts you could use to make a 256 byte block of memory special from an additional memory chip and where in Z80 memory controlled by an output port (Logic Comparators 8bit Identity ).But the really great thing you could directly connect 138 to Z80 for some tests if connection to Q4 fails.So Test stepsRead complete post and change order for what you see happening.Looking at Grant's basic codeLooks like it wants ram starting at 16k & has question for top of ram.So quick question you might know, will it work with just 16k of ram?Thinking of telling Basic that it has 16k of ram.If you connect Z80 A14 to 138's address input you can have 16k rom & 16k ram.You could disconnect Q1-Q4 from memoryWith RAM & ROM your interrupt SIO could work.Should be small change if it does not work.You could use BASIC output port command to test some of 670 function.Knowing that GR(pin 11) RA ( pin 5) & RB(pin 4 ) for 670 dip control what happens on Q1-Q4 and nothing else you could jumper these to what you want.Use basic output port instruction to write to 670 and check Q1-Q4You could also check the connection that should go to GRThe problems come with connecting 670 to memory.IT is almost work or die.If the copies of rom are the same then you could swap rom with out crash.The question is then did it work?The way to find this out is make each of the rom copies different in a way that does not crash the Z80.You could make Power up prompt output the Bank value.8 copies of your 16k rom with one byte changed.How you connect output of 670 and the inputs listed above determines what you get.With original connection of 670 inputsArea 0 could switch to even banksArea 1 change is a risk of crashArea 2 could switch to even banksArea 3 could switch to odd banksArea 0 & 2 would always be ROM but you can change bank.Area 1 & 3 would always be RAM.but not connected for change.First connect Q1-Q3 only to ROM keeping the 138 connected via A14 to control RAM/ROMUn-used address inputs to ram strapped to a level.You could change area 0 & 2 via basic the then peek the changed byte.When this is working you could add RAM to Q1-Q3This is the big step. Change area 1 and expect a crashYou can test area 3 changing ram bankAll software must be correctYou can not swap bank where program is running.You can not swap bank where stack is located.You can not swap a bank and mess up interrupts.when you change connection of 138 from Z80 A14 to Q4You have 0-7 = RAM, 8-F = ROMNow you know that basic should not change ROM code.Break the rule and swap area 0 with a copy of area 9Use Z80 to copy ROM to a unused block of ram.You can then swap area 0 with this ram block.Remember to change that one byte when coping rom.Check byte after swap.Think of what you have testedYou have not changed Area 1 and above only works if it stays the same.You have tested Area 0 of 670You can test area 2 & 3You used the Rom BASIC to make changes and test change worked.Now think about using MMUYou could setup a new table for interrupts in a different area.When you change the I register You just made new table active.This could be only a table location change.Any time you want you can change contents of interrupt table as long as you keep it pointing to good code.You can move the stack to a new area. With good code you could move back to old stack at proper time if needed.CP/M3 with proper code you write will do this changing for you.Even with CP/M2 you can do huge programs & huge data.Think about your scope or meterOften you can use even when out of calibration.You meter is a ratio device. The same scale is showing a ratio. You can use this to check if meter is working.The scope uses voltage for one ratio and time for other ratio.A lot of time when using a scope you just care about the shape.You have things you know what they should be.Instead of measuring everything compare things.If you have a logic divider you know output should be about 1/2 input in time.Think about your Z80, standard test conditions for CMOS version is 4.5v to 5.5v for supply.Good TTL logic 0 is < 0.8v with a logic 1 > 2.4Lots of things you can compare with scope.Most of time you are looking for a difference from something that should be close to same.USB power shows X, 74LS670 should be close to sameZ80 is close, other chips are close, you have why the difference for any half way working scope.This works even with changing signals if you have something else to check for comparison.Old analog volt meters would shake needle some on DC with low frequency noise. Digital gives a slow average.Scope shows noise and lets you decide that is about correct DC level.A bad diode or cap shows quickly on scope.

author: nockieboy
author_rank: Super Contributor
timestamp: November 26, 2017, 12:33:06 pm
content: Okay, spent about 15 minutes sanity-checking the wiring and found two howlers where I'd mis-connected a couple of address lines and for some reason had two select lines running from the 138 (one through the OR gate with ~WR and the other direct from ~Y7.)It's working beautifully now, even at 8MHz!!I'm able to swap RAM and ROM banks in and out with ease (confirmed using my memory viewing program and writing the bank numbers to the start of the 16K block using POKEs) using the BANK command I created for the monitor (DMI) program - all I need to do now is tweak a couple of CP/M programs that handle returning to the DMI without doing a (very) hard reset (have to power the SBC off until I MMU-ify the appropriate CP/M program that returns me to the DMI) and create the BANK command for CP/M and I've got a 256K computer.Thanks C and Ian.M especially for your assistance. Couldn't have done it without you!(On to the PSG now!)

author: C
author_rank: Super Contributor
timestamp: November 26, 2017, 12:53:03 pm
content: For Z80 you have a CALL instructionCall instruction puts return address on stackSub uses RET instructionreturn address gets usedMMU versionZ80 calls bank swap sub whth data, Data = address of sub or address of dataBank swap subpushes return bank address info on stackswaps the bankcalls the subSub returns to bank swap subswaps back to original bankreturns to program.For data you need to move it both ways.The Z80 has a PUSH instructionYou need bank PUSHZ80 has a POP instructionYou need a bank POPKeep in mind that sometime a word value or something else like a buffer will be split across two banks.

author: Ian.M
author_rank: Super Contributor
timestamp: November 26, 2017, 01:44:59 pm
content: If you manage to add an extra FLASH chip for ROMdisk, get CP/M Plus running, loading from ROMdisk and layout a nice PCB for it you'll have a really nice 'retro' system. Consider designing it as a S100 bus CPU card to make it easily expandable. You'll need bus buffers and probably a programmable wait state generator for accessing S100 bus peripherals, and some of the memory space will need to be mappable to the bus, so you may need to add another '670 to gain some extra address lines EA18-EA21

author: C
author_rank: Super Contributor
timestamp: November 26, 2017, 02:14:10 pm
content: Sorry I forgot theNow before you get tooo distracted by other things.Would be a good GREAT idea to look at your timing.Is the Z80 working with low time margin when running a 8Mhx?Could this margin be such that some instructions could be read from memory wrong?lan.MI would not build to S100. Old bus with high dollar cards due to the hack on top of what was previous S100 standard.Has a lot of good ideas that should be copied.The Z80 will work on a VME bus. This is a large step up from S100. Built with idea of vector interrupts, many processors, large address space & 8 or 16 bit CPU's.Should take less chips and just work better.Would be a good idea to get out your scope and measure things.For instruction fetchTrigger on M1Look at Z80 data sheet that lists times and measure them using your scope.What you want to know is all at the Z80 chip pins.For address bus you are looking for a range of when change starts and endsA range for data bus.here you have two ranges you can collect Rom/Ram Boot rom / CP/MGet range of Q1-Q4 of 670Get values at Rom Ram pins.Get values for Z80 memory read/writeGet values for Z80 IO read/write.If you think you have poor scope then record the time base setting.Think you have an AVR with a crystal get it's time.A 16mhz crystal should be close to 16mhz. This is a check on scope time base and could be a correction factor for an out of cal scope.Last circuit I saw for PSC, could have data on bus for too long a time. Would be good to check.It could be working, but not good long term to have two things driving a signal.EDIT ADDThe MMU control is output only.You will need MMU area values when you try to get back from using or working with a different area.Software FIXYou have a copy of what was last written to MMU in common memory.When you start to make a change to a new bank,1. push a copy of common memory MMU values on to stack2. as you make changes to MMU change common memory MMU values also.Use the new MMU map3. on return from using MMU mapRead old MMU values from stack and update MMU and common memory MMU valuesThis setup lets you change MMU many times and return back to previous settings.This is foundation for what could look like magic.

author: nockieboy
author_rank: Super Contributor
timestamp: November 27, 2017, 12:05:17 pm
content: Quote from: C on November 26, 2017, 02:14:10 pmAlready sorted that before the MMU was functional, C.The command I used to change Area/Bank mapping will, if no parameters are passed, show you what the current mappings are:Code:OKbankCurrent memory mapping:AREA 00 -> BANK 00 (RAM) *LOCKEDAREA 01 -> BANK 01 (RAM) *LOCKEDAREA 02 -> BANK 02 (RAM)AREA 03 -> BANK 03 (RAM)RAM: 64KB, ROM: 00KBOKbank 02,06OKbank 03,0bOKbankCurrent memory mapping:AREA 00 -> BANK 00 (RAM) *LOCKEDAREA 01 -> BANK 01 (RAM) *LOCKEDAREA 02 -> BANK 06 (RAM)AREA 03 -> BANK 0B (ROM)RAM: 48KB, ROM: 16KBOKEDIT: In case you're wondering (you're probably not) - the *LOCKED comment means that Area is fixed and cannot be changed with the BANK command, so you can't inadvertently crash the system by swapping out the stack and currently-executing code. Of course, there's nothing stopping you doing it with direct OUT commands, but it's an idiot filter for when I'm not thinking about what I'm doing.Code:bank 00,0fCannot remap locked AreasOK

author: Ian.M
author_rank: Super Contributor
timestamp: November 27, 2017, 03:45:23 pm
content: Adding hardware read-back of the MMU registers could be done, but the logic cost of doing so is probably prohibitive in a LSI/MSI glue logic build.Unfortunately the cost in logic to guard the MMU I/O port so it can only be accessed immediately after a specific instruction sequence is also prohibitive, so you'll have to be careful to avoid rogue programs that probe or scan ports etc. but its something that you should consider if you ever add a CPLD or FPGA that has access to the whole data bus, and the signals required to decode all memory and I/O accesses.

author: C
author_rank: Super Contributor
timestamp: November 27, 2017, 05:22:29 pm
content: Think you are ready to work on CP/M3For long termThink it would best to use CP/M3's relocating assembler.If you were doing TurboDos I would suggest it's relocating assembler.From memory the source changes were small to none.Do not remember is source to both works.There is also M80 that was from microsoft.All three have linkers that let you put relocatable binary output together to make a working programL80 is microsoft linker.For text processing I used wordstar3.3Some programs/code contained their own reallocators in memory.The ones I remember used a simple bit table to change the value of a byte.You assemble code two times with a ORG change of 100HThe binary bytes that are different are the bytes needing to change to move code in steps of 256 bytes.From memory SID and ZSID did this.Now that you have a MMU, what other areas do you want to learn?I am assuming that you now know what would need to be changed if you wanted to use larger memory chips or a larger address space.

author: Ian.M
author_rank: Super Contributor
timestamp: November 27, 2017, 06:07:05 pm
content: Also seehttps://www.z88dk.org/for a relatively modern toolchain for Z80 cross-development in assembler and C.

author: C
author_rank: Super Contributor
timestamp: November 27, 2017, 06:16:24 pm
content: CP/M3 & TurboDos both have a large amount of relocatable code modules that you use to build the system.If you do not have new code in compatible relocatable code modules the build tools do not work.

author: nockieboy
author_rank: Super Contributor
timestamp: November 28, 2017, 04:12:47 pm
content: Quote from: Ian.M on November 27, 2017, 06:07:05 pmThanks Ian - I'm already aware of the site as I found it in previous searches to do with building the SBC. I haven't had the opportunity to take a long look at the site yet, but if it offers tools that will help with getting CP/M 3 up and running, I will certainly do so!Quote from: C on November 27, 2017, 05:22:29 pmYes, I think that's going to be the next project - I'll leave the PSG until CP/M 3 is stable, as the majority of the work to do with getting the PSG running is software-based rather than hardware (although there's still the clock timing issue I have to resolve.)Quote from: C on November 27, 2017, 05:22:29 pmWell, I'd like to get CP/M 3 up and running!Not sure where to start with it, really, as CP/M 2.2 was provided ready-configured on Grant Searle's website, so there was nothing I had to do to get it working from the start. I've added a few tweaks to CBIOS since then, but nothing too complicated and only relating to varying the baud rate of the SIO depending on the system clock speed and getting the MMU up and running.I'm going to have to sit down with the CP/M 3 System Guide I think and see what questions arise from reading that.Quote from: C on November 27, 2017, 05:22:29 pmI think so, yes. If I start thinking about upgrading the physical memory space, I'll be sure to check in here first to check my designs out with you guys though.

author: Ian.M
author_rank: Super Contributor
timestamp: November 28, 2017, 04:44:35 pm
content: Take a Z80 emulator that supports banked memory and, ignoring any existing CP/M, port CP/M Plus to it. Here's a configurable Z80 system emulator:https://k1.spdns.de/Develop/Projects/Z80%20EMUF/that appears to be recently maintained, and from a quick skim it looks like you can code an exact emulation of your Z80 system using it.If you want a more advanced MMU in the future, I'd suggest the one I initially pointed you to using '486 era cache RAM for the address translation. These very fast small 5V SRAM chips are getting rarer and harder to find, so it would be worth acquiring a few sooner rather than later.

author: C
author_rank: Super Contributor
timestamp: November 28, 2017, 04:59:49 pm
content: CP/M 3 is just an expanded CBIOSThink that you will find that most grant's CBIOS will work for same CP/M3 CBIOS Function.You are just adding some new functions fo most part.There were some code cleanup's done.From memoryCP/M2.2 CBIOS had most sector blocking code in CBIOS, the putting/getting the 128 byte blocks ito/from to large block for drive.CP/M3 now does more work making user created CBIOS simpler.Just start with Grant's CBIOS for 2.2.Check each function in Grants for a change on how it is called and what output is wanted.Add the new function calls.Think there are examples where you have dummy functions for CP/M3 running in 64k or less memory.Do this step first. Result should be a CP/M2.2 program that changes OS from 2.2 to 3.0.Should see little change, A CP/M2.2 program most times see no change.Disk format should not change.Not worth time jumping to emulator where you have a working CP/M2.2 CBIOS to start from.

author: Ian.M
author_rank: Super Contributor
timestamp: November 28, 2017, 05:16:13 pm
content: Jumping to emulation gives you debugging capabilities that aren't possible on a real Z80 system without FPGA assistance, . I did a paper study way way back in the '80s before FPGAs and cheap MCUs were a thing of what it would take to build an invisible Z80 hardware debugger - no resources used on the target system, and CPU state restored as fully as possible on a normal Z80 chip before resuming execution, and it was going to be a real bear to build and implement.Also, if you want to share your project, a working emulator will go a long way towards popularising it . . . . .

author: C
author_rank: Super Contributor
timestamp: November 28, 2017, 06:14:37 pm
content: Sorry lan.MDid not say last very goodDepending on emulator capability nockieboy having access to one would be in good to great range.For CP/M3Here he states that he has software that he used to change the MMU and Check it's function.Only step left is to make parts of this a CP/M3 function.Do not think nockieboy will have much trouble with this step.Remaining steps are also smallMost CBIOS functions will be un-changed.Un-like CP/M2.2, CP/M3 is a CP/M2.2 program.The old load cpm2.2 from boot track has changed to a loader that then loads the OS as a OS file and runs it.You can have many different versions of CP/M3 on the boot disk and a change is just running a program.Run program A to get CP/M3 for non-banked.Run program B to get CP/M3 for banked.A rename can change which starts at boot.The capability to quickly build a new version is why you want to use CP/M3 tools.A linker input change could be all that is needed to create the wanted version.Modular Assembly code.

author: nockieboy
author_rank: Super Contributor
timestamp: December 04, 2017, 02:38:57 pm
content: Okay, I'm going to just throw this out there with an acceptance that 'you told me so' previously....Now that I'm working on getting CP/M 3 running on my SBC, I've realised that 128K SRAM isn't a whole lot - it only allows CP/M 3 to have a maximum of three banks effectively, if I allow 32KB for each bank rather than 48KB - and onlytwobanks if I use 48KB each.So I'm considering replacing my 128KB SRAM with a 512KB version. This (with the 128KB EEPROM) would take the memory up to 640KB - and as someone once famously said,"640KB ought to be enough for anybody."There's a big hurdle to jump first though - namely that my current 128KB SRAM is embedded amongst address and data wires on the breadboard. So I might leave the physical upgrade until I get my SBC onto PCB.But thinking ahead, I'll need to upgrade my current MMU to allow for another two address lines (EA18 & EA19.) This can easily be done with the addition of another 74LS670 chip, but what would be the best way to wire it in to the existing MMU circuit? I presume EA17, the existing ~RAM/ROM select line, would become the ~GR input for the second 670 and I'd remove the inverter to place it on EA19 coming out of the second 670 and going to ROM?

author: Ian.M
author_rank: Super Contributor
timestamp: December 04, 2017, 03:39:10 pm
content: Nope.Its read mode input connections (RA RB, /ER) go in parallel with the existing one, and its outputs Q1:Q4 become EA18:EA21 for a 4MB address space.Then you have to sort out its write mode inputs so you can load a page table.Currently you are using a one address write only port with two bits in the byte for '670 addressing. The way forward is to move the existing and the new '670 write addressing (WA,WB) to Z80 A0,A1 and use four I/O addresses. Then you can hook the new '670's D1:D4 to Z80 D4:D7, so the low nibble gets stored in the old '670 and the high nibble in the new '670. You then have to sort out the BOOT mode disable signal - it was a port bit, but the easiest thing to do now would be to make any write to that port block leave BOOT mode. The first value written would need to map the boot block at the current execution page so the bootup code doesn't crash. Then you can map the other three pages as required, and finally transfer execution out of page 0 and remap page 0. It wouldn't be possible to return to BOOT mode for a soft Reset, but you could fake it by mapping the boot block to all the pages and jumping to address 0.It gets a lot easier to page efficiently if your MMU page size is a lot smaller (4KB seems optimum, giving a 1MB address map) and it can swap between preloaded page tables with a single OUT() instruction. As Imentionedin your old topic, a 486 era fast cache SRAM can be used to do that. Up to 256 page tables could be preloaded, with separate entries for read and write mapping, which allows write protection, and also easy copying of ROM to RAM. When you don't want that fine grained paging, simply create page tables that swap between 16K blocks.I'd have to look at the details, but I believe that would permit a CP/M Plus or MPM system to have nearly 60K of TPA!

author: glarsson
author_rank: Frequent Contributor
timestamp: December 04, 2017, 03:57:59 pm
content: Quote from: Ian.M on December 04, 2017, 03:39:10 pmYou do not need a 4k page size to get 60k of TPA. My CP/M3 system I built in the early eighties used 32k page size with 62k TPA.Never looked closer at MP/M, but I expect a small page size to be important when combining multiple users and large TPA.

author: C
author_rank: Super Contributor
timestamp: December 04, 2017, 07:21:44 pm
content: Note first post had error in table below.QuoteThink of what you are saying here.Existing MMU always has some memory enabled for a memory cycle. The CS enable is just by the address lines.The current MMU is 4 16k areas of 256KUsing Q4 of 670#1 to control -GR of 670#2670#1 16k area 0670#1 16k area 1670#1 16k area 2 670#2 16k area 2 <-( left this out on first post )670#1 16k area 3 670#2 16k area 3OR670#1 16k area 0670#1 16k area 1670#1 16k area 2 670#2 16k area 2670#1 16k area 3 670#2 16k area 3 <-( left this out on first post )With extra I/O input to 670#2670#2 16k area 0 could change to 670#2 16k area 2or670#2 16k area 1 could change to 670#2 16k area 3I would say this is a big fail.You only have two address inputs from Z80 to use to select expanded memory. Each bit added to output of MMU doubles the memory size you can select a 16k area from.========You always need to think of big picture.Look at this from other way, not as how many banks CP/M can use but use of your memory.With 16k banks, 4 are used by CP/M user programSo for big picture, your problem is lack of banks in expanded memory.A second problem is no space to put more banks in Z80 memory.First question should be how many areas of Z80 memory can CP/M manage.Remember that CP/M can use two modes.Z80 does the work or DMA does the work.DMA here can be something you write and can use more memory areas then CP/M.For just one area managed by CP/MCP/M will move data to common memory and then change banks and move data from common memory to new area.DMA will be Move data at this address with a size of in bank X toBank Y at this address.Need to remember that data could be in two source banks or detestation banks.CP/M can not force a program to put the Disk I/O block all in one memory area.With 16k banks, CP/M should know that only three can be changed and still have a common memory ares.A CP/M program works with blocks of 128 bytes or lessCP/M storage interface can have larger sizes of blocks.CPM will try to have all of a data block fit in one swapped area.So two main use casesMove a small block of data to/from user space.Move a larger block of data to/from storage.A large block to/from user space becomes a small block move of many blocks.Ok time to think ahead and also do what you want.From CP/M view,two areas allows direct copy between areas.Larger areas could allow CP/M to manage a larger total address space.Areas that are outside of CP/M managed area can be storagemanaged by your programming.So think about thisAdding second 670 can give 4096k total expanded memory.More logic will be needed for a smaller block size when using the 670'sFirst step could be for your current memory to act like normal memory.To do this put a 138 in place of inverter chip select.Before MMU you just jumper-ed UN-Used address lines to a level.You now have a memory chip that is half RAM and half ROM.By using A 138 to decode chip select to memory chips you could have 7 ram & one ROM of same size.Do not use messy logic to decode memory.Use a 138 to decode memory for each size of memory!!You need more address lines to address more memory. Best use of added 670 is to add address lines so that each 16k area is from a larger address space.look at how you are building now.Putting memory on breadboard takes a lot of space and a lot of wries that can get disconnected. Most of the wires are daisy chained.1. Look at having many 32 pin dip sockets you can plug your memory into.For max flexibility only a few pins need to be special and not connected to daisy chain.You need a 0.05 bus off wires ( a ribbon cable is 0.05). Three ribbon cable connectors could hold two dip sockets. Look at this to get some ideas. And you can have two more dips on other side of ribbon cable.On a board with solder pads this is a four hole bridge of wire, top dip, bottom dip, wire , then a space and again for other side of top dip..

author: C
author_rank: Super Contributor
timestamp: December 04, 2017, 09:11:19 pm
content: CP/M PlusTM(CP/M Version 3.0)Operating SystemSystem Guidehttp://www.cpm.z80.de/manuals/cpm3-sys.pdfThink the following is correctOn page 11 it states banked system A min of 2 and a max of 16 of what CP?M calls a bankLooking at Figure 1-2 on page 5If you had Bank 0 split at 32kLower part could switch between 16 32k areas (512k)and you need 32k for upper half.A 512k Ram chip would let you have 15 CP/M banks.Matching your MMUUpper half of 16k for bank 0lower could be 16 48K blocks (768k)A 512k Ram chip would let you have 10 48k CP/M Blanks16k for common and 16K unused by CP/MorAbove 15 CP/M banks and 32k common.Note the max for CP/M32k switch area is 512k + 32k common48K switch area is 768K +16K commonAbove these limits can be memory managed by your code.It would be easy to have Ram or Rom disks in memory.If you look at figure 1-7 page 10That could be a ROM disk driveYour Z80 power-up boot could exist above Track MThink of how little you need to write code to do this.To power-up boot Z80 you need top 16k as ROM for power-up boot code.Current code iscopy "Cold Boot Loader" from CF card (disk drive)So a switch from CF to Expanded memory ROM choice on CP/M boot.To Treat Some ROM as a disk driveTable for CP/M to know structure of drive.Code for CP/M to use to read/write to drive.As Disk drive CP/M has tools to write/read "Cold Boot Loader"After formating can manage all remaining space.Drive size = ROM size - 16k(power-up boot)

author: Ian.M
author_rank: Super Contributor
timestamp: December 04, 2017, 10:29:37 pm
content: Quote from: page 11If your MMU permits fast paging in 4K blocks, (giving an address space of 1MB), a 16 x 60KB CP/M bank system is possible using a total of 964KB of RAM. That's two 512KB (4Mbit) RAM chips, leaving 60K unused. Add a latched port bit somewhere to swap the top one with a 512KB FLASH chip, that is initially selected on Reset, and you can use it for the bootstrap and also as a ROMDISK. Obviously you need to double-buffer if you need to transfer data from FLASH into the top RAM chip, but that isn't too much of a PITA. About 500KB should be fine for holding CP/M Plus System and Utilities.If you hook up the /WR signal, you can also write to the FLASH, but I'd make that manually switchable to avoid rogue code smashing your bootstrap or system disk. With an appropriate utility (to run from RAM), that would allow re-flashing your system in-situ.The quiescent current for two 4Mbit SRAMs is low enough that you could make them battery backed - with some logic to force Z80 /Reset low if the unregulated supply drops, that could give you a non-volatile RAM disk. Generate a NMI instead of a Reset, and add a handler for it and you could do suspend/resume.

author: C
author_rank: Super Contributor
timestamp: December 05, 2017, 03:29:57 am
content: Quote from: Ian.M on December 04, 2017, 10:29:37 pmWith fast static cache ram you could do this for a MMU.Not possible using two 670 chips with out a lot of logicSimple is 4 16k banks for Z80 using one address space.With 8 bit output from the two 670's you could have 4MB total expanded space.Or waste some expanded address space and use some 670 bits for extra control.CP/M MMUBlock managed blocksize memory space size32K 512K 32K48K 768K 16k56K 896K 8k60K 960K 4kNeed to remember that the floppy disk drives that most systems has wore small by todays standards.If there was a standard floppy disk for CP/M it was a8" single side, single density, 128 byte sector, 26 sector per track ,77 track driveThis is about 250k when formatedDouble density increased this to 500KDual side to about 1MA lot of computers used 5 1/2" drives 100k, 200k, 400kCP/M3 can speed up a CF drive some.A fast drive for CP/M is a ram disk.So a small MMU block size sounds great but gains less with each step smaller for CP/M.Using parts of the 4M space for RAM/ROM disks us a gain.Using some of the 4M space to access new hardware or other systems is a gain.

author: nockieboy
author_rank: Super Contributor
timestamp: December 07, 2017, 08:04:47 am
content: Quote from: Ian.M on December 04, 2017, 10:29:37 pmI think this has been mentioned before - either in this discussion or one of my other related posts - and probably by yourself Ian.M, so apologies if my memory is failing me. Although my current system has the FLASH ROM sitting in a ZIF socket on the motherboard, it's not without its own fiddly complications as the ZIF doesn't always quite sit properly and has to be pushed down to re-seat it etc. after a number of programming cycles.I have every intention of putting this SBC onto a PCB in due course - either stripboard or (if costs allow) something more permanent, like a professionally-manufactured PCB - and whilst I don't mind having a ZIF socket on the PCB, in-circuit programming of the ROM would be a very nice feature to have!Is there much involved in doing it? I'm guessing that a switch would control the ROM's ~WR, after putting the Z80 into tri-state with a ~BUSREQ (not necessarily in that order, of course - I have an Atmega328 on the board which could run this sequence) and allowing the 328 DMA access to the ROM?I'll start researching this idea I think. I'm up to my eyes in CP/M 3 BIOS at the moment, so a hardware challenge will be a welcome distraction!

author: Ian.M
author_rank: Super Contributor
timestamp: December 07, 2017, 08:52:04 am
content: Yes, if you can grab the bus, you can do it that way, but a much simpler approach is for the Z80 to run from RAM, bootstrapped by the ATmega328. You need some way of getting code into RAM - but that's just a matter of disconnecting (or inhibiting) /RD to the memory, releasing /Reset + a hardware circuit to assert /WAIT every /MREQ + /RD from the Z80, and signal the ATmega328 so it can stuff a byte on the bus then release /WAIT.It would send opcodes and data bytes to configure the MMU, and load DE with the desired address to copy to in RAM then stream LDI instructions to copy the desired code into RAM - probably a simple monitor program. For each LDI the write to (DE) taking effect but the read from (HL) actually being supplied by the ATmega328, without reference to HL on the address bus, so one payload byte is transferred for every two opcode bytes. Finally it stuffs a jump instruction and re-enables /RD from memory and disables the /WAIT circuit.At that point the Z80 is running the monitor, and a PC application can use it to bootload the system with *ANYTHING* from a simple IntelHEX download + FLASH write utility, up to a full CP/M Plus system running from RAMdisk. The PC application can be just about any off-the-shelf terminal program that supports paced sending of text files.

author: C
author_rank: Super Contributor
timestamp: December 07, 2017, 09:05:35 am
content: Your flash rom has a software protect feature to prevent accidental writes.You should be able to just connect your existing /WR that goes to RAM to your Rom chip with no problems.You would gain the most power by having the Z80 able to write the Flash Rom.Now as you are working on CP/M3 BIOS keep in mind a few things.In addition to the CP/M3 config that will build your CP/M3 system, some systems also have/had a special program that could change some data fields in the working BIOS.For example, you might boot from one CP/M drive and after running some code or CP/M programs, change the CP/M drive map.Keep in mind that CP/M has a program that can write to boot/system area.IF you add the proper drive tables you could have RAM or ROM disks.You could use CP/M format to put directory structure in place. Then just copy files to new drive.The only special thing you will need to do after getting capability to FLASH Rom write is a special program to put the power up boot in the highest 16k area. Make your CP/M ROM Drive 16k smaller then top of ROM.With some good code even CP/M2 can use a RAM or ROM drive.With CP/M3 capability to run a program on CP/M2 and change to CP/M3 you have a great test environment.Build a NON-Banked version of CP/M3Use this to build two more CP/M3 versionsCP/M3 with ROM and/or RAM disk drives.Banked CP/M3Banked CP/M3 with ROM and/or RAM disk drives.For future keep in mind that a CP/M disk drive could be a file or array of blocks on PC or something.You will gain more by having Z80 write to Flash Rom then Atmega328 writing to Flash Romlan.M's post is forNO CFcard drive in system that is working.NO Rom in system that is working.

author: nockieboy
author_rank: Super Contributor
timestamp: December 07, 2017, 12:37:07 pm
content: Yeah, I like the idea of having some sort of storage media like Compact Flash (or SD card via an SPI interface) rather than using the 328 to completely bootstrap the Z80 with no ROM. Would be great if I could just flick a switch, put the SBC into 'ROM programming'-mode, and stream a new monitor HEX file from the terminal or via the 328 and its USB connection.All I'd need to do is hold the Z80 in reset, or tri-state its address/data buses with a ~BUSREQ and let the 328 do the rest. The only problem with that system is that currently, the 328 is only connected to the Z80 system via a serial interface to the SIO. I'd need a bigger micro-controller if I want it to be able to take over the address and data buses...

author: Ian.M
author_rank: Super Contributor
timestamp: December 07, 2017, 01:07:09 pm
content: Not really. Just add a 74HC595 hooked up to the ATmega328 SPI pins. Its output is tristateable so it can go direct to the data bus, then you only need a few more I/O pins for the bus stuffing logic. By stuffing Z80 commands (+ data) you avoid the need to interface to the address bus + can get the CPU internal state if you add a 74HC165 to read the data bus. You can even use it to implement a hardware debugger though it will need two bytes of stack in RAM - add hardware to decode a M1 cycle at address 0x0066 to detect a NMI has occurred, then your ATmega328 takes over and stuffs instructions, the first being PUSH AF with the memory disabled to read out the Accumulator and flags from the bus, then you can push the other register pairs and start shuffling stuff internally to get a full readout. Once you've got the CPU state without affecting RAM (other than the address stacked on NMI entry) you can stuff instructions to manipulate memory or I/O, and disable the stuffer for just the right number of /MREQ or /IORQ cycles for the instruction just stuffed to access the memory or peripherals. To resume normal execution, you stuff POP instructions + the previous register contents to restore the CPU state then stuff a RETN. and disable the stuffer. To implement single stepping is easy - the next /M1 after debugger exit must trigger a NMI. To implement breakpoints is harder - the easiest option for RAM only breakpoints is to put DI + JP 0x0066 at one of the RST vectors, then that RST instruction can be used as a software breakpoint.

author: nockieboy
author_rank: Super Contributor
timestamp: December 07, 2017, 07:39:35 pm
content: Ouch.. that sounds waaay beyond my feeble digital electronics and assembly comprehension and skills...Okay, well maybe I should just focus on getting CP/M 3 up and running for the moment. I'm getting sidetracked by interesting ideas that are ballooning into quite complex concepts (at least to my inexperienced mind!)

author: C
author_rank: Super Contributor
timestamp: December 07, 2017, 08:24:07 pm
content: Why not do the easy thing?You have CP/M running.There are many programs that allowed one CP/M computer to talk to another computer and transfer filesfile transfer protocolsKermitXMODEM,YMODEM, ZMODEMSome of these are built in to a PC terminal programTeraTerm is one of many for PC side

author: Ian.M
author_rank: Super Contributor
timestamp: December 07, 2017, 09:37:12 pm
content: It should be easy enough to understand. Think about it some more and consider what it would take to feed the Z80 a known sequence of opcodes and data bytes in place of what would normally come from the external memories. If you want to use a smaller ATmega, it needs a couple of shift registers so it can do the Z80 data bus interface via SPI, to save pins, it doesn't hook up to the address bus but does need several control signals and some of them have to be intercepted - do that with analog switches to minimise the propagation delay when the hardware bootstrap/debugger is not in control - and some glue logic to handle some control signals that are too fast for the Atmega to handle in code.If you want a full debugger, it has to know when the CPU is about to start a new instruction so it can jump in and take over. Its a PITA intercepting NMI by decoding a M1 fetch from 0x0066 as that's 16 address lines, 12 low and 4 high that have to be decoded, but that's the cost you have to pay because you don't have access to an ICE bondout version of the Z80 CPU if you want to do it in hardware. The alternative is for the ATmega to assert /Wait, sniff the data bus for the byte on it then release /Wait till the next /M1 cycle (needs some logic to do that autonomously), while it runs the stream of /M1 bytes received through a state machine that recognises ALL the z80 multi-byte opcode prefixes. When it reaches a M1 fetch that hasn't been modified by a prefix, it can take over from the memory and substitute its own data on the bus to take control of the CPU.

author: jgh
author_rank: Newbie
timestamp: December 07, 2017, 10:52:37 pm
content: Is it too late to chuckthisin the mix?(I only stumbled across this forum yesterday)

author: nockieboy
author_rank: Super Contributor
timestamp: December 08, 2017, 03:15:40 pm
content: Quote from: jgh on December 07, 2017, 10:52:37 pmWow - that's certainly an impressive spec for 3 chips and some glue logic! Might have to give that one a try at some point in the future when I get hold of some larger memory chips! Also an interesting web site with some fascinating information on it.

author: nockieboy
author_rank: Super Contributor
timestamp: December 08, 2017, 03:33:46 pm
content: Quote from: C on December 07, 2017, 08:24:07 pmI'd like to keep the SBC as simple and standalone as possible - I eventually plan to add a keyboard interface and CRT driver so it is complete standlone, so I won't be connecting it to a PC except for debugging/software updates, perhaps.EDIT:Actually C, I think I follow you - you mean transfer the data into CP/M in the same way I currently do with files from my PC (as a pasted data stream). Once in CP/M, I can just write a program to do exactly what I've outlined below in my response to Ian.M's post and write the data to the ROM with just a simple hardware change to allow me to set the ROM for write access...?Quote from: Ian.M on December 07, 2017, 09:37:12 pmI understand the principle of injecting op codes and data onto the data bus to make the Z80 do the heavy lifting and store the ROM hex file in RAM before writing (or flashing it) to the ROM, but in practice it just seems like a huge task. So I'd be looking to intercept a 'POP DE' op code from the Z80, for example, and injecting (e.g.) the first 2 bytes of the new ROM hex file onto the data bus, so the Z80 thinks it's getting DE off the stack but is actually getting two bytes of data from the micro-controller.The program running on the Z80 would then take the contents of the DE registers and LD it to a RAM address in HL. INC HL, rinse and repeat until the ROM hex file is fully transferred from the micro-controller to RAM. Then the program running on the Z80 could just write the data to ROM with an IO select via a flip flop to pull the ROM's ~WR line low and LDIR it across, resetting the flip flop (and making the ROM read-only again) when its done?The issue is that for such a simple concept, it requires a detailed knowledge of the Z80 architecture in terms of control signals and timings - one I don't believe I have at the moment, not to mention hijacking the data bus. I'll admit to finding the idea highly elegant but somewhat scary and fraught with problems.

author: Ian.M
author_rank: Super Contributor
timestamp: December 08, 2017, 04:49:35 pm
content: My explanation of how you can make the ATmega bootstrap the Z80 is really not that tricky, and doesn't need a deep knowledge of the bus timings - or at least no more so than you need to build a Z80 system that's more complex than a minimal one in the first place. The idea of a zero CPU resources hardware debugger is however a lot more complex so I quite understand your reluctance to start down that road at thios stage. Its something you could retrofit later by adding a daughterboard carrying the hardware bootstrap/debugger between the Z80 and its socket. Adding mounting holes to permit such a daughterboard to be secured with PCB standoffs would future-proof your design.However if you aten't going to have a hardware bootstrap of any sort, then you are up s--t creek if the boot block in the FLASH chip gets corrupted. If you want to avoid having to pull the FLASH chip to put in your programmer, I strongly recommend writing a monitor ROM that can cold-boot the machine, and can also receive data in IntelHEX format and store it to RAM. Burn it to EPROM and provide a socket for it on your memory board. You'll also need a SPDT switch to select between routing the ROM chip select to the FLASH or the EPROM, while the non-selected one is held inactive by a pullup on its /CS pin.Then if you brick the FLASH bootblock, you can switch to the monitor ROM, restart anduse it to load an IntelHEX downloader + FLASH writer utility into RAM and run it, then flip the switch back to select the FLASH before sending it the FLASH image to be programmed.

author: nockieboy
author_rank: Super Contributor
timestamp: December 08, 2017, 06:19:37 pm
content: Quote from: Ian.M on December 08, 2017, 04:49:35 pmYeah, I see the wisdom in adding daughterboard mounting holes to the motherboard - you never know what you might want to add in future to the processor socket.Quote from: Ian.M on December 08, 2017, 04:49:35 pmAh - hadn't thought of that... the random nasty power-outages mid-way through writing the new boot block etc.Quote from: Ian.M on December 08, 2017, 04:49:35 pmYeah it's an added expense, but a necessary one I suppose if I'm going to go the route of being able to program the FLASH in-circuit. Stupid question time - could the FLASH still be written to (to fix the previous corrupt boot block) if its ~CS pin is held high, I wonder? I suppose it wouldn't be a problem if it couldn't be - I could just copy the necessary program to RAM from the backup ROM and switch it out again, making the FLASH ROM active and then updating it with the new boot code..

author: C
author_rank: Super Contributor
timestamp: December 08, 2017, 07:48:44 pm
content: If you think ahead some things get easer.You have a MMU that can access a large area of memory.You could have a dip switch between the Flash Rom's WR pin and system, a hardware write protect.By using a 138 to decode which chip, you could have many flash roms in the system. You can then change which is used for power-up boot by changing which connection of 138 is used for CS.This is keeping it simple.

author: C
author_rank: Super Contributor
timestamp: December 08, 2017, 09:38:37 pm
content: nockieboyThink for a bit of starting over or someone else starting to make a copy of what you have.Trying to use Grant's design has caused you all kinds of problems.Some comes from using small often costly memory.As you know now, the cost of new 512k byte memory is cheap.It is not that hard to connect an address line high or low on a breadboard.You can use a DIP switch to do this and be able to change it just by changing the switch.So Grant's design using a larger Rom could have had many things in the rom at a change of a switch.You could have played with many different rom based z80 systems with just a switch settings change.One switch setting could be CP/M with ROM & RAM disks.The needed CP/M programs could have been put on ROM when the rom was created.Grant went to some work to make a crippled system that is hard to upgradeWhen basic system was running, a 273 could have been added to reduce the need to change dip switch settings.A 374 could have been added to read a dip switch.This can add many different modes for system software. One of my systems uses a dip switch to select what drive to boot for system. This system could boot from 8, 5 1/4 | 3.5 disk drives as well as SCSI and network, a nice important switch.Your MMU then becomes a simple upgrade.When you added MMU to system, you would just remove some connections from dip switch or 273 and connect to MMU outputs.In addition to the 273 above changing address lines of Memory chips, it or a second 273 could give you a status output on LED's. Makes testing a lot easer.Now think of what the above isA working CP/M system with RAM & ROM disks;A CP/M program that can send or receive HEX files via console would let you transfer data to/from PC.Data could be to/from ROM or CP/M files.A terminal program on PC that knows a file transfer protocol could then be used to transfer files, removing need to convert to HEX on PC.The un used console port can then be used.With a working CP/M system, there exists many programs to cure problems.A. It was not uncommon to use console port to send/receive programs or data files.B. It was not uncommon to use a second port to connect to a different system and send/receive programs or data files.So to summarizeWith a working computer, it is easer to get a second computer running.It can be easy to get a second copy of a computer running with just a little planning ahead.ONE is a bad number.For Z80 having a switch or jumper change to have a second choice for power-up book makes things easer. It is not hard to have two flash roms in the system and keep one write protected with hardware.Simple would be flash rom's WR pulled high with a resistor & dip switch to connect system WR for each flash rom chipWith Z80 able to read/write Flash Rom it is not hard to have an image stored on PC.Keep in mind that some things are just easer to have Z80 do the job then the PC.You are working on CP/M BIOS. One small function is write sector or block. You will be reading/writing blocks of ram. Small change to have a Ram disk. An it's a second small change to have a ROM disk.You can have CP/M use part of chip and have your bios capable of writing any area of chip.When you can read/write blocks of a rom/ram you can then use CP/M format command to create a working disk.With good foundation steps it becomes easer to expand.

author: nockieboy
author_rank: Super Contributor
timestamp: December 08, 2017, 10:24:22 pm
content: Quote from: C on December 08, 2017, 09:38:37 pmThat's the one thing I haven't had any time to look at yet. At the moment, I have absolutely *no* idea whatsoever how CP/M handles reading/writing to disk. I'm going to have a go at writing some routines to handle programming sectors of the FLASH ROM first as a step towards getting In-Circuit Programming of the ROM up and running.Once that's working and I've got CP/M 3 up and running, I can start looking at getting it working with RAM/ROM disks. The CP/M 3 setup is stalling at the moment as I'm having difficulty working out exactly what I need to do with the CP/M 2.2 BIOS to get it working for CP/M 3, but hopefully it won't take me too long to work it out.

author: C
author_rank: Super Contributor
timestamp: December 08, 2017, 11:44:58 pm
content: Break it down into simple steps.CP/M3 has some tools to make this easer. You should use them as they can create some of the data structures that CP/M3 needs an uses.Step one is to modify your current CP/M2 BIOS code to work with CP/M3 tools and code.Your source should assembly properly using CP/M3's relocating assembler.When you have this, modify your BIOS source to be compatible with CP/M3's changes.When you have this working you have a non-banked CP/M3 system.This is a good point to test and get working RAM & ROM disks in banked memory.When you have this working then add bank control to CP/M3Now you can work on modifying your BIOS to work banked.=====Your current CP/M system is just using 64k of RAMYou know your Z80 can read and write RAM.Simple CP/M wants to read/write 128 byte blocks on storageStart with a 16K ram disk for your CPM.Ram disk = 16K total with 128 byte blocks or sectors.Your CP/M programs will end up in your BIOS at top of Z80's 64k memory.Your code will need to1. move data to/from a buffer in high memory BIOS.Source or Destination will be in current 64K memory.The other will be storage, the ram drive.so if write Move source ram to bufferbank swapif write then move buffer to RAM disk sector.if read then move from Ram disk sector to buffer.bank swap backif read then move buffer to ram.CP.M data structures tells your code all it needs to know.A sector is 128 bytesRead/writewhere in Z80 64k memory for 128 byte blockwhat sector, track, drive.If you pick good numbers your code gets easer.Using 128 sectors a track lets you use track value to select what bank of 16kThis is fine if you do not need to put os system before the directory on disk.Best to use a power of 2 for sectors per track.Using 64 sectors per track will put one bit in track value that is not needed for bank select. So each power of 2 smaller tracks per sector value is from 128 adds a bit not needed for bank select.With raw read/write, CP/M's format code turns it into a CP/M disk drive.CP/M's put system turns it into a system diskWhen you get this working, expand drive to have more then one bank used.When you get to this point, a swap from ram to rom gives you a read from rom but no CP/M directory.Adding the Flash Rom's software write protect code for writes then gives you a working disk stored on Flash Rom.Simple steps that you can code to test for proper operation.

author: nockieboy
author_rank: Super Contributor
timestamp: December 09, 2017, 11:15:11 am
content: Okay, quick question regarding the hardware ROM write enable - will this work?The idea is that the ~WE pin is held high, unless the switch is closed when the ~WE is pulled low and the warning LED illuminates. My electronics skills aren't great, so I thought I'd just check to make sure this would work as intended?

author: Ian.M
author_rank: Super Contributor
timestamp: December 09, 2017, 11:36:06 am
content: No. /WE needs to be driven by the Z80 /WR signal (probably buffered due to fanout limitations). Put the switch in series with the signal with the pullup resistor on the FLASH side of it. If you want an indicator LED, use a DPST switch and use the other pole for the LED.As an alternative, if you need to mount the switch off-board, or must use a SPST switch, insert an OR gate in line with the /WR signal, and supply a logic level from a switch to the other input. The extra propagation delay is preferable to running a fast logic control signal to a front panel switch and back. You cant wire the switch as you have drawn as the LED will prevent the level going low enough for a valid logic 0. Move the logic takeoff point to the LED cathode and a 4K7 resistor across the LED to fix it.

author: nockieboy
author_rank: Super Contributor
timestamp: December 09, 2017, 03:21:02 pm
content: Right, so based on Ian.M's feedback I've come up with the below:... but I have no idea where or how to wire up a warning LED with this arrangement?The switch type I'm using isn't because of any particular reason, its just that I have a few of these knocking about in a drawer.

author: C
author_rank: Super Contributor
timestamp: December 09, 2017, 05:24:24 pm
content: To get better at this you need to understand small parts and then put them together into something that works.Gain some knowledge.First look at drawing before this with Led.What is the voltage at top of led ( D1 pin 2 ) with switch opened and closed?What is logic Low voltage range for /WR pin of ram?What is logic High voltage range for /WR pin of ram?Now re-read the last part of Ian.M's post again.Now dig into lan.M's post an you have some answers to last drawing.Hint, logic is logic, output of switch is a logic output.Now last drawing.Question is "do you trust your switch and what happens if it has a poor connection?"Look at what you want to happen at U4 pin BIf that connection from S1 pin C1 comes loose, what is at U4 pin B?You have all the answers you need to answer your question from Ian.M's post.Now go a step further and change how switch is connected.Wire the switch with C1 connected to ground.If you understand Ian.M's post, this is a small change.Now what happens when connection to U4 pin B gets disconnected or switch fails?Do not make it hard, take simple steps from first drawing to improversion of last drawing.Start here in postQuote from: Ian.M on December 09, 2017, 11:36:06 amYou should know answers to my above questions if you go step by step changing circuit as lan.M suggests.Understanding now will save you time later.Now continue reading lan.M's post.

author: Kilo Tango
author_rank: Regular Contributor
timestamp: December 09, 2017, 06:11:02 pm
content: How about using the HD64180 ?. it already has an MMU giving access to 512K of memory plus other facilities. It was marketed as a "Super Z80" and sold by Zilog as the Z180. You can still find them :https://www.ebay.com/itm/Hitachi-64180-Kits-HD64180-MPU-TC551001-128K-SRAM-W27C020-EEPROM-DIP32-/161337103516An example of its use is athttps://www-users.cs.york.ac.uk/~pcc/Circuits/64180/doc.htmlKen

author: nockieboy
author_rank: Super Contributor
timestamp: December 10, 2017, 11:42:21 am
content: Quote from: Kilo Tango on December 09, 2017, 06:11:02 pmThanks Ken - but the reason I haven't gone for a more modern processor / microcontroller is because it defeats the purpose of doing all this in the first place - to build something similar in capability to my first ever computer, and maybe learn something about electronics at the same time.Quote from: C on December 09, 2017, 05:24:24 pmI feel as though I'm groping around for solutions here, C, I'll admit. I don't know whether it's because I've misread what Ian.M and you have written, or if it's because I just don't grasp how it all works.Here's the latest version, based off of what you've explained and a re-reading of Ian.M's post:It's probably entirely wrong but, if it's not, how does the LED not light up when the switch is open? Surely it's earthed via U4:B? And what is the purpose of the 4K7 resistor in parallel with the LED?

author: David Hess
author_rank: Super Contributor
timestamp: December 10, 2017, 12:54:36 pm
content: Quote from: nockieboy on December 10, 2017, 11:42:21 amThe 4.7k resistor pulls input U4:B up fully preventing the LED from lighting up. Open TTL inputs do not really require pull-ups but they are a good idea.

author: C
author_rank: Super Contributor
timestamp: December 10, 2017, 01:13:26 pm
content: Your last will work!The proper connection for the 4K7 is S1 C2 to +5VQuoteFirst U4 B is an input, as such very little current can flow out, it is high resistance.A poor way to think about it, when you put your volt meter across the switch does the led light?Meter is high resistance.LED's are very poor diodes.You get to thinking that diodes are great, current flows in one direction and nothing in the other, NOT THE CASE.As the voltage across diode increases a small current flows until at some point the current starts increasing fast with little change in voltage.LED's have a very high Vo that changes by type and color of led.So looking at your last,You remove the switch and your are write protected.If you put the 4K7 resistor close to U4 B then you could even have LED get disconnected and still be in write protected mode.

author: glarsson
author_rank: Frequent Contributor
timestamp: December 10, 2017, 02:30:23 pm
content: Quote from: nockieboy on December 10, 2017, 11:42:21 amThen why all this talking about flash memory and extreme amounts of memory? Imagine that the memory cost is about 5 UKP per kilobyte static RAM and build with what you "can afford".

author: nockieboy
author_rank: Super Contributor
timestamp: December 10, 2017, 06:34:30 pm
content: Quote from: glarsson on December 10, 2017, 02:30:23 pmSimilarin capability. If I was going for that level of fidelity, I'd be trying to duplicate my old computer chip-for-chip. Using something like a Z180 (or whatever) with a built-in MMU, timer and I/O would mean I would be just plugging a couple of chips together to get a working system. This way I'm learning all kinds of stuff while I'm going and learning how toexceedthe spec of my originalAmstrad CPC464in places (like memory size and clock speed currently.) I'm doing the things I wanted to but could never afford to do as a kid (and with information resources like the internet with easy datasheet access, tutorials and forums like this one, that never existed back then.)

author: nockieboy
author_rank: Super Contributor
timestamp: December 11, 2017, 09:59:32 pm
content: Quote from: C on December 10, 2017, 01:13:26 pmIt certainly does, C!I can now program the ROM without having to remove it from the breadboard - I've impressed myself with how smoothly it went!I thought I had the ROM iteration down to a quick turnaround before, but now I can just type a command, paste the new ROM Intel Hex into the terminal window and watch as it buffers the data, erases the appropriate sector on the ROM and then writes the new data! It even does it more quickly that my EEPROM programmer does!I'm using an SST39SF010A, which has software protection against accidental writes, so there's a sequence of up to three address/value writes I have to do which, considering I'm writing to a RAM Area mapped to an arbitrary ROM Bank, involves some card-shuffling with the MMU to get the write sequence to the correct addresses on the ROM - but it works!

author: nockieboy
author_rank: Super Contributor
timestamp: December 11, 2017, 10:16:55 pm
content: Quote from: C on December 07, 2017, 09:05:35 amYes, that's exactly what I've done. Couldn't be fussed messing around with switches and LEDs in the end when the ROM has software protection against accidental writes and (for the most part) is hidden behind the MMU and not always mapped into view for the Z80 anyway.Quote from: C on December 07, 2017, 09:05:35 amYes, I'm now quite intrigued about the idea of a ROM drive seeing as how quickly writing to (and obviously reading from) the ROM is done. This little sub-project has been a pleasant diversion from my CP/M 3 BIOS-writing woes, though - I need to get back to that and, in the process, no doubt I'll learn a bit about how drives work in CP/M and be better armed to deal with creating a FLASH ROM-drive later...

author: C
author_rank: Super Contributor
timestamp: December 11, 2017, 11:11:56 pm
content: With you being able to write to rom you have a good foundation you can build on.If you have a good copy of Flash Rom, you couldProgram the ROM using any programmer and if hardware was working, off you go with a working Z80Now if a part of that Flash Rom looks like a CP.M disk thenYou could boot to CP/M2 or CP/M3If that CP/M disk hasCF Tools you could create a new CFCard disk driveFormat new card & put on CP/M bootIf that CP/M disk hassome comm programs, you could just run a program to send/receive via one of the many file transfer protocols.A BBS program would let you really go to town making it easy to move files from Z80 <-> PCCP/MYou should have a copy of all Digital Research CP/M3 files on your Z80.By using the relocatable macro assembler that comes with CP/M3 you can have files that work with rest of CP/M3Run your current assembly files through the rmasm to see what you need to change if you are going to use PC to edit the files.For small edit changes it could be faster to just startup WordStar3.3 on Z80.Make Grant's code your own.Grant has many different source files that only have a small change. This is hard to maintain. That rmasm assembler program for CP/M3 will let you remove this problem. Some will still work with PC assembler.Think of thisMy Z80 could have many types of disk drives attached, many formats for floppies. Seldom did I need to change CP/M to work with these.For my system's standard format floppies it would look at what was in the drive and make the needed changes in bios & CP/M.You can make this easer by having a data table on each drive at a fixed spot.If is not hard to have first Z80 instructions on a boot track to jump over a data table that has information of disk format.For PC's this is the Master boot record at the start of drive.So do not make getting CP/M3 hard.what CP/M3 wants is a table that has entry points for each character I/O device. It really wants a driver for a SIO and wants the driver to work with many SIO's.The same is true of storage. You just need a few chunks of code that will use CP/M3's data tables to find out what to read or write.One chunk of code to work with RAM/ROM disks.One chunk of code to work with CFcard drives.Where CP/M2 left a lot of work on BIOS programmer, CP/M3 does a lot more.CP/M3 can do the blocking of 128 byte sectors into what the storage needs.You driver gets simple,move this data <-> storage sector.The What is in the tables but to make it easer to change from CP/M2 will still call set DMA, set drive, set track, ....So just make a quick hack to Grant's to get it working. Then start making changes that will let you tap into CP/M3's full capabilities.With CP/M'3 program that can build the CP/M3 drive tables, it could be easer to just skip the CP/M2 interface to bios and just jump to CP/M3's bios interface.CP/M lets you have 16 drives. You could keep 8 working with Grant's drivers and 8 working with your drivers so that you can test your driver's functions.A Drive is just chunks of storage that you have to work at a chunk of bytes level. Called a sector of which you put a bunch of sectors on a track and a bunch of tracks makes a drive.

author: alank2
author_rank: Super Contributor
timestamp: February 26, 2018, 06:13:37 pm
content: Let me ask a question - maybe I am missing something.With the 74LS670 being talked about on page 1. Is there any reason you can't parallel two of them and have an 8 bit register? The first one would get D0-D3 and then second one would get D4-D7. They would share A0/A1/BANK/A14/A15.I ask so one could have A14/A15/A16/A17 on one of them and A18/A19/A20/A21 on the other. Then you could access up to 4M for each of the 4 16K banks at 0x0000, 0x4000, 0x8000, and 0xC000, is that right?

author: Ian.M
author_rank: Super Contributor
timestamp: February 26, 2018, 06:47:56 pm
content: Yes you can do that. See reply#29onwards in this thread.However it is sub-optimal for a fast Z80 system due to the high propagation delay of a '670 compared to '486 era cache RAM which can be found in speed grades from 15ns cycle time down to as little as 10ns, so has considerable advantages for a MMU address translator.N.B. In a twin '670 MMU, to keep the software reasonably simple, you need to be able to write the mapping for a block to both simultaneously. i.e. to map a block to any page set it up so you just write the block number to the mapping port. The easy way to do that is to decode a block of four I/O addresses, + Z80 /WR to drive /WE, connect the WA and WB pins to A0 and A1, and connect the Dn inputs of each to one nibble of the databus. Don't forget the pullups and logic to enforce a default mapping for the boot ROM until the MMU has been set up by your code, then enabled by taking /RE low.

author: alank2
author_rank: Super Contributor
timestamp: February 26, 2018, 06:53:47 pm
content: Ian.M given speed concerns - what speed of SRAM would you need for 16 or 20 MHz Z80? Digikey has sram in 10ns, 12ns, and 25ns.I am thinking of just doing a very simple bank where the lower 48K is bank 0 or bank 1 and the upper 16K is common. Selected with 1 signal and using 3 nand gates (2 in series). The NAND used to decode a14/a15 to decide to keep the top 16K common. With HC or AHC logic, would that limit the Z80 max speed to below 16 or 20 MHz?

author: C
author_rank: Super Contributor
timestamp: February 26, 2018, 07:20:40 pm
content: Give your self a cookie.At power-up contents of 74LS670 is unknown.Disabling output and using pull up resistors puts top 16k of 4m space repeating 4 times.A 74ls273 can be reset at power-up and one output can control output of 74LS670 leaving 7 for other uses.This uses 5 output ports total for control ( 1 74Ls273,4 74ls670)Power-up4 writes to set 74LS670 and enable. now have full control.Big problem with 74LS670 is address input to output delay.Other option is cache ram chip that is faster then 74LS670.Down side is A14 & A15 of Z80 must be directly connected to cache ram. This makes Z80 output more complicated but due able. You still need an additional chip to connect Z80 data bus to cache to write new map & proper logic to control.Note a cache ram is just a very fast static ram that gives an output after ram delay.One 138 decodes 4m into 8 512k spaces.Reading other posts sense started this.Memory timing becomes very tight and tighter getting up to 20M.Think you are starting to see that fancy/powerful can be simple.Note that one or more of the 512k spaces if not used gives future expansion.One could be dual port.

author: alank2
author_rank: Super Contributor
timestamp: February 26, 2018, 07:33:00 pm
content: Is the CD74HC670 faster in terms of speed?http://www.ti.com/lit/ds/symlink/cd74hc670.pdf

author: C
author_rank: Super Contributor
timestamp: February 26, 2018, 08:20:52 pm
content: 74LS670[http://www.ti.com/lit/ds/sdls193/sdls193.pdf/url]there is a drawingRead Select that appliesAddress changes and output is delayed with two values tphl tplhFrom what I see if labels match between datasheets then LS is faster.

author: Ian.M
author_rank: Super Contributor
timestamp: February 26, 2018, 08:46:06 pm
content: For the full discussion of a possible 486 cache ram based MMU seehttps://www.eevblog.com/forum/microcontrollers/retro-z80-project-memory-layout-and-software-management/msg832195/#msg832195(reply#112 onwards, + some stuff back at reply #34)

author: alank2
author_rank: Super Contributor
timestamp: February 27, 2018, 05:57:23 pm
content: I've got another idea for a very simple MMU.Something provides signals for bank0, bank1, bank2, bank3 such as a shift register. Then you use OR gates to switch the lower 32K and keep the top 32K as a common area:a15 from z80 OR bank0 --> a15a15 from z80 OR bank1 --> a16a15 from z80 OR bank2 --> a17a15 from z80 OR bank3 --> a18When a15 is low, then the a18/a17/a16/a15 come from bankX. When a15 is high, a18/a17/a16/a15 are all high.

author: C
author_rank: Super Contributor
timestamp: February 27, 2018, 08:37:09 pm
content: The problem with logic is time delays. This can lead to glitches down stream.Simple question, do all your mmu outputs change at the same time?Look at the logic inside a 74xx138 at the amount of effort to remove glitches. Still you get best results with care using the inputs and what is connected.Your or is a version of a switch

author: alank2
author_rank: Super Contributor
timestamp: February 27, 2018, 08:43:19 pm
content: I plan to drive bank0/1/2/3 from AVR I/O pins and they will only change when changing the bank, else they will be unchanging.It will need to be able to respond to A15 changing very quickly, but it is a single OR gate to go through before the memory pins.

author: alank2
author_rank: Super Contributor
timestamp: February 28, 2018, 02:06:14 pm
content: How fast does it have to be? Enough that the memory can stabilize before its outputs are sampled, right?Last night I was thinking about the typical four 16K banks where each bank can be selected from any of 32 pages in a 512 K SRAM.For each bit (A18/A17/A16/A15/A14) you need a multiplexer to selection between 4 possible inputs. A fast multiplexer like 74AC153 it has a prop delay if <7ns. You feed it A14 and A15 and it will select the proper bit out of four for that signal. Instead of supplying the (5x4) 20 bits you can use 3 shift registers to supply them. The page setting bits don't change often. It just needs to be able to respond to A14/A15 quickly, correct? This would need 3 dual multiplexer IC's and 3 shift registers and could b changed with SPI.

author: C
author_rank: Super Contributor
timestamp: February 28, 2018, 04:00:00 pm
content: First some things to keep in mind.For I/O, some CPU's like 68k have memory mapped IO.Z80 has option of memory or i/o space for i/o.Some day you might want to expand the Z80. If you do not have space it gets very hard to expand. For memory you have un-used memory space or memory you can disable.There is a difference in microcontroller attached hardware and microprocessor.Think of big picture1. Z80 needs to update memory map.2. Z80 uses mapped memory.#2 memory accessIf the Z80 was working with 100ns memory and you add a MMU that takes 15ns you will probably need 80ns or faster memory.You want some ns between them to get stability.That Z80 timing spreedsheet I suggested will let you get the numbers.Many different ways to do MMU, it's the result that counts.The 74xx670 combines three major parts.A selector to write data.The dataA selector to read data.Your 153 is selector to read data in separate chips. You could think of two being in one 74xx670#1 Write Data.With Z80 using out instructions to change map, the map is active at end of out instruction.Look at AVRThe Z80 requests map change and has to wait for AVR to make the change.To be fair with 16k blocks being mapped into 48k banks this could take 6+ instructions,. one to read mad data from memory and one out repeated three times.This is 8 bits per block, at 4 bits per block you have 4 instructions.You are talking of using SPI which I think can be clocked at 16m.This sets the max for data move at 500ns a byte.AVR still needs to get request to change memory and start pumping it out SPI.Best for AVR is if Z80 caused and interrupt to AVR.AVR reading a byte from Z80 and here I think two bytes more likely.Computing what request and then outputting map.The big move to and from CPM's TPA will be blocks of 128 bytes.A fancy bios might use the 16k map capability to put source in one bank with dest in second bank while making the move.This fancy method would probably use three map changes.The simple is move from TPA to common and then to bank, a possible larger bios common. This is still two map changes.Worse case would be something like character I/O where bytes are movedSo yes mux or switches like 153 have been used for map.Some systems had a chain of these but most were not trying to get max speed.You talked about high speedLook at spec for /mreq and note it changes with the CPU you have. A 20m z80 running at same speed of a slower spec Z80 will be faster./Mreq 8m = 100ns, 10m=75ns, 20m=25nsThese are pre-computed values that are not complete.The actual address can be before with some time or after mreq goes low.Data has to be valid at proper time.You do not know if it's a read or write until the signals go low.The numbers have to work properly with a little extra time or you get a CPU that works randomly.

author: alank2
author_rank: Super Contributor
timestamp: March 01, 2018, 12:19:45 am
content: C - Thanks for the detailed reply!

author: alank2
author_rank: Super Contributor
timestamp: March 01, 2018, 02:24:31 am
content: How are these control signals driven? (WAIT, INT, NMI, BUSRQ, RESET)I've looked at the Z80 Big Board schematics and they show a 10K pullup on WAIT/NMI/INT/BUSRQ.Since multiple devices might pull down BUSRQ, do they use an open collector type of output? On my AVR that might be HiZ or Output LOW. I'm wanting to drive BUSRQ with the output of a 74AHC74 flip flop which doesn't have an open collector output. I'm assuming it will drive high or low. How should I make that work with BUSRQ?

author: C
author_rank: Super Contributor
timestamp: March 01, 2018, 02:46:05 am
content: By driving these pins with open collector gates you have a wired OR. With out this capability you have a hard time expanding.With a wired OR you can add more outputs to drive these pins.If you connect normal logic to Z80 input, have some place that has a pull-up and will create the signal.Some use a Schmitt-Trigger Input gate to drive the Z80. Advantage is faster change on Z80 pin, bad is the added delay.

author: alank2
author_rank: Super Contributor
timestamp: March 01, 2018, 03:01:31 am
content: What is the best/easiest way to have the 74AHC74's output seem like an open collector to the Z80? Use a schottky diode?

author: David Hess
author_rank: Super Contributor
timestamp: March 01, 2018, 03:23:15 am
content: Quote from: alank2 on March 01, 2018, 03:01:31 amA schottky diode or even a small signal switching diode usually works fine. An NPN transistor driven at its emitter with a base resistor to the positive supply can be used to make a millivolt drop diode. A low threshold n-channel MOSFET can do the same thing.