Урок 5. «Игра в хаос»: треугольник из случайности
В картинкахПосле этого урока на втором экране тот же треугольник Серпинского вырастет из случайных точек. Схема бросает «кубик», делает шаг на полпути к выпавшей вершине и ставит точку — и ни одна точка не ложится мимо.
5.1. Идея: шаг на полпути
Возьми три вершины треугольника и любую точку. Брось кубик: выпала вершина — шагни на полпути к ней и поставь точку. Повторяй. Кажется, что точки лягут как попало, — а они складываются в треугольник Серпинского.
5.2. Идея: шаг — это сдвиг
Шаг на полпути — (x + v) / 2, нужен бы сумматор. Но если поставить вершины в (0, 0), (64, 0) и (0, 64), то (x + 64) / 2 и x / 2 — просто сдвиг вправо, а сверху вталкивается бит вершины: 1 — к 64, 0 — к нулю.
Единица никогда не вталкивается в x и y сразу — поэтому у точки нет общих разрядов с единицей: это ровно правило урока 4 (x AND y) = 0.
Откуда случайность. LFSR — сдвиговый регистр, который сам себя подпитывает: новый бит — XOR нескольких разрядов. 12 разрядов перебирают все 4095 ненулевых значений в «случайном» порядке. Короче не хватит: точка зависит от шести последних бросков, и короткий генератор не выдаст всех сочетаний — треугольник не закрасится.
5.3. Сборка
Тот же проект: развёртка и треугольник урока 4 остаются, рядом встаёт второй экран.
Игра. Возьми три вершины треугольника и любую точку. Брось кубик: выпала вершина — сделай шаг на полпути к ней и поставь точку. Повторяй. Кажется, что точки лягут как попало, — а складываются в треугольник Серпинского.
Как это в железе. Шаг на полпути — это (x + v) / 2, нужен бы сумматор. Но если поставить вершины в (0, 0), (64, 0) и (0, 64), то (x + 64) / 2 и x / 2 — просто сдвиг вправо, а сверху вталкивается бит вершины: 1 — к 64, 0 — к нулю. Координата — сдвиговый регистр, сумматор не нужен.
| a | b | Вершина | Что вталкивается: x | y |
|---|---|---|---|---|
| 1 | 0 | (64, 0) | 1 | 0 |
| 0 | 1 | (0, 64) | 0 | 1 |
| 0 | 0 | (0, 0) | 0 | 0 |
| 1 | 1 | (0, 0) | 0 | 0 |
Единица никогда не вталкивается в x и y сразу — поэтому у точки нет общих разрядов с единицей: это ровно условие урока 4 (x AND y) = 0. Тот же треугольник — из логики слева и из случайности справа.
Откуда случайность. LFSR — сдвиговый регистр, который сам себя подпитывает: новый бит — XOR нескольких разрядов. Он перебирает все 4095 ненулевых значений в «случайном» порядке. Короче 12 разрядов не хватит: точка зависит от шести последних бросков, и короткий генератор не успеет выдать все их сочетания — треугольник не закрасится.
Шаг 1. LFSR12 — генератор случайных бит
| Деталь | Нога | Метка |
|---|---|---|
| Порт входа | выход | CLK |
| Порт входа | выход | RST |
| NOT | I0 O0 | RST nRST |
| XOR | I0 I1 O0 | r11 r5 f1 |
| XOR | I0 I1 O0 | f1 r3 f2 |
| XOR (обратная связь) | I0 I1 O0 | f2 r0 fb |
| AND | I0 I1 O0 | fb nRST g0 |
| OR (сброс в 1) | I0 I1 O0 | g0 RST d0 |
| DFF (разряд 0) | D CLK Q nQ | d0 CLK r0 — (свободна) |
| AND (разряд 1) | I0 I1 O0 | r0 nRST d1 |
| DFF (разряд 1) | D CLK Q nQ | d1 CLK r1 — (свободна) |
| AND (разряд 2) | I0 I1 O0 | r1 nRST d2 |
| DFF (разряд 2) | D CLK Q nQ | d2 CLK r2 — (свободна) |
| AND (разряд 3) | I0 I1 O0 | r2 nRST d3 |
| DFF (разряд 3) | D CLK Q nQ | d3 CLK r3 — (свободна) |
| AND (разряд 4) | I0 I1 O0 | r3 nRST d4 |
| DFF (разряд 4) | D CLK Q nQ | d4 CLK r4 — (свободна) |
| AND (разряд 5) | I0 I1 O0 | r4 nRST d5 |
| DFF (разряд 5) | D CLK Q nQ | d5 CLK r5 — (свободна) |
| AND (разряд 6) | I0 I1 O0 | r5 nRST d6 |
| DFF (разряд 6) | D CLK Q nQ | d6 CLK r6 — (свободна) |
| AND (разряд 7) | I0 I1 O0 | r6 nRST d7 |
| DFF (разряд 7) | D CLK Q nQ | d7 CLK r7 — (свободна) |
| AND (разряд 8) | I0 I1 O0 | r7 nRST d8 |
| DFF (разряд 8) | D CLK Q nQ | d8 CLK r8 — (свободна) |
| AND (разряд 9) | I0 I1 O0 | r8 nRST d9 |
| DFF (разряд 9) | D CLK Q nQ | d9 CLK r9 — (свободна) |
| AND (разряд 10) | I0 I1 O0 | r9 nRST d10 |
| DFF (разряд 10) | D CLK Q nQ | d10 CLK r10 — (свободна) |
| AND (разряд 11) | I0 I1 O0 | r10 nRST d11 |
| DFF (разряд 11) | D CLK Q nQ | d11 CLK r11 — (свободна) |
| OR (выход A) | I0 I1 O0 | r0 r0 A |
| OR (выход B) | I0 I1 O0 | r6 r6 B |
| Порт выхода | вход | A |
| Порт выхода | вход | B |
Ctrl+G → имя LFSR12. Ноги: входы CLK, RST; выходы A (разряд 0), B (разряд 6). OR с одинаковыми входами — просто «провод» от внутренней метки к порту.
Шаг 2. SHIFT6 — сдвиговый регистр координаты
| Деталь | Нога | Метка |
|---|---|---|
| Порт входа | выход | CLK |
| Порт входа | выход | RST |
| Порт входа | выход | IN |
| NOT | I0 O0 | RST nRST |
| AND (разряд 5) | I0 I1 O0 | IN nRST d5 |
| DFF (разряд 5) | D CLK Q nQ | d5 CLK Q5 — (свободна) |
| AND (разряд 4) | I0 I1 O0 | Q5 nRST d4 |
| DFF (разряд 4) | D CLK Q nQ | d4 CLK Q4 — (свободна) |
| AND (разряд 3) | I0 I1 O0 | Q4 nRST d3 |
| DFF (разряд 3) | D CLK Q nQ | d3 CLK Q3 — (свободна) |
| AND (разряд 2) | I0 I1 O0 | Q3 nRST d2 |
| DFF (разряд 2) | D CLK Q nQ | d2 CLK Q2 — (свободна) |
| AND (разряд 1) | I0 I1 O0 | Q2 nRST d1 |
| DFF (разряд 1) | D CLK Q nQ | d1 CLK Q1 — (свободна) |
| AND (разряд 0) | I0 I1 O0 | Q1 nRST d0 |
| DFF (разряд 0) | D CLK Q nQ | d0 CLK Q0 — (свободна) |
| Порт выхода | вход | Q0 |
| Порт выхода | вход | Q1 |
| Порт выхода | вход | Q2 |
| Порт выхода | вход | Q3 |
| Порт выхода | вход | Q4 |
| Порт выхода | вход | Q5 |
Ctrl+G → имя SHIFT6. Ноги: входы CLK, RST, IN; выходы Q0–Q5.
Шаг 3. Холст: случайность, вершина, координаты, второй экран
| Деталь | Нога | Метка |
|---|---|---|
| LFSR12 | CLK RST A B | CLK RST ra rb |
| NOT | I0 O0 | ra nra |
| NOT | I0 O0 | rb nrb |
| AND (вершина x) | I0 I1 O0 | ra nrb kx |
| AND (вершина y) | I0 I1 O0 | rb nra ky |
| SHIFT6 (координата x) | CLK RST IN Q0 Q1 Q2 Q3 Q4 Q5 | CLK RST kx px0 px1 px2 px3 px4 px5 |
| SHIFT6 (координата y) | CLK RST IN Q0 Q1 Q2 Q3 Q4 Q5 | CLK RST ky py0 py1 py2 py3 py4 py5 |
| Dot display (второй) | X0 X1 X2 X3 X4 X5 Y0 Y1 Y2 Y3 Y4 Y5 D0 WE CLK CLR | px0 px1 px2 px3 px4 px5 py0 py1 py2 py3 py4 py5 VCC VCC nCLK GND |
CLK, nCLK и RST — те же метки, что у развёртки урока 3.
5.4. Проверка
| № | Что сделать | Что видно |
|---|---|---|
| 1 | второй экран — те же настройки, что первый (Dots, 64 × 64, 1 dot) | — |
| 2 | RST = 1, один такт, RST = 0; генератор 60Hz | на втором экране точки появляются по одной, в случайных местах |
| 3 | присмотрись: ни одна точка не встала «мимо» | каждая — на месте треугольника, хотя место выбрано случайно |
| 4 | генератор 4kHz или быстрее, подождать пару секунд | второй экран закрасился — тот же треугольник, что на первом |
Если точки ложатся вне треугольника — проверь вершины: у AND (вершина x) второй вход nrb, у AND (вершина y) — nra. Если второй экран закрашивается не весь — проверь разряды обратной связи LFSR12: r11, r5, r3, r0.
Вставка урока 5 (Cmd+I)
Нужны NOT, AND, OR, XOR, DFF; метки CLK, nCLK, RST — с урока 3.
# Урок 5 — «игра в хаос»: случайная вершина, шаг на полпути. Вершины (0,0), (64,0), (0,64) — шаг = сдвиг вправо# со вставкой бита сверху. Тот же треугольник Серпинского вырастает из случайных точек на втором экране.# Вставка: Cmd+I поверх урока 4 (нужны NOT, AND, OR, XOR, DFF; CLK, nCLK, RST — с урока 3). # --- генератор случайных бит: 12 разрядов по кругу, обратная связь XOR от разрядов 11, 5, 3, 0 ---# RST = 1 по фронту: младший разряд 1, остальные 0 (из одних нулей генератор не выйдет)chip LFSR12 { portIn(CLK) portIn(RST) portOut(A) portOut(B) NOT(RST, nRST) XOR(r11, r5, f1) XOR(f1, r3, f2) XOR(f2, r0, fb) AND(fb, nRST, g0) OR(g0, RST, d0) DFF(D=d0, CLK=CLK, Q=r0) AND(r0, nRST, d1) DFF(D=d1, CLK=CLK, Q=r1) AND(r1, nRST, d2) DFF(D=d2, CLK=CLK, Q=r2) AND(r2, nRST, d3) DFF(D=d3, CLK=CLK, Q=r3) AND(r3, nRST, d4) DFF(D=d4, CLK=CLK, Q=r4) AND(r4, nRST, d5) DFF(D=d5, CLK=CLK, Q=r5) AND(r5, nRST, d6) DFF(D=d6, CLK=CLK, Q=r6) AND(r6, nRST, d7) DFF(D=d7, CLK=CLK, Q=r7) AND(r7, nRST, d8) DFF(D=d8, CLK=CLK, Q=r8) AND(r8, nRST, d9) DFF(D=d9, CLK=CLK, Q=r9) AND(r9, nRST, d10) DFF(D=d10, CLK=CLK, Q=r10) AND(r10, nRST, d11) DFF(D=d11, CLK=CLK, Q=r11) OR(r0, r0, A) OR(r6, r6, B)} # --- сдвиговый регистр: новый бит IN — в старший разряд, остальные на шаг вправо (деление на 2) ---chip SHIFT6 { portIn(CLK) portIn(RST) portIn(IN) portOut(Q0) portOut(Q1) portOut(Q2) portOut(Q3) portOut(Q4) portOut(Q5) NOT(RST, nRST) AND(IN, nRST, d5) DFF(D=d5, CLK=CLK, Q=Q5) AND(Q5, nRST, d4) DFF(D=d4, CLK=CLK, Q=Q4) AND(Q4, nRST, d3) DFF(D=d3, CLK=CLK, Q=Q3) AND(Q3, nRST, d2) DFF(D=d2, CLK=CLK, Q=Q2) AND(Q2, nRST, d1) DFF(D=d1, CLK=CLK, Q=Q1) AND(Q1, nRST, d0) DFF(D=d0, CLK=CLK, Q=Q0)} # --- на холст: случайные биты → вершина → две координаты точки → второй экран ---LFSR12(CLK=CLK, RST=RST, A=ra, B=rb)NOT(ra, nra)NOT(rb, nrb)# вершина (64, 0): только a; вершина (0, 64): только b; иначе вершина (0, 0)AND(ra, nrb, kx)AND(rb, nra, ky)SHIFT6(CLK=CLK, RST=RST, IN=kx, Q0=px0, Q1=px1, Q2=px2, Q3=px3, Q4=px4, Q5=px5)SHIFT6(CLK=CLK, RST=RST, IN=ky, Q0=py0, Q1=py1, Q2=py2, Q3=py3, Q4=py4, Q5=py5)dotdisplay SCR2{layout=dots, w=64, h=64}(X0=px0, X1=px1, X2=px2, X3=px3, X4=px4, X5=px5, Y0=py0, Y1=py1, Y2=py2, Y3=py3, Y4=py4, Y5=py5, D0=VCC, WE=VCC, CLK=nCLK, CLR=GND)Не получается? Что-то не работает →