Verilog: память и время — триггеры, регистры, RAM

До сих пор в цикле «От кода к кремнию» все схемы были честными эгоистами настоящего: их выход зависел только от текущих входов. Сколько ни жми на входы — схема не вспомнит, что было секунду назад. Память появляется в тот момент, когда в схему входит время: тактовый сигнал и D-триггер. Уровни 3.37–3.39 добавляют именно эту способность — и вместе с ней почти всё, что отличает процессор от калькулятора.

Схема уровня «Память и время»: восемь D-триггеров, собранных generate-for, в RTL-вьюере
Уровень 3.37 «Память и время» в RTL-вьюере: восемь триггеров dff, развёрнутых циклом generate-for, образуют 8-битный регистр

Время в схеме: примитив dff

D-триггер — единственный примитив курса, который «живёт» во времени. Правило его работы: на фронте такта (переход clk 0 → 1) триггер запоминает то, что сейчас на входе D, и держит это на выходе Q до следующего фронта. Между фронтами любые изменения D игнорируются.

В структурном Verilog триггер — такой же примитив, как and или not:

module bit_latch(input d, input clk, output q);
  dff cell(q, d, clk);
endmodule

Ключевая мысль, которую проверяет уровень 3.37: такт — это не «кнопка обновить», а граница между «прошлым» и «будущим» схемы. Всё комбинационное (вентили) живёт внутри такта, всё последовательное (dff) перескакивает через фронт.

Регистр: восемь триггеров одной строкой

8-битный регистр — это просто восемь dff с общим тактом, каждый хранит свой бит. Писать восемь строк и соединять вручную незачем: Verilog умеет разворачивать одинаковые конструкции циклом generate-for — той самой возможностью, которую вы освоили на уровне 3.37:

module reg8(input [7:0] d, input clk, output [7:0] q);
  genvar i;
  generate
    for (i = 0; i < 8; i = i + 1) begin : bits
      dff cell(q[i], d[i], clk);
    end
  endgenerate
endmodule

Цикл превращается в восемь отдельных триггеров ещё на этапе «сборки» схемы — железо не умеет циклов, они существуют только для удобства записи. На уровень 3.38 «Шаг за шагом» регистр уже работает в связке с сумматором: каждый такт к счётчику прибавляется шаг — так рождается счётчик команд, сердце любого процессора.

RAM256: память с адресом

Следующий шаг — хранить не один байт, а сотни. RAM256 — встроенный модуль курса: 256 ячеек по байту, доступ по 8-битному адресу. Запись: подаём адрес и данные, поднимаем сигнал записи — на фронте такта значение ложится в ячейку. Чтение: подаём адрес — на выходе содержимое.

Уровень «Оперативная память» в RTL-вьюере: RAM256 с адресной логикой
Уровень 3.39 «Оперативная память»: RAM256 — встроенный блок, к которому вы проводите адрес, данные и сигнал записи

На уровне 3.39 RAM256 выдаётся как готовый «чёрный ящик» — ваша задача, комбинаторная логика вокруг него: дешифрация режима чтения/записи и разводка шин. Ровно этот блок дальше станет памятью данных процессора из уровня 3.40 «Сердце процессора»: ROM хранит программу, RAM — данные, и та самая гарвардская развязка, о которой писали в статье об архитектуре, обретает конкретные провода.

Что дальше

Триггер + регистр + RAM + такт — это полный набор «жизни» схемы. Уровень 3.40 собирает из них процессор с программой, а вы уже готовы читать его схему в RTL-вьюере и понимать каждый блок. Про то, как довести проект до настоящей платы Tang Nano 9K — следующая статья цикла.

Проверь себя

Когда именно dff запоминает вход D?

На фронте такта — в момент перехода clk из 0 в 1. Между фронтами изменения на D ни на что не влияют.

Во сколько строк Verilog разворачивается generate-for из регистра reg8?

В восемь экземпляров dff — по одному на бит. Цикл существует только в записи; в железе это восемь независимых триггеров с общим тактом.

Почему RAM256 адресуется именно восемью битами?

Восемь бит дают 256 комбинаций — ровно по одной на каждую из 256 ячеек байтовой памяти.

Попробовать в симуляторе →