Урок 2. Память 16×4: шестнадцать строк и выбор одной

В картинках

После этого урока у вас будет настоящая память: RAM16x4 — 16 слов по 4 бита. Ставишь адрес и данные тумблерами, жмёшь WE — слово записано; меняешь адрес — табло показывает, что лежит в этой ячейке. Внутри — 16 строк WORD4 из урока 1 и дешифратор DEC16 из процессорного набора.


2.1. Идея: выбрать одну строку из шестнадцати

Адрес из 4 бит — это число от 0 до 15, номер строки. Его превращает в «один горящий провод из шестнадцати» дешифратор DEC16 — тот же, что в процессорном наборе выбирал команду. Дальше всё делают провода r0–r15:

  • «выдай»: провод rN идёт прямо на R своей строки — выбранная строка открывает «кран», остальные дают нули;
  • «запиши»: AND(rN, WE) → W строки — записать может только выбранная строка и только пока нажата WE;
  • выход: по каждому биту 16 выходов строк сходятся в ИЛИ на 16 входов (4 × OR4 → OR4). Нули невыбранных строк ничего не меняют — на выходе слово выбранной.
A0–A3адрес = 2DEC161 из 16WEr0RWWORD4c0 = 0r1RWWORD4c1 = 0r2RWWORD4c2 = 5r15RWWORD4c15 = 0⋮⋮ИЛИ16 → 1Q = 5D0–D3 идут во все строки сразу (не нарисовано)
Память 16×4. Дешифратор зажигает ровно одну строку (r2): она получает «выдай» R, а при WE = 1 — ещё и «запиши» W (через AND). Остальные 15 строк выдают нули, и ИЛИ по каждому биту оставляет на выходе слово выбранной строки.

Данные D0–D3 идут во все 16 строк сразу: записывает всё равно только та, у которой W = 1.

Как у настоящей статической памяти: пока WE нажата, идёт запись; адрес менять при отпущенной WE, иначе слово запишется и туда, куда переехал адрес.

2.2. Почему чтение на вентилях, а не общий провод

В настоящих микросхемах памяти выходы строк не собирают через ИЛИ: все ячейки одного бита сидят на общем проводе («битовой линии») через ключи-транзисторы, и выбранная строка подключает свою ячейку к этому проводу. Так меньше деталей. У нас так не выйдет:

общий провод данных — как в настоящих чипахQ0строка 1 уходиттянет к VCCключ открытстрока 2 приходиттянет к GNDключ открытна миг открыты оба ключа: VCC ↔ GND
Почему не общий провод. При смене адреса новая строка подключается на миг раньше, чем отключается старая: одна тянет провод к питанию, другая к земле — короткое замыкание. Настоящие чипы спасает аналоговая схемотехника (предзаряд провода, усилители чтения), у нас ключи идеальные — поэтому чтение собираем на вентилях И-ИЛИ.

И-ИЛИ дороже по деталям, но в нём каждый провод всегда гонит ровно один вентиль — замкнуть нечему.

2.3. Сборка

Тот же проект, что в уроке 1: стенд урока 1 не мешает (у него свои метки wD, wO). Нужны WORD4 (урок 1), DEC16 и OR4 (процессорный набор).

Шаг 1. Чип RAM16x4

Что собираем. Дешифратор, 16 «запиши» (AND), 16 строк и дерево ИЛИ.

ПОРТЫ-ВХОДЫ: A0, A1, A2, A3, D0, D1, D2, D3, WE · ПОРТЫ-ВЫХОДЫ: Q0, Q1, Q2, Q3

ЭлементНогаНаправлениеМетка
DEC16I0входA0
DEC16I1входA1
DEC16I2входA2
DEC16I3входA3
DEC16Y0выходr0
DEC16Y1выходr1
DEC16Y2выходr2
DEC16Y3выходr3
DEC16Y4выходr4
DEC16Y5выходr5
DEC16Y6выходr6
DEC16Y7выходr7
DEC16Y8выходr8
DEC16Y9выходr9
DEC16Y10выходr10
DEC16Y11выходr11
DEC16Y12выходr12
DEC16Y13выходr13
DEC16Y14выходr14
DEC16Y15выходr15
ANDI0входr0
ANDI1входWE
ANDO0выходw0
ANDI0входr1
ANDI1входWE
ANDO0выходw1
ANDI0входr2
ANDI1входWE
ANDO0выходw2
ANDI0входr3
ANDI1входWE
ANDO0выходw3
ANDI0входr4
ANDI1входWE
ANDO0выходw4
ANDI0входr5
ANDI1входWE
ANDO0выходw5
ANDI0входr6
ANDI1входWE
ANDO0выходw6
ANDI0входr7
ANDI1входWE
ANDO0выходw7
ANDI0входr8
ANDI1входWE
ANDO0выходw8
ANDI0входr9
ANDI1входWE
ANDO0выходw9
ANDI0входr10
ANDI1входWE
ANDO0выходw10
ANDI0входr11
ANDI1входWE
ANDO0выходw11
ANDI0входr12
ANDI1входWE
ANDO0выходw12
ANDI0входr13
ANDI1входWE
ANDO0выходw13
ANDI0входr14
ANDI1входWE
ANDO0выходw14
ANDI0входr15
ANDI1входWE
ANDO0выходw15
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw0
WORD4Rвходr0
WORD4O0выходc0_0
WORD4O1входc0_1
WORD4O2входc0_2
WORD4O3входc0_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw1
WORD4Rвходr1
WORD4O0выходc1_0
WORD4O1входc1_1
WORD4O2входc1_2
WORD4O3входc1_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw2
WORD4Rвходr2
WORD4O0выходc2_0
WORD4O1входc2_1
WORD4O2входc2_2
WORD4O3входc2_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw3
WORD4Rвходr3
WORD4O0выходc3_0
WORD4O1входc3_1
WORD4O2входc3_2
WORD4O3входc3_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw4
WORD4Rвходr4
WORD4O0выходc4_0
WORD4O1входc4_1
WORD4O2входc4_2
WORD4O3входc4_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw5
WORD4Rвходr5
WORD4O0выходc5_0
WORD4O1входc5_1
WORD4O2входc5_2
WORD4O3входc5_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw6
WORD4Rвходr6
WORD4O0выходc6_0
WORD4O1входc6_1
WORD4O2входc6_2
WORD4O3входc6_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw7
WORD4Rвходr7
WORD4O0выходc7_0
WORD4O1входc7_1
WORD4O2входc7_2
WORD4O3входc7_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw8
WORD4Rвходr8
WORD4O0выходc8_0
WORD4O1входc8_1
WORD4O2входc8_2
WORD4O3входc8_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw9
WORD4Rвходr9
WORD4O0выходc9_0
WORD4O1входc9_1
WORD4O2входc9_2
WORD4O3входc9_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw10
WORD4Rвходr10
WORD4O0выходc10_0
WORD4O1входc10_1
WORD4O2входc10_2
WORD4O3входc10_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw11
WORD4Rвходr11
WORD4O0выходc11_0
WORD4O1входc11_1
WORD4O2входc11_2
WORD4O3входc11_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw12
WORD4Rвходr12
WORD4O0выходc12_0
WORD4O1входc12_1
WORD4O2входc12_2
WORD4O3входc12_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw13
WORD4Rвходr13
WORD4O0выходc13_0
WORD4O1входc13_1
WORD4O2входc13_2
WORD4O3входc13_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw14
WORD4Rвходr14
WORD4O0выходc14_0
WORD4O1входc14_1
WORD4O2входc14_2
WORD4O3входc14_3
WORD4D0входD0
WORD4D1входD1
WORD4D2входD2
WORD4D3входD3
WORD4Wвходw15
WORD4Rвходr15
WORD4O0выходc15_0
WORD4O1входc15_1
WORD4O2входc15_2
WORD4O3входc15_3
OR4Aвходc0_0
OR4Bвходc1_0
OR4Cвходc2_0
OR4Dвходc3_0
OR4Yвыходg0_0
OR4Aвходc4_0
OR4Bвходc5_0
OR4Cвходc6_0
OR4Dвходc7_0
OR4Yвыходg1_0
OR4Aвходc8_0
OR4Bвходc9_0
OR4Cвходc10_0
OR4Dвходc11_0
OR4Yвыходg2_0
OR4Aвходc12_0
OR4Bвходc13_0
OR4Cвходc14_0
OR4Dвходc15_0
OR4Yвыходg3_0
OR4Aвходg0_0
OR4Bвходg1_0
OR4Cвходg2_0
OR4Dвходg3_0
OR4YвыходQ0
OR4Aвходc0_1
OR4Bвходc1_1
OR4Cвходc2_1
OR4Dвходc3_1
OR4Yвыходg0_1
OR4Aвходc4_1
OR4Bвходc5_1
OR4Cвходc6_1
OR4Dвходc7_1
OR4Yвыходg1_1
OR4Aвходc8_1
OR4Bвходc9_1
OR4Cвходc10_1
OR4Dвходc11_1
OR4Yвыходg2_1
OR4Aвходc12_1
OR4Bвходc13_1
OR4Cвходc14_1
OR4Dвходc15_1
OR4Yвыходg3_1
OR4Aвходg0_1
OR4Bвходg1_1
OR4Cвходg2_1
OR4Dвходg3_1
OR4YвыходQ1
OR4Aвходc0_2
OR4Bвходc1_2
OR4Cвходc2_2
OR4Dвходc3_2
OR4Yвыходg0_2
OR4Aвходc4_2
OR4Bвходc5_2
OR4Cвходc6_2
OR4Dвходc7_2
OR4Yвыходg1_2
OR4Aвходc8_2
OR4Bвходc9_2
OR4Cвходc10_2
OR4Dвходc11_2
OR4Yвыходg2_2
OR4Aвходc12_2
OR4Bвходc13_2
OR4Cвходc14_2
OR4Dвходc15_2
OR4Yвыходg3_2
OR4Aвходg0_2
OR4Bвходg1_2
OR4Cвходg2_2
OR4Dвходg3_2
OR4YвыходQ2
OR4Aвходc0_3
OR4Bвходc1_3
OR4Cвходc2_3
OR4Dвходc3_3
OR4Yвыходg0_3
OR4Aвходc4_3
OR4Bвходc5_3
OR4Cвходc6_3
OR4Dвходc7_3
OR4Yвыходg1_3
OR4Aвходc8_3
OR4Bвходc9_3
OR4Cвходc10_3
OR4Dвходc11_3
OR4Yвыходg2_3
OR4Aвходc12_3
OR4Bвходc13_3
OR4Cвходc14_3
OR4Dвходc15_3
OR4Yвыходg3_3
OR4Aвходg0_3
OR4Bвходg1_3
OR4Cвходg2_3
OR4Dвходg3_3
OR4YвыходQ3

Выделить всё → Ctrl+G → в библиотеке двойной клик по имени чипа → RAM16x4.

Шаг 2. Стенд

Что собираем. Четыре тумблера адреса, четыре тумблера данных, кнопка WE и три табло: адрес, что пишем, что лежит в памяти.

ЭлементНогаНаправлениеМетка
poweroutвыходVCC
groundoutвыходGND
inputOutвыходmA0
inputOutвыходmA1
inputOutвыходmA2
inputOutвыходmA3
inputOutвыходmD0
inputOutвыходmD1
inputOutвыходmD2
inputOutвыходmD3
buttonoutвыходmWE
RAM16x4A0входmA0
RAM16x4A1входmA1
RAM16x4A2входmA2
RAM16x4A3входmA3
RAM16x4D0входmD0
RAM16x4D1входmD1
RAM16x4D2входmD2
RAM16x4D3входmD3
RAM16x4WEвходmWE
RAM16x4Q0выходmQ0
RAM16x4Q1выходmQ1
RAM16x4Q2выходmQ2
RAM16x4Q3выходmQ3

Три табло: у каждого ⚙ — ширина 4, вид HEX; источник — шина mA (адрес), mD (что пишем), mQ (что в памяти). Стенд в чип не сворачивать.

2.4. Проверка

Адрес и данные — двоичные числа на тумблерах, младший бит справа (mA0, mD0).

№Что делаешьАдрес mAДанныеТабло: адрес / данные / память
1адрес 0000000000000 / 0 / пусто — ещё не писали
2набрать 1000000010 / 1 / пусто — только набрали
3нажать и отпустить WE000000010 / 1 / 1 — записано
4адрес 0001000100011 / 1 / пусто
5набрать 2, нажать и отпустить WE000100101 / 2 / 2 — записано
6адрес 0000000000100 / 2 / 1 ← то, что в ячейке 0
7адрес 0001000100101 / 2 / 2 ← то, что в ячейке 1

Главное — шаг 6: тумблеры данных стоят на 2, а память по адресу 0 показывает 1. Табло памяти показывает не тумблеры, а то, что запомнила ячейка. Читать ничего нажимать не надо: поменял адрес — сразу видно содержимое.

Незаписанные ячейки — пусто или оранжевое (в Fast — F), так и должно быть. Пока WE нажата, табло памяти повторяет тумблеры данных — защёлки выбранной строки открыты.

Если не так:

ВидноГде смотреть
запись идёт во все ячейки сразуW строк: у каждой свой wN = AND(rN, WE), не общий WE
читается не та ячейкаDEC16: I0–I3 = A0–A3 по порядку; rN → R строки N
один бит всегда 0дерево ИЛИ этого бита: 4 × OR4 → OR4 → QN

Вставка урока 2 (Cmd+I)

Поверх урока 1.

# Урок 2 — память 16×4: чип RAM16x4 + стенд.# Вставка: Cmd+I поверх урока 1 (нужны WORD4 урока 1, DEC16 и OR4 процессорного набора). # память 16 слов × 4 бита: дешифратор выбирает строку, WE разрешает запись в неё,# выходы строк сходятся по каждому биту в ИЛИ на 16 входов (4 × OR4 → OR4)chip RAM16x4 {  portIn(A0)  portIn(A1)  portIn(A2)  portIn(A3)  portIn(D0)  portIn(D1)  portIn(D2)  portIn(D3)  portIn(WE)  portOut(Q0)  portOut(Q1)  portOut(Q2)  portOut(Q3)  DEC16(I0=A0, I1=A1, I2=A2, I3=A3, Y0=r0, Y1=r1, Y2=r2, Y3=r3, Y4=r4, Y5=r5, Y6=r6, Y7=r7, Y8=r8, Y9=r9, Y10=r10, Y11=r11, Y12=r12, Y13=r13, Y14=r14, Y15=r15)  AND(r0, WE, w0)  AND(r1, WE, w1)  AND(r2, WE, w2)  AND(r3, WE, w3)  AND(r4, WE, w4)  AND(r5, WE, w5)  AND(r6, WE, w6)  AND(r7, WE, w7)  AND(r8, WE, w8)  AND(r9, WE, w9)  AND(r10, WE, w10)  AND(r11, WE, w11)  AND(r12, WE, w12)  AND(r13, WE, w13)  AND(r14, WE, w14)  AND(r15, WE, w15)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w0, R=r0, O0=c0_0, O1=c0_1, O2=c0_2, O3=c0_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w1, R=r1, O0=c1_0, O1=c1_1, O2=c1_2, O3=c1_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w2, R=r2, O0=c2_0, O1=c2_1, O2=c2_2, O3=c2_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w3, R=r3, O0=c3_0, O1=c3_1, O2=c3_2, O3=c3_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w4, R=r4, O0=c4_0, O1=c4_1, O2=c4_2, O3=c4_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w5, R=r5, O0=c5_0, O1=c5_1, O2=c5_2, O3=c5_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w6, R=r6, O0=c6_0, O1=c6_1, O2=c6_2, O3=c6_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w7, R=r7, O0=c7_0, O1=c7_1, O2=c7_2, O3=c7_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w8, R=r8, O0=c8_0, O1=c8_1, O2=c8_2, O3=c8_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w9, R=r9, O0=c9_0, O1=c9_1, O2=c9_2, O3=c9_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w10, R=r10, O0=c10_0, O1=c10_1, O2=c10_2, O3=c10_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w11, R=r11, O0=c11_0, O1=c11_1, O2=c11_2, O3=c11_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w12, R=r12, O0=c12_0, O1=c12_1, O2=c12_2, O3=c12_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w13, R=r13, O0=c13_0, O1=c13_1, O2=c13_2, O3=c13_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w14, R=r14, O0=c14_0, O1=c14_1, O2=c14_2, O3=c14_3)  WORD4(D0=D0, D1=D1, D2=D2, D3=D3, W=w15, R=r15, O0=c15_0, O1=c15_1, O2=c15_2, O3=c15_3)  OR4(A=c0_0, B=c1_0, C=c2_0, D=c3_0, Y=g0_0)  OR4(A=c4_0, B=c5_0, C=c6_0, D=c7_0, Y=g1_0)  OR4(A=c8_0, B=c9_0, C=c10_0, D=c11_0, Y=g2_0)  OR4(A=c12_0, B=c13_0, C=c14_0, D=c15_0, Y=g3_0)  OR4(A=g0_0, B=g1_0, C=g2_0, D=g3_0, Y=Q0)  OR4(A=c0_1, B=c1_1, C=c2_1, D=c3_1, Y=g0_1)  OR4(A=c4_1, B=c5_1, C=c6_1, D=c7_1, Y=g1_1)  OR4(A=c8_1, B=c9_1, C=c10_1, D=c11_1, Y=g2_1)  OR4(A=c12_1, B=c13_1, C=c14_1, D=c15_1, Y=g3_1)  OR4(A=g0_1, B=g1_1, C=g2_1, D=g3_1, Y=Q1)  OR4(A=c0_2, B=c1_2, C=c2_2, D=c3_2, Y=g0_2)  OR4(A=c4_2, B=c5_2, C=c6_2, D=c7_2, Y=g1_2)  OR4(A=c8_2, B=c9_2, C=c10_2, D=c11_2, Y=g2_2)  OR4(A=c12_2, B=c13_2, C=c14_2, D=c15_2, Y=g3_2)  OR4(A=g0_2, B=g1_2, C=g2_2, D=g3_2, Y=Q2)  OR4(A=c0_3, B=c1_3, C=c2_3, D=c3_3, Y=g0_3)  OR4(A=c4_3, B=c5_3, C=c6_3, D=c7_3, Y=g1_3)  OR4(A=c8_3, B=c9_3, C=c10_3, D=c11_3, Y=g2_3)  OR4(A=c12_3, B=c13_3, C=c14_3, D=c15_3, Y=g3_3)  OR4(A=g0_3, B=g1_3, C=g2_3, D=g3_3, Y=Q3)} # ---------- мини-стенд ----------power(VCC)ground(GND)# адрес (4 тумблера) и данные для записи (4 тумблера)input(Out=mA0)input(Out=mA1)input(Out=mA2)input(Out=mA3)input(Out=mD0)input(Out=mD1)input(Out=mD2)input(Out=mD3)# кнопка записи: держишь — пишетсяbutton{label="WE", hostKey="KeyW"}(mWE)RAM16x4(A0=mA0, A1=mA1, A2=mA2, A3=mA3, D0=mD0, D1=mD1, D2=mD2, D3=mD3, WE=mWE, Q0=mQ0, Q1=mQ1, Q2=mQ2, Q3=mQ3)# табло: адрес, что пишем, что лежит в памяти по адресуdisplay{bits=4, base="HEX", busSource="mA"}()display{bits=4, base="HEX", busSource="mD"}()display{bits=4, base="HEX", busSource="mQ"}()

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