├── .gitignore
├── README.md
├── control_lines.md
├── hardware.md
├── instruction_decoding.md
├── instruction_set.md
├── issues.md
├── programs
├── add_two_numbers.md
├── count_0_255.md
├── fibonacci.md
├── increase_by_three.md
└── multiply_two_numbers.md
└── resources
├── 8-bit-computer-600w.jpg
├── 8-bit-computer-fritzing-600w.jpg
├── 8-bit-computer-fritzing-breadboard.png
├── 8-bit-computer-fritzing.png
├── 8-bit-computer-fritzing.svg
├── 8-bit-computer.fzz
├── 8-bit-computer.jpg
├── clock_double_step.png
├── clock_double_step_cap.jpg
├── clock_speed_cap.jpg
├── clock_spurious_step_lm555cn.png
├── clock_spurious_step_ne555p.png
├── leds_with_resistors.jpg
├── mar_decoupling_cap.jpg
├── power.jpg
├── ram_mode_switch_cap.jpg
├── ram_mode_switch_press.png
├── ram_resonance_post_fix.jpg
├── ram_resonance_pre_fix.jpg
├── reset_line_cap.jpg
├── reset_line_noise.png
├── thermal.jpg
├── yt-0-to-255-thumb.png
├── yt-add-two-numbers-thumb.png
├── yt-double-step-glitch-thumb.png
├── yt-fibonacci-thumb.png
├── yt-increase-by-three-thumb.png
├── yt-mar-reset-glitch-thumb.png
├── yt-multiply-two-numbers-thumb.png
├── yt-ram-mode-glitch-thumb.png
├── yt-ram-resonance-glitch-thumb.png
├── yt-reset-noise-glitch-thumb.png
└── yt-spurious-step-glitch-thumb.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 8-bit-computer
2 |
3 | This is my 8-bit computer. Based on a project by Ben Eater.
4 |
5 | [](resources/8-bit-computer.jpg)
6 |
7 | See the computer in action:
8 |
9 | [](https://www.youtube.com/watch?v=DTxpwynaN34 "Click to play")
10 |
11 | See [8-bit-computer-emulator](https://github.com/blurpy/8-bit-computer-emulator) for a version of this computer implemented in software. See [8-bit-computer-eeprom](https://github.com/blurpy/8-bit-computer-eeprom) for code for generating microcode for the EEPROMs.
12 |
13 |
14 | ## Documentation
15 |
16 | * [programs](programs) is a folder with code for some example programs, with videos and description of how they work.
17 | * [hardware.md](hardware.md) describes the hardware with a summary of how it works.
18 | * [instruction_set.md](instruction_set.md) describes the supported instructions.
19 | * [control_lines.md](control_lines.md) describes the different control lines.
20 | * [instruction_decoding.md](instruction_decoding.md) contains the lookup table used by the instruction decoder, and a short description of how it works.
21 | * [issues.md](issues.md) describes a list of the issues I had with getting the computer to work reliably, and what I did to fix them.
22 |
23 |
24 | ## Links
25 |
26 | * [eater.net/8bit](https://eater.net/8bit) - Homepage of the computer, for schematics, kits and more.
27 | * [/r/beneater](https://www.reddit.com/r/beneater/) - Useful subreddit to get help when building.
28 | * [Building an 8-bit breadboard computer](https://www.youtube.com/playlist?list=PLowKtXNTBypGqImE405J2565dvjafglHU) - Videos by Ben Eater on how to build the computer.
29 |
--------------------------------------------------------------------------------
/control_lines.md:
--------------------------------------------------------------------------------
1 | # Control lines
2 |
3 | |Code|Description|
4 | |----|-----------|
5 | |HLT|Halt the computer. Stops the clock.|
6 | |MI|Memory address register in|
7 | |RI|RAM in|
8 | |RO|RAM out|
9 | |II|Instruction register in|
10 | |IO|Instruction register out|
11 | |AI|A register in|
12 | |AO|A register out|
13 | |BI|B register in|
14 | |BO|B register out (not connected)|
15 | |S- (_SU_)|ALU subtract mode|
16 | |SO (_EO_)|ALU sum register out|
17 | |OI|Output display register in|
18 | |O-|Output display signed mode (not connected)|
19 | |CE|Program counter enable. Increment on clock pulse.|
20 | |CO|Program counter out|
21 | |CJ (_J_)|Program counter jump (program counter in)|
22 | |FI|Flags register in|
23 |
24 | _Code in parentheses is what Ben uses in the videos._
25 |
--------------------------------------------------------------------------------
/hardware.md:
--------------------------------------------------------------------------------
1 | # Hardware
2 |
3 | [](resources/8-bit-computer-fritzing.png)
4 |
5 | The diagram above has all the components, but most of the wiring is not displayed.
6 |
7 |
8 | ## Summary
9 |
10 | * 8-bit wide bus
11 | * 16 bytes of memory (4-bit addressing)
12 | * 2 general purpose registers
13 | * Arithmetic logic unit with support for addition and subtraction
14 | * 7-segment output display
15 | * Programmable using DIP-switches
16 | * Based on the SAP-1 architecture with some additions from SAP-2
17 | * Instruction set is a subset of Intel 8080
18 | * Support for single stepping the clock
19 | * Instruction decoder based on microcode
20 | * Zero and carry flags
21 |
22 |
23 | ## Integrated circuits
24 |
25 | |Name|Type|
26 | |---|---|
27 | |555|Timer|
28 | |74LS00|Quad NAND gate|
29 | |74LS02|Quad NOR gate|
30 | |74LS04|Hex Inverter|
31 | |74LS08|Quad AND gate|
32 | |74LS32|Quad OR gate|
33 | |74LS86|Quad XOR gate|
34 | |74LS107|Dual JK flip-flop|
35 | |74LS138|3:8 line demultiplexer|
36 | |74LS139|Dual 2:4 line demultiplexer|
37 | |74LS157|Quad 2:1 line multiplexer|
38 | |74LS161|4-bit binary counter|
39 | |74LS173|4-bit D register|
40 | |74189|64-bit (16 x 4 bits) Static RAM|
41 | |74LS245|8-bit 3-state buffer / bus transceiver|
42 | |74LS273|8-bit D register|
43 | |74LS283|4-bit binary adder with carry|
44 | |AT28C16|16Kb (2K x 8 bits) EEPROM|
45 |
46 |
47 | ## Bus
48 |
49 | The bus is an 8-bit wide signal path used for communication between the different parts of the computer. The instruction decoder decides who can read and write to the bus at any point in time, to avoid concurrency issues.
50 |
51 | * LEDs
52 | * 8x Red: for showing the current value on the bus.
53 |
54 |
55 | ## Clock
56 |
57 | The clock is a square wave at 50% duty cycle and is used for triggering and synchronizing operations in the computer. Supports variable speed from 1.5Hz to 1kHz and also single stepping.
58 |
59 | * Chips
60 | * 3x 555 timer
61 | * The first is in astable mode. It generates a 50% duty cycle square wave for a continuous clock timer.
62 | * The second is in monostable mode. It's used as a debounce circuit for the single step push button, to generate a manual pulse.
63 | * The third is in bistable mode. It's used as a debounce circuit for mode toggle switch.
64 | * 74LS04 inverter: these 3 last chips are for creating the logic circuit that allows outputting the clock signal from the selected mode, as well as disabling the clock output when halted.
65 | * 74LS08 AND gate: see above.
66 | * 74LS32 OR gate: see above.
67 | * Inputs
68 | * Potentiometer: for controlling the speed of the clock.
69 | * Push button: for single stepping the clock.
70 | * Toggle switch: for switching between continuous mode or single step mode.
71 | * Outputs
72 | * The normal clock signal.
73 | * The inverted clock signal. This is just the normal clock signal sent through the inverter.
74 | * LEDs
75 | * 3x Yellow
76 | * The first shows the square wave from the first 555 timer.
77 | * The second shows the debounced output of the second 555 timer.
78 | * The third shows the mode the clock is in. The LED is off in single step mode and on in continuous mode.
79 | * 1x Blue: this LED shows the normal outgoing clock signal, either in sync with the clock timer or the single steps.
80 | * Control signals
81 | * HLT: halts the clock.
82 |
83 |
84 | ## Memory Address Register (MAR)
85 |
86 | A 4-bit register that keeps track of the active memory address for the RAM.
87 |
88 | Can be put in programming mode together with the RAM for manual control with DIP-switches.
89 |
90 | * Chips
91 | * 74LS173 register: for storing the current 4-bit address in run mode.
92 | * 74LS157 multiplexer: for selecting between the address from the MAR or from the DIP-switch.
93 | * Inputs
94 | * 4-bit DIP switch: for setting the address in programming mode.
95 | * Toggle switch: for switching between run mode and programming mode. Also applies to the RAM.
96 | * Outputs
97 | * The 4-bit address from the selected mode goes to the RAM.
98 | * LEDs
99 | * 1x Green: for showing when it's in run mode.
100 | * 1x Red: for showing when it's in programming mode.
101 | * 4x Yellow address LEDs: shows the current 4-bit address in the selected mode.
102 | * Control signals
103 | * MI: store a 4-bit address from the bus into the MAR, on the next clock tick.
104 |
105 |
106 | ## Random Access Memory (RAM)
107 |
108 | 16 bytes of static RAM.
109 |
110 | Any of the 16 bytes can be read and written to, but it behaves like a regular 8-bit register in that it only works with 1 byte at a time. The MAR must be used for selecting which byte to read from or write to.
111 |
112 | Can be put in programming mode together with the MAR for manual control with DIP-switches.
113 |
114 | * Chips
115 | * 2x 74189 RAM: for storing 16 bytes of data or instructions. The outputs are inverted.
116 | * 2x 74LS04 inverter: to invert back the data in the RAM.
117 | * 74LS245 buffer: to control when it's outputting to the bus.
118 | * 3x 74LS157 multiplexer
119 | * The first is used for controlling whether the program button, or the RI control signal can write to the RAM, depending on mode.
120 | * The two others are used for selecting between the 8-bits of data coming from the bus, or from the DIP-switch, depending on mode.
121 | * 74LS00 NAND gate: enables the RI control signal only on the rising edge of the clock.
122 | * Inputs
123 | * 4-bit memory address from the MAR.
124 | * Push button: for setting the value from the DIP switch into the current memory address of the RAM in programming mode.
125 | * 8-bit DIP switch: for setting the value to be put into RAM when pushing the button, in programming mode.
126 | * Toggle switch: for switching between run mode and programming mode. From the MAR. Goes into all the multiplexers.
127 | * LEDs
128 | * 8x Red LEDs: for showing the 8-bit value at the current address in RAM.
129 | * Control signals
130 | * RI: store an 8-bit value from the bus into the current memory address, on the next clock tick.
131 | * RO: put an 8-bit value from the current memory address onto the bus.
132 |
133 |
134 | ## Reset
135 |
136 | Reset button that connects to all the different parts of the computer to clear the state. This is required before starting a program since the computer comes up in a random state, and when restarting a program.
137 |
138 | * Chips
139 | * 74LS00 NAND gate: for creating the necessary signals that will reset the other chips.
140 | * Inputs
141 | * Push button: for initiating a reset.
142 |
143 |
144 | ## Instruction Register
145 |
146 | 8-bit register that contains the currently executing instruction.
147 |
148 | Instructions are made up of an opcode and an operand, both 4 bits each. The opcode tells which instruction to execute while the operand contains extra data related to the instruction, like a memory address to jump to, or a small value to put into another register. See [instruction_set.md](instruction_set.md) for more about instructions.
149 |
150 | The instruction register is very similar to the general purpose A and B registers, except how it's used. The 4 bits for the opcode goes to the instruction decoder, and only the 4 bits of the operand can be put out onto the bus.
151 |
152 | * Chips
153 | * 2x 74LS173 register: these are used for storing the 8-bit instruction.
154 | * 74LS245 buffer: to control when it's outputting to the bus.
155 | * Outputs
156 | * The opcode: goes directly to the instruction decoder.
157 | * LEDs
158 | * 4x Blue: shows the opcode.
159 | * 4x Yellow: shows the operand.
160 | * Control lines
161 | * II: store an 8-bit value from the bus into the register, on the next clock tick.
162 | * IO: put the 4-bit operand of the instruction onto the bus.
163 |
164 |
165 | ## Step Counter
166 |
167 | The step counter is a simple 3 bit binary counter, that counts in a loop from 0 to 4. The current step is shown both in binary and decimal using LEDs, and is used by the instruction decoder to know which of the 5 steps of the current instruction to execute. These steps are also called T-states, or timing states.
168 |
169 | Incrementing the steps happens on the inverted clock to give the instruction decoder time to prepare the control lines before the next normal clock tick.
170 |
171 | * Chips
172 | * 74LS161 counter: for doing the counting.
173 | * 74LS138 demultiplexer: used for converting the binary value from the counter into decimal. Also used for resetting the counter after it reaches step 5.
174 | * Outputs
175 | * 3-bit step: goes directly into the instruction decoder.
176 | * LEDs
177 | * 3x Red: shows the current step in binary. Note that the bit order is opposite compared to the other binary displays, so 4 is `001` instead of `100`.
178 | * 5x Green: shows the current step, as the LED that is off.
179 | * 1x Blue: shows the inverted clock.
180 |
181 |
182 | ## Instruction Decoder
183 |
184 | The instruction decoder is responsible for orchestrating the control lines of the computer to make it do something useful.
185 |
186 | The control lines are the switches to the supported operations of the different parts, like RAM In and Instruction Register Out. Typically an operation either reads (in) from the bus or writes (out) to the bus.
187 |
188 | Every instruction takes 5 steps (microinstructions) to complete, called the instruction cycle, split into 2 phases.
189 |
190 | The first phase is the fetch phase. It consists of 2 steps that are the same every time:
191 | - step 0: Put the current value of the program counter into the memory address register.
192 | - step 1: Put the value of the RAM at the current address into the instruction register and increment the program counter.
193 |
194 | At this point the instruction decoder have access to the opcode from the instruction register, and the execution phase begins. The last 3 steps will differ for each instruction. An example could be to load some data from a specified location in RAM into the B-register, and store the sum of the A-register and B-register into the A-register. This is the ADD instruction.
195 |
196 | To make everything work, the instruction decoder gets which step to execute from the step counter on the falling edge of the clock cycle. It will then prepare the control lines for a particular step of a particular instruction, and that combination is called a control word. Output operations are executed right away, while input operations are executed on the next rising edge of the clock cycle.
197 |
198 | Some instructions also use flags to make decisions.
199 |
200 | EEPROMs are used for implementing the instruction decoder, based on a simple lookup table. See [instruction_decoding.md](instruction_decoding.md) for more details. They both have 11 address lines for inputs, and 8 outputs. 9 of the address lines are used by the opcode, the step and the flags, and are connected the same on both. The EEPROMs combined offer 16 outputs used as control lines, and one address line (A7) is hard wired differently to make the EEPROMs control 2 different sets of 8 control lines, since they are programmed the same.
201 |
202 | * Chips
203 | * 2x AT28C16 EEPROM: for the microcode that selects which control lines are to be enabled, based on the input.
204 | * 2x 74LS04 inverter: for inverting control signals going to active low inputs, like the memory address in, so the microcode and the LEDs don't have to worry about whether a signal being "on" activates or deactivates a function.
205 | * Inputs
206 | * 3-bit step counter value.
207 | * 4-bit opcode from the instruction register.
208 | * 2-bit flags, carry and zero, from the flags register.
209 | * Outputs
210 | * 16x control lines.
211 | * LEDs
212 | * 16x Blue: for showing which control lines are active.
213 | * 2x Blue: these are with the others, but are connected to 2 control lines that are manually controlled.
214 |
215 |
216 | ## Program Counter
217 |
218 | 4-bit counter that keeps track of the memory location of the next instruction to execute.
219 |
220 | Normal operation is to output the current value to the bus during the fetch cycle, and increment by 1 afterwards. Also supports jumping to a memory location read from the bus.
221 |
222 | * Chips
223 | * 74LS245 buffer: to control when it's outputting to the bus.
224 | * 74LS161 counter: for doing the counting.
225 | * LEDs
226 | * 4x Green: shows the value in the counter.
227 | * Control lines
228 | * CE: increment the counter by 1, on the next clock tick.
229 | * CO: put the 4-bit value from the counter onto the bus.
230 | * CJ: jump, by overwriting the current counter with a 4-bit value from the bus, on the next clock tick.
231 |
232 |
233 | ## A + B Register
234 |
235 | These are 2 independent 8-bit general purpose registers, primarily used in combination with the ALU.
236 |
237 | * Chips
238 | * 74LS245 buffer: to control when the register is outputting to the bus.
239 | * 2x 74LS173 register: these are used for storing an 8-bit value.
240 | * Outputs
241 | * Current value from both registers goes directly to the ALU.
242 | * LEDs
243 | * 8x Red: shows the value in the register.
244 | * Control lines
245 | * AI: store an 8-bit value from the bus into the A register, on the next clock tick.
246 | * AO: put the 8-bit from the A register onto the bus.
247 | * BI: store an 8-bit value from the bus into the B register, on the next clock tick.
248 | * BO: put the 8-bit from the B register onto the bus. This line is not in use in any of the current instructions.
249 |
250 |
251 | ## Arithmetic Logic Unit (ALU)
252 |
253 | An 8-bit ALU that can do addition and subtraction based on the values in the A- and B-registers, and output the result to the bus.
254 |
255 | Addition is performed as `A-register + B-register` and stored as soon as any of the registers change value, without waiting for the clock to tick.
256 |
257 | Subtraction can be invoked using the `S-` control line to perform a recalculation as `A-register - B-register`. Subtraction is a one off operation and not a state change, so the result will be overwritten using addition when `S-` turns off.
258 |
259 | Both types of calculations result in some status bits being set.
260 |
261 | The bits are:
262 | - Carry: whether the calculation results in a number larger than 8 bit (255) and has wrapped around.
263 | - Zero: whether the calculation results in 0.
264 |
265 | The bits change immediately after a calculation. The carry bit is part of the adder chips, while the zero bit is calculated using additional circuitry that was added to support the flags register.
266 |
267 | Subtraction happens using two's compliment.
268 |
269 | Example:
270 | ```
271 | 30 - 12
272 | 30 = 0001 1110
273 | 12 = 0000 1100
274 | ```
275 |
276 | Since the computer only does addition, we can convert 12 to -12 using two's compliment, and then think of the calculation as 30 + -12.
277 |
278 | Two's compliment of 12 is done by inverting the bits and adding 1.
279 |
280 | ```
281 | Inverted 12 = 1111 0011
282 | +1 = 1111 0100
283 | = 244
284 | ```
285 |
286 | The calculation then becomes:
287 |
288 | ```
289 | 30 + 244 = 274
290 | 274 = 1 0001 0010
291 | ```
292 |
293 | Or 18 (`0001 0010`) + the carry bit
294 |
295 | This is why the carry bit LED is often on when subtracting.
296 |
297 | The carry bit is not set when the result is 255 and less.
298 | Example:
299 |
300 | ```
301 | 0 - 1
302 | 0 = 0000 0000
303 | 1 = 0000 0001
304 | Inverted 1 = 1111 1110
305 | +1 = 1111 1111
306 | = 255
307 | 0 + 255 = 255 (no carry needed)
308 | ```
309 |
310 | Technically this is solved using the XOR gates and `S-`. The B register is connected to one of the sets of inputs, and `S-` to the other sets of inputs. When `S-` is enabled, the XOR gates will output the inverted value of the B register, and when it's disabled it will output the original value of the B register. That output goes into the adders. To get the +1 we need for two's compliment we send `S-` to carry in on the adders as well.
311 |
312 | * Chips
313 | * 74LS245 buffer: to control when the result is outputted to the bus.
314 | * 2x 74LS283 adder: to support 8-bit addition.
315 | * 2x 74LS86 XOR gate: to invert the value in the B register when `S-` is enabled, to support subtraction.
316 | * Inputs
317 | * Current value from both A and B registers.
318 | * Outputs
319 | * Carry bit: goes to the flags register.
320 | * Result: goes to the flags register circuitry for the zero bit.
321 | * LEDs
322 | * 8x Red: shows the result of the calculation.
323 | * 1x Blue: shows if there is a carry in the result.
324 | * Control lines
325 | * SO: put the 8-bit result onto the bus.
326 | * S-: calculate using subtraction instead of addition.
327 |
328 |
329 | ## Flags Register
330 |
331 | Register used for flags.
332 |
333 | Flags are 1 bit values (0 or 1 / false or true) that can be stored and used for making decisions by the instruction decoder.
334 |
335 | The flags are:
336 | - Carry: whether the ALU calculation results in a number larger than 8 bit (255) and has wrapped around.
337 | - Zero: whether the ALU calculation results in 0.
338 |
339 | I included the circuitry for the zero bit here, but it can be debated whether it's part of the ALU or the flags register. I chose here, because the ALU by itself does not use the extra chips for anything, while the flags register depend on them.
340 |
341 | * Chips
342 | * 74LS173 register: for storing the 2 flags.
343 | * 74LS02 NOR gate: these gates make up the circuit that will detect if all the bits from the result in the ALU is 0. This becomes the zero bit.
344 | * 74LS08 AND gate: see above.
345 | * Inputs
346 | * Carry bit: from the ALU.
347 | * 8-bit result from the ALU: for checking for 0.
348 | * Outputs
349 | * 1-bit carry flag: goes directly into the instruction decoder.
350 | * 1-bit zero flag: goes directly into the instruction decoder.
351 | * LEDs
352 | * 2x Green: for showing the value of the flags.
353 | * 1x Blue: for showing the value of the zero bit.
354 | * Control lines
355 | * FI: stores the current value of the carry bit and zero bit into the register, on the next clock tick.
356 |
357 |
358 | ## Output Register
359 |
360 | The register that drives the four 7-segment LEDs, for displaying an 8-bit value that can be signed or unsigned.
361 |
362 | The normal operation is the unsigned mode, where the 8-bit value goes from 0 to 255.
363 | The signed mode allows it to display values from -128 to 127. This is the same two's compliment representation of numbers as used in the ALU for subtraction. The first bit is the sign, so counting from 0 to 255 in this mode would go like this:
364 |
365 | ```
366 | 0 (0000 0000)
367 | 1 (0000 0001) (skip...)
368 | 126 (0111 1110)
369 | 127 (0111 1111)
370 | -128 (1000 0000)
371 | -127 (1000 0001) (skip...)
372 | -1 (1111 1111)
373 | ```
374 |
375 | The way the display works is by multiplexing the 7-segment LEDs, which is a very common way of working with these. The concept is that only one LED is displaying at any time, and you cycle through them very fast to create an illusion of a solid display.
376 |
377 | The circuit has a separate clock and counter for that cycling. The counter decides which LED is active, and the EEPROM uses a lookup table to know which of the segments of that LED to enable to get the correct number displayed.
378 |
379 | The clock runs at 760Hz, making the counter enable each LED 190 times per second.
380 |
381 | * Chips
382 | * 555 timer: used as an independent clock for the counter.
383 | * 74LS107 flip-flop: used as a 2-bit counter that increments on clock ticks.
384 | * 74LS139 demultiplexer: converts the 2-bit counter into 4 separate lines to control the LEDs.
385 | * AT28C16 EEPROM: for the microcode that converts the binary value into which segments to enable on the LEDs.
386 | * 74LS273 register: for storing the 8-bit value to display.
387 | * 74LS08 AND gate: used for combining the clock signal with the control signal to decide when to store a value from the bus into the register, since the register lacks an enable pin.
388 | * LEDs
389 | * 4x 7-segment LEDs: for showing a binary value in decimal.
390 | * Control lines
391 | * OI: store an 8-bit value from the bus into the register, on the next clock tick.
392 | * O-: enable signed mode. This line is not in use in any of the current instructions.
393 |
394 |
395 | ## Thermals
396 |
397 | The computer runs pretty cool. None of the chips get hot to the touch.
398 |
399 | The image below was taken after more than 30 minutes of continuously running the program that counts between 0 and 255, at high speed. It's interesting to see that there are 2 "hot spots". The first is the 74189 RAM chips, which is not that surprising. The second is the 74LS08 AND gate on the output register, which I do find surprising. I am not sure why that gets hotter than other chips.
400 |
401 | Also interesting to note that the power wires along the top right corner get hotter than the rest of the power wiring. It might be a good spot to make improvements to power transportation.
402 |
403 | 
404 |
--------------------------------------------------------------------------------
/instruction_decoding.md:
--------------------------------------------------------------------------------
1 | # Instruction decoding
2 |
3 | This is a table of how instructions are decoded, or mapped to the control lines in the CPU microcode in the EEPROMs.
4 |
5 | An instruction consists of 5 steps, or microinstructions. In binary they are represented as 000 -> 100, seen in the red LEDs, and as individual steps, or T-states, seen in the green LEDs. The first 2 steps in every instruction is FETCH. FETCH is not an actual instruction, but included in the table at the top to avoid repetition. The FETCH step is used to load the next instruction from memory into the instruction register. The other instructions are described in [instruction_set.md](instruction_set.md), and the control lines in [control_lines.md](control_lines.md).
6 |
7 | Every clock cycle increases the step counter until it reaches 5 and then it wraps around and starts at 1 again. The line in this table to execute after FETCH is decided based on the opcode in the instruction register, the current step, and the flags. That's why some instructions show 2 lines for the same step with different flags. Only one of the lines will be executed at that step.
8 |
9 | X in this table means that the value in that field can be anything and the line will still execute if the others match.
10 |
11 | |Instruction|Opcode|Step|CZ|ZF| |HLT|MI|RI|RO|II|IO|AI|AO|BI|BO|S-|SO|OI|O-|CE|CO|CJ|FI|
12 | |-----------|------|----|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
13 | |FETCH|XXXX|000|X|X| | |1| | | | | | | | | | | | | |1| | |
14 | | | |001|X|X| | | | |1|1| | | | | | | | | |1| | | |
15 | |NOP |0000|010|X|X| | | | | | | | | | | | | | | | | | | |
16 | | | |011|X|X| | | | | | | | | | | | | | | | | | | |
17 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
18 | |LDA |0001|010|X|X| | |1| | | |1| | | | | | | | | | | | |
19 | | | |011|X|X| | | | |1| | |1| | | | | | | | | | | |
20 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
21 | |ADD |0010|010|X|X| | |1| | | |1| | | | | | | | | | | | |
22 | | | |011|X|X| | | | |1| | | | |1| | | | | | | | | |
23 | | | |100|X|X| | | | | | | |1| | | | |1| | | | | |1|
24 | |SUB |0011|010|X|X| | |1| | | |1| | | | | | | | | | | | |
25 | | | |011|X|X| | | | |1| | | | |1| | | | | | | | | |
26 | | | |100|X|X| | | | | | | |1| | | |1|1| | | | | |1|
27 | |STA |0100|010|X|X| | |1| | | |1| | | | | | | | | | | | |
28 | | | |011|X|X| | | |1| | | | |1| | | | | | | | | | |
29 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
30 | |LDI |0101|010|X|X| | | | | | |1|1| | | | | | | | | | | |
31 | | | |011|X|X| | | | | | | | | | | | | | | | | | | |
32 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
33 | |JMP |0110|010|X|X| | | | | | |1| | | | | | | | | | |1| |
34 | | | |011|X|X| | | | | | | | | | | | | | | | | | | |
35 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
36 | |JC |0111|010|0|X| | | | | | | | | | | | | | | | | | | |
37 | | | |010|1|X| | | | | | |1| | | | | | | | | | |1| |
38 | | | |011|X|X| | | | | | | | | | | | | | | | | | | |
39 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
40 | |JZ |1000|010|X|0| | | | | | | | | | | | | | | | | | | |
41 | | | |010|X|1| | | | | | |1| | | | | | | | | | |1| |
42 | | | |011|X|X| | | | | | | | | | | | | | | | | | | |
43 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
44 | |OUT |1110|010|X|X| | | | | | | | |1| | | | |1| | | | | |
45 | | | |011|X|X| | | | | | | | | | | | | | | | | | | |
46 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
47 | |HLT |1111|010|X|X| |1| | | | | | | | | | | | | | | | | |
48 | | | |011|X|X| | | | | | | | | | | | | | | | | | | |
49 | | | |100|X|X| | | | | | | | | | | | | | | | | | | |
50 |
--------------------------------------------------------------------------------
/instruction_set.md:
--------------------------------------------------------------------------------
1 | # Instruction set
2 |
3 | The full instruction set of the 8-bit computer.
4 |
5 | The instructions can either reference a 4-bit memory address or a 4-bit value in the operand.
6 |
7 | |#|Mnemonic|Name|Opcode|Operand|Flags set|Flags read|Description|
8 | |---|------|----|---------|------------|----|---|---|
9 | |0|NOP|No operation|0000|Unused| | |Do nothing for a cycle|
10 | |1|LDA|Load the accumulator|0001|Memory reference| | |Put the value of the referenced memory address into the A-register|
11 | |2|ADD|Add|0010|Memory reference|CZ| |Put the value of the referenced memory address into the B-register, and put the sum of A+B into the A-register|
12 | |3|SUB|Subtract|0011|Memory reference|CZ| |Put the value of the referenced memory address into the B-register, and put the sum of A-B into the A-register|
13 | |4|STA|Store the accumulator|0100|Memory reference| | | Store the value of the A-register into the referenced memory address|
14 | |5|LDI|Load immediate|0101|Value| | |Put the value from the operand into the A-register|
15 | |6|JMP|Jump|0110|Memory reference| | |Jump to the instruction at the referenced memory address|
16 | |7|JC|Jump if carry|0111|Memory reference| |C|Jump to the instruction at the referenced memory address if the carry flag is set|
17 | |8|JZ|Jump if zero|1000|Memory reference| |Z|Jump to the instruction at the referenced memory address if the zero flag is set|
18 | |14|OUT|Output|1110|Unused| | |Output the value of the A-register on the 7-segment display|
19 | |15|HLT|Halt|1111|Unused| | |Halt the computer|
20 |
--------------------------------------------------------------------------------
/issues.md:
--------------------------------------------------------------------------------
1 | # Issues
2 |
3 | I ran into many issues trying to get the 8-bit computer to work. This is my documentation of the issues and the fixes.
4 |
5 |
6 | ## LEDs without resistors
7 |
8 | I started by following the videos step by step, and when it came to testing the first register I couldn't get it to work. The red LEDs on the register would be very faint and randomly on/off, and the yellow LEDs on the temporary bus would not light up at all.
9 |
10 | The booklet that came with the kit suggested adding resistors to the LEDs, but there wasn't any room on the breadboard for that. I found a good tip in this post on reddit: [What I Have Learned (a master list of what to do and what not to do)](https://www.reddit.com/r/beneater/comments/dskbug/what_i_have_learned_a_master_list_of_what_to_do/)
11 |
12 | I soldered resistors to the LEDs as suggested, and the register started working like in the video.
13 |
14 | 
15 |
16 | I grew tired of soldering resistors to all the LEDs, so I went for LEDs with resistors built-in instead:
17 |
18 | * [Kingbright L-7113ID-5V - 5v Red LED](https://no.rs-online.com/web/p/leds/8609709/)
19 | * [Kingbright L-7113GD-5V - 5v Green LED](https://no.rs-online.com/web/p/leds/8609696/)
20 | * [Kingbright L-7113YD-5V - 5v Yellow LED](https://no.rs-online.com/web/p/leds/8609712/)
21 | * [VCC LTH5MM12VFR4600 - 12v Clear Blue LED](https://www.digikey.no/product-detail/en/visual-communications-company-vcc/LTH5MM12VFR4600/LTH5MM12VFR4600-ND/6691221)
22 |
23 | The red, green and yellow LEDs were directly replaceable with the 5v ones from Kingbright, but I could not find any of the blue kind. Most of the blue LEDs are in positions with room for a resistor on the breadboard, so I kept the original ones. I soldered resistors only on the 4 used in the instruction register, seen in the picture above.
24 |
25 | The blue were a bit bright with the 220Ω resistors, so I went with 1kΩ resistors on those.
26 |
27 | I used the clear blue 12v LEDs for the ALU carry and zero bits (not the flags). They are way too bright on 12v, but fine on 5v.
28 |
29 |
30 | ## Single stepping the clock leads to occasional double step
31 |
32 | Video showcasing the glitch:
33 |
34 | [](https://www.youtube.com/watch?v=wE0VCkTokac "Click to play")
35 |
36 | The video shows me single stepping the clock. After a few steps, we can see the program counter going from `1000` to `1010` from one click of the button, skipping very quickly past the expected value of `1001`. The oscilloscope in the video shows the output from the button. Notice the very thin dip about 2/3 of the way. This is enough for it to register as 2 clock ticks. The same can be seen in this screenshot:
37 |
38 | 
39 |
40 | The problem is in the monostable 555 timer circuit that is supposed to handle debouncing. The size of the capacitor used on pin 6 decides how long the debounce lasts, and the capacitor used by default in the kit is 0.1μF (104). This works fine usually, but not every time. Replacing it with a 0.33μF (334) capacitor makes the debounce much more reliable.
41 |
42 | 
43 |
44 |
45 | ## Long single step leads to spurious clock ticks
46 |
47 | Video showcasing the glitch:
48 |
49 | [](https://www.youtube.com/watch?v=cVWIPq9-fGs "Click to play")
50 |
51 | The video shows me single stepping the clock by holding the button down, and the program counter increments at a very rapid rate. The oscilloscope in the video shows the output from the button. Notice the amount of high frequency noise in the signal from the button. The same can be seen in this screenshot:
52 |
53 | 
54 |
55 | This is related to the same monostable 555 timer circuit as in the previous issue. But for some reason the signal is clean for a short period when first pressing the button, but pretty soon it gets very noisy. I fixed it by replacing the monostable timer that came with the kit, a Fairchild LM555CN, with a Texas Instruments NE555P I had lying around.
56 |
57 | The same test looks much better afterwards:
58 |
59 | 
60 |
61 | And the clock only ticks once when keeping the button pressed.
62 |
63 |
64 | ## Registers latching out of phase with the clock
65 |
66 | Video showcasing the glitch:
67 |
68 | [](https://www.youtube.com/watch?v=abie2o01HV0 "Click to play")
69 |
70 | The video shows a program running that should count from 0 to 15 in repeat. The program counter and the bus are reacting much faster than the clock, and when looking at the output display we can also see that it skips values, counting 0 -> 2 -> 5 -> 11 -> 15. I have a temporary configuration in place where I can move between the original circuit and the fixed circuit to demonstrate that it counts normal with the fixed circuit.
71 |
72 | Everything seemed to work fine when building the RAM module and testing it in isolation. However, when I started connecting the other modules the whole thing started behaving erratic, like in the video.
73 |
74 | The problem stems from the clock signal that goes into the NAND-gate on the right, through the RC-circuit. The capacitor creates some resonance that travels back through the clock wires and disturbs everything else connected to the same clock, leading to registers latching out of phase with the actual clock.
75 |
76 | This shows the original circuit:
77 |
78 | 
79 |
80 | And this shows the fixed circuit. The NAND-gate is used to isolate the clock signal by running it through the inverter 2 times before being sent to the RC-circuit.
81 |
82 | 
83 |
84 | More about this issue on Reddit: [What I Have Learned](https://www.reddit.com/r/beneater/comments/dskbug/what_i_have_learned_a_master_list_of_what_to_do/).
85 |
86 |
87 | ## RAM mode switch changes memory content
88 |
89 | Video showcasing the glitch:
90 |
91 | [](https://www.youtube.com/watch?v=y0mx79ixhco "Click to play")
92 |
93 | The video shows repeated switching between run mode and programming mode on the RAM module. The address set by the DIP switch is `1111`, and that address in RAM contains the value `0000 1110`. The MAR itself is set to `0001` and that address in RAM contains the value `1100 1111`. The first mode switches works fine, but suddenly the value in RAM at address `0001` changes to `0000 0010`.
94 |
95 | The reason can be seen on the oscilloscope:
96 |
97 | 
98 |
99 | The oscilloscope probe is connected to pin 12 of the 74LS157 (next to the program button), that goes to pin 3 of the 74189, which is the active-low write-enable pin. The signal should be high when it's not writing to the RAM, but sometimes there is a dip in the signal when pressing the mode switch, making it write whatever it can see on the inputs at the moment. The switch probably has a debounce problem. Putting a 104 capacitor (highlighted) on pin 12 to VCC solves the issue. The signal is not affected anymore when pressing the mode switch after that.
100 |
101 | 
102 |
103 | Note that I'm not using the mode switch that came with the kit.
104 |
105 |
106 | ## A register resetting
107 |
108 | Video showcasing the glitch:
109 |
110 | [](https://www.youtube.com/watch?v=n3ou3BL5uEU "Click to play")
111 |
112 | The video shows the program for counting back and forth between 0 and 255, and when it's supposed to go from 126 to 127 it goes from 126 to 1 instead.
113 |
114 | Looking at the reset line connected to the 74LS173 flags register on pin 15 (CLR) we can see quite a bit of noise, including a large spike on the right side at 1.84v. The spike is enough to cause the A register to reset to 0 at the last step of the ADD instruction in the video, when it's about to move 127 from the ALU to the bus. Since the A register turns 0, and the B register is 1, the result of the ADD is 1 which is stored in the A register and displayed shortly after as part of the OUT instruction.
115 |
116 | I'm guessing the noise spikes on the reset line are related to power. In this example the ALU has 7 LEDs enabled, the A register has 6. When trying to enable 7 LEDs on the bus it causes a sudden power increase and creates noise that resets the A register.
117 |
118 | 
119 |
120 | Putting a 104 capacitor (highlighted) on the reset line to ground on the flags register removes the noise and solves the issue. It's a bit cramped on the A register itself, but the reset line is directly connected between the flags register and the A register, so that's probably why it still has the desired effect.
121 |
122 | 
123 |
124 |
125 | ## Memory address register resetting
126 |
127 | Video showcasing the glitch:
128 |
129 | [](https://www.youtube.com/watch?v=8U1HI5aMM8Q "Click to play")
130 |
131 | The video shows the program for counting back and forth between 0 and 255, but in steps of 31 instead of 1, as can be seen from the binary value of `0001 1111` in the B register. The program seems to get a bit stuck when counting down, taking a long time before continuing.
132 |
133 | The trick to provoking this issue is calculations with larger values. Lower values like the regular counting by 1 works like expected.
134 |
135 | The problem starts when it's at the last instruction of the program, and jumps to memory address 4. As soon as the memory address changes to `0100`, which is the subtract instruction, the memory address resets to 0, and the output instruction at address 0 is loaded into the instruction register instead of the subtract instruction. This effectively makes that round in the loop a no-op. This happens a few times before it eventually manages to load the subtract instruction and gets one step further in the countdown. In the video we see the struggle from 124 > 93 > 62, and it's slightly easier to get to 31, and very easy to get to 0, as well as counting up.
136 |
137 | There is noise on the reset line on the memory address register as well, but putting a capacitor on pin 15 doesn't completely fix the issue, even though it helps a bit. What fixes it is adding a 104 decoupling capacitor across VCC (pin 16) and ground (pin 8) on the 74LS173, like shown below. The position is very awkward, so be sure not to short any of the pins.
138 |
139 | 
140 |
141 |
142 | ## Power
143 |
144 | Reliable power is important for a stable computer. These are the fixes I did.
145 |
146 | 1. Bad connection with the breadboard.
147 |
148 | I originally used breadboard wire with dupont pins from the terminal connector of the power supply to the breadboard. The dupont pins didn't make good enough contact to transfer the power required, so LEDs would change in intensity all the time, and touching the power wires or moving the breadboard would make the whole computer blink and sometimes reset.
149 |
150 | To make a better connection I soldered much more solid wire to 2x4 header pins and that solved the problem fully.
151 |
152 | 2. Low voltage.
153 |
154 | I started with a 180cm commercial cable with banana plugs on one end and a terminal plug on the other end, but under load I noticed it would lose about 0.4v. I have the power supply set to 5.1v and on the pins connected to the breadboard it would read 4.7v, and on the opposite side of the bus it would be as low as 4.4v.
155 |
156 | To avoid unnecessary voltage loss, I made my own cable, using thicker wires and also much shorter at only 60cm. The voltage on the pins connected to the breadboard now read 5.05v.
157 |
158 | 3. Power fluctuations.
159 |
160 | That's where capacitors are helpful, they make sure power spikes don't bring the voltage too low.
161 |
162 | I tried many different strategies, but what worked the best for me was having larger capacitors on each side of the power connector, and lots of the 104 capacitors that came with the kit spread on the power rails of each breadboard.
163 |
164 | This picture demonstrates all the fixes:
165 |
166 | 
167 |
168 |
169 | ## Replacement parts
170 |
171 | Other than those mentioned elsewhere.
172 |
173 | 1. Slide switches
174 |
175 | The slide switches that came with the kit were troublesome. They would not sit firmly on the breadboard, and it was difficult to use them without bumping into other components in the tight space. I replaced them with these push buttons instead:
176 |
177 | * [NKK BB16AP - Miniature Pushbutton Switch](https://www.elfadistrelec.no/en/miniature-pushbutton-switch-1co-on-on-white-nkk-bb16ap/p/30141579)
178 |
179 | 2. DIP switches
180 |
181 | I had a bad experience with the DIP switches as well. Every time I tried to use them, they would pop out of the breadboard. I replaced them with these, and they sit perfectly on a breadboard:
182 |
183 | * [RND 210-00641 - DIP Switch, 8 Positions](https://www.elfadistrelec.no/en/dip-switch-slide-positions-54mm-pcb-pins-rnd-components-rnd-210-00641/p/30161218)
184 | * [RND 210-00637 - DIP Switch, 4 Positions](https://www.elfadistrelec.no/en/dip-switch-slide-positions-54mm-pcb-pins-rnd-components-rnd-210-00637/p/30161214)
185 |
186 | 3. Breadboard wire
187 |
188 | I ran out of green breadboard wire while working on the last kit. Ordering more wire from Jameco would be very expensive due to customs, but I tried the wire from SparkFun, and it was very similar to the original one.
189 |
190 | * [SparkFun PRT-11367 - Solid Core Hook-Up Wire 7.6m](https://www.elfadistrelec.no/en/solid-core-hook-up-wire-assortment-6m-sparkfun-electronics-prt-11367/p/30145492)
191 |
192 | These parts can be seen in the pictures of the computer.
193 |
194 | 4. Clock capacitor
195 |
196 | I replaced the 1μF electrolytic capacitor on the astable 555 timer with a 0.47μF (474) ceramic capacitor instead, to give me a faster clock. This allows the clock to go from 1.5Hz to 1kHz, instead of 0.7Hz to 500Hz.
197 |
198 | 
199 |
--------------------------------------------------------------------------------
/programs/add_two_numbers.md:
--------------------------------------------------------------------------------
1 | # Program: Add two numbers
2 |
3 | Example program that calculates 28+14 and displays the result on the display.
4 |
5 | |#|Instruction|Address|Memory|Comment|
6 | |---|---------|-------|------|-------|
7 | | 0|LDA 14|0000|0001 1110|Put the value 28 from the X variable in the A-register|
8 | | 1|ADD 15|0001|0010 1111|Put the value 14 from the Y variable in the B-register and store A+B in the A-register|
9 | | 2|OUT |0010|1110 0000|Output 42 from the A-register|
10 | | 3|HLT |0011|1111 0000|Halt the computer|
11 | | | | | | |
12 | |14| X|1110|0001 1100|The X variable predefined with the value 28|
13 | |15| Y|1111|0000 1110|The Y variable predefined with the value 14|
14 |
15 | [](https://www.youtube.com/watch?v=i1SjtPZZONY "Click to play")
16 |
17 | This program is from [8-bit CPU control logic: Part 3](https://www.youtube.com/watch?v=dHWFpkGsxOs).
18 |
--------------------------------------------------------------------------------
/programs/count_0_255.md:
--------------------------------------------------------------------------------
1 | # Program: Counting between 0 and 255
2 |
3 | Example program that counts up and down between 0 and 255 in an infinite loop.
4 |
5 | |#|Instruction|Address|Memory|Comment|
6 | |---|---------|-------|------|-------|
7 | | 0|OUT |0000|1110 0000|Output the value of the A-register|
8 | | 1|ADD 15|0001|0010 1111|Put the value of the X variable in the B-register and store A+B in the A-register|
9 | | 2|JC 4|0010|0111 0100|Jump to instruction 4 if the A-register is past 255|
10 | | 3|JMP 0|0011|0110 0000|Jump to instruction 0|
11 | | 4|SUB 15|0100|0011 1111|Put the value of the X variable in the B-register and store A-B in the A-register|
12 | | 5|OUT |0101|1110 0000|Output the value of the A-register|
13 | | 6|JZ 0|0110|1000 0000|Jump to instruction 0 if the A-register is 0|
14 | | 7|JMP 4|0111|0110 0100|Jump to instruction 4|
15 | | | | | | |
16 | |15| X|1111|0000 0001|The X variable predefined with the value 1|
17 |
18 | This table displays the values of registers, variables and output after the first 5 iterations of the program, and at the 2 points where it switches between increasing and decreasing.
19 |
20 | | | 0 | 1 | 2 | 3 | 4 |...|253|254| 255 |256|257|...|508|509| 510 |511|512|
21 | |---|---|---|---|---|---|---|---|---|-------|---|---|---|---|---|-----|---|---|
22 | | A | 1 | 2 | 3 | 4 | 5 | |254|255|0+C,255|254|253| | 2 | 1 |0+Z,1| 2 | 3 |
23 | | B | 1 | 1 | 1 | 1 | 1 | | 1 | 1 | 1 | 1 | 1 | | 1 | 1 | 1 | 1 | 1 |
24 | | X | 1 | 1 | 1 | 1 | 1 | | 1 | 1 | 1 | 1 | 1 | | 1 | 1 | 1 | 1 | 1 |
25 | |OUT| 0 | 1 | 2 | 3 | 4 | |253|254|255,255|254|253| | 2 | 1 | 0,0 | 1 | 2 |
26 |
27 | * Iteration 255 does both an ADD and a SUB due to the carry flag being set during ADD.
28 | * Iteration 510 does both an SUB and a ADD due to the zero flag being set during SUB.
29 | * Both results in the same value being output twice.
30 |
31 | [](https://www.youtube.com/watch?v=j12CcFnC9jI "Click to play")
32 |
33 | This program is from [Conditional jump instructions](https://www.youtube.com/watch?v=Zg1NdPKoosU).
34 |
--------------------------------------------------------------------------------
/programs/fibonacci.md:
--------------------------------------------------------------------------------
1 | # Program: Fibonacci
2 |
3 | Example program that computes the Fibonacci sequence from 0 to 233 in an infinite loop.
4 |
5 | In a Fibonacci sequence each number is the sum of the two preceding ones, starting from 0 and 1.
6 |
7 | |#|Instruction|Address|Memory|Comment|
8 | |---|---------|-------|------|-------|
9 | | 0|LDI 0|0000|0101 0000|Put the value 0 in the A-register|
10 | | 1|STA 13|0001|0100 1101|Store 0 from the A-register in the X variable|
11 | | 2|OUT |0010|1110 0000|Output the value of the A-register|
12 | | 3|LDI 1|0011|0101 0001|Put the value 1 in the A-register|
13 | | 4|STA 14|0100|0100 1110|Store the value from the A-register in the Y variable|
14 | | 5|OUT |0101|1110 0000|Output the value of the A-register|
15 | | 6|ADD 13|0110|0010 1101|Put the value of the X variable in the B-register and store A+B in the A-register|
16 | | 7|JC 0|0111|0111 0000|Jump to instruction 0 if the A-register is past 255|
17 | | 8|STA 15|1000|0100 1111|Store the value from the A-register in the Z variable|
18 | | 9|LDA 14|1001|0001 1110|Put the value of the Y variable in the A-register|
19 | |10|STA 13|1010|0100 1101|Store the value from the A-register in the X variable|
20 | |11|LDA 15|1011|0001 1111|Put the value of the Z variable in A-register|
21 | |12|JMP 4|1100|0110 0100|Jump to instruction 4|
22 | |13| X|1101| |The X variable|
23 | |14| Y|1110| |The Y variable|
24 | |15| Z|1111| |The Z variable|
25 |
26 | The output should be: `0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233`. This table displays the values of registers, variables and output after the first 5 iterations of the program.
27 |
28 | | | 0 | 1 | 2 | 3 | 4 | 5 |
29 | |---|---|---|---|---|---|---|
30 | | A | 1 | 2 | 3 | 5 | 8 |13 |
31 | | B | 0 | 1 | 1 | 2 | 3 | 5 |
32 | | X | 1 | 1 | 2 | 3 | 5 | 8 |
33 | | Y | 1 | 1 | 2 | 3 | 5 | 8 |
34 | | Z | 1 | 2 | 3 | 5 | 8 |13 |
35 | |OUT|0,1| 1 | 2 | 3 | 5 | 8 |
36 |
37 | [](https://www.youtube.com/watch?v=DTxpwynaN34 "Click to play")
38 |
39 | This program is based on [Programming Fibonacci on a breadboard computer](https://www.youtube.com/watch?v=a73ZXDJtU48).
40 | Using modified instructions from `csbruce` in the comments due to bug in the video that makes it wrap around at 144.
41 |
--------------------------------------------------------------------------------
/programs/increase_by_three.md:
--------------------------------------------------------------------------------
1 | # Program: Increase by 3
2 |
3 | Example program that increases by 3 in an infinite loop.
4 |
5 | |#|Instruction|Address|Memory|Comment|
6 | |---|---------|-------|------|-------|
7 | | 0|LDI 3|0000|0101 0011|Put the value 3 in the A-register|
8 | | 1|STA 15|0001|0100 1111|Store the value 3 from the A-register in the X variable|
9 | | 2|LDI 0|0010|0101 0000|Put the value 0 in the A-register|
10 | | 3|ADD 15|0011|0010 1111|Put the value of the X variable in the B-register and store A+B in the A-register|
11 | | 4|OUT |0100|1110 0000|Output the value of the A-register|
12 | | 5|JMP 3|0101|0110 0011|Jump to instruction 3|
13 | | | | | | |
14 | |15| X|1111| |The X variable|
15 |
16 | This table displays the values of registers, variables and output after the first 5 iterations of the program.
17 |
18 | | | 0 | 1 | 2 | 3 | 4 | 5 |
19 | |---|---|---|---|---|---|---|
20 | | A | 3 | 6 | 9 |12 |15 |18 |
21 | | B | 3 | 3 | 3 | 3 | 3 | 3 |
22 | | X | 3 | 3 | 3 | 3 | 3 | 3 |
23 | |OUT| 3 | 6 | 9 |12 |15 |18 |
24 |
25 | [](https://www.youtube.com/watch?v=IgK4RUf5AlI "Click to play")
26 |
27 | This program is from [Adding more machine language instructions to the CPU](https://www.youtube.com/watch?v=FCscQGBIL-Y).
28 |
--------------------------------------------------------------------------------
/programs/multiply_two_numbers.md:
--------------------------------------------------------------------------------
1 | # Program: Multiply two numbers
2 |
3 | Example program that calculates 7x8 and displays the result on the display.
4 |
5 | |#|Instruction|Address|Memory|Comment|
6 | |---|---------|-------|------|-------|
7 | | 0|LDA 14|0000|0001 1110|Put the value of the X variable in the A-register|
8 | | 1|SUB 12|0001|0011 1100|Put the value of the C constant in the B-register and store A-B in the A-register|
9 | | 2|JC 6|0010|0111 0110|Jump to instruction 6 if the A-register is past 255|
10 | | 3|LDA 13|0011|0001 1101|Put the value of the P variable in the A-register|
11 | | 4|OUT |0100|1110 0000|Output the value of the A-register|
12 | | 5|HLT |0101|1111 0000|Halt the computer|
13 | | 6|STA 14|0110|0100 1110|Store the value from the A-register in the X variable|
14 | | 7|LDA 13|0111|0001 1101|Put the value of the P variable in the A-register|
15 | | 8|ADD 15|1000|0010 1111|Put the value of the Y variable in the B-register and store A+B in the A-register|
16 | | 9|STA 13|1001|0100 1101|Store the value from the A-register in the P variable|
17 | |10|JMP 0|1010|0110 0000|Jump to instruction 0|
18 | | | | | | |
19 | |12| C|1100|0000 0001|The C constant predefined with the value 1|
20 | |13| P|1101|0000 0000|The P (product/answer) variable predefined with the value 0|
21 | |14| X|1110|0000 0111|The X (multiplicand) variable predefined with the value 7|
22 | |15| Y|1111|0000 1000|The Y (multiplier) variable predefined with the value 8|
23 |
24 | The computer does not have a dedicated instruction for multiplication, so the program adds in a loop. The algorithm can be translated to this C code:
25 |
26 | ```c
27 | int c = 1, p = 0, x = 7, y = 8;
28 | while (x > 0) {
29 | x = x - c;
30 | p = p + y;
31 | }
32 | printf("%d", p);
33 | ```
34 |
35 | The assembly doesn't immediately make sense, as it looks like it would skip the jump with carry and output 0 and halt, due to the first subtraction resulting in the value 6 and not something past 255. The trick is the usage of two's complement when subtracting in the ALU. The subtract instruction tells the ALU to treat the value 1 from the B-register as -1 and add the numbers. -1 is 1111 1111 in two's compliment. So the calculation turns into 0000 0111 (7) + 1111 1111 (255) which is 1 0000 0110 (262), or 0000 0110 (6) with carry since we only have 8 bits and a carry. That jump with carry is actually very useful in this case, as it can be used to easily decrement X by 1 until it's 0, in which case 0 + 255 is 255 and no more carry so the loop ends and the result is printed.
36 |
37 | The subtractions are calculated as follows:
38 |
39 | | | | | | | | | | | | |
40 | |-----|---|------------|---|---------------------|---|-----------|---|---|---|---|
41 | |7 - 1| ->|7 + -1 (255)| = |0000 0111 + 1111 1111| = |1 0000 0110| = |262| = |6+C|
42 | |6 - 1| ->|6 + -1 (255)| = |0000 0110 + 1111 1111| = |1 0000 0101| = |261| = |5+C|
43 | |5 - 1| ->|5 + -1 (255)| = |0000 0101 + 1111 1111| = |1 0000 0100| = |260| = |4+C|
44 | |4 - 1| ->|4 + -1 (255)| = |0000 0100 + 1111 1111| = |1 0000 0011| = |259| = |3+C|
45 | |3 - 1| ->|3 + -1 (255)| = |0000 0011 + 1111 1111| = |1 0000 0010| = |258| = |2+C|
46 | |2 - 1| ->|2 + -1 (255)| = |0000 0010 + 1111 1111| = |1 0000 0001| = |257| = |1+C|
47 | |1 - 1| ->|1 + -1 (255)| = |0000 0001 + 1111 1111| = |1 0000 0000| = |256| = |0+C|
48 | |0 - 1| ->|0 + -1 (255)| = |0000 0000 + 1111 1111| = | 1111 1111| = |255| = |255|
49 |
50 | This table displays the values of registers, variables and output during all iterations of the program.
51 |
52 | | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
53 | |---|---|---|---|---|---|---|---|---|
54 | | A | 8 | 16| 24| 32| 40| 48| 56| 56|
55 | | B | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 1 |
56 | | C | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
57 | | P | 8 | 16| 24| 32| 40| 48| 56| 56|
58 | | X | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 0 |
59 | | Y | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 |
60 | |OUT| x | x | x | x | x | x | x | 56|
61 |
62 |
63 |
64 | [](https://www.youtube.com/watch?v=xFFEQVPULzI "Click to play")
65 |
66 | This program is from [Conditional jump instructions](https://www.youtube.com/watch?v=Zg1NdPKoosU).
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/resources/8-bit-computer-600w.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/8-bit-computer-600w.jpg
--------------------------------------------------------------------------------
/resources/8-bit-computer-fritzing-600w.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/8-bit-computer-fritzing-600w.jpg
--------------------------------------------------------------------------------
/resources/8-bit-computer-fritzing-breadboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/8-bit-computer-fritzing-breadboard.png
--------------------------------------------------------------------------------
/resources/8-bit-computer-fritzing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/8-bit-computer-fritzing.png
--------------------------------------------------------------------------------
/resources/8-bit-computer-fritzing.svg:
--------------------------------------------------------------------------------
1 |
2 |
167 |
--------------------------------------------------------------------------------
/resources/8-bit-computer.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/8-bit-computer.fzz
--------------------------------------------------------------------------------
/resources/8-bit-computer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/8-bit-computer.jpg
--------------------------------------------------------------------------------
/resources/clock_double_step.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/clock_double_step.png
--------------------------------------------------------------------------------
/resources/clock_double_step_cap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/clock_double_step_cap.jpg
--------------------------------------------------------------------------------
/resources/clock_speed_cap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/clock_speed_cap.jpg
--------------------------------------------------------------------------------
/resources/clock_spurious_step_lm555cn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/clock_spurious_step_lm555cn.png
--------------------------------------------------------------------------------
/resources/clock_spurious_step_ne555p.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/clock_spurious_step_ne555p.png
--------------------------------------------------------------------------------
/resources/leds_with_resistors.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/leds_with_resistors.jpg
--------------------------------------------------------------------------------
/resources/mar_decoupling_cap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/mar_decoupling_cap.jpg
--------------------------------------------------------------------------------
/resources/power.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/power.jpg
--------------------------------------------------------------------------------
/resources/ram_mode_switch_cap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/ram_mode_switch_cap.jpg
--------------------------------------------------------------------------------
/resources/ram_mode_switch_press.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/ram_mode_switch_press.png
--------------------------------------------------------------------------------
/resources/ram_resonance_post_fix.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/ram_resonance_post_fix.jpg
--------------------------------------------------------------------------------
/resources/ram_resonance_pre_fix.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/ram_resonance_pre_fix.jpg
--------------------------------------------------------------------------------
/resources/reset_line_cap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/reset_line_cap.jpg
--------------------------------------------------------------------------------
/resources/reset_line_noise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/reset_line_noise.png
--------------------------------------------------------------------------------
/resources/thermal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/thermal.jpg
--------------------------------------------------------------------------------
/resources/yt-0-to-255-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-0-to-255-thumb.png
--------------------------------------------------------------------------------
/resources/yt-add-two-numbers-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-add-two-numbers-thumb.png
--------------------------------------------------------------------------------
/resources/yt-double-step-glitch-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-double-step-glitch-thumb.png
--------------------------------------------------------------------------------
/resources/yt-fibonacci-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-fibonacci-thumb.png
--------------------------------------------------------------------------------
/resources/yt-increase-by-three-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-increase-by-three-thumb.png
--------------------------------------------------------------------------------
/resources/yt-mar-reset-glitch-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-mar-reset-glitch-thumb.png
--------------------------------------------------------------------------------
/resources/yt-multiply-two-numbers-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-multiply-two-numbers-thumb.png
--------------------------------------------------------------------------------
/resources/yt-ram-mode-glitch-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-ram-mode-glitch-thumb.png
--------------------------------------------------------------------------------
/resources/yt-ram-resonance-glitch-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-ram-resonance-glitch-thumb.png
--------------------------------------------------------------------------------
/resources/yt-reset-noise-glitch-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-reset-noise-glitch-thumb.png
--------------------------------------------------------------------------------
/resources/yt-spurious-step-glitch-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blurpy/8-bit-computer/162c7473b9ea829c593940e0575953180aa20d65/resources/yt-spurious-step-glitch-thumb.png
--------------------------------------------------------------------------------