Introduction

Installing up to 1MB of memory on the IBM PC XT motherboard is a relatively straightforward process, allowing for a maximum of 896KB of addressable storage. This upgrade involves replacing chips that IBM has conveniently positioned in sockets. In my case, I have acquired an old IBM 5155 Portable Personal Computer, which is in exceptional condition and fully functional. I want to upgrade its memory from the existing 256KB to mind blowing 1MB. It’s worth noting that this upgrade can vary depending on the motherboard version, as there were two distinct variants: the 64-256KB motherboard, which requires additional steps, and the 256KB-640KB motherboard, which has a simpler upgrade process. My machine has a 64KB-256KB board installed.

IBM 5155 Portable Personal Computer
IBM 5155 Portable Personal Computer

Bill of Materials (BOM)

Quantity Part Number Component Description
36 Samsung KM41C256P-7 1-bit x 256k CMOS DRAM @ 70ns
1 Lattice GAL16V8D-7LP Generic Array Logic (DIP20)
1 TI SN74LS158N Data Selector / Multiplexer

Additional tools used in this guide:

  • Xgecu TL866II Plus programmer for flashing the GAL
  • ESD wrist strap and mat to protect the DRAM ICs

What is High Memory?

In the realm of vintage computing, understanding high memory is key to making the most of your hardware. The heart of early IBM PCs and XTs, the 8088 chip, can access a vast 1MB memory space, segmented into 16 individual 64K segments, ranging from 0 to F.

IBM meticulously designed the PC and XT hardware to provide the first 640K of this memory space for PC-DOS and user applications, reserving the upper 360K for essential hardware functions like ROM storage and screen buffers. This upper portion of the 1MB addressable space is aptly termed “HIGH MEMORY”. However, accessing it in 64K segments is contingent upon the absence of specific hardware that occupies those segments.

To break it down further, the allocation of the six 64K segments above 640K is as follows:

  • Segment A: Reserved for the fully expanded Enhanced Graphics Adapter (EGA).

  • Segment B: Primarily reserved for the Mono and Color graphics adapters, although it’s seldom entirely available. In some cases, you can reclaim unused space not occupied by screen buffers.

  • Segment C: Designated for the EGA ROM, Hard Disk Adapter, and the 3270 card.

  • Segments D and E: Allocated for expanded memory (EMS, etc.) and several miscellaneous adapters, including the voice adapter card. In the case of the PCJr, this space is utilized for ROM cartridges.

  • Segment F: Reserved exclusively for BIOS and Basic ROM and, as such, is never accessible for user applications or data.

Understanding this segmentation of high memory is crucial for optimizing your vintage IBM PC or XT and ensuring that your chosen hardware and applications can efficiently coexist within this limited memory space.

Installation

On the IBM PC XT motherboard, there’s only one switch block. Most machines label it as SW2, but in some cases, it’s labeled as SW1. I will adhere to the convention and refer to it as SW2 throughout this guide.

Installing HIGH MEMORY (a combination of segments A, C, D, E) on an IBM PC XT that already boasts 640K on the motherboard, the process is surprisingly straightforward:

  • Replace the Original U44 Decoder PROM: Swap out the original U44 decoder PROM with a custom programmed GAL chip. For detailed information on the chip and how to program it, refer below.

  • Upgrade the 64K Chips: Replace the existing 64K chips in the appropriate memory banks with 41256 (256K) chips.

All banks are filled with 41256 chips
All banks are filled with 41256 chips

Caution: Use an anti-static wrist strap and a grounded ESD mat. These old components are very sensitive to electrical discharges.

  • Configure SW2: Set the positions of SW2 switches 3 and 4 to select your desired memory configuration. There is a table below. For commonly used configurations on 256KB-640KB boards, there’s usually no need to adjust the jumpers at E2.

Indeed, it’s as uncomplicated as that!

Please Note:

If your machine lacks any 256K chips from the outset, you’ll also need to insert a 74LS158 chip into the vacant chip socket U84. Additionally, you might need to install a jumper at E2. Both steps are always required for 64KB-256KB motherboards.

E2 Jumper on soldered Header
E2 Jumper on soldered Header
74LS158 in U84
74LS158 in U84

Replacement of IC U44 with a GAL

We are flashing the GAL using a Xgecu TL866II universal programmer and minipro:

[robert@gram U44V2M]$ minipro -p GAL16V8D -w U44V2M.JED 
Found TL866II+ 04.2.86 (0x256)
Warning: Firmware is out of date.
  Expected  04.2.131 (0x283)
  Found     04.2.86 (0x256)

VPP=16V
Declared fuse checksum: 0x2A7F Calculated: 0x2A7F ... OK
Declared file checksum: 0x0000 Calculated: 0xC083 ... Mismatch!
JED file parsed OK

Use -P to skip write protect

Erasing... 0.82Sec OK
Writing jedec file...  3.52Sec  OK
Reading device...  0.19Sec  OK
Writing lock bit... 0.25Sec OK
Verification OK

Here are the GAL16V8 JEDEC, EQN, and LOG files for replicating this setup: U44V2M.ZIP

Since we’ll be inserting a 20-pin DIP into a 16-pin socket, it’s necessary to establish connections between pins 8 and 10 (you can also include pin 9 for convenience) on the 20-pin DIP or on the socket if you opt for a stacked socket configuration. Simply insert the GAL in a manner that aligns pin 1 on the GAL with pin 1 of the U44 socket.

GAL16V8 seated in U44 socket
GAL16V8 seated in U44 socket

Caution: Check if there is a short circuit and trim the overhanging legs if necessary.

These are the underlying equations which control bank selection:

CHIP MEMV2 GAL16V8

;       GAL programming for PCXT U44 Memory expansion.
;       Only the first and third tables of the HIMEMV2 ROM are implemented.

gnd=10 A6=1 A5=2 A4=3 A3=4 A2=7 A1=6 A0=5 A7=19
Vcc=20 Q2=14 Q1=15 Q0=16

@UES Sydex

EQUATIONS

/Q2 =
        /A3

/Q1 =
        A7*A3*A2*A1*/A0 +
        /A3*/A2 + /A2*/A1 + /A7*/A2

/Q0 =
        /A7*A5*/A4*A3*A2*/A1 +
        /A7*A5*A4*A3*A2*/A0 +
        A4*A3*A2*/A1*/A0 +
        A7*A5*A3*/A2*A1 +
        A7*A3*A1*A0 +
        A3*A2*A1*A0

You can include one of the missing implementations mentioned below and adapt them to your system. But be warned, a GAL doesn’t have much memory.

Utilizing HIGH MEMORY

Incorporating HIGH MEMORY into your computing experience offers unique possibilities, but it comes with specific limitations. There are two possibilities how you can make the most of it:

Segment A (640K to 704K) and Segment B (704K to 736K)

These regions cannot be directly accessed by DOS. However, various specialized programs, such as HIRAMDSK, can harness HIGH MEMORY. These programs can use any or all of HIGH MEMORY as a virtual disk (vdisk) and even merge HIGH MEMORY with standard (low) memory to create a robust RAM disk with a capacity of up to 500K.

“Lid Lifter” Programs

Another category of HIGH MEMORY software includes “lid lifter” applications like SET704K and SET736K. These programs adjust the maximum size of the DOS memory region from 640K to 704K or 736K.

Both SET704K and SET736K function as non-resident device drivers, executing their tasks and subsequently freeing up system resources.

Unfortunately, at the time I’m writing this article, I haven’t been able to retrieve these two programs.

Understanding the U44 Chip

At the heart of this system lies a crucial 16-pin chip that securely fits into the U44 socket. U44 itself is a 256 X 4 bit Schottky PROM, meaning it has 256 addresses, with each containing a single hexadecimal digit (four bits) of data. These data bits are organized into sixteen decoding tables, each of which consists of sixteen entries. These tables play a pivotal role in informing the machine about the existence and location of a specific 64K storage segment within the array of memory chips.

A U44 chip is a TBP24S10N PROM
A U44 chip is a TBP24S10N PROM

Determining which table to use involves a combination of settings, namely the E2 jumpers and SW2 positions 3 & 4. Together, these settings contribute to the configuration of the four high-order input bits to U44 (A7-A4). The two jumpers, A7 & A6, select one of four sets of tables, while the switches, A5 & A4, pinpoint the specific table within the chosen set.

Now, as for identifying the particular entry within the selected table that will be used for decoding a specific storage address, this is determined by the four high-order bits of that storage address (CA19-CA16 of the PC address bus). These four bits are routed to the four low-order input bits of U44 (A3-A0).

Each entry within U44’s decoding tables holds one of five hexadecimal values: 0x9 (indicating bank 0 selection), 0xB (representing bank 1 selection), 0xD (signifying bank 2 selection), 0xF (corresponding to bank 3 selection), or 0xE (indicating that the segment is not addressable). By constructing a table with the appropriate values, it becomes possible to decode any combination of 64K and/or 256K storage chips, extending up to one megabyte—provided there are no conflicts with installed adapters and ensuring that no two 64K segments map into the same region of a 256K chip.

However, it’s essential to clarify the last sentence further. In addition to U44’s decoding, PC address bus bits A17 and A16 are multiplexed to each bank of chips. These two bits are responsible for determining which of four regions within a 256K chip a specific segment will be mapped into. Without delving too deeply into technical details, this means that each bank of chips must refrain from containing more than one segment from each of the following four groups: 0-4-8-C, 1-5-9-D, 2-6-A-E, and 3-7-B-F.

To gain insight into the program within the U44 chip provided by IBM, refer to the chart below. Across the top, you’ll find segment numbers (the high-order character of the address), while the numbers on the left side correspond to the E2 jumpers and SW2 positions 3 & 4.

IBM Standard U44 Storage Decoder PROM Program

With both jumpers installed

                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
 Seg# >>>=====>  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
(Up to 4     0 = 9  9  E  E  E  E  E  E  E  E  E  E  E  E  E  E  = 128K
banks of     1 = 9  9  B  B  E  E  E  E  E  E  E  E  E  E  E  E  = 256K
128K chips)  2 = 9  9  B  B  D  D  E  E  E  E  E  E  E  E  E  E  = 384K
             3 = 9  9  B  B  D  D  F  F  E  E  E  E  E  E  E  E  = 512K

E2 jumper 3 to 4 only

                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
 Seg# >>>=====>  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
(1 bank of   4 = F  E  E  E  E  E  E  E  E  E  E  E  E  E  E  E  = 64K
64K chips    5 = F  E  E  E  E  E  E  E  E  E  E  E  E  E  E  E  = 64K
in bank 3)   6 = F  E  E  E  E  E  E  E  E  E  E  E  E  E  E  E  = 64K
             7 = F  E  E  E  E  E  E  E  E  E  E  E  E  E  E  E  = 64K

E2 jumper 1 to 2 only

                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
 Seg# >>>=====>  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
(Up to 2     8 = 9  9  9  9  E  E  E  E  E  E  E  E  E  E  E  E  = 256K
banks of     9 = 9  9  9  9  B  B  B  B  E  E  E  E  E  E  E  E  = 512K
256K and     A = 9  9  9  9  B  B  B  B  D  E  E  E  E  E  E  E  = 576K
2 of 64K)    B = 9  9  9  9  B  B  B  B  D  F  E  E  E  E  E  E  = 640K

No jumpers installed

                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
 Seg# >>>=====>  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
                 =  =  =  =  =  =  =  =  =  =  =  =  =  =  =  =
(Up to 4     C = 9  E  E  E  E  E  E  E  E  E  E  E  E  E  E  E  = 64K
banks of     D = 9  B  E  E  E  E  E  E  E  E  E  E  E  E  E  E  = 128K
64K chips)   E = 9  B  D  E  E  E  E  E  E  E  E  E  E  E  E  E  = 192K
             F = 9  B  D  F  E  E  E  E  E  E  E  E  E  E  E  E  = 256K

(Examples: 02 in => E out, 34 in => D out, B9 in => F out, etc.)

Conclusion

With the GAL16V8 chip, the third set of tables proves to be the most versatile. It enables the utilization of three banks of 256K chips and one bank of 64K chips, effectively addressing a total of 640K of LOW MEMORY in addition to 128K of HIGH MEMORY. What’s more, if you already have 640K installed on your motherboard, there’s no need to make changes to the E2 jumpers. Simply insert the GAL16V8 chip along with the supplementary storage, configure SW2 POS 3 & 4 accordingly, and your setup is complete!

To achieve 640K plus 192K or 256K of HIGH MEMORY, you’ll need to install four banks of 256K chips.

Exploring Memory Configurations and SW2 Settings

The following information discusses various memory configurations and SW2 settings with the GAL16V8 chip installed.

First Set of Tables

For adventurous users with MDA or CGA display adapters

The first set of tables caters to more adventurous users and can only be employed on machines equipped with either an MDA or CGA display adapter (but not both). These tables map addressable motherboard storage into Segment B. While a portion of this storage overlays display adapter screen buffer addresses, it often doesn’t interfere with system operation. By using these tables alongside suitable software, it’s possible to reclaim portions of Segment B not used by the display adapter. However, exercise caution, as some software may misinterpret this non-standard environment and behave unpredictably.

Second Set of Tables

Primarily for testing purposes - unimplemented in our GAL equations!

The second set of tables is mainly intended for testing purposes, such as assessing storage or evaluating compatibility between different storage configurations and hardware or software.

Third Set of Tables

SW2 settings with the GAL16V8 chip installed

With the GAL16V8 decoder chip installed and a jumper at E2 1 - 2, you have four switch-selectable memory configurations:

- SW2 4 & 3 = 00 (both closed) ===> 640K plus Segments A, C, D, and E (no EGA and no Hard Disk)
- SW2 4 & 3 = 01 (4 closed, 3 open) ===> 640K plus Segments A, D, and E (OK with Hard Disk but no EGA)
- SW2 4 & 3 = 10 (4 open, 3 closed) ===> 640K plus Segments C, D, and E (no EGA and no Hard Disk)
- SW2 4 & 3 = 11 (both open) ===> 640K plus Segments D and E (OK with EGA and Hard Disk)

Without any jumpers at E2 and the HIMEMV2 chip installed, memory decodes as follows:

- SW2 4 & 3 = 00 (both closed) ===> 640K plus Segments D and E (OK with EGA and HD)
- SW2 4 & 3 = 01 (4 closed, 3 open) ===> 640K plus Segments A and E (OK with no EGA)
- SW2 4 & 3 = 10 (4 open, 3 closed) ===> "Normal" 640K arrangement
- SW2 4 & 3 = 11 (both open) ===> "Normal" 256K arrangement (using 64K from each bank)

With the HIMEMV2 chip installed and a jumper at E2 3 - 4 only, memory decodes as:

- SW2 4 & 3 = 00 (both closed) ===> 640K plus Segments A, C, D, and E (Segment assignments reversed)
- SW2 4 & 3 = 01 (4 closed, 3 open) ===> 640K plus Segment A (segments reversed, and bank 0 not used)
- SW2 4 & 3 = 10 (4 open, 3 closed) ===> "Normal" 640K arrangement

With the HIMEMV2 installed and jumpers at both E2 1 - 2 and 3 - 4, memory decodes as:

- SW2 4 & 3 = 00 (both closed) ===> 640K plus Segments A, B, C, D, & E (No EGA and NO HD, Segment B overlap)
- SW2 4 & 3 = 01 (4 closed, 3 open) ===> 640K plus Segments A, B, D, & E (OK with HD, NO EGA, Segment B overlap)
- SW2 4 & 3 = 10 (4 open, 3 closed) ===> 640K plus Segments A, B, & E (OK with HD, NO EGA, Segment B overlap)
- SW2 4 & 3 = 11 (both open) ===> 640K plus Segments A, B, & D (OK with HD, NO EGA, Segment B overlap)

These SW2 settings offer diverse memory configurations to suit various system setups and requirements.

Fourth Set of Tables

Suitable for older XT systems with soldered 64K chips in bank 0 - unimplemented in our GAL equations!

The fourth set of tables is particularly beneficial for owners of vintage XT systems with 64K chips soldered into bank 0 (no sockets). These tables allow for upgrades to 448K or 640K by installing 256K chips in bank 1 or in banks 1 and 2, while retaining the 64K chips in bank 0. Alternatively, you can install 256K chips into banks 1, 2, and 3, achieving 640K with an additional 128K of HIGH MEMORY. Notably, there’s no need to make adjustments to the E2 jumper block, as this set of tables is accessible without any jumpers installed.

Circuit Details

Each of the two E2 jumper positions and SW2 POS 3 & 4 is connected to one of the high order bits of the input to U44 with a circuit similar to the one pictured below:

           +5v ----\/\/\/\/\/\/\/\/\/-------+------> U44 input (A7-A0)
                   (pull-up resistor)       |
                                            +->   |
    When this circuit is open, the input          |-- SW (shown open)
        to U44 for that bit is high (1).    +->   |
    If the circuit is closed, the input     |
        for that bit is low (0).            V
                                       (to ground)

This means that the U44 inputs A7-A4 decode like this:

   Jumper   E2  3 to 4 :   Installed --> A7 = 0    Removed --> A7 = 1
   Jumper   E2  1 to 2 :   Installed --> A6 = 0    Removed --> A6 = 1
   Switch2  Position 4 :   Closed -----> A5 = 0    Open -----> A5 = 1
   Switch2  Position 3 :   Closed -----> A4 = 0    Open -----> A4 = 1

Therefore, we develop the numbers at the left edge of the U44 program charts as follows:

   E2  3 to 4 (input bit A7) >>>====> 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
   E2  1 to 2 (input bit A6) >>>====> 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
   SW2  Pos 4 (input bit A5) >>>====> 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
   SW2  Pos 3 (input bit A4) >>>====> 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
                                      = = = = = = = = = = = = = = = =
   Chart Numbers (left edge) >>>====> 0 1 2 3 4 5 6 7 8 9 A B C D E F

The U44 outputs (Q3-Q0) decode this way:

            Q3 is the high order bit, and is not used.
            Q2 is "Bank Select 2", and has a value of 2.
            Q1 is "Bank Select 1", and has a value of 1.
            Q0 is "Segment Enable".  If it is off, there is
                  no addressable memory in this 64K segment.

The values of Q2 and Q1 are added to determine the bank in which the addressed storage is to be found.

Therefore:               Q Q Q Q
                         3 2 1 0
            Output 9  (b'1 0 0 1')  ==>  select Bank 0
            Output B  (b'1 0 1 1')  ==>  select Bank 1
            Output D  (b'1 1 0 1')  ==>  select Bank 2
            Output F  (b'1 1 1 1')  ==>  select Bank 3
            Output E  (b'1 1 1 0')  ==>  segment not addressable

Finally, this is the pin layout of the U44 prom:

   Pin  1  input A6 ------ E2 pad 2
   Pin  2  input A5 ------ SW2 pos 4
   Pin  3  input A4 ------ S7W2 pos 3
   Pin  4  input A3 ------ CA 19
   Pin  5  input A0 ------ CA 16
   Pin  6  input A1 ------ CA 17
   Pin  7  input A2 ------ CA 18
   Pin  8  ground
   Pin  9  output Q3 ----- not connected
   Pin 10  output Q2 ----- E3 pad 1 (Bank Select 2)
   Pin 11  output Q1 ----- E3 pad 7 (Bank Select 1)
   Pin 12  output Q0 ----- U24 pin 4
   Pin 13  ground
   Pin 14  ground
   Pin 15  input A7 ------ E2 pad 4
   Pin 16  VCC ----------- +5V

      16_15_14_13_12_11_10__9
     |                       |
     |                       |
     >                       |
     |                       |
     |_______________________|
       1  2  3  4  5  6  7  8

Considerations for Clones and XT Compatible Systems

This modification was specifically developed for on the IBM PC XT platform. Its design relies on intricacies unique to the IBM XT motherboard. Given the considerable variations in manufacturing techniques and board layouts among compatible boards, attempting to install a decoder chip originally intended for an IBM board into a compatible system carries a significant risk of damaging either or both the chip and the motherboard.

In theory, if one had access to a complete schematic and a detailed readout of the factory-installed decoder PROM on these compatible boards, it might be possible to devise a similar modification.

Appendix

This table outlines the memory configurations, the corresponding SW2 settings, and compatibility considerations when using the GAL16V8 chip in different configurations.

SW2 4 & 3 Jumper at E2 Memory Configuration Compatibility
00 (both closed) 1 - 2 640K plus Segs A, C, D, and E No EGA and no Hard Disk
01 (4 closed, 3 open) 1 - 2 640K plus Segments A, D, and E OK with Hard Disk but no EGA
10 (4 open, 3 closed) 1 - 2 640K plus Segments C, D, and E No EGA and no Hard Disk
11 (both open) 1 - 2 640K plus segments D and E OK with EGA and Hard Disk
00 (both closed) None 640K plus Segments D and E OK with EGA and HD
01 (4 closed, 3 open) None 640K plus Segments A and E OK with no EGA
10 (4 open, 3 closed) None 640K (NO HIGH MEMORY) N/A
11 (both open) None 448K (NO HIGH MEMORY) N/A
00 (both closed) 3 - 4 640K plus Segs A, C, D, and E (Segment assignments reversed) N/A
01 (4 closed, 3 open) 3 - 4 640K plus Segment A (segs rev. and bank 0 not used at all) N/A
10 (4 open, 3 closed) 3 - 4 “Normal” 640K arrangement N/A
11 (both open) 3 - 4 “Normal” 256K arrangement (using 64K from each bank) N/A
00 (both closed) 1 - 2 and 3 - 4 640K plus Segs A, B, C, D, & E (No EGA & NO HD – Seg B overlap) N/A
01 (4 closed, 3 open) 1 - 2 and 3 - 4 640K plus Segs A, B, D, & E (OK w/HD, NO EGA - Seg B overlap) OK with HD, NO EGA - Seg B overlap
10 (4 open, 3 closed) 1 - 2 and 3 - 4 640K plus Segs A, B, & E (OK w/HD, NO EGA - Seg B overlap) OK with HD, NO EGA - Seg B overlap
11 (both open) 1 - 2 and 3 - 4 640K plus Segs A, B, & D (OK w/HD, NO EGA - Seg B overlap) OK with HD, NO EGA - Seg B overlap

References