цифровая электроника
вычислительная техника
встраиваемые системы

 

Verilog. Базовый курс. Часть III

Автор: Mike(admin) от 3-02-2014, 08:30

Модульная конструкция


Модульная конструкция проекта – это, пожалуй, базовый принцип построения схем на ПЛИС, поэтому этой теме стоит уделить пристальное внимание.


Ранее мы уже касались термина «модуль», но теперь мы уточним некоторые важные нюансы. Каждый исходный файл Verilog содержит один и только один раздел определения модуля. Тогда как мы можем создавать сложные проекты, которые включают в себя множество мелких модулей? Давайте в качестве примера возьмем создание цепи управления светодиодом с использованием таймера. Что нужно для нашей схемы, чтобы светодиод мигал каждую секунду при нажатии, например, какой-нибудь кнопки, которая подавала бы на вход лог. «1»? Также на входе у нас есть таймер 50 МГц.


Нам нужны входы, выходы и внутренние компоненты. В данном случае у нас будет два входа (для осциллятора и для кнопки), один выход (на светодиод) и какие-то компоненты, которые в соответствии с входными сигналами будут выдавать определенные сигналы на выход. Не все из них должны быть подключены к портам верхнего уровня, но все должны быть соединены в соответствии с заданным маршрутом. Здесь можно провести аналогию с математическими уравнениями. Входы – это независимые переменные, выходы – зависимые переменные, внутренние компоненты – само уравнение. Такая аналогия в будущем, возможно, поможет в разграничении этих трех понятий при работе над серьезными проектами.


Итак, мы определились: входы – осциллятор 50 МГц и кнопка, выход – светодиод, внутренние компоненты – делитель частоты с 50 МГц до 1 Гц и один логический элемент «И». Блок-схема цепи показана на рисунке ниже.


verilog

Блок-схемы, подобные этой, помогают при написании программы на Verilog, поскольку каждый ее блок должен быть представлен модулем в программе. Заметьте, что у нас есть один большой блок, содержащий несколько маленьких блоков. Его называют модулем верхнего уровня. Он отвечает за связь всех внутренних модулей между собой, а также за соединение с портами верхнего уровня, то есть с физическими входами и выходами.


Внутри модуля верхнего уровня есть два внутренних модуля: делитель частоты и элемент «И». Следует заметить, что делитель также сам должен состоять из компонентов, в данном случае из D-триггеров. И как вы уже догадались, нам придется описывать на Verilog и этот модуль. Но прелесть модульного подхода в том, что однажды создав такой модуль с D-триггерами, мы сможем использовать его в нашем проекте сколько угодно раз.


Создание модулей


Отдельные модули чем-то похожи на вызываемые функции в C/C++. Давайте посмотрим на модуль RS-триггера, с которым мы будем работать в этой главе:



`timescale 1ns / 1ps

module srlatch(
input S,
input R,
output Q
);

wire Q_int, Qn_int;

assign Q_int = ~(S & Qn_int);
assign Qn_int = ~(R & Q_int);
assign Q = Q_int;

endmodule


Здесь должно быть все понятно. Допустим, мы хотим сделать схему с двумя RS-триггерами. Каждый будет иметь свой вход на «Set» и общую кнопку на сброс «Reset». На выходе каждого триггера будет светодиод. С учетом этого давайте создадим модуль верхнего уровня, помня о том, что модуль верхнего уровня содержит входы и выходы, непосредственно связывающие нашу цепь с реальным миром.



`timescale 1ns / 1ps

module top(
input switch0,
input switch1,
input btn0,
output led0,
output led1
);

endmodule


Отлично! Теперь нужно добавить два RS-триггера. Для этого мы создадим по модулю для каждого из них. Вот так это будет выглядеть:



`timescale 1ns / 1ps

module top(
input switch0,
input switch1,
input btn0,
output led0,
output led1
);

srlatch sr0(
.S(switch0),
.R(btn0),
.Q(led0)
);

srlatch sr1(
.S(switch1),
.R(btn0),
.Q(led1)
);

endmodule


Давайте повнимательнее рассмотрим модуль первого (в данном случае нулевого) триггера. Первая строка «srlatch sr0(» содержит в себе имя базового модуля (srlatch) и имя непосредственно данного модуля (sr0). Скобка сообщает о начале определения модуля. Далее идут три строчки:


.S(switch0),
.R(btn0),
.Q(led0)


Обратите внимание на имена портов модуля srlatch и посмотрите на эти три строки. Это примерно то же, что и в C/C++ является передачей параметров функции. Разница только в том, что в Verilog мы передаем модулю и входы, и выходы.


Теперь давайте рассмотрим отдельно строчку «.S(switch0)». Здесь «.S» отсылает нас к входу «S» модуля srlatch, а «switch0» связан с входом «switch0» верхнего модуля.


Как уже упоминалось ранее, в модуле каждому порту нужна инициализация. Но если, допустим, вы создаете 8-разрядную шину T[7:0], то вам не нужно писать 8 строк инициализаций типа «.T[0](Input[0])». Вы можете ссылаться на шины только по их именам, например, «.T(Input)». Только имейте ввиду, что размеры шин должны совпадать, то есть вы не можете вызывать 5-портовую шину 3-портовым экземпляром. Кроме того, должны совпадать и типы, то есть входы должны соответствовать входам, а выходы – выходам. Выражения инициализации отделяются друг от друга запятыми. Сам блок инициализации закрывается скобкой и точкой с запятой. После успешной инициализации мы можем подключать выход к портам верхнего уровня или, при желании, к входам других модулей.


В следующей части, используя эту информацию, мы будем непосредственно разбираться с делителем частоты на D-триггерах.


Часть I


Часть II


Часть IV


Часть V


Часть VI




Перевод © digitrode.ru


<Источник>


Теги: Verilog, ПЛИС



Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий