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

Сумматор

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

 Структура курса лабораторных работ: Основы Verilog 

 1. Знакомство со средой моделирования ModelSim
 2. Исследование комбинационных устройств
 3. Комбинационные устройства
 4. Исследование последовательностных логических устройств 
 5. Исследование арифметических устройств
 6. Исследование конечных автоматов
 7. Исследование многофункциональных устройств
 8. Простой процессорный модуль

Скачать Материалы к лабораторной работе по Verilog №5.

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: Спроектировать умножитель с накоплением (операция МАС).

 

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