Урок 6 (бонус). Десятичный счёт: прибавить шесть
В картинкахПосле этого урока сумматор будет считать десятками, как калькулятор: 38 + 47 = 85 — и на табло именно эти цифры. Урок по желанию: калькулятор урока 5 закончен и без него.
6.1. Идея: цифра в четырёх битах
Люди считают десятками, а сумматор — шестнадцатью. Калькуляторы и кассы решали это просто: каждую десятичную цифру хранили в своих 4 битах. Это двоично-десятичный код (BCD): 38 — это 0011 (3) и 1000 (8), то есть 0011 1000.
Цифры складывает обычный ADDER4. Пока сумма цифр не больше 9, всё верно. Если больше — в 4 битах есть шесть кодов 1010…1111, которые десятичная цифра не использует, и их надо перепрыгнуть: прибавить 6. Заодно рождается перенос в следующую цифру.
Сумма цифр больше 9, когда:
- двоичный сумматор дал перенос — это 16…19, или
s3 = 1и (s1 = 1илиs2 = 1) — это 10…15.
Так считали калькуляторы и первые микропроцессоры: у Intel 4004 для этого есть команда DAA, а у 6502 — десятичный режим (SED).
6.2. Почему табло в режиме HEX
Табло ничего не знает про BCD: оно берёт 8 бит и показывает их как число в выбранной системе.
- В HEX одна цифра табло — ровно 4 бита. Младшая цифра — биты 0–3, старшая — 4–7. А в BCD мы тоже кладём в каждые 4 бита одну цифру. Поэтому HEX-табло показывает наши цифры как есть:
0011 1000→38. - В DEC табло прочитает те же 8 бит как одно двоичное число:
0011 1000= 32 + 16 + 8 =56.
Коррекция «+6» следит, чтобы в четвёрке бит никогда не оказалось 1010…1111, поэтому букв A…F на табло не бывает — только цифры 0–9. Появилась буква — значит, коррекция не сработала.
Настоящие калькуляторы так и делали: каждая цифра хранилась своими 4 битами и шла прямо на свой индикатор. Перевести двоичное число в десятичное — это деление на 10, и это гораздо больше железа, чем коррекция «+6».
6.3. Сборка
Урок по желанию: калькулятор урока 5 закончен и без него.
Тот же проект. Стенд урока 5 (17 тумблеров, два ADDSUB8, лампы, табло) удали; Power/Ground оставь.
Идея. Люди считают десятками, а сумматор — шестнадцатью. Запишем каждую десятичную цифру в свои 4 бита (двоично-десятичный код, BCD): 38 = 0011 1000. Сложим цифры обычным ADDER4. Пока сумма цифр ≤ 9, всё верно. Если больше 9, в 4 битах «пропали» шесть кодов 1010…1111, которые десятичная цифра не использует, — их надо перепрыгнуть: прибавить 6. Заодно рождается перенос в следующую цифру.
Сумма цифр больше 9, когда:
- двоичный сумматор дал перенос (16…19), или
s3 = 1и (s1 = 1илиs2 = 1) — это 10…15.
Так считали калькуляторы и первые микропроцессоры: у Intel 4004 для этого есть команда DAA, у 6502 — режим SED.
Шаг 1. BCD1 — одна десятичная цифра
| Деталь | Нога | Метка |
|---|---|---|
| Порт входа | выход | A0 |
| Порт входа | выход | A1 |
| Порт входа | выход | A2 |
| Порт входа | выход | A3 |
| Порт входа | выход | B0 |
| Порт входа | выход | B1 |
| Порт входа | выход | B2 |
| Порт входа | выход | B3 |
| Порт входа | выход | CI |
| ADDER4 (сумма цифр) | A0 A1 A2 A3 B0 B1 B2 B3 CI S0 S1 S2 S3 CO | A0 A1 A2 A3 B0 B1 B2 B3 CI s0 s1 s2 s3 c |
| OR | I0 I1 O0 | s1 s2 s12 |
| AND (10…15) | I0 I1 O0 | s3 s12 big |
| OR (больше 9) | I0 I1 O0 | c big CO |
| ADDER4 (+6) | A0 A1 A2 A3 B0 B1 B2 B3 CI S0 S1 S2 S3 CO | s0 s1 s2 s3 GND CO CO GND GND D0 D1 D2 D3 — (свободна) |
| Порт выхода | вход | D0 |
| Порт выхода | вход | D1 |
| Порт выхода | вход | D2 |
| Порт выхода | вход | D3 |
| Порт выхода | вход | CO |
Ctrl+G → имя BCD1. Ноги: входы A0–A3, B0–B3, CI; выходы D0–D3, CO.
CO — сразу две вещи: «прибавь 6» (идёт на B1, B2 второго ADDER4, ведь 6 = 0110) и перенос в следующую цифру.
Шаг 2. Холст: две цифры
| Деталь | Нога | Метка |
|---|---|---|
| Input | выход | A0 |
| Input | выход | A1 |
| Input | выход | A2 |
| Input | выход | A3 |
| Input | выход | A4 |
| Input | выход | A5 |
| Input | выход | A6 |
| Input | выход | A7 |
| Input | выход | B0 |
| Input | выход | B1 |
| Input | выход | B2 |
| Input | выход | B3 |
| Input | выход | B4 |
| Input | выход | B5 |
| Input | выход | B6 |
| Input | выход | B7 |
| BCD1 (единицы) | A0 A1 A2 A3 B0 B1 B2 B3 CI D0 D1 D2 D3 CO | A0 A1 A2 A3 B0 B1 B2 B3 GND D0 D1 D2 D3 c10 |
| BCD1 (десятки) | A0 A1 A2 A3 B0 B1 B2 B3 CI D0 D1 D2 D3 CO | A4 A5 A6 A7 B4 B5 B6 B7 c10 D4 D5 D6 D7 H |
| LED («100») | вход | H |
| Display | ⚙ | ширина 8, HEX, шина A |
| Display | ⚙ | ширина 8, HEX, шина B |
| Display | ⚙ | ширина 8, HEX, шина D |
Табло в режиме HEX: каждая шестнадцатеричная цифра — это ровно 4 бита, поэтому табло показывает двоично-десятичные цифры как есть: 0011 1000 видно как 38.
Как набирать цифры
Младшая цифра — тумблеры A0–A3 (B0–B3), старшая — A4–A7 (B4–B7). Каждая цифра от 0 до 9:
| Цифра | Тумблеры 3 2 1 0 |
|---|---|
| 0 | 0 0 0 0 |
| 1 | 0 0 0 1 |
| 2 | 0 0 1 0 |
| 3 | 0 0 1 1 |
| 4 | 0 1 0 0 |
| 5 | 0 1 0 1 |
| 6 | 0 1 1 0 |
| 7 | 0 1 1 1 |
| 8 | 1 0 0 0 |
| 9 | 1 0 0 1 |
6.4. Проверка
| A | Тумблеры A7…A0 | B | Тумблеры B7…B0 | Табло D | Лампа | Внутри |
|---|---|---|---|---|---|---|
| 23 | 0010 0011 | 45 | 0100 0101 | 68 | — | 3 + 5 = 8 и 2 + 4 = 6: коррекция не нужна |
| 38 | 0011 1000 | 47 | 0100 0111 | 85 | — | 8 + 7 = 15 → +6 → 5, перенос; 3 + 4 + 1 = 8 |
| 09 | 0000 1001 | 01 | 0000 0001 | 10 | — | 9 + 1 = 10 → +6 → 0, перенос |
| 99 | 1001 1001 | 01 | 0000 0001 | 00 | 100 | перенос бежит через обе цифры |
| 99 | 1001 1001 | 99 | 1001 1001 | 98 | 100 | 9 + 9 = 18: перенос из двоичного сумматора → +6 |
В колонках «Тумблеры» слева — старший тумблер (A7), справа — A0; 1 — включён, 0 — выключен. Каждая группа из 4 — одна десятичная цифра: слева десятки, справа единицы.
Если ответ верен до 9, а дальше — буквы (A…F) на табло, — коррекция не срабатывает: проверь OR/AND внутри BCD1 и что CO подан на B1 и B2 второго ADDER4.
Вставка урока 6 (Cmd+I)
Нужны AND, OR и ADDER4. Стенд урока 5 удали, кроме питания.
# Урок 6 (бонус) — десятичный счёт. Цифра 0–9 в 4 битах; если сумма цифр больше 9 — прибавить 6.# Вставка: Cmd+I поверх урока 5 (нужны AND, OR, ADDER4). Стенд урока 5 удалить, кроме питания. # --- одна десятичная цифра: двоичная сумма, потом коррекция +6 ---chip BCD1 { portIn(A0) portIn(A1) portIn(A2) portIn(A3) portIn(B0) portIn(B1) portIn(B2) portIn(B3) portIn(CI) portOut(D0) portOut(D1) portOut(D2) portOut(D3) portOut(CO) ADDER4(A0=A0, A1=A1, A2=A2, A3=A3, B0=B0, B1=B1, B2=B2, B3=B3, CI=CI, S0=s0, S1=s1, S2=s2, S3=s3, CO=c) # больше 9: перенос (16…19) или 1x1x / 11xx (10…15) OR(s1, s2, s12) AND(s3, s12, big) # CO = «цифра больше 9»: это и перенос в следующую цифру, и сигнал «прибавь 6» OR(c, big, CO) # +6 = 0110: CO на разряды 1 и 2 ADDER4(A0=s0, A1=s1, A2=s2, A3=s3, B0=GND, B1=CO, B2=CO, B3=GND, CI=GND, S0=D0, S1=D1, S2=D2, S3=D3)} # --- на холст: две цифры A, две цифры B; сумма 00–99 и лампа «100» ---input(A0)input(A1)input(A2)input(A3)input(A4)input(A5)input(A6)input(A7)input(B0)input(B1)input(B2)input(B3)input(B4)input(B5)input(B6)input(B7)BCD1(A0=A0, A1=A1, A2=A2, A3=A3, B0=B0, B1=B1, B2=B2, B3=B3, CI=GND, D0=D0, D1=D1, D2=D2, D3=D3, CO=c10)BCD1(A0=A4, A1=A5, A2=A6, A3=A7, B0=B4, B1=B5, B2=B6, B3=B7, CI=c10, D0=D4, D1=D5, D2=D6, D3=D7, CO=H)led(H)Не получается? Что-то не работает →