Ben Eater 8 Bit Breadboard Computer SAP1

BEN'S INFOS

Homepage: https://eater.net/8bit

YouTube Playlist: https://www.youtube.com/watch?v=HyznrdDSSGM&list=PLowKtXNTBypGqImE405J2565dvjafglHU

COMMUNITY / FORUMS

https://www.reddit.com/r/beneater/

Questions

  • Is control Flags in (FI) really necessary? Can't it be auto done with sum out (EO)
    Hard to say, but with separated flags it would be possible to do a compare without sum out to the bus (which would not be a problem for a compare instruction because we are not obliged to read from the bus.

Community Information

Nice diagramms: https://easyeda.com/jakdimi/Computer_Clock_with_manual_pulsing-6535542c737c464fa1d1b75ef3fbb154

Beautiful layout with connectors: https://www.youtube.com/watch?v=3EdC4eJjpLU&feature=youtu.be

DIAGRAMS

 

INSTRUCTIONS

The SAP1 is not a real 8bit computer. Important parts are only 4 bits wide:

  • Program counter, can only count to 16
  • Memory address space is only 16 words, so programs can only be 16 steps long, or even shorter if memory locations are occupied by data
  • There are only 16 possible instructions
  • The machine code instruction format is:
    oooo (4bit instruction) xxxx (4bit address or value)
OPC   DEC HEX         DESCRIPTION
-------------------------------------------------------------------------------------
NOP   00  0000
LDA   01  0001 aaaa   Load contents of memory address aaaa into register A.
ADD   02  0010 aaaa   Put content of memory address aaaa into register B, 
                      add A + B, store result in A.
SUB   03  0011 aaaa   Put content of memory address aaaa into register B,
                      substract A - B, store result in register A.
STA   04  0100 aaaa   Store contents of register A at memory address aaaa.
LDI   05  0101 vvvv   Load 4 bit immediate value in register A (loads 'vvvv' in A).
JMP   06  0110 aaaa   Unconditional jump. Set program counter (PC) to aaaa, 
                      resume execution from that memory address.
JC    07  0111 aaaa   Jump if carry. Set PC to aaaa when carry flag is set and resume 
                      from there. When carry flag is not set resume normally.
JZ    08  1000 aaaa   Jump if zero. As above, but when zero flag is set.
      09  1001
      10  1010
      11  1011
      12  1100
      13  1101
OUT   14  1110        Output register A to 7 segment LED display as decimal.
HLT   15  1111        Halt execution.

Instructions that could be added:

  • LDB aaaa - Load content of memory adress aaaa into register B
  • STB aaaa - Store content of register B at memory adress aaaa
  • ADI vvvv - Add immediate value, but 4 bits only (could save memory)
  • CMP aaaa - Compare. Similar to substract but do not update register A, only set zero flag

CONTROLS

01  HLT   Halt the computer
02  MI    Memory address register in
03  RI    RAM in
04  RO    RAM out
05  II    Instruction register in
06  IO    Instruction register out (not needed with 256B RAM mod)
07  AI    Register A in
08  AO    Register A out
09  EO    ALU sum out
10  SU    Switch ALU to substract (otherwise add)
11  BI    Register B in  
12  OI    Output in (display bus value on 7segment display as decimal value)
13  CE    Counter enable (increment program counter PC)
14  CO    Counter out (Put program counter value on bus)
15  J     Jump (Counter in = read bus into program counter)
16  FI    Flags register in (store alu flags in flags register)

Controls signals that could be added:

  • BO - Register B out (control signal hardware is there, but not used)
  • RIC - Reset micro instruction counter (performance gain for instructions with few microcode steps)

Signals from upgrade ideas:

  • BRI - bank register in - read address value from bus into bank register
  • FPO - output generic bus switches on the bus("front panel")
  • GPO - output gamepad buttons latch on the bus
  • GPR - reset gamepad latch (could be automatically done by counter?)
  • VI - read bus content into video display
  • SI - sound input

can be removed: "IO" - We do not need the instruction register out control signal with 256B mod

ASSEMBLY / MACHINE CODE

Tricks

  • Substracting 1 from any positive number except 0 will enable the carry bit

Example Programs

Add two numbers

   OPC    VAL     MEMAD   INST VALUE  DESCRIPTION
----------------------------------------------------------
00 LDA    14      0000    0001 1110   Put value "28" from mem addr 14 into A
01 ADD    15      0001    0010 1111   Add value "14" from mem addr 15 to A
02 OUT            0010    1110 xxxx   Output result ("42") 
...
14        28      1110    0001 1100   Value 28 in memory
15        14      1111    0000 1110   Value 14 in memory

Add two 16bit numbers (untested)

Add 12473 + 48089

MSB / LSB = most/least significant byte

Notes

  • Too long, not possible without register overwriting.
  • LDI cannot be used for immediate loading, because it loads 4bit values only.
  • No output, 7segment display can only display 1 8bit integer, no place in memory.
    Examine output by manual setting memory address register.

 

   ASSEMBLER      MEMAD   INST VALUE  DESCRIPTION
----------------------------------------------------------
00 LDA    (13)    0000    0001 1001   Load LSB part of 12473 from mem addr 13 in A.
01 ADD    (15)    0001    0010 1111   Add LSB part of 48049, overflow -S> carry is set.
02 STA    (15)    0010    0100 1111   Store result from A into mem addr 15
                                      (Overwrite to save memory, can run only once).
03 JC     (08)    0011    0111 1000   Jump to mem addr 8 when carry is set,
                                      otherwise continue with next instruction. 

04 LDA    (12)    0100    0001 1100   Load MSB part of 12473 in A.
05 ADD    (14)    0101    0010 1110   Add MSB part of 48089.
06 STA    (14)    0110    0100 1110   Store result in mem addr 14 (overwrites).
07 HLT            0111    1111 xxxx   Halt the computer, result is in (14,15).
                                      =60562 (1110 1100 1001 0010).
08 LDI    1       1000    0101 0001   Load value "1" (carry) in A
09 ADD    (12)    1001    0010 1100   Add MSB part of 12473 from mem addr 12
10 STA    (12)    1010    0100 1100   Store in mem addr 12
11 JMP    (04)    1011    0110 0100   Jump to addr 04 to finish calculation
  
12                1100    0011 0000   MSB part of 12473
13                1101    1011 1001   LSB part of 12473
14                1110    1011 1011   MSB part of 48089
15                1111    1101 1001   LSB part of 48089

https://theshamblog.com/programs-and-more-commands-for-the-ben-eater-8-bit-breadboard-computer/

https://bread80.com/2019/09/13/breadboarding-with-diode-logic/

Arduino EEPROM Programmer

https://github.com/beneater/eeprom-programmer

 

MISC

Python Simulator: https://github.com/LuisMichaelis/Computer-Simulation

Google Calc Spreadsheet Emulator

https://www.youtube.com/watch?v=wB8R0oOkaAw

https://docs.google.com/spreadsheets/d/19bIGZXmD_VY89bpfnw9qf1uBbb2Kua-rAPWddzYNm7Y/edit#gid=653976056

 

Upgrades

Full 8 bit mod (256mem locations)

https://www.reddit.com/r/beneater/comments/ad2uko/upgrading_the_ram_module_to_256_bytes/
Also: https://www.youtube.com/watch?v=gqYFT6iecHw&list=PL_i7PfWMNYobSPpg1_voiDe6qBcjvuVui

Parts:

  • Second 74LS161 for 8bit programm counter

  • Memory address register:

    • Second 74LS173 4bit 3state register

    • Second 74LS157 quad 2-input multiplexer (switch output from two 4bit busses) Only neccessary for manual ram programming circuit

  • RAM:

    • Before: 74LS189s 64bit ram (16x4) with 3state outputs

    • Replacement: 7130LA35PDG (1Kx8, 9 address lines) dual port static ram

  • Microcode has now 2 bytes

    • 1 byte instruction, 1 byte data

    • Workflow:

      • program counter out

      • memory address register in

      • memory out

      • instruction register in

      • increment program counter

      • memory address register in

      • memory out

      • actual instructions follow here...

    • We do not need the instruction register out control signal anymore!
      Instead microcode counter reset?

  • Further 16 control signals are rather limiting. 24 would be nicer (=3 eeproms)

 

Bus control / "Keyboard"

 

  • 8 bus status leds, similiar to SAP1
  • 8 switches to form an 8bit word, a bit similar to old computer front panels
  • 74LS245 8bit bus transceiver connects the switches with the bus
  • Possible control signal: KYI keyboard in
  • Could replace SAP1 memory programming circuits

 

RAM Bank Switching

Assumes 256B mod, would theoretically be possible with 4bit too,

RAM > 256B could be used with bank switching. Different layout would be possible.

Switch complete RAM to other bank

  • Add a 8 bit register (bus transceiver 74LS245 + 2x 74LS173) between the bus and the RAM address lines greater than 8. (For 64KB of RAM, for 1KB one 74LS173 is enough)
  • New control signal: BRI - bank register in - read value from bus into bank register
  • New instruction SBK 0000 0010 - Select/Switch BanK 2
  • Would work with ROM too
  • Workflow: a long programm could
    • Switch to the next bank if near current memory address limit
    • Reset the program counter as the PC is relative to the bank
    • Proceed at new bank, relative memory location 0, where the next instruction would need to be located
  • Cons: No "global" RAM space, banks could not be used for data only, there would need to be instructions too

Bank only a window of the RAM

  • We could split the ram e.g. in half and bank the second part.
  • Similiar as above, but the banking register would start to control the ram from line 7 instead of 8
  • That would leave 128B of "global" ram, and 128B banked (e.g. 7x 128B banks with 1KB RAM)
  • Pros: Allows program code to stay in fixed part, and flexible data loading from banks