Update: 11-6-15: Adding notes re: necessary pinout at the end...
--------------------
I've had this running thought to try to make use of various processors without actually writing code for 'em. And even, plausibly, not needing to learn too much about the processor/architecture to get it to do something useful.
The simplest example I've thought of, so far, is to turn a processor into a simple binary-counter... I'm not familiar with too many architectures, but I figure for many/most random old CPUs in my collection (Z80s, 8086s, 8051s, 6800s, mostly, but a few newer) it might be as simple as merely hard-wiring the data pins to a "NOP" instruction (and supplying a clock source). The idea, then, is the CPU will read a NOP, then advance to the next instruction, and do so repeatedly... Each time, incrementing the address output on the address-pins... Then the address pins are a binary-counter. Done. (Right?)
(TODO: link the dude who figured out how to create moody-faces via floating "instructions")
So, after years (more than a decade!?) of percolation, I finally started this crazy venture, and for some crazy reason I decided to start with an Intel 486 chip. (I dunno squat about low-level x86 stuff, certainly not assembly-level).
Some initial nicities; noticed, as well as later discovered:
The PGA package is 0.1inch-spacing. Cool.
I have several floating 'round.
The data/address bus is apparently pretty standard... It uses parallel TTL-level signals, and doesn't do any sort of strange multiplexing that would require additional chips such as a latch...
(I'm not certain about other processors, but I have an inkling some of the newer ones might have sophisticated busses that would be quite a bit more difficult to hack without e.g. a "bridge" chip... apparently I lucked-out that the 486 doesn't seem to require one).
Managed to find the 396 page scanned-datasheet online (the PDF claims DataSheet4U.com, but I'm pretty sure i got it from a different domain).
Thankfully there's a pretty decent overview of the pin functions, and despite there being 168 pins, there aren't *really* that many different ones to learn about. The vast-majority are Power, Data, or Address. But there're some control signals that need to be tied to certain levels. E.G. to avoid triggering interrupts. There are a few features which I don't care to make use of, cache configuration, etc. that need to be understood at least well-enough to disable their functionality. Thankfully, the "Quick Pin Reference" table is clear enough to figure out what levels to set these to, so I don't have to dig into the intricate details of a function I don't care to use.
Another input indicates the byte-width of whatever "device" it's talking to. Does the BIOS-ROM have an 8-bit, 16-bit, or 32-bit data-bus? What about the RAM, or the ISA card...? That's handy, the NOP instruction (also found in the datasheet) is only one byte, so maybe I can get away with only "hard-wiring" 8 signals rather than 32... (though, of course, floating-inputs is generally a "bad" thing, this is DEFINITELY a hack-job).
There's also one pin to signal that the "device" is currently feeding the data on the lines and the data is ready to be read by the CPU. This one... I might have to come back to.
Oh, Reset and Clock, of course...
Again, luckily, the 486 still uses "easy" signals ... the clock input is a single TTL-level pin. Specs claim it's only guaranteed down to 4 (or 8?) MHz, but elsewhere they claim it was designed to run slower, just not tested... so that'll be a test for the future. Note that the 486DX processor I'm using doubles (or triples?) the clock-speed for internal-use... That means the clock signal has to be "stable", it probably won't work with a pushbutton to "step" the clock. Earlier 486s didn't have this, so they might even be pushbutton-steppable. (TODO: Note Re: clock-multiplying and the effect on actual execution when instructions can't possibly be read at that speed?)
Reset is supposed to be active until the power and clock have stabilized... I thought, maybe, I could get away with a technique I'd seen on an 8051 circuit... Simply, tie a capacitor between V+ and the reset line, then a resistor between reset and ground... Choose a large enough time-constant that power and clock start-up times are negligible. (I used a 33k resistor and a 10uF capacitor).
Now, here's where I'm at:
First: The processor doesn't seem to *start* all the time, but sometimes it does.
I *think* this might have to do with the reset-input. I haven't yet looked into the timing diagrams, but a slowly-rising reset input, combined with electrical noise (e.g. 60Hz) might have something to do with it. From what I *have* looked at, so far, I recall seeing something about reset having to be active for 15 clock-cycles, lest things be in an "unknown" state...
Well, here's what I'm visualizing, anyhow... This is a *processor* not a *microcontroller*, so it's designed to be in a somewhat more "ideal" environment... I haven't checked, yet, but the reset input may not have a Schmitt-Trigger, in which case, the slowly-rising signal may be near the trigger-value long enough for additional electrical-interference to cause it to "bounce" around the trigger-value a few times... So, that's one possibility. There's also the possibility that the reset input fans-out immediately to different parts of the processor, one may have a slightly lower threshold-voltage than the next... Neither of these "theories" would be problematic if the reset signal switched within a single clock-cycle... and it may well be that most motherboards have a synchronously-clocked flip-flop to do-so.
So, that's one thing I'll be looking into.
Second: When it *does* start, the lowest address-bit (bit 2, oddly) isn't toggling at a rate I would've expected.
I'd already kinda figured there may be some funkiness with the processor trying to execute instructions at twice (or thrice?) the speed they can be read... So, I did kinda expect that the lowest address line might not toggle with every clock-cycle. But, wouldn't it be consistent, and the higher address-bits would appear to toggle at 50% duty-cycle...? Well, they don't, and that's weird. Oh, and A27 never toggles, which is also weird... (to me).
So, first, I found a bit about the boot-mode of the CPU... I don't fully understand the details, but something about: It starts at 0xffff fff0, where it expects to see a jump instruction to somewhere within the first 1MB, which is where the BIOS-ROM is generally located. OK, but if it doesn't find a jump, and instead finds a NOP, wouldn't it just continue to the next addresses and eventually wrap-around to 0x0000 0000?
I dunno, because the next bit I found says that after the expected "jump" the system limits itself to addresses within that first 1MB... So, then, that might explain why I don't see any toggling on A26.
Great. So, if I don't learn how to program this thing, my binary-counter might only be, what... 12-bits? Oh well, still it'll do *something* plausibly-useful, and that's what I'm after...
So, I'm still confused about why the toggling of the bits doesn't seem to be occuring at a regular rate... And it occurs to me: What if, for some really weird reason, the processor attempts to write data *to* the data-bus (maybe not actually intending to write to a *device*)... I don't know *why* it would, but then again I don't really understand quite a bit about this architecture... (How the heck does "caching" make any sense?! Who tells it what to cache? And what's it do when it's twiddling its thumbs because it's waiting for data on its slow bus? etc. etc. etc. Could it be attempting to send an "error code" to some outside "device" that isn't implemented...? I dunno...)
I'd set up my "hard-wired" NOP via pull-up and pull-down resistors... Mostly thinking that I might choose to wire up something else later (like, maybe, a ROM, plausibly filled with instructions? Crazy, I know). But, it looks like it was a good thing I did it that way, rather'n wiring the data pins directly to VCC and GND... Because, indeed, after scoping it out, sure-enough there's data being driven on that Data Bus, despite my "hard-wired" NOPs.
Whew. Where's this leaving us...?
It's there, and the NOPs are getting mangled because of the internal-capacitance in the CPU's Data pins, combined with the resistors... It clearly takes on the order of 100 bus cycles for the resistors to "recover" from being driven. OK...
So, logically, the CPU, at some point, appears to be sending data to the bus, for some weird reason (plausibly due to oddities in the reset-process, as well as a multitude of other plausibilities, many of which may actually be *proper* functionality that I just don't understand). WHEN that happens, the next instruction that's read is *definitely* mangled. Who knows what it's doing at that point... It could be jumping to another address, or doing math on random values, or who knows.
But... often, it seems to be *repetitive*, whatever it's doing...
And, interestingly, the pattern seems to be different each time the CPU's reset.
Here's where I should just stop... it's kinda cool, really, a randomly-generated pattern that repeats... Maybe if it runs at low frequencies I could assign a percussive instrument to each bit... hmm...
But, of course, I've troubleshooting in my brain, so I've obviously been thinking about ways to solve this "problem"...
(Which is kinda ridiculous, 'cause what am I going to do with a 12bit counter that's stuck at a fixed frequency that I wouldn't just do with a chip designed for that purpose? The whole point was to make something "useful", but "useful" could just be "interesting"... that "Moody-Face" thing is pretty durn cool, and it does it with the utter-randomness of *floating* inputs)
But, of course, I've troubleshooting in my brain, so I've obviously been thinking about ways to solve this "problem"...
And, I have a few ideas...
A) Clean up that reset. Plausibly, if it resets in the "right" state, it will read the NOPs as expected and never drive the bus and get "mangled" instructions in the first-place. (Plausibly). Schmitt-Trigger (+ D-flip-flop?). Done.
B) Maybe driving the data-bus is something the CPU is *supposed* to be doing... I dunno it that well. So, what can be done about that...? Well, there's the "Ready" pin, and an output pin from the processor saying when it drives the bus... or another output pin from the processor saying when it wants to read from the bus... So, another R/C delay (possibly another Schmitt-Trigger/Flip-Flop) with a time-constant that's longer than the time it takes for the resistors to "recover". Done.
This also presents another interesting path... Maybe the CPU won't run at pushbutton *clock*-speeds... But, what about this "Ready" pin... could *that* be slowed down dramatically...? The next instruction is requested one clock-cycle after the last one was executed, but then it doesn't actually *receive* the next instruction until... maybe I set the R/C time-constant to a full second later, or maybe not until I decide to push a button. hmmm....
What *am* I making with this thing, anyways?
--------------
Update 11-6-15:
Here's the PGA-168 pinout... This is *nearly* identical for all 486 PGAs... (486, 486SX, 486DX, DX2, DX4...)
But they do differ, slightly. They should, however, be compatible, as the differing pins are usually added to old N/Cs and usually have internal pull-resistors for default backwards-compatibility. But, definitely look at the datasheet, section 3. This contains pinouts, descriptions of the pins, and also contains a table which shows the differences between different versions of the chip. My circuit's a 486DX-50, but my initial research was for a 486DX4-100, so there's a bit of notes re: both parts. Sorry it's so blurry, if you're really interested I can scan it for yah, lemme know.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
LOL, all these years, at it sorta again...
I somewhat distinctly recalled being confused at how to signal to the processor that the device/memory it's accessing is, say, only 8bits wide. But upon looking up the datasheet again (before coming here) I'm pretty certain there are /inputs/ for exactly that...
So, here I may've forgotten to tie the 8bit input active. Which may mean it was getting random "instructions" from three of every four addresses.
Another thing is the addressing... As I now think I understand, A0 and A1 are non-existent. Instead they've been demultiplexed into Byte-Selects 3-0. I guess that's not particularly important with this NOP-counter thing.
I think I had some other big ideas I'm forgetting.
I'm pretty sure #Improbable AVR -> 8088 substitution for PC/XT came after this, wherein I learned a little about memory segments, which I have long-since forgotten, but may have something to do with the NOPs not cycling through all addresses?
Anyhow, a few ideas.
Are you sure? yes | no
LOL, idiot... keep reading the newer logs...
Are you sure? yes | no
A friend, lay out the scans of the documentation, it is very necessary.
Are you sure? yes | no