Урок 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.
десяткиединицыA = 380011100038B = 470100011147сумма111115 > 9 → +6+01100101цифра 5, перенос 1перенос +110003 + 4 + 1 = 8 ≤ 9коррекция не нужнаответ: 1000 0101 — на HEX-табло 85
38 + 47 в двоично-десятичном коде. Единицы: 8 + 7 = 1111 — это 15, больше 9, поэтому прибавляем 0110 (шесть): получается 1 0101 — цифра 5 и перенос в десятки. Десятки: 3 + 4 + 1 = 8, коррекция не нужна. Ответ 1000 0101 — 85.

Так считали калькуляторы и первые микропроцессоры: у 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
ORI0
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
00 0 0 0
10 0 0 1
20 0 1 0
30 0 1 1
40 1 0 0
50 1 0 1
60 1 1 0
70 1 1 1
81 0 0 0
91 0 0 1

6.4. Проверка

AТумблеры A7…A0BТумблеры B7…B0Табло DЛампаВнутри
230010 0011450100 010168—3 + 5 = 8 и 2 + 4 = 6: коррекция не нужна
380011 1000470100 011185—8 + 7 = 15 → +6 → 5, перенос; 3 + 4 + 1 = 8
090000 1001010000 000110—9 + 1 = 10 → +6 → 0, перенос
991001 1001010000 000100100перенос бежит через обе цифры
991001 1001991001 1001981009 + 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)

Не получается? Что-то не работает →