FPGA > САПР > Основы Verilog: Курс лабораторных работ

ЛР5 > Язык Verilog: Исследование арифметических устройств

Тема: Краткие теоретические сведения по языку Verilog (продолжение) – иерархия проекта, подключение модулей, блокирующее и неблокирующее присваивание, системные функции, построение арифметических устройств.

1. Теоретические сведения.

Подключение модулей в файле верхнего уровня иерархии

Основной проектной единицей на языке Verilog являются модули. При создании сложных устройств удобно использовать иерархический подход к их построению, т.е. в состав одного устройства может входить несколько модулей. Пришло время научиться подключать готовые модули к проектируемой схеме и связывать между собой. Обычно выход одного модуля соединяется со входом другого проводником, поэтому изменения выходного сигнала источника будут немедленно передаваться на вход приемника. Можно соединять порты ввода/вывода модуля с входами устройства. Связи между модулями могут быть типа wire и reg.

Синтаксис подключения модуля имеет следующий вид:

Где module_name – имя вызываемого модуля, который необходимо подключить. Можно

подключить в одном проекте одновременно несколько одинаковых модулей, просто указав для них разные имена – instance_name. Здесь уместно вспомнить механизм объявления переменных в языках программирования. Сначала записывается тип переменной, а затем – имя переменной. Так и при подключении модуля – вначале записывается имя модуля, который необходимо подключить, а затем имя конкретного экземпляра этого модуля в вызывающем его файле. Далее, в круглых скобках, указывается подключение сигналов (типа reg или wire) к портам ввода-вывода модуля.

Рассмотрим следующий пример:

Рисунок 1. Иерархическое подключение модулей

Допустим, проектируемое устройство включает в себя три модуля (рис. 1): debounce,onepulse, clk_div, каждый из которых описан в соответствующем файле на языке Verilog (имя файла должно совпадать с именем модуля). Соответствующие входные и выходные порты этих модулей изображены на рисунке. Вход модуля изображается с левой стороны блока, выход – с правой. В устройстве необходимо объединить между собой эти модули в файле верхнего уровня иерархии. Соединение модулей осуществляются с помощью сигналов (тип reg) – Clock_100Hz,Clock_1MHz, PB1_Debounced. Файл описания устройства будет выглядеть следующим образом:

Операторы блокирующего и неблокирующего присваивания

В языке Verilog существуют два типа операторов присвоения: блокирующее blocking (=) и неблокирующее nonblocking (<=).

Для того чтобы понять разницу между данными типами операторов присвоения, необходимо рассмотреть принцип работы Verilog симулятора. В реальном устройстве

(например – цифровой схеме), которая моделируется с помощью языка Verilog, события могут происходить одновременно – при изменении входного сигнала во всех элементах, связанных с ним, начинаются процессы. Они протекают одновременно и приводят к соответствующим изменениям выходных сигналов. Моделирующая программа не может выполнять события одновременно, она создает списки событий, которые будут выполняться

последовательно. Когда все события из списка выполнены, симулятор переходит к обработке

следующего временного шага – увеличивает текущее время моделирования на временной интервал (второй параметр в директиве `timescale) и выполняет обработку списка событий, которые должны произойти на данном шаге. Рассмотрим события происходящие «одновременно»– т.е. на одном временном шаге моделирования.

Допустим, имеется следующий набор команд:

В данном примере переменные а и b – одноразрядные регистры, к моменту появления положительного фронта тактового сигнала CLK хранящие значения а==0 и b==1. Какое же значение будут иметь эти переменные после выполнения операции присвоения? Это зависит от того, в какой последовательности операции присваивания попадут в список. То есть, поведение такой конструкции зависит от порядка следования операторов в программе. Это означает, что либо обе эти переменные будут равны 0, либо обе равны 1 (в нашем примере – 1). Операцияблокирующего присвоения (=) блокирует исполнение других последовательных операций до тех пор, пока она не будет выполнена. Использование операции блокирующего присвоения в параллельно исполняемых блоках нежелательно. Но если в блоке необходимо обеспечить последовательное выполнение операторов, следует использовать данный тип присвоения.

Следующий фрагмент программы гарантирует обнуление переменных a и b по переднему фронту сигнала CLK:

Если в предыдущих примерах использовать оператор неблокирующего присвоения (<=), то поведение устройства изменится:

В данном случае в список событий, исполняемом на текущем временном шаге моделирования после изменения сигнала CLK, обе операции будут помещены как параллельно исполняемые, т.е. переменные a и b обменяются своими значениями. После прохождения переднего фронта сигнала CLK значения переменных будут следующими: а==1 b==0. Последовательность записи a<=b; b<=a; или b<=a; a<=b; в данном случае не имеет значения, т.к. события моделируются одновременно.

Системные функции языка Verilog

Язык Verilog предоставляет программисту специальные возможности для управления и анализа результатов моделирования. Эти возможности реализованы в виде системных функций симулятора. Следует помнить, что при синтезе системные функции игнорируются.

Благодаря наличию механизма PLI, обеспечивающего подключение исполняемой программы (написанной либо пользователем, либо третьей стороной) к тестовым файлам, число системных функций и задач, которые могут выполняться с их помощью, очень велико. Основное назначение системных функций – сбор и анализ информации, взаимодействие с операционной системой. Признаком системной функции является знак $. Перечислим наиболее популярные системные функции:

$finish – завершение процесса моделирования;

$stop – переход в интерактивный режим;

$display, $write – вывод данных в stdout (данные дублируются в файл протокола), поведение такой функции соответствует функции printf языка C (вывод форматированной строки с поддержкой дополнительных форматов, например, %b -бинарный), или процедуре write языка Паскаль с разделенными «,» аргументами. Функция $display завершает вывод строки командой «перевод строки»;

$monitor – отслеживает изменения аргументов и в конце каждого временного шага моделирования отображает текущие результаты (если были обнаружены изменения значений сигналов). Формат данной функции – как у $display;

$readmemb, $readmemh – обеспечивают считывание данных (в двоичном или шестнадцатеричном формате) из файла в память. Формат файла очень простой – в каждой строке указывается слово заданной разрядности, или указатель адреса (конструкция @<адрес загрузки>). Данную функцию удобно применять для моделирования ПЗУ;

$system – выполняет команду операционной системы (вызов функции языка С system()).

Для выполнения файловых операций используются функции $fopen, $fclose, $fwrite,$fmonitor. Они позволяют сохранять передаваемые данные в файлах. Функции $dumpfile,$dumpvars позволяют записывать изменения сигналов тестируемого модуля, всего проекта или его составных частей, в файле специального формата для дальнейшего анализа. Очень полезные и эффективные функции для обработки данных.

Функция $time – возвращает значение текущего времени моделирования.

Это небольшой перечень стандартных функций. Их полный список указан в документации к моделирующей программе.

Арифметические устройства

К арифметическим устройствам относятся преобразователи, выполняющие арифметические действия (сложение, вычитание, умножение) над входными данными.

На рисунке 1 представлена схема полного одноразрядного сумматора и его графическое изображение.

Рисунок 2. Схема полного одноразрядного сумматора и его графическое изображение.

Назначение сигналов сумматора следующее: a и b – входные сигналы (слагаемые), Сi – вход переноса, s – выходной сигнал (сумма), Со – выход переноса. Таблица истинности одноразрядного сумматора выглядит следующим образом:

Таблица истинности

a b Сi Со s
0 0 0 0 0
0 0

1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1

    Для создания сумматоров большей разрядности используется каскадное соединение одноразрядных сумматоров. Например, на рисунке 2 показан полный четырехразрядный сумматор с последовательным переносом, состоящий из четырех одноразрядных сумматоров.

Рисунок 3. Полный четырехразрядный сумматор с последовательным переносом.

Пример выполнения операции умножения двух 4-разрядных чисел в двоичном виде показан на рисунке 3. На рисунке 4 показана структурная схема реализации такого перемножителя. Он состоит из логических элементов «И» и полных одноразрядных сумматоров (FA).

Рисунок 4. Операция умножения двух 4-разрядных чисел.

Рисунок 5. Структурная схема перемножителя двух 4-разрядных чисел.

    Данные два компонента используются как базовые для создания различных арифметических или арифметико-логических устройств (АЛУ).

2. Порядок выполнения работы.

В лабораторной работе мы создадим проект, описывающий работу полного четырехразрядного сумматора, изображенного на рисунке 3. Для исходного модуля используется структурное описание. Для проверки сумматора создадим эталонную модель, использующую поведенческое описание, и тестовый файл (test-bench). Для этого:

1. Создайте новый проект в среде ModelSim.

2. Создайте исходный файл сумматора на структурном уровне:

Обратите внимание на подключение готовых модулей в данном файле.

3. Создайте исходный файл эталонного сумматора на поведенческом уровне:
4. Создайте тестовый файл для подачи входных сигналов и сравнения работы двух модулей:

Обратите внимание на подключение модулей в данном файле и использование системных функций.

5. Скомпилируйте все программы. После успешной компиляции перейдите в режим моделирования. В качестве основного файла для моделирования укажите тестовый файл.

6. Отройте графическое окно и добавьте в него проверяемые сигналы. Запустите проект на моделирование. Ответьте НЕТ на вопрос, хотите ли Вы закончить работу с симулятором. Проверьте полученные результаты:

7. Объясните полученный результат. Выйдите из режима моделирования.

2. Самостоятельная работа.

Спроектировать следующие арифметико-логические устройства (входные данные – восьмиразрядные):

Вариант 1. АЛУ с функциями: А+В, АxorВ, А-1, А-В.

Вариант 2. АЛУ с функциями: А+В, А*В, А-1, В.

Вариант 3. АЛУ с функциями: А+(А+В), А, А+1, А-В-1.

Вариант 4. АЛУ с функциями: not(А+В), not(А*В), А+В+1, (А + notВ)+1.

Вариант 5. АЛУ с функциями: АxorВ, А*В+(А+notВ), А, В.

Вариант 6: Спроектировать умножитель с накоплением (операция МАС).

    Для проверки работы устройства создать тестовый файл.


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