A 12-bit TTL-based Microprogrammed Computer
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
VAPID.pngPortable Network Graphics (PNG) - 80.94 kB - 03/03/2023 at 06:26 |
|
|
fibonacci.asmAssembly language program to generate Fibonacci numbers up to 64 digits in lengthasm - 3.56 kB - 05/28/2018 at 03:38 |
|
|
tasm.plSTUPID assembler (rev 0)pl - 20.06 kB - 05/28/2018 at 03:37 |
|
|
microcode.micSTUPID microcodemic - 33.71 kB - 05/28/2018 at 03:37 |
|
|
memtest.micMemory Test microcodemic - 5.92 kB - 02/27/2018 at 00:52 |
|
VAPID: Vector Adorned Programmed Instruction Decoder
Added a new output device: 3 channels of D/A conversion using a Burr Brown DAC7624. This chip provides four 12-bit D/A converters, but I'm only using 3 and only using 10 bits to make the interfacing simple.
The implementation is a bit of a kludge, as the original STUPID computer was designed with only a single I/O device so there is no clean way to specify which I/O device to use. The solution used here (for output only) is to have the high bits of the AC (which holds the value to be output) specify the device. Four 8-bit devices and 3 10-bit devices are supported. If the high-order 4 bits are all zero, the TTY is indicated. This makes the mod backward-compatible with existing code, as only 8 bits are used when outputting to the terminal and the high bits are always zero. They didn't absolutely have to be in the original implementation, but no existing code uses the high bits for anything. One additional instruction, OUTPUT, is defined as the existing PUTC instruction waits for the UART to be idle before sending the byte. The new instruction sends the data directly without checking whether the device is ready for it, so any necessary checking must be done under program control. But again, for backward-compatibility, the PUTC instruction is retained (just don't try to use it if any of the high bits of the AC are set...)
...and on that note, this project will be taking a vacation so I can work on other projects. I still have to figure out what's going on with the serial communication (and will use that as an excuse to pick up an old HP Protocol Analyzer somewhere down the line). There are many other things I could do as well, but as Proof of Concept (which is the most fun part of any project imo), it's done.
Evil plan starts to come together...
Almost complete... Case of Aluminum and acrylic. Still need to install the serial cable.
Just to make sure nobody asks if it's a Raspberry Pi or a 6502...
I added a new instruction, break, which halts the processor after incrementing the program counter. The halt instruction does not increment the PC before halting, so it is not possible to continue (or single step forward) from a halt. When debugging a program through the front panel, it is handy to be able to stop execution (to allow examination of registers or memory) but allow the program to be continued.
Uploaded the microcode. I can't believe I didn't put this up before now. Also uploaded rev 0 of the assembler and the Fibonacci number assembly language program, for those who are curious what a STUPID program looks like in assembly language.
I still need to update the schematics and upload the latest version...
When it's too much to toggle in...
OK, let's see if anyone can explain this:
After making the changes shown in the previous log, I fires it up with the same microcode that was in before the changes (changes are fully backward-compatible), and everything seemed to work fine. So I put the decrement back in the microcode instead of the workaround I had and...it failed miserably. Couldn't even make it through the power-on self test. The most common failure mode had it branching to E2F when the microinstruction said to branch to E1F. Bad build? I reassembled and burned the Flash again and...same thing. Maybe the counter chip's gone bad (very low probability, but easy to check). Swapped chips around. Same thing. Verify input signal is valid & setup time OK. But the middle counter (there are 3 cascaded 74F161 counters providing a microcode address) was already at 2 - I can't tell if it's failing to load that counter, or if it loads the 1 and then increments it. Well, what does the clock signal look like? Attach an oscilloscope probe to the clock input of the counter chip and...everything works. And the clock signal looks fine. Just a small amount of ringing. Well, this is the end of a run (clock drives 6 loads across 3 boards, so it's not a true bus). Try Thevenin termination. No change. Fails without scope lead attached, works with it attached. Let's see...the scope adds capacitance, which will slow the rise time of the signal. 74F chips have a very fast rise time. Let's try a 74S instead. They're fast but from what I've seen, don't have as fast a rise time on the leading edge. No difference. Well, how about a 74LS? Fails miserably in a different manner than the F & S chips.
Hmmm, I've got a 74HC chip here, let's try that... Everything works! wtf???
The signal I'm looking at is CLK2.
There's no pullup on the input to the other half of the flip flop (pin 12), which is driven by a 74S374, but that part works fine as well. The MIR9 signal is not connected to any other inputs, so it's not seeing much of a load. So really just reduced noise immunity there, which, as I said, is not (currently) showing up as a problem.
So what's going on? It doesn't seem like a reflection issue, as terminating the signal line should have at least helped with that. The hardware change was in the ALU, which is on another board and does not see the CLK2 signal, though the CLK2 signal is present on that board (clocks the "result=0" flip flop). Crosstalk causing a glitch on the clock signal? Enough to trigger the counter but not the logic analyzer? Scope probe capacitance filters it out, and higher output voltage of the HC chip keeps it from crossing the logic threshold levels? And why did it work OK until I changed the microcode???
Don't know if I'm going to have time to do a video for this, so will try it the old fashioned way...
Progress:
These signals are not carried out to the bus, so required the use of grabbers to access. With the pins, the leads can connect directly. The pins are mounted upside down so they stick up from the top of the board.
The Moving Inversions Memory test does occasionally fail, but it's not a memory problem. It always fails on the reverse test when it is decrementing the memory address. Example failure: MemAddr = 8FF, expecting a pattern of E00 but seeing a pattern of C00. Memory locations 0-7FF contain E00 while locations 800-FFF contain C00. This appears to be a carry propagation time issue with the ALU. Assume MemAddr was at 800 and was decremented, but we latched the output before the high 4 bits settled. Then, instead of 7FF we have 8FF. Have not been able to confirm this with the Logic Analyzer because it is so infrequent, but changing the decrement instruction (MAR <- --MAR) to 3 instructions (MAR <- ~MAR/MAR <- ++MAR/MAR <- ~MAR) eliminates the problem. Looking at the '181 data sheet, a difference operation does take slightly longer than a sum operation (on the order of 1-2nsec), so it appears that it is running right on the edge. Which is odd, because I calculated the worst-case delay for a microinstruction as something like 88 nsec, which is well within the 100nsec cycle time. Either I calculated wrong somewhere or the chips I'm using didn't read the data sheet...
Anyway, a couple of solutions come to mind:
Since I have some '182 chips, I'm going to try solution #2. The only problem is that the ALU board is full. But there are some individual pads down by the bus lines (you can see in the lower left in the picture above) where it can be put - they're the pads that the power input connector is soldered to on the microcontroller board - just won't have the niceness of 3 holes-per-pad... I think once this chip is added, the hardware will be done.
Create an account to leave a comment. Already have an account? Log In.
This would be a good addition to the https://hackaday.io/list/25846-homebrew-cpu list, @Dusan Petrovic !
just found your project last night, and worked through the videos. really enjoyed the details! (i see you are attracting all of the homebrew/diy cpu guys on hackaday.io!)
Nice. We could do with more 12 bit machines here... everyone seems to default to either 8 or 16 without really considering the compromise position. :) Looks like you've designed this for high speed... what kind of speeds are you getting?
The microcycle time is 200ns. That breaks down into 100nsec for reading out the microinstruction (of which 70 is taken by the flash mem), and 100 for the ALU or RAM operation...
Hi Steve,
Okay, in essence I was suggesting some support for stack operations.
I have not actually seen the "Little Man Computer" before, I will have to have a closer look.
---
If you interested (in where I am coming from) have a look at:
http://www.dustyoldcomputers.com/pdp-8/software/pl0/Readme
Doug Ingraham (May 2015) modified PL/0 to cross-compile for his PDP-8.
AlanX
You can create a basic stack with an indirect register. This will get you push/pop, but is still missing the ability to do any indexed addressing into the stack... To index, you'd have to copy the stack pointer (or frame pointer) register to the AC, add the offset, copy the resulting AC value to a different indirect register, then access the data through that. Not very efficient, as you pointed out...
And another interesting presentation. Rather glad you discussed "Final Thoughts" as I was starting to have doubts as the OpCode scope was a pretty big jump from the original design.
I was playing around with PL/0 a while ago, looking at building a compiler for home brew CPUs. The particular CPU is was looking at, at the time, was SUBLeq. What I found was that simple compilers (i.e. unoptimised P-Code compilers) have a rather limited set of instructions. That focused my attention on the P-Code like OpCodes, but mostly on stack type operations (and away from bit operations etc).
So while your instruction set is good for hand crafted assembler, are you or have you considered higher language support for you CPU? Because if you do go down this path your current instruction set is not ideal.
AlanX
High level language? No. Remember what I said in the previous video about the KISS principle: Keep it STUPID, stupid. This is just intended to be an evolution of the original STUPID design, which was basically a derivative of the Little Man Computer (Wikipedia: "The Little Man Computer (LMC) is an instructional model of a computer, created by Dr. Stuart Madnick in 1965.") It's meant more as a teaching tool than a practical computer...
Hi Steve,
I enjoyed your presentation (and presentation style) and look forward to your project logs.
Can I suggest you join Hackaday TTLers. We are a group that do TTL (okay also CMOS, HC etc.) and often do CPUs as well.
Regards AlanX
Become a member to follow this project and never miss any updates
Great project! Really fascinating to see how similar problem can solved in a different way - I wrote a microcode compiler (or maybe it should be called assembler?) too, but with the goal to be adaptable for a wide variety of CPUs (and other controllers) https://hackaday.io/project/172073-microcoding-for-fpgas