• Please review our updated Terms and Rules here

Cloning a PAL/HAL, Part 13

Chuck(G)

25k Member
Joined
Jan 11, 2007
Messages
44,227
Location
Pacific Northwest, USA
Part 12 of this series is here. The beginning of this series is here.

Cloning the Trantor T130B ROM PAL, continued.

In the preceding entry, we've discovered that simply reading and crunching the original PAL results in impossible garbage. In particular, nothing appears to be happening with the output on pin 13. So, let's pull out the datasheets and continuity tracer and see what gives.

The controller chip on this board is an NCR 53C400. The datasheet tells us that this is an all-in-one controller that interfaces directly to the ISA bus and provides space for a BIOS, 64 bytes of scratchpad RAM and access to the NCR 53C80 SCSI core buried in this thing. Everything is memory-mapped and there is no I/O port usage. Had Trantor used the native capabilities of the 53C400, this card would look a lot like the Seagate ST01--basically a BIOS chip, the controller and a bus transceiver. But there's more to this thing--it uses I/O ports, for example. Obviously, what Trantor has done is to map part of the memory that belongs to this thing into I/O space with some PALs to juggle signals.

So let's buzz thie PAL socket out and see what we find:
Code:
Pin 1-9 (I)  ISA bus, address lines A11-A19 (positions A20-A12)
Pin 11 (I)   ISA bus, MEMR (position B12)
Pin 10 Ground
Pin 12 (O)   U4, pin 27 (EPROM)  See postscript (below)
Pin 13 (O)   U4, pin 22 (/OE), looks to be tristated with pullup RN5
Pin 14 (I)   ISA bus, MEMW (position B11)
Pin 15 (I)   SW1-3 (ROM address select) (pullup)
Pin 16 (I)   SW1-4
Pin 17 (I)   SW1-5
Pin 18 (O?)  PAL U4 Pin 5
Pin 19 (O)   Pin 38, (U3) 53C400 A11, pullup.
Pin 20 +5

Well, there the mystery of pin 13 is solved--it's another tri-stated pin and active low. So, we repeat the PAL read, except this time, we connect pin 13 to a 1Kohm pullup resistor to +5. Crunching the dump, and translating the equation symbols to something that EQN2JED can understand, we get:
Code:
Pin12 =
    /Pin14*/Pin15*Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*/Pin5*/Pin4*/Pin3 +
    /Pin14*/Pin15*Pin16*Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*Pin4*Pin3 +
    /Pin14*Pin15*/Pin16*/Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*/Pin4*Pin3 +
    /Pin14*Pin15*/Pin16*Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*Pin4*Pin3 +
    /Pin14*Pin15*Pin16*/Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin14*/Pin15*/Pin16*Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin14*/Pin15*/Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*Pin4*Pin3

Pin13 =
    /Pin15*Pin16*/Pin17*/Pin11*Pin9*Pin8*Pin7*/Pin6*/Pin5*/Pin4*/Pin3 +
    /Pin15*Pin16*Pin17*/Pin11*Pin9*Pin8*/Pin7*Pin6*Pin5*Pin4*Pin3 +
    Pin15*/Pin16*/Pin17*/Pin11*Pin9*Pin8*/Pin7*Pin6*Pin5*/Pin4*Pin3 +
    Pin15*/Pin16*Pin17*/Pin11*Pin9*Pin8*/Pin7*/Pin6*Pin5*Pin4*Pin3 +
    Pin15*Pin16*/Pin17*/Pin11*Pin9*Pin8*/Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin15*/Pin16*Pin17*/Pin11*Pin9*Pin8*Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin15*/Pin16*/Pin17*/Pin11*Pin9*Pin8*Pin7*/Pin6*Pin5*Pin4*Pin3

Pin18 =
    /Pin15*Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*/Pin5*/Pin4*/Pin3 +
    /Pin15*Pin16*Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*Pin4*Pin3 +
    Pin15*/Pin16*/Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*/Pin4*Pin3 +
    Pin15*/Pin16*Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*Pin4*Pin3 +
    Pin15*Pin16*/Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin15*/Pin16*Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin15*/Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*Pin4*Pin3

Pin19 =
    /Pin15*Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*/Pin5*/Pin4*/Pin3*/Pin1 +
    /Pin15*Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*/Pin5*/Pin4*/Pin3*/Pin2 +
    /Pin15*Pin16*Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*Pin4*Pin3*/Pin1 +
    /Pin15*Pin16*Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*Pin4*Pin3*/Pin2 +
    Pin15*/Pin16*/Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*/Pin4*Pin3*/Pin1 +
    Pin15*/Pin16*/Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*/Pin4*Pin3*/Pin2 +
    Pin15*/Pin16*Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*Pin4*Pin3*/Pin1 +
    Pin15*/Pin16*Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*Pin4*Pin3*/Pin2 +
    Pin15*Pin16*/Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*/Pin4*Pin3*/Pin1 +
    /Pin15*/Pin16*Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*/Pin4*Pin3*/Pin1 +
    /Pin15*/Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*Pin4*Pin3*/Pin1 +
    Pin15*Pin16*/Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*/Pin4*Pin3*/Pin2 +
    /Pin15*/Pin16*Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*/Pin4*Pin3*/Pin2 +
    /Pin15*/Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*Pin4*Pin3*/Pin2
That's better, but we still have to change the equation at pin 13 to a tri-state type. And look at all those terms! We can't compile that!

But compare the equations at pin 12 and pin 18--they're mostly the same, except that the product terms at pin 12 have pin 14 included. Similarly, the terms at pin 19 look a lot like the terms at pin 18, except that pin1 and pin2 are included in each set of 7 terms. And pin 13 looks like pin 18, but includes pin 11.

Fortunately for us, the PAL16L8 (and the GAL16V8 ) allows you to take the output of one set of terms and feed it back as an input term for the other outputs. Rewriting the equations above to match our observations, we get:
Code:
CHIP T130B 16V8

;  GAL programming for the Trantor T130B memory PAL, U6

;	Pin assignments

Pin1=1 Pin2=2 Pin3=3 Pin4=4 Pin5=5 Pin6=6 Pin7=7 Pin8=8 Pin9=9 gnd=10
Pin11=11 Pin12=12 Pin13=13 Pin14=14 Pin15=15 Pin16=16 Pin17=17
Pin18=18 Pin19=19 vcc=20

EQUATIONS

/Pin12 =
    /Pin18*/Pin14

Pin13.trst = /Pin18
/Pin13 = /Pin11

/Pin18 =
    /Pin15*Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*/Pin5*/Pin4*/Pin3 +
    /Pin15*Pin16*Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*Pin4*Pin3 +
    Pin15*/Pin16*/Pin17*Pin9*Pin8*/Pin7*Pin6*Pin5*/Pin4*Pin3 +
    Pin15*/Pin16*Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*Pin4*Pin3 +
    Pin15*Pin16*/Pin17*Pin9*Pin8*/Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin15*/Pin16*Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*/Pin4*Pin3 +
    /Pin15*/Pin16*/Pin17*Pin9*Pin8*Pin7*/Pin6*Pin5*Pin4*Pin3

/Pin19 = /Pin18*/Pin1 + /Pin18*/Pin2

Note a peculiarity of EQN2JED: if an output is mentioned as a true-low term, it's assumed to be that way in any subsequent use. So, if we have a true-low output and need to use it in a true-high feedback term, we need to invert it again. Confusing? Yup, but that's the way things work.

And, it works! (JED file attached).

Don, I'm sorry for the untimeliness, but better late than never, eh? :)

----------------------
Postscript I didn't really think about it, but sometimes you run across some very odd stuff on these old cards. In particular, note that PAL pin 12 connects to an otherwise unused pin on a 2764 EPROM. Decoding the PAL logic shows that this is derived from the basic address select and MEMW (memory write) on the ISA bus. So, what's this all about?

Well, I think the intention here was to enable the developers to replace the 2764 EPROM with a 6264 SRAM and perform debugging of new code without having to burn a new ROM each time. The output of this pin is connected to /WE (write enable) on the 6264, so a developer would be able to write his new ROM image to the SRAM, then do a three-key salute to reset the machine and then check out how the thing works. Pretty nifty.

However, this also says that if you put a 28C64 EEPROM in this socket, you may be very upset, should a rogue program attempt to write to it. So, if you substitute a 28C64 for the original 2764 EPROM, be sure to bend pin 27 out of the socket so it doesn't get clobbered by a wayward store.
 

Attachments

  • T130B.ZIP
    525 bytes · Views: 10
Sanguino PAL reader

That's a nice board!

However, I don't see how you are able to detect tri-stated outputs on a PAL--which appear to occur with more frequency than I'd anticipated.

The way I did it with my board was to add an additional 8 outputs that, through a resistor could "push" on an output to see if it was tri-stated (i.e. high impedance) or not. That requires one input and one output for each pin to be tested--one to "push" and the other to read the result.

My apology if I somehow missed that, but I don't see it in your implementation yet.






fjkraan;bt530 said:
Based on this very interesing series, I adapted a Sanguino board to read PALs: http://fjkraan.home.xs4all.nl/comp/divcomp/ppread/palread.html.
 
Hi, thanks for the reaction!

I did try to to add tri-state detection, but it is not yet very clear, and the algorithm might not be complete either. It works as you describe: an input connected to the pin to get the actual level and an output connected via a resistor, to push. The reading algorithm should try each potential tri-state pin to push it high and pull it low. It might be possible to add the tri-state to the software, but currently it is just dumping the measured state. I'll add a diagram to the page.

Currently I use a AT Mega644, which has 30 pins usable. I might switch to an Arduino Mega256 which has around 50 usable pins. I prefer to use them in complete bytes to keep the program simple, so some extra pins become useful when a lot of pins can become tri-state.

Some of the PALs I try to decode are PAL16R6 (from the TRS-80 MII 68000 card) which have both registered and tri-state capability.
 
fjkraan;bt532 said:
Hi, thanks for the reaction!

I did try to to add tri-state detection, but it is not yet very clear, and the algorithm might not be complete either.

If you're running out of pins, you may be interested in a port expander that's interfaced with I²C. TI has a good selection:

http://www.ti.com/lit/sg/sszc003c/sszc003c.pdf?HQS=hpa_i2cguide_050611

Registered PALs can be very difficult, if not next to impossible to decode. Because they're not strictly combinatorial (i.e. they have a memory) and can include feedback terms, it can be extremely difficult to figure them out unless you have some prior knowledge of their function. Many old parallel-port dongles used registered PALs as their security device.
 
Back
Top