• Please review our updated Terms and Rules here

Intel 80186 Memory Chip Select and Memory Map help!

80186 Enthusiast

Experienced Member
Joined
May 18, 2023
Messages
53
Hello VCF, I need some help with an Intel 80186 Computer project I am designing. A while ago, before my reddit account got suspended, I made This Post on the r/beneater subreddit. A user replied to my post saying "To add 1MB of Memory you need two 8bit 512K chips (lower, upper) and connect them by A0/BHE and the other pins."

Since I do want 1MB of RAM for this project, how do I include a ROM?

If I have 2 512k SRAM ICs for the 1MB of ram, how would the 80186 find code to execute? or was that reply talking about 1 512k SRAM and 1 512k ROM chip to create 1MB total memory?

However, if I do use 2 512k SRAM chips, is there a way to add an ROM chip with the x86 code, or is the Memory Map just full of RAM now?

Unlike what that Reddit Post says, I no longer want to create an PC-Compatible Computer with the 186, I'll code my own OS for this Computer. I'll create another post about this project when I have an idea on what to do with the Memory Chips.

Any help, information and advice will be thanked in advance! Thank you for Reading!
 
See this document, specifically section 8.1. UCS is programmed at reset for the uppermost 1K of memory. You didn't say which 80186 you're using--there are some significant differences between, say, the original 80186 CLCC and an AM80186ER or even an Intel 80186ED.
I much prefer the NEC V50 for this kind of work--the peripherals work more like standard PC ones.
 
Last edited:
See this document, specifically section 8.1. UCS is programmed at reset for the uppermost 1K of memory. You didn't say which 80186 you're using--there are some significant differences between, say, the original 80186 CLCC and an AM80186ER or even an Intel 80186ED.
I much prefer the NEC V50 for this kind of work--the peripherals work more like standard PC ones.
For the start of this Project, I will use a 80c188XL20. But later down the road, I'll upgrade to a C80186-6 CLCC. I don't have the 80c188XL yet, but I do have a C80186-6 and a socket for it.

I do not wish to create a Computer that's even remotely similar to a PC, the Computer I am developing will be similar to a Commodore 64/ 128 with a focus on adding somewhat modern features like reading data off of an SD card. Of which, I'll do with a 82C55a PPI, similar to what someone did with a 6502, 6522 and a Micro SD Card reader.
 
I do not wish to create a Computer that's even remotely similar to a PC, the Computer I am developing will be similar to a Commodore 64/ 128 with a focus on adding somewhat modern features like reading data off of an SD card. Of which, I'll do with a 82C55a PPI, similar to what someone did with a 6502, 6522 and a Micro SD Card reader.
That's a strange choice. But whatever floats your boat. I was part of the pre-release guinea pig group of the 80186 back in around 1981-82. This was the product. The 186 and 286 came out at about the same time.
 
As I see it, you have two choices:

You can use the chip select pins of the 80186; in that case, you'd need to design a boot ROM that will fit in the top 1K so it's ready to run at power-on, and provides enough functionality to define the rest of the memory map before handing over to code outside that safely mapped range. There may be some mild hairiness with that. It looks like the standard chip select logic offers a maximum of 256k for the "low memory" select, and no easy way to make a single select for a range with gaps in it. So you'd likely have to combine a couple selects for the big RAM chips.

Or you can ignore the 186's chip-select features and build your own logic-- either a few gates or a PAL/GAL. You could probably put together a pretty simple truth table that converted your desired combinations of high address pins into specific chip selects. This gives you nice flexibility-- you can easily enable a 512k chip wherever you want, and you can make a single select signal that's active on disjoint address ranges.

For example:
* A19 low alone matches the entire lower 512k, it's an obvious match for "use it for the lower RAM"
* A19 + A18 + A17 all high matches the top 128K, so you can have a ROM covering E000 and F000
* A19 high + A18 low + A16 low matches 512k to 576k and 640k to 704k-- a simple example of a "disjoint" selection.

Notice that either way, you will want to think about holes in the memory map for things like external memory mapped devices (like video controllers).
 
As I see it, you have two choices:

You can use the chip select pins of the 80186; in that case, you'd need to design a boot ROM that will fit in the top 1K so it's ready to run at power-on, and provides enough functionality to define the rest of the memory map before handing over to code outside that safely mapped range. There may be some mild hairiness with that. It looks like the standard chip select logic offers a maximum of 256k for the "low memory" select, and no easy way to make a single select for a range with gaps in it. So you'd likely have to combine a couple selects for the big RAM chips.

Or you can ignore the 186's chip-select features and build your own logic-- either a few gates or a PAL/GAL. You could probably put together a pretty simple truth table that converted your desired combinations of high address pins into specific chip selects. This gives you nice flexibility-- you can easily enable a 512k chip wherever you want, and you can make a single select signal that's active on disjoint address ranges.

For example:
* A19 low alone matches the entire lower 512k, it's an obvious match for "use it for the lower RAM"
* A19 + A18 + A17 all high matches the top 128K, so you can have a ROM covering E000 and F000
* A19 high + A18 low + A16 low matches 512k to 576k and 640k to 704k-- a simple example of a "disjoint" selection.

Notice that either way, you will want to think about holes in the memory map for things like external memory mapped devices (like video controllers).
You have given me a lot to think about, But if I make an address decoder that's similar to your example, Can I still use the Memory Chip Select Pins to add more RAM IC's to expand the amount of RAM I have?
 
There's not really a point in doing so. The 80186 only has the 20-bit address space, so you can only reasonably cram 1MB into it with straight addressing.

If you wanted to do something more complex, like bank switching, you would need some way to engage that, and it would likely be its own kettle of fish; I doubt the canned Memory Chip Select would help there, because it's only based on the current address. It might be possible to gimmick it a little-- changing the mapping on the fly when you wanted address block X to Y to go to the "other bank" memory ICs, but you're still stuck with a lot of the limitations.

I think the normal way to handle bank selection would be to add some additional selection logic. For example, you could set up some latches (maybe wired up so that a write to a specific I/O port sets them) and extend the chip select "formulas" to incorporate them.

A simple example:
Chip 1 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" low + "Bank Select Latch B" low
Chip 2 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" high + "Bank Select Latch B" low
Chip 3 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" low + "Bank Select Latch B" high
Chip 4 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" high + "Bank Select Latch B" high

That would allow four 128k slots, each mapped between 512k and 640k, so you can now work with 384K more memory. If you're doing your own software, that's manageable, but obviously no off-the-shelf code will know how to use it effectively.

It might be tempting to bank-switch the bottom 512k, because it's easy to map (just "A19 low"), but it's riskier because you need the interrupt table at the bottom of memory to be coherent, so you'd have to inscribe it in each bank before you turned on any interrupts.
 
There's not really a point in doing so. The 80186 only has the 20-bit address space, so you can only reasonably cram 1MB into it with straight addressing.

If you wanted to do something more complex, like bank switching, you would need some way to engage that, and it would likely be its own kettle of fish; I doubt the canned Memory Chip Select would help there, because it's only based on the current address. It might be possible to gimmick it a little-- changing the mapping on the fly when you wanted address block X to Y to go to the "other bank" memory ICs, but you're still stuck with a lot of the limitations.

I think the normal way to handle bank selection would be to add some additional selection logic. For example, you could set up some latches (maybe wired up so that a write to a specific I/O port sets them) and extend the chip select "formulas" to incorporate them.

A simple example:
Chip 1 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" low + "Bank Select Latch B" low
Chip 2 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" high + "Bank Select Latch B" low
Chip 3 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" low + "Bank Select Latch B" high
Chip 4 select = A19 high + A18 low + A17 low + A16 low + "Bank Select Latch A" high + "Bank Select Latch B" high

That would allow four 128k slots, each mapped between 512k and 640k, so you can now work with 384K more memory. If you're doing your own software, that's manageable, but obviously no off-the-shelf code will know how to use it effectively.

It might be tempting to bank-switch the bottom 512k, because it's easy to map (just "A19 low"), but it's riskier because you need the interrupt table at the bottom of memory to be coherent, so you'd have to inscribe it in each bank before you turned on any interrupts
So either use an Address Decoder or use the Memory Chip Selects? Is that correct?
Though, for my system (as you've said previously) I will be using an address decoder to allow for more flexibility with memory map ranges. Before I make a Truth Table, I'll learn how each Address Pin works and learn how to write code that'll use each Address Pin I'll use for the decoder.

I have another question, why is A19 used to assign a 512k SRAM chip to the lower half of a memory map? Shouldn't that assign the 512k of memory to the top because A19 is the Most Significant Bit (MSB) of the Address Bus? And if I don't need the 512k of ram to be at the very bottom, would I use A18 instead? And if I do use A19 to put the 512k of RAM at the bottom of the Memory Map, Would the Interrupts behave normally even if I did hard code them into the Memory Banks? Because Interrupts will be extremally important for the 80186 System I'll be creating.
 
A19 will be low in all addresses below 0x80000, the lower half of a 1Mb memory map.

If the chip select is active low (as it is on the AS6C4000, at least), that means that you can wire the A19 pin directly to the chip select of the lower 512k RAM chip, so it's super easy. When you're accessing an address below 512k, A19 will be low, and the chip will be enabled.

Addresses over 512k tend to be more complex because you're likely only going to want to select a chip in tighter windows, so you could route, say, the top most area to a ROM.

The thing about interrupts is mostly that there's a table of vectors at the bottom of memory. If you call, say, "INT 0x01", it looks at memory location 0x00004 to find the segment and offset for the IRQ handler.

If you try to bank switch the lowest portion of memory, you just have to make sure that table is in place in every bank, and consistent/correct. This is doable if you set it all up during early boot time, before you start handling interrupts, but it's more delicate than just making a mental note "anything below 0x00400 is off limits."
 
I have another question, why is A19 used to assign a 512k SRAM chip to the lower half of a memory map? Shouldn't that assign the 512k of memory to the top because A19 is the Most Significant Bit (MSB) of the Address Bus?

Back up a moment: do you want RAM to be 8 or 16 bits wide, and are the chips you’re using 8 or 16 bit? The common ASC4008 512kbyte RAMs are 8 bits wide, so unless you want to cripple your 80186 you‘ll need to use a pair of them and understand what that Reddit post was talking about in reference to A0/BHE. In essence the optimal architecture here is two use two of them, one supplying the “even” bytes and the other the “odd” bytes.

Two 512kbyte RAM chips arranged as a 512kx16 bit word memory array is a full 1 Mbyte, filling the entirety of the ‘186s memory map. As long as you don’t care about wasting a little of it this is no skin off your nose whatsoever if you need space for ROM, just set up your decoder so it’s essentially hierarchical; decode the smaller ROM blocks so if you’re in those regions it overrides a “default” chip select (for non-I/O port operations) activating the RAM bank.

I have another question, why is A19 used to assign a 512k SRAM chip to the lower half of a memory map? Shouldn't that assign the 512k of memory to the top because A19 is the Most Significant Bit (MSB) of the Address Bus?

I think you might be a little unclear about how memory select works based on address lines. A19 is “present” in all memory accesses and decoders have to take it into account. The suggestion about using it directly for a chip select is just a cheat often used on really minimal computers. For instance: memory chip selects are usually active on “low”, IE, a zero. So if you’re building a really minimal 8-bit computer and you want half the memory map to be RAM supplied by one chip that’s conveniently an appropriate size you can just wire the highest address line directly to the CE input on the RAM and, bam, whenever you’re in the bottom half of the memory map that chip is selected.

A scheme this dumb isn’t really apropos for a 16 bit chip that does bus sizing, etc, however.
 
Back up a moment: do you want RAM to be 8 or 16 bits wide, and are the chips you’re using 8 or 16 bit? The common ASC4008 512kbyte RAMs are 8 bits wide, so unless you want to cripple your 80186 you‘ll need to use a pair of them and understand what that Reddit post was talking about in reference to A0/BHE. In essence the optimal architecture here is two use two of them, one supplying the “even” bytes and the other the “odd” bytes.

Two 512kbyte RAM chips arranged as a 512kx16 bit word memory array is a full 1 Mbyte, filling the entirety of the ‘186s memory map. As long as you don’t care about wasting a little of it this is no skin off your nose whatsoever if you need space for ROM, just set up your decoder so it’s essentially hierarchical; decode the smaller ROM blocks so if you’re in those regions it overrides a “default” chip select (for non-I/O port operations) activating the RAM bank.



I think you might be a little unclear about how memory select works based on address lines. A19 is “present” in all memory accesses and decoders have to take it into account. The suggestion about using it directly for a chip select is just a cheat often used on really minimal computers. For instance: memory chip selects are usually active on “low”, IE, a zero. So if you’re building a really minimal 8-bit computer and you want half the memory map to be RAM supplied by one chip that’s conveniently an appropriate size you can just wire the highest address line directly to the CE input on the RAM and, bam, whenever you’re in the bottom half of the memory map that chip is selected.

A scheme this dumb isn’t really apropos for a 16 bit chip that does bus sizing, etc, however.
I decided to make a 8-Bit system first, before I make a 16-Bit system. So I'll be using an Intel 80188. I'll make an 8-Bit system first to develop everything I need for the 16-Bit, finalized version Of this Computer which will use an 80186.

Do you know where I can find examples of Address Decoders for the 8088, 8086, 80188 and 80186? I need to avoid only using A19 as the memory chip enable for this project because I want to build something a little more complex.
 
A19 will be low in all addresses below 0x80000, the lower half of a 1Mb memory map.

If the chip select is active low (as it is on the AS6C4000, at least), that means that you can wire the A19 pin directly to the chip select of the lower 512k RAM chip, so it's super easy. When you're accessing an address below 512k, A19 will be low, and the chip will be enabled.

Addresses over 512k tend to be more complex because you're likely only going to want to select a chip in tighter windows, so you could route, say, the top most area to a ROM.

The thing about interrupts is mostly that there's a table of vectors at the bottom of memory. If you call, say, "INT 0x01", it looks at memory location 0x00004 to find the segment and offset for the IRQ handler.

If you try to bank switch the lowest portion of memory, you just have to make sure that table is in place in every bank, and consistent/correct. This is doable if you set it all up during early boot time, before you start handling interrupts, but it's more delicate than just making a mental note "anything below 0x00400 is off limits."
Understood. Do you know where I can find examples of Address Decoders for the 8088/ 80188 and 8086/ 80186 that allow for bank switching? or more complex Address Decoders in general?
 
Understood. Do you know where I can find examples of Address Decoders for the 8088/ 80188 and 8086/ 80186 that allow for bank switching? or more complex Address Decoders in general?

Backing up a bit: do you have at least a rough idea of what you want the architecture of this beast to look like? For at least a rev-1 version of this is bank switching really a thing you need? How much ROM do you actually need to have online, and is it something you want there permanently (IE, are you thinking that you want to have an embedded ROM operating system/BASIC or whatever), or do you want it to bank switch because you want to have the ROM online only at boot and then switch it out so you can have the entire 1MB of RAM available? Or do you want bank switching because you want more than 1MB of RAM? (And if that's the case... are you sure the '186 is what you want? You said you don't care about PC compatibility, so if you want more than a megabyte of RAM there are certainly other chips you might consider, like the 68000 series... or if you're truly mad and really want to stick with segments you could go with the '286 for 16MB of hardware address plus the possibility of virtual addressing up to a gigabyte.)

One downside of the '186 (and '188) if you're looking to build a "as simple as possible" system is that both of them have multiplexed data/address busses, so just like an 8088/8086 system you're going to have to use external address latches and otherwise need a more complex bus than you would for some other CPUs.

You can use the chip select pins of the 80186; in that case, you'd need to design a boot ROM that will fit in the top 1K so it's ready to run at power-on, and provides enough functionality to define the rest of the memory map before handing over to code outside that safely mapped range. There may be some mild hairiness with that. It looks like the standard chip select logic offers a maximum of 256k for the "low memory" select, and no easy way to make a single select for a range with gaps in it. So you'd likely have to combine a couple selects for the big RAM chips.

So far I've just started scanning the manual for the '186, but from what I've seen so far it actually looks pretty straightforward to use the built-in memory selects? If you're willing to live with a maximum of 768K of RAM and 256K of ROM it looks to me is all you need to do is connect UCS to your ROM memory subsystem (If I were doing this 16 bit I'd probably use a pair of 128Kbyte flash ROMs, they only cost about a buck and a half each, for that), and connect LCS and the four MCS lines to an AND gate (a 74HCT30 would do) to create a combined "RAM enable" signal that I'd use as CE for a RAM block made out of two 512Kbyte SRAM chips, as mentioned. At boot time, yes, UCS will only activate the top 1K of the ROM chip, but that just means that the very first block of code in the boot ROM would be the needful to program LCS and UCS to their full 256K ranges and the four LCSes to the maximum 128K block size with a starting address for the MCS block of 40000h. Bam, you're done, as long as you don't mind wasting the last 256K of the SRAM block. (Maybe that would have been a big deal back in the 80's, but these days it's only about $3 worth of RAM, so we can probably live with it.)

Beauty of this system is if this machine is going to have memory-mapped video and you don't need the whole 256K for ROM then just set UCS's block size for however much you *do* need, and that will open up a hole between the LCS/MCS-addressed RAM and ROM where you can use external decoding to address peripherals. Alternatively, if you *really* want to get more of the main memory block back then, again, just set UCS for however much ROM you actually need and use an external decoder to provide a RAM chip select for however much of the 768K->1023K block you want back and feed its output into that AND gate we tied LCS and MCS to. You could potentially even add an external preset/reset latch to control this external block decoding so it's disabled after system reset, thereby allowing you to use more ROM for your BIOS for as long as you want it, but later could be enabled after shrinking the UCS allocation back down to its minimal 1K.
 
If the OP was interested in external bankswitching, the LS612 would have expanded the memory addressing considerably, if bankswitching/page mapping was your goal.
 
If the OP was interested in external bankswitching, the LS612 would have expanded the memory addressing considerably, if bankswitching/page mapping was your goal.

I've looked at that chip before myself for a couple projects I've been vaguely working on, I wish it was easier to source. The low-rent alternative that's at least still in production (but getting a little hard to find too) is a pair of 74LS670s; with 16K pages that's good for 4MB, but only four pages within a 64K window.

That said, I still think it would benefit the OP to better define exactly what they want this system to look like before adding a complex moving part like that into the mix. If the goal is a "Commodore 64-like" small computer it seems like overkill.
 
Back
Top