Close
0%
0%

BREDSAC

Electronic Dynamic Storage Breadboard Computer

Public Chat
Similar projects worth following
This is an attempt to reimplement the historic EDSAC computer on breadboards using 74 series TTL and parts of a similar era.

What possessed me to do this?

Inspiration for this project came from two sources.

One is the effort underway at the National Museum of Computing in
Bletchley Park to build a replica of the EDSAC, one of the earliest
stored-program computers, built at Cambridge University in the late
1940s.

EDSAC Replica Project

The other is a series of videos by Ben Eater about the construction of
a simple computer on breadboards from 74 series logic chips.

Ben Eater's 8-bit Computer

Put these two things together, add in a hankering to do something with
hardware and a pile of parts burning a hole in the bottom of my junk
box, and the conclusion is obvious. I need to build a breadboard
implementation of the EDSAC!

bit_counter.png

Logisim - Bit counter

Portable Network Graphics (PNG) - 15.76 kB - 06/13/2018 at 06:37

Preview
Download

state_counter.png

Logisim - State counter

Portable Network Graphics (PNG) - 6.75 kB - 06/13/2018 at 06:37

Preview
Download

run_control_2.png

Logisim - Run control logic

Portable Network Graphics (PNG) - 15.12 kB - 06/13/2018 at 06:34

Preview
Download

BlockDiagram.png

Overall organisation of the computational logic.

Portable Network Graphics (PNG) - 48.38 kB - 06/07/2018 at 10:53

Preview
Download

BasicCycle.png

Diagram showing the basic short-word timing cycle of BREDSAC.

Portable Network Graphics (PNG) - 18.06 kB - 06/07/2018 at 10:51

Preview
Download

  • Automated Input Testing

    greg.ewing08/16/2020 at 11:21 0 comments

    I added tests to the combined test suite for the Input instruction and the telephone dial input facility.

    So that dial input could be tested automatically, I added a trigger circuit that watches the teletype output looking for the sequence of characters D#n, where n is a digit, and dials that digit.

    Changes to main circuit

    Dial test trigger subcircuit

    Changes to dial simulator subcircuit

    Additions to test program for input testing

    #
    #   INPUT instruction
    #   Enter with AC = 0
    #   Exit with AC = 0
    #   Expected output: INP
    #
    I_test:     O cI F
                I temp F
                A temp F
                L ^12
                T temp F
                O temp F
                I temp F
                A temp F
                L ^12
                T temp F
                O temp F
                O sp F
    
    #
    #   Dial Input test
    #   Enter with AC = 0
    #   Exit with AC = 0
    #   Expected output: D#5P
    #
    dial_test:  O cD F
                O figs F
                O chash F
                O c5 F
                Z F
                O lets F
                A temp F
                S k_5 F
                F fail D
                O cP F
                O sp F
    

  • Telephone Dial

    greg.ewing08/15/2020 at 13:54 0 comments

    The telephone dial is a somewhat unusual input device, as there is no way for the program to explicitly read it. When dial input is required, the program executes a Halt instruction. Dialling a digit n causes n to be added to the upper word of the accumulator (with the digit 0 giving n=10). Execution is then automatically resumed.

    I expanded the IOSEL field to 3 bits so that I could add two more I/O sense inputs:

    DIAL - high when the dial is turned away from its home position.

    DIALP - goes high for each dial pulse.

    Inside the State Control subcircuit, DIAL is inverted so that the branch condition is true when dialling has finished.

    DIAL is also connected to the Run Control circuit to trigger a NIMS to handle dial input.

    Main circuit changes

    State Control changes

    Dial Simulator

    The dial simulator runs on a slow internal clock so that the computer simulation can keep up with it. It has 4 states. In State 0, it is paused waiting for a button to be pressed. When that happens, the digit dialled is loaded into the pulse counter and the state counter is allowed to advance. State 1 provides a delay. In state 2, pulses are generated at the DIALP output and the pulse counter counts down. When it reaches zero, the state counter advances again, through state 3 which provides another delay, and back to state 0.

    Dial Timing

    Dial Input Microcode

    # IOSEL values for IOTST
    TDFIN = 001  # Telephone dial finished
    TDPUL = 101  # Telephone dial pulse
    
    # Dial Input
       1 00011 0 0000 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    TDFIN -  # If dialling finished
       1 00011 0 0001 :  -  EOI  --  ---   -  --    -     -   --   -   -   -   -   -    -   ----    -   BNIOT  0100     #   then continue program
       1 00011 0 0010 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    TDPUL -  # If no dial pulse
       1 00011 0 0011 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   ----    -   BNIOT  0000     #   then wait for pulse
       1 00011 0 0100 :  -   -   11  XAC   -  Y0   CY1    -   WAC  -   -  MSW LSW  -    -   ----    -   ---    ----     # Add 1 to MSW of accumulator
       1 00011 0 0101 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    TDPUL -  # If no dial pulse
       1 00011 0 0110 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   ----    -   BNIOT  0000     #   then wait for pulse
       1 00011 0 0111 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    TDFIN -  # If dialling finished then continue
       1 00011 0 1000 :  -  EOI  --  ---   -  --    -     -   --   -   -   -   -   -    -   ----    -   BNIOT  1010     #   program else wait for no pulse
    

  • Bit Timing Change

    greg.ewing08/13/2020 at 23:27 0 comments

    I found another problem. When entering a NIMS, the first RUNCLK pulse, which is used to load the starting microcode address into the opcode register, was prematurely advancing the bit counter, skipping T0 of the first microinstruction.

    To fix this, I modified the Bit Counter subcircuit so that the bit number is incremented only when RUN is true.

  • Bootstrapping

    greg.ewing08/13/2020 at 09:41 0 comments

    I created a boot device simulation and hooked it into the main circuit. To support booting, I added a PIBD value (boot device to PIB) for the IOSEL field,  a CLRPC (clear program counter) operation and a BDSTA (boot device start) I/O signal.

    I also changed the sense of the BDRUN input and renamed it to BDFIN (boot device finished), because it turned out I wanted to branch the other way on it in the microcode.

    Changes to main circuit

    Boot Device Simulator

    The boot device simulator is very similar to the paper tape simulator, with the addition of a flip flop to keep track of whether the boot device is running.  The memory is 18 bits wide; 17 of them are used for boot data, and one is used to flag the last word of the data.

    Boot Timing

    Boot Microcode

    The boot sequence is entered when the Start button on the front panel is pressed. It first clears the PC, starts the boot device and then enters a loop reading words from the boot device and writing them to memory. Along with reading each word, BDFIN is tested; when it is true, the PC is cleared again and execution of the program begins.

    # MISC values
    CLRPC = 0011  # Clear PC
    
    # PISEL values
    PIBD = 01  # Boot device data to PIB
    
    # IOSEL values for IOSIG
    BDSTA = 00  # Start boot device
    BDACK = 11  # Acknowledge boot device input
    
    # IOSEL values for IOTST
    BDFIN = 00  # Boot device is finished
    BDRDY = 11  # Data available from boot device
    
    # Boot
       1 00010 0 0000 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   CLRPC   -   ---    ----     # Clear PC
       1 00010 0 0001 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOSIG   -   ---    BDSTA -- # Start boot device
       1 00010 0 0010 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    BDRDY -- # Test for boot data
       1 00010 0 0011 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   ----    -   BNIOT  0100     # Loop until ready
       1 00010 0 0100 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   PLS     -   ---    PIBD  -- # Load boot data into S
       1 00010 0 0101 : SHS  -   --  XSR   -  --    -    WMEM --   -   -   -   -   -    -   MAPC    -   ---    ----     # Write S to memory at PC
       1 00010 0 0110 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    BDFIN -- # Test for boot finished
       1 00010 0 0111 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOSIG   -   ---    BDACK -- # Ack boot data
       1 00010 0 1000 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   INCPC   -   BNIOT  0100     # Inc PC and loop if boot not finished
       1 00010 0 1001 :  -  EOI  --  ---   -  --    -     -   --   -   -   -   -   -    -   CLRPC   -   ---    ----     # Clear PC and enter program
    
    

  • I/O Timing Diagrams

    greg.ewing08/13/2020 at 09:37 0 comments

    Teletype output timing

    Paper tape input timing

  • Redesigning I/O

    greg.ewing08/11/2020 at 06:40 0 comments

    The next thing I want to tackle is bootstrapping, or as the EDSAC team would have called it, "loading the initial orders".

    I haven't decided exactly what form the bootstrap device will take yet, but I'm assuming it will be some kind of parallel input device that interfaces in a similar way to the paper tape reader. So before going any further I decided to make some changes to the way I/O devices are handled so I can treat them in a more uniform way.

    I/O condition testing

    I didn't have any more branch condition inputs available, so I added an IOTST operation that samples one of four input conditions and latches it for branching on by a subsequent microinstruction. The conditions are assigned as follows:

    PTRDY - data is available from the paper tape reader
    TTRDY - teletype is ready to accept data
    BDRDY - data is available from the boot device
    BDRUN - boot device is running

    TTRDY and PTRDY were previously connected directly to inputs of the branch condition multiplexer. One of those inputs is now called IORDY and is used to sense the condition latched by IOTST; the other is currently spare.

    The condition to be tested by IOTST is selected by the IOSEL field, which again re-uses two bits from the UBRANCH field.

    I/O control signals

    On the outwards side, there is an IOSIG operation that produces one of four output pulses during the second half of T17, selected by IOSEL.

    PTACK - acknowledge data from paper tape reader
    TTOUT - signal teletype that data is available
    BDACK - acknowledge data from boot device
    BDSTART - start the boot device

    Paper tape input

    Input data from the paper tape is now read into the S register via the PIB, instead of having its own dedicated shift register.

    Logisim Changes

    Main circuit

    State Control

    Paper tape simulation

    For testing purposes, I put together a circuit that simulates a paper tape reader feeding in a few characters using the input device protocol. It incorporates a timer to slow down the input so that I can test whether the microcode correctly waits for the device to become ready.

    New microcode for Input and Output instructions

    # UBCOND values
    BNIOT = 011  # I/O test false
    
    # MISC values
    IOSIG = 1010  # Generate I/O signal selected by IOSEL
    IOTST = 0110  # Test I/O sense line selected by IOSEL
    
    # PISEL values
    PIPT = 10
    
    # IOSEL values for IOSIG
    PTACK = 10
    TTOUT = 01
    BDACK = 11
    
    # IOSEL values for IOTST
    BDRUN = 00
    PTRDY = 10
    TTRDY = 01
    BDRDY = 11
    
    # O - Output
       0 01001 0 0001 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    TTRDY --  # Test TTY
       0 01001 0 0010 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   ----    -   BNIOT  1000      # Loop until ready
       0 01001 0 0011 : SHS EOI  --  ---   -  --    -     -   --   -   -   -   -   -    -   IOSIG   -   ---    TTOUT --  # Read memory into S and signal TTY
    
    # I - Input
       0 01000 0 0001 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   IOTST   -   ---    PTRDY --  # Test paper tape
       0 01000 0 0010 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   ----    -   BNIOT  1000      # Loop until ready
       0 01000 0 0011 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   PLS     -   ---    PIPT  --  # Load paper tape data into S
       0 01000 0 0100 : SHS EOI  --  XSR   -  --    -    WMEM --   -   -   -   -   -    -   IOSIG   -   ---    PTACK --  # Write S to memory and ack paper tape
    

  • Fixing Instruction Register Timing

    greg.ewing08/08/2020 at 01:53 0 comments

    It turns out that clocking the instruction register with BITCLK wasn't such a good idea, because its transitions occur slightly ahead of RUNCLK, and this was leading to glitchy behaviour.

    So I came up with another solution to the problem that the change to the IR clocking was designed to solve. The IR is clocked with BITCLK as before, and the Run Control subcircuit lets through a RUNCLK pulse during a Continue pulse.

    Changes to main circuit

    Changes to Run Control

  • Front Panel Load Address Operation

    greg.ewing07/28/2020 at 15:16 0 comments

    The way the data paths are set up, the easiest way to get a value from the switches to the PC is to go through the instruction register. However, I can't load the whole instruction register in the middle of a microcode sequence, because that would mess up the microcode address. So, I have split out the address part of the instruction register into a Memory Address register that I can load separately.

    A quirk of this approach is that the value to be loaded into the PC needs to be set into switches 2 to 11, not 1 to 10 as might have been expected. This is due to the fact that IR/MA is loaded with an instruction during T17 of a fetch cycle, at which time the final shift of the value in the S register has not yet been performed; to compensate for this, inputs 0 to 16 of IR/MA are wired to outputs 1 to 17 of the S register.

    This is not really a problem, it's just a matter of labelling the switches appropriately. I created a bezel for the switches on the main schematic showing where the hex digits go for PC values and data.


    Load Address Microcode

    # MISC values
    LDMA  = 1101  # Load MA register from S register
    
    # Load Address
       1 00001 0 0000 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   PLS     -   ---    PISW -- # Load switches into S
       1 00001 0 0001 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   LDMA    -   ---    ----    # Load MA from S
       1 00001 0 0010 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   LDPC    -   ---    ----    # Load PC from MA
       1 00001 0 0011 :  -  EOI  --  ---   -  --    -     -   --   -   -   -   -   -    -   HALT    -   ---    ----    # Stop
    

  • Corrections

    greg.ewing07/28/2020 at 15:14 0 comments

    I found a couple of problems. The first is that XUSTART was being asserted for as long as a button was held down, instead of just a single BITCLK cycle as intended. A small change to the Run Control subcircuit fixed this.

    The second is that, on reaching the end of a NIMS, bit 17 of the instruction register was left as 1. This meant that subsequently pressing Continue without an intervening Reset would not start the program running, but instead just repeat the last executed NIMS.

    To fix this, I arranged for the instruction register to be reloaded at the end of the NIMS. Since XUSTART is inactive by then, this sets IR17 to 0. The rest of the instruction register is loaded with whatever data happens to be in the S register at the time, but this does not matter, because every microinstruction sequence addressed by IR17=0 begins with a Fetch microinstruction.

  • Front Panel Deposit Operation

    greg.ewing07/26/2020 at 07:17 0 comments

    The Run Control subcircuit now has provision for initiating up to four different non-instruction microcode sequences (NIMS). The inputs for triggering these are first latched to synchronise them with BITCLK, and then fed to a priority encoder which generates a microcode address. At the same time, the Continue FF chain is activated, producing a one-BITCLK pulse at XUSTART and then setting the Run FF.

    NIMS Timing

    Run Control

    Instruction Register Loading

    I found a problem with the logic for loading the NIMS entry point address into the instruction register. It doesn't work if the instruction register is clocked with RUNCLK, because the XUSTART pulse occurs before RUNCLK is activated. So the instuction register is now continuously clocked with BITCLK, and functions that should only occur while the machine is running are gated with RUN.

    Input Switches and Parallel Input Bus

    I added a set of switches for manual data entry1. These are gated onto a Parallel Input Bus (PIB) which connects to new parallel inputs on the S register.
    There is currently only one data source for the PIB, but there will be others later. I needed a way of selecting the PIB source in the microcode, but there are no more bits available, so I have re-used part of the UBADDR field. This means I won't be able to perform a microcode branch and use the PIB at the same time, but I don't think that will be a problem. The function of the Deposit switch will be to write the value from the input switches into memory at the address currently in the PC, and then increment the PC. To do this, I need to be able to select the PC as the source for the memory address, and increment the PC, independently of other functions.

    I also need to be able to select the serial output of the S register as an X source in the ALU input selector.

    Deposit microcode

    # XSEL values
    XSR  = 011  # S Register
    
    # MISC values
    PLS   = 1110  # Parallel load S register
    LDPC  = 0001  # Load PC from IR
    INCPC = 1001  # Increment PC
    MAPC  = 0101  # Memory address = PC
    
    # Deposit
       1 00000 0 0000 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   PLS     -   ---    PISW -- # Load switches into S
       1 00000 0 0001 : SHS  -   --  XSR   -  --    -    WMEM --   -   -   -   -   -    -   MAPC    -   ---    ----    # Write S to memory
       1 00000 0 0010 :  -   -   --  ---   -  --    -     -   --   -   -   -   -   -    -   INCPC   -   ---    ----    # Increment PC
       1 00000 0 0011 :  -  EOI  --  ---   -  --    -     -   --   -   -   -   -   -    -   HALT    -   ---    ----    # Stop
    

    Footnotes

    1. This is not quite historically accurate. The EDSAC designers deliberately did not provide a way for users to enter programs manually, because they didn't want people taking up machine time debugging at the console. It did have a set of "engineering switches" that were used for maintenance, but I don't know exactly what they did or how they were used.

View all 48 project logs

Enjoy this project?

Share

Discussions

Dr. Cockroach wrote 08/13/2020 at 15:56 point

I must say that your BREDSAC design is giving me a lot of food for thought for my LLTP. Your build will be fantastic to see in action.

  Are you sure? yes | no

Ken Yap wrote 07/10/2020 at 12:57 point

Very well documented project you have created. 👍 I'm old-school, I much rather read a pile of documents than watch a video.

If you need more vintage TTL chips (mostly LS and ALS) send me a message. I have a fair collection of pulls and it shouldn't cost that much to post you a bag, seeing as you're just across the Tasman ditch. Also have lots of DRAM chips.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates