05/29/2018 at 01:43 •
Replaced TD4B PCB
Well not much choice, EasyEDA corrupted the PCB after an upgrade (gone wrong again?).
Anyway, this version does not have the RAM add attached or the page register:
The PCB is public so if you want you can get your own version of the PCB (x5) from EasyEDA.
09/20/2017 at 07:15 •
First Power Up
Sorry, it did not work!
Address 0-3 light up concurrently
Tracked this down to duplicate labels RA0-3 in the schematic.
Fixed by cutting tracks (8) and adding wire links (4).
Jump does not work
The problem was that the diode ROM low voltage is about 0.9v but the 74LS14 needs less than 0.8v to trip. A 74LS04 would work (trip voltage is about 1.3v) but better to use a 74HC14. I am migrating to HC anyway.
Read/Write to RAM does not work
What can I say, I did not check the schematic and it does not work!
Removed the RAM and support chips.
Okay, the basic TD4B now works (except for the memory):
Use different coloured LEDs, it adds to the visual appeal of the CPU.
I also have to redesign the decoder, !WE is flawed and the next step is to add a Page register.
Also the AOUT and DOUT registers should be reset on RESET.
At the moment the the TD4B is programmed to count from 0 to 255 and then stop:
08/08/2017 at 07:12 •
TD4 CPU Version B
Here id the full schematic
And the PCB:
Simulating A TTA
A TTA is a Transport Triggered Architecture (i.e. a single instruction move only CPU). An example is my Weird CPU.
Why simulate TTA? It is a good test for a CPU, can it simulate another CPU.
The TTA CPU model:
- PC Mem
- JC Mem (n.b. it could be JNC)
- Hardware sets Mem to "15" to signal not carry.
- Other memory locations would "hide" the ALU, I/O etc.
Here is my program:
In the above I explicitly test the jump address for the not carry flag. There are other hardware/software arrangements. You could read the PC and write it back as PC+2. The carry signal would determine which of Mem or Mem was read.
Here are the modified OpCode for reference:
So pretty cool for a 4 bit CPU. The power of this CPU is the automatic adding of immediate data with every OpCode, without it it would be dead.
Expanding the TD4B
There are two basic approaches:
- Increase the 4 bus to 8 bit but keep the 4 bit OpCode.
- Increase the only the PC to 8 bit.
The second approach is not easy. We need to add a page register. For this we have to remap on of the OpCodes (okay you could multiplex DOUT using AOUT and get 16 registers but that would take an extra instruction each time). We could remap JNC, B to Page, B. The new Page register would set the high nibble of the PC on a jump. There would still only be 16 RAM words to play with.
A Few Days Later
I coded the Page Register:
By adding three chips I have 256 bytes of program memory. I cannot program it with the CPU directly (they call it Harvard Architecture) so what to do? It needs some thought.
08/06/2017 at 09:51 •
I have designed the PCB:
And I have written a short demo program (actually all programs are short for the TD4):
The demo shows the basic OpCode syntax and how data is written to or read from memory. The "... + 0" etc. for all the OpCodes, is the immediate data that is always added to the source data before being written to the destination register. The OpCode structure is much more pleasant to use than TTA. An expanded version (i.e. increased address space) would need to be able to access an ALU (perhaps in the memory address space) to be considered a complete CPU. It remains to be seen how efficient this set of OpCodes would be in an expanded CPU.
Here are the current OpCodes:
08/03/2017 at 12:19 •
The TD4 opcodes are designed for minimum decoder chip count (2) and therefore only 12 of the 16 possible opcodes have been mapped (at least that is what the text suggests):
Immediate OpCode Mnemonic ; Comment DCBA 0011 MOV A, Imm ; MOVE Imm to A register DCBA 0111 MOV B, Imm ; MOVE Imm to B register 0000 0001 MOV A, B ; MOVE A register to B register 0000 0100 MOV B, A ; MOVE B register to A register DCBA 0000 ADD A, Imm ; ADD Imm to A register DCBA 0101 ADD B, Imm ; ADD Imm to B register 0000 0010 IN A ; Copy input port to A register 0000 0111 IN B ; Copy input port to B register DCBA 1011 OUT Imm ; Copy Im to output register DCBA 1001 OUT B ; Copy B register to output port DCBA 1111 JMP Imm ; Jump to Imm DCBA 1110 JNC Imm ; Jump to Imm if C flag is not 1
I found however, author (Iku Watanabe) has actually mapped 14 of the 16 OpCodes!
You will note that the OpCodes always add the Immediate value to the source register so if an immediate value is not required then it must be set to zero.
Here is a CPU block diagram of the CPU:
Remapping The OpCodes
Let us begin by using format [DST][SRC]. The results in the following mapping:
DST SRC Comment A A Move A + Immediate to A A B Move B + Immediate to A A IN Move Input + Immediate to A A Z Move Zero + Immediate to A B A Move A + Immediate to B B B Move B + Immediate to B B IN Move Input + Immediate to B B Z Move Zero + Immediate to B OUT A Move A + Immediate to Output OUT B Move B + Immediate to Output OUT IN Move Input + Immediate to Output OUT Z Move Zero + Immediate to Output PC A Move A + Immediate to PC PC B Move B + Immediate to PC PC IN Move Input + Immediate to PC PC Z Move Zero + Immediate to PC
You should be able to see that for some OpCodes, they only make sense if the Immediate data is zero.
I have mapped the set of basic OpCodes (as shown above), Iku's OpCodes and two of my own OpCode transformations:
(If you like, each step across the table adds one chip to the decoder design.)
My first transformation is to honour Iku's OpCodes but to release the unused OpCodes.
My final transformation is to add an address output register.
Now it is not absolutely necessary to take my approach as you can just use the A Register value to directly apply the RAM address, but for a CPU with so few registers an extra register is probably worth the extra two or three chips.
Here is the Iku decoder:
And here is mine (version 2):
Although mine has four chips instead of two, it does release a spare inverter and nand gate which I will need for the RAM databus decoding. That is, in order to access the RAM I need to have a tri-state databus, I will need to swap the Output 74LS161 with a 74LS173 and provide output logic to tri-state the output buffer when a memory input is preformed. Sounds hard but it is just an inverter or two.
Iku has the PC clock in phase with the other clock signals, for most of my CPU designs I have it out of phase. It works because all outputs are shunted via the adder and delayed, making the clock/data transition reliable. As I have found out, this will also work for the !WE and !CS of RAM that does not have an !OE. It could be tricky in some cases if the buffer has a data hold period greater than the data delay. Something to watch out for.
How many times have I said that?
Anyway, I worked out a simpler way. I can demultiplex the OUT signal using ROM_D4 (Version 3):
I have also renamed the label to suit access to a 16 bit RAM (74LS189). Yes that was 16 bit (not 16k or 16M). You could use a 74LS138 to do this but I used a 74LS02 (quad NOR gate) as I want to invert the select and create a !WE signals. Here is part of the schematic:
You should recognise Iku decoder to the bottom right and my demultiplexer to the bottom left. I have also swapped out the 74LS161s for 74LS75s as I need to invert the output for the 74LS189 RAM. As I am using LS TTL the inverting outputs of the 74LS75s work better with LEDs. I have added the CLOCK signal to the !WE to minimise propagation delays to the RAM. I used the 74LS75s as they are a transparent latch and I need the output from them ASAP (not the next clock cycle).
Iku's TD4 has 13 chips but I have 17:
- I gain one because I swapped 2x 74LS138s for 1x 74LS154.
- I swapped the 74LS540 for a 74LS14.
- I swapped two 74LS161 for two 74LS173 (Registers A and B).
- I swapped a 74LS161 for a 74LS75 (OUT1 or AOUT).
- I added a 74LS02 to decode the second output register (OUT2 or DOUT).
- I added another 74LS75 for the second output register (OUT2 or DOUT).
- I added a 16 bit RAM (74LS189).
So all in all I am very happy with the result.