TD4 4-bit DIY CPU – Part 4
Having had quite a good play with the TD4 so far, I’m now starting to think how I might be able to enhance it slightly. First, I’m thinking about fairly simple things I can do with the kit as is. Then I might consider what I could do if I was to redesign it myself.
- Part 1 – Introduction, Discussion and Analysis
- Part 2 – Building and Hardware
- Part 3 – Programming and Simple Programs
- Part 4 – Some hardware enhancements
- Part 5 – My own PCB version
- Part 6 – Replacing the ROM with a microcontroller
- Part 7 – Creating an Arduino “assembler” for the TD4
Debug Register Output
The biggest limitation I’ve found with using the kit as is, compared to say using a simulator online, is that it isn’t possible to see what is going on with the registers.
But there is a pretty simple hack that will add LED outputs to each register.
The pinout for the 74HC161 is as follows:
And looking at the schematic, we can see that TC (15) is unconnected, but CET (10) links to GND. This means that if we want to catch the outputs O0-O3 (14-11) we just need an LED and resistor between the On pin and pin 10.
By far the easiest way to do that is with one of these LED “bars”:
These are available very cheaply online and tend to be blocks of four, six or eight surface mount LEDs and resistors connected to a common GND or VCC point. These are common-GND, six-way, blue modules which are perfect.
When the GND is aligned with CET on pin 10, the LED connections cover pins 11-16, which provides a handy VCC indicator for the register chip too, which makes it easy to know everything is connected and working.
The best way of installing these I decided was to use a spare 16-way DIP socket and insert the LED bar in the correct place as shown above. Then this can be simply slotted over the top of the chip itself on the PCB. This isn’t, obviously, a robust connection, but it is sufficient for debugging.
I’ve used two of these as shown below, for each register. I don’t need one for OUT as that is shown on the board anyway, and whilst I could add one for the PC, for now, this is fine.
Debug PC Output
As mentioned above, adding an indicator for the Program Counter should be relatively straight forward.
But I’d forgotten something. The PC has an automatic increment enabled which means that CET isn’t tied to GND, but to VCC. this means that the above won’t work directly as there is no convenient GND point next to the OUTPUTs. Still, once rewired to an actual GND it would still work in principle, but it will be a binary number representing the instruction.
What I’d really like is something next to the ROM bank showing which instruction is being read. One option is to hang LEDs off the ROM address decoder, shown in the schematic below.
But when we look at the pinout, it isn’t quite as simple as the registers. Also, as these are active LOW then I’d need one of the common VCC LED modules I think so that the LED will only turn on when the signal goes LOW, or just accept that all LEDs will be on apart from the active instruction.
One option might be a small, custom PCB to provide the required readout that can go between the 154 and the PCB. But ultimately all the signals from the 154 end up connected to each back of 8 diodes feeding the DIP switches, so that is another possibility.
Each DIP switch circuit is as follows:
The “scan” works as follows:
- All data lines are pulled HIGH by the resistors shown.
- By default all feed lines (the single connection point for all the diodes) will also be HIGH.
- Except when the 154 selects that output and drives it LOW.
- When the block is selected, then any switches that are set will drive the associated data lines LOW too, but just for this selected switch block.
- Later in the circuit all data lines go via the 74HC540 octal inverting buffer/line driver so they become active HIGH again.
So attaching an LED between the common connection point and VCC could show which block is active (LOW).
But now I’m wondering if the diodes could simply be replaced with LEDs anyway. In principle they would serve the same purpose – prevent “ghosting” between the blocks of switches, and the current is already limited by the 10K pull-up resistors.
This would mean that the active program counter would have its data word illuminated when active for all situations apart from the data word being all zero. This would correspond to the instruction ADD A, 0000 which is kind of a “NOP” anyway, so I don’t think that would be a significant limitation.
I am seriously considering buying a second kit now to see if I can use LEDs instead of diodes…
Returning to some kind of PC indicator for a moment. It would be possible to attach an LED to the underside of the board across the diode and switch such that it could indicate when that last block in the row is active. However this would only work if the switch that the LED is soldered to is open.
The LED has to be soldered so that the cathode (short leg) is soldered to the top of the existing diode and the anode (long leg) is bent around to connect to the bottom of the switch block as shown below.
So when switch 8 is ON the LED will not work. That means if there is an OUT or a JMP then the LED won’t light, but that is better than nothing perhaps and is a pretty simple addition to the board.
And if there are spare instruction slots remaining then the last instruction can just be a NOP (ADD A, 0).
Simulator Enhancement
Whilst testing out the log2 idea from Part 3, I started with the simulator provided by umtkm on github here: umtkm.github.io/td4/
But that has a minor issue in that it implements the TD4 as described, but not as fully implemented in logic. In particular, the undocumented feature that all commands will always add an immediate value if provided, even if the officially described assembler instruction doesn’t include it.
The example in question, used for the log2 code, was IN A. The logic actually implements IN A + im even though the description doesn’t mention it. The instruction table lists this as:
IN A 0010 0000
But there is no reason why that 0000 couldn’t be any value. This is a consequence of using the adder to load a register – it will always add in the immediate value too.
By downloading the javascript from the original repository github.com/umtkm/td4 it is possible to tweak it to implement the undocumented feature.
The function “purse_order” handles the implementation of each instruction, so the immediate value needs adding to the register for the IN instruction, and it needs the CARRY building in too. I’ve also added it to the two MOV register functions too.
Here is my new implementation:
function purse_order(bin) { var op = bin.slice(0,4); var im = parseInt(bin.slice(-4),2); registor_a &= 15; registor_b &= 15; switch (op) { case '0000': registor_a += im; c_flag = registor_a&16 ? 1 : 0; return; case '0101': registor_b += im; c_flag = registor_b&16 ? 1 : 0; return; case '0011': registor_a = im; break; case '0111': registor_b = im; break; case '0001': registor_a = registor_b + im; c_flag = registor_a&16 ? 1 : 0; return; case '0100': registor_b = registor_a + im; c_flag = registor_b&16 ? 1 : 0; return; case '1111': program_counter = im; break; case '1110': if (c_flag === 0) program_counter = im; break; case '0010': registor_a = input_port + im; c_flag = registor_a&16 ? 1 : 0; return; case '0110': registor_b = input_port + im; c_flag = registor_b&16 ? 1 : 0; return; case '1001': output_port = registor_b; break; case '1011': output_port = im; break; } c_flag = 0;}
There are four instructions not implemented in the emulator at present – the two duplicate OUT instructions, JMP B and JNC B. I might see if I can add the two jumps as that would be really useful too.
But this allows me to test the log2 routine in simulation now too.
Conclusion
Both of the hardware updates described so far are relatively simple, but quite useful additions to the kit.
I’ll come back to this post as I think of other things to do.
Kevin
#td4
GitHub - umtkm/td4: TD4 Emulator Web
TD4 Emulator Web. Contribute to umtkm/td4 development by creating an account on GitHub.GitHub