Один из фундаментальных строительных блоков любой вычислительной системы, регистр представляет собой не что иное, как объединение нескольких триггеров, что позволяет хранить в памяти множество битов. В то время как отдельный триггер может хранить только один бит информации, регистр позволяет хранить nбитов. В свою очередь, банк регистров может быть создан из объединения нескольких регистров, что позволяет еще больше увеличить объем памяти.
Наша цель здесь — использовать язык описания оборудования Verilog для разработки модели банка регистров. Тем не менее, мы не будем использовать зарезервированное слово Verilog «reg» для реализации каждого регистра, поскольку мы хотим получить полное представление о том, что происходит с нашим банком. То есть при использовании «reg» по умолчанию у нас мало контроля над тем, какой тип триггера Verilog будет использовать для своих регистров.
Поэтому у нас нет другого выбора, кроме как реализовать собственный модуль триггера в Verilog. К счастью, по этому поводу есть много литературы, в частности, Verilog на примере: краткое введение в проектирование FPGA (https://www.amazon.com.br/Verilog-Example-Concise-Introduction-Design/dp/0983497303). ).
Как описано в вышеупомянутой книге, следующий код реализует триггер D-типа в Verilog:
Как мы видим, приведенный выше код представляет модуль с пятью входами: тактовый сигнал, сигнал сброса, вход d, представляющий вход D-триггера, а также входы «q» и «qb». представляющие, соответственно, текущее значение, хранящееся на триггере, и его противоположность.
Если тактовый сигнал активирован, q получает значение входа d. И наоборот, когда активируется сигнал сброса, «q» получает ноль, сбрасывая триггер.
Отлично, теперь у нас уже есть первый важный строительный блок нашего регистрового банка. Все, что осталось сделать, это создать модуль регистров, а также наш модуль банка регистров.
Во-первых, мы должны установить размер нашего реестра. Для приведенного ниже кода мы будем использовать 32-битный регистр, но вы можете создать регистры значительно большего размера. Наш регистр можно реализовать следующим образом:
И снова у нас есть часы и сигнал сброса. Вход A — это наш 32-битный массив, каждый из которых несет сигнал для входа триггера. Кроме того, Q — это массив битов, представляющий текущее значение каждого триггера. Обратите внимание, что мы используем команду «создать для», чтобы избежать объявления 32 триггеров вручную.
Еще раз мы проверяем, активирован ли тактовый сигнал, и в этом случае массив входов «d» получает «A».
Наконец, мы объявляем наш модуль банка регистров:
Как и ожидалось, наш банк регистров имеет два режима: режим записи и режим чтения. Поведение банка определяется входом option: «0» для записи, «1» для чтения. Адрес памяти идентифицирует каждый из восьми регистров в двоичном режиме (поэтому он имеет длину 3 бита).
Режим чтения: берет заданный адрес памяти и извлекает содержимое, хранящееся в соответствующем регистре, обновляя вывод «out».
Режим записи:записывает данные «b_entry» в регистр, адресованный «b_address».
Короче говоря, мы создали очень простой 32-битный банк регистров, который позволяет нам хранить и извлекать данные по своему усмотрению.
Несмотря на свою простоту, наш банк регистров, тем не менее, представляет собой весьма интересную аппаратную часть, поскольку позволяет нам поближе взглянуть на ключевую концепцию любого компьютера. Более того, красота абстракции и модуляризации, используемых при разработке таких устройств, никогда не перестанет очаровать настоящего поклонника компьютеров.