Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Подготовка модулей на языке Verilog





Лабораторная работа № 1

 

Подготовка модулей на языке Verilog

 

Введение

 

Цель работы - знакомство с основными синтаксическими блоками описания проекта цифрового устройства на языке Verilog. Приобретение начальных навыков функционального моделирования цифровых устройств, описанных на языке Verilog, в пакете ModelSim. В качестве примеров простейших устройств в работе используются реализации базовых булевых функций. При выполнении задания необходимо руководствоваться краткой инструкцией по применению пакета ModelSim (приложение А).

 

Необходимые сведения

 

При подготовке проектов цифровых устройств на языке Verilog применяются два основных вида файлов на этом языке. Конструкторский файл (design file) и испытательный файл (testbench). В первом файле с помощью синтезируемых синтаксических конструкций языка описывается сущность проекта. Во втором - устанавливается модуль разработанного устройства (объявляется его экземпляр), описанный в первом файле, и с помощью синтаксических конструкций языка последовательно во времени задаются необходимые комбинации значений входных сигналов, которые используются пакетом моделирования для определения реакции на них разработанного устройства. Оба файла обычно снабжаются расширением "v".

Для облегчения ориентировки в файлах проекта целесообразно имя испытательного файла создавать из имени конструкторского файла, добавляя в начале символы - "t_". Например:

dec3_8.v - конструкторский файл;

t_dec3_8.v - испытательный файл.

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

Примеры содержания конструкторского и испытательного файлов приведены в задании.

 

В языке Verilog используются 4 основных значения для одноразрядных данных, представляющих логические сигналы на линиях (литеральные константы). Эти значения приведены в табл. 1.1.

 

Таблица 1.1. Основные значения логических данных

Значение Функциональная сущность
  Нуль, низкий логический уровень, ложь
  Единица, высокий логический уровень, истина
z или Z Высокий импеданс, третье состояние (отключено)
x или X Неизвестное значение или не инициализировано

 

Важными сигнальными линиями в модуле являются его внешние выводы, называемые портами. Порты могут быть трех вариантов направленности:

- input - применяется для одноразрядных (скалярных) или многоразрядных (векторных) входных портов;

- output - для одноразрядных или многоразрядных выходных портов;

- inout - для двунаправленных одноразрядных или многоразрядных портов.

При объявлении многоразрядного порта должен быть указан диапазон разрядов, например:

input [7:0] address;.

Если диапазон разрядов не указан, то порт считается одноразрядным.

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

reg [7:0] address;.

При использовании отдельного оператора типа объявление порта должно предшествовать объявлению его типа.

Ниже приведены примеры объявления портов (лист. 1.1).

 

input a,b,clk; //три одноразрядных (скалярных) входных порта

input [15:0] data,addr; //два 16-разрядн. (векторных) входных порта

output [31:0] q; //один 32-разрядный выходной порт

reg [31:0] q; //тип этого 32-разрядного порта

parameter w = 16; //объявление именованной константы

input [w-1:0] bus; //один 16-разрядный входной порт

 

Листинг 1.1. Примеры объявления портов

 

Основные правила подключения к портам внутренних и внешних переменных, базовые типы которых описаны ниже, приведены в табл. 1.2.

 

 

Таблица 1.2. Допустимые для подключения к портам типы данных

Порт input output inout
Вне модуля wire,reg,integer wire wire
Внутри модуля wire wire,reg,integer wire

 

Логические значения переменных в цифровом устройстве могут существовать на проводниках (линиях или узлах), при этом проводник только передает значение из одного точки схемы в другую, а сам не может ни генерировать, ни хранить эти значения. Подобные проводники в языке Verilog представлены типом данных без памяти wire (в стандарте [2] - Net Data Types). Логические значения могут также существовать в объектах другого рода, в которых они могут храниться как в триггерах (как, например, в переменных языка С). Такие объекты представлены типом данных с памятью reg (в стандарте - Variable Data Types). Есть и другие, менее употребляемые, типы данных [2].

При использовании переменных в описании устройства следует пользоваться следующими правилами:

- применять данные типа wire, если сигнал управляется выходом экземпляра модуля нижнего уровня или примитива или ему присваивается значение с помощью оператора непрерывного присваивания assign;

- применять данные типа reg, если сигналу присваивается значение в процедурном операторе (initial или always).

Переменные, так же как и порты, могут быть многоразрядными. Ниже приведены примеры объявления переменных (лист. 1.2).

 

wire a, b, clk; //три 1-разрядные (скалярные) цепи

wire [7:0] data, addr; //две 8-разрядные шины

reg q, s; // две одноразрядные переменные с памятью

reg [7:0] dataout; //8-разрядная переменная с памятью

reg [7:0] qout [3:0]; //массив из 4-х 8-разрядных регистров

 

Листинг 1.2. Примеры объявления переменных

 

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

 

Таблица 1.3. Примитивы логических функций

Имя примитива Функция Порядок и количество портов
not Инверсия (1 или более output, 1 - input)
and И (конъюнкция) (1- output, 2 или более - input)
nand И-НЕ (1- output, 2 или более - input)
or ИЛИ (дизъюнкция) (1- output, 2 или более - input)
nor ИЛИ-НЕ (1- output, 2 или более - input)
xor Исключающее ИЛИ (1- output, 2 или более - input)
xnor Исключающее ИЛИ-НЕ (1- output, 2 или более - input)

 

Пример объявления (установки) экземпляра примитива в устройстве (модуле) с подключением его портов приведен в задании.

Наряду с использованием логических примитивов простые логические функции могут описываться с помощью выражений, состоящих из побитовых логических операций (bitwise operators). Эти операции выполняют соответствующие булевы функции над отдельными битами в общем случае многоразрядных данных. Для присваивания результата выражения какой-либо цепи (что характерно для так называемой комбинационной логики, т. е. для цифровых устройств, не содержащих элементов памяти - триггеров) необходимо использовать оператор непрерывного присваивания assign. В следующем примере линии dout типа wire присваивается результат выражения, стоящего справа от знака равенства, т. е. логического умножения (конъюнкции) переменных ina и inb.

assign dout = ina & inb;

При этом оператор непрерывного присваивания assign будет автоматически выполняться каждый раз, когда изменится значение любой из переменных, стоящих справа от знака равенства.

В языке Verilog предусмотрены побитовые операции, представленные в табл. 1.4.

 

Таблица 1.4. Побитовые операции языка Verilog

Обозначение Применение Содержание
~ ~a Инверсия каждого разряда (бита) переменной a
& a & b Операция И над одноименными разрядами a и b
| a | b Операция ИЛИ над одноименными разрядами a и b
^ a ^ b Операция исключающее ИЛИ над одноименными разрядами a и b
~^ или ^~ a ~^ b Операция исключающее ИЛИ-НЕ над одноименными разрядами a и b
<< a << n Сдвиг a влево на n разрядов (справа вдвигаются нули)
>> a >> n Сдвиг a вправо на n разрядов (слева вдвигаются нули)

 

Для задания изменений входных сигналов во времени в испытательных файлах на языке Verilog предусмотрены два процедурных оператора (в стандарте называются "Procedural Blocks") - initial и always. (На самом деле применение этих операторов более широкое, о чем пойдет речь в описаниях следующих лабораторных работ.) Оператор initial выполняется один раз. Оператор always повторяется, в общем случае, бесконечное число раз. Внутри процедурных операторов могут использоваться блочные операторы begin.. end. Все процедурные операторы initial и always, установленные в модуле, начинают выполняться в один и тот же момент модельного времени, равный нулю.

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

Если не предпринять специальных мер, то процесс моделирования, параметры которого описаны в испытательном файле, может продолжаться бесконечно. Для ограничения процесса во времени после завершающего оператора следует применить системную задачу $stop, которая остановит процесс моделирования. Пример применения этой системной задачи приведен в задании.

Задание

 

1. Создать в пакете ModelSim проект цифрового устройства, выполняющего одну из простых логических функций нескольких переменных. Число входных переменных и вид функции выбираются по указанию преподавателя. Для описания логики проекта подготовить конструкторский файл на языке Verilog, пользуясь приведенным примером (лист. 1.3), описывающим простую функцию инвертора на базе примитива not.

 

module z_not(ia,o); //заголовок модуля - имя модуля и список портов

input ia; //объявление однобитного входн. порта с именем ia

output o; //объявление однобитного выходн. порта с именем o

not g1(o,ia); //объявление экземпляра примитива not с именем g1,

//подключение к выходу примитива выходного порта

//модуля - o (первый по порядку в скобках)

//и подключение к входу примитива входного порта

//модуля ia (второй в скобках)

endmodule //завершение описания модуля

 

Листинг 1.3. Содержание конструкторского файла инвертора "z_not.v"

2. Откомпилировать подготовленный модуль и устранить все синтаксические ошибки.

3. Подготовить испытательный файл, предназначенный для моделирования разработанного модуля. Такие файлы носят общее наименование testbench и содержат объявление экземпляра разработанного модуля и задаваемую разработчиком последовательность поступления на входы модуля испытательных сигналов. Испытательный файл должен формировать все возможные комбинации входных сигналов для моделируемого устройства. Ниже приведен пример испытательного файла ("t_z_not.v") для моделирования модуля z_not (лист. 1.4).

 

module t_z_not; //testbench для модуля инвертора z_not

reg ina; //переменная тестового сигнала, должна быть типа reg

wire outa; //выходная линия для контроля работы устройства

reg times; //переменная для задания момента времени смены хара-

// ктера тестирующего сигнала

z_not gg1(ina,outa); //объявление экземпляра модуля z_not с //именем gg1 и подключение к входу модуля //тестирующего сигнала ina,

//и к выходу модуля контрольной линии outa

initial //включение однократно исполняемого оператора

begin //начало блока, состоящ. из неск. операторов

ina = 0; //задание начального значения входн. сигнала

times = 1'b0; // начальное значение управляющей переменной

#2 ina = 1'b1; //измен. через 2 ед. времени сигнала ina на 1

#2 ina = 1'b0; //измен. через 2 ед. времени сигнала ina на 0

#2 ina = 1'b1; //измен. через 2 ед. времени сигнала ina на 1

#2 ina = 1'b0; //измен. через 2 ед. времени сигнала ina на 0

#2 times = 1'b1; //измен. управ. переменной times на 1

end //завершение блока в операторе initial

always //включение непрерывно повторяемого оператора always

//начинает работу одновременно с оператором initial

begin

#5 if (times) //анализ сост. переменной times (через 5 ед.времени)

ina = ~ina; //если times == 1, то инвертирование ina

end // завершение блока в операторе always

initial //включение еще одного оператора initial

//начинает работу одновременно с предыдущими операторами

#50 $stop; //остановка моделирования на 50-й единице времени

endmodule //окончание испытательного файла

 

Листинг 1.4. Содержание испытательного файла (testbench) – "t_z_not.v"

 

4. Откомпилировать модуль testbench и устранить все синтаксические ошибки.

5. Запустить процесс моделирования пакета ModelSim, выбрав в качестве исполняемого файла (Design Units) файл модуля testbench (в приводимом примере это файл "t_z_not.v").

6. Проанализировать характер полученных временных диаграмм входных и выходных сигналов ("Wave"). В случае несоответствия их предполагаемой логике работы устройства выявить логические (не синтаксические) ошибки в файлах проекта, исправить их и повторить моделирование.

 

7. Создать новый проект (средствами пакета ModelSim в новой папке), в котором будет реализовано то же самое устройство, но без применения примитива логической функции, а на основе оператора непрерывного присваивания assign и логических операций. Для этого в новую папку скопировать файлы "*.v" предыдущего проекта и дать им новые имена, например в случае инвертора: "z_not_1.v"; "t_z_not_1.v".

8. В пакете ModelSim включить файлы в новый проект и изменить их, пользуясь приведенными примерами (лист. 1.5 и лист. 1.6).

 

module z_not_1(ia,o); //имя модуля изменено (новый проект)

input ia;

output o;

// not g1(o,ia); установка примитива должна быть удалена

assign o = ~ia; //всякий раз при изменении ia выходу o будет

//присваиваться инвертированное значение ia

endmodule

 

Листинг 1.5. Содержание конструкторского файла "z_not_1.v"

 

 

module t_z_not_1; //новое имя испытательного модуля

reg ina;

wire outa;

reg times;

 

z_not_1 gg1(ina,outa); //новое имя модуля устройства

//все остальное остается без изменения

initial

begin

ina = 0;

times = 1'b0;

#2 ina = 1'b1;

#2 ina = 1'b0;

#2 ina = 1'b1;

#2 ina = 1'b0;

#2 times = 1'b1;

end

always

begin

#5 if (times)

ina = ~ina;

end

initial

#50 $stop;

 

endmodule

 

Листинг 1.6. Содержание испытательного файла (testbench) – "t_z_not_1"

 

9. Запустить процесс моделирования пакета ModelSim для нового проекта. Проанализировать характер полученных временных диаграмм входных и выходных сигналов ("Wave"). В случае несоответствия их предполагаемой логике работы устройства выявить ошибки в файлах проекта, исправить их и повторить моделирование.

10. Подготовить отчет. Отчет должен содержать листинги всех конструкторских файлов (на языке Verilog) и рисунки с временными диаграммами по каждому варианту реализации устройства.

 

Контрольные вопросы

 

1. Основные синтаксические блоки конструкторского файла на языке Verilog.

2. Основные синтаксические блоки испытательного файла (testbench) на языке Verilog.

3. Порты в модуле цифрового устройства. Назначение, типы портов.

4. Переменные типа wire и reg. Назначение, объявление, особенности.

5. Примитивы булевых функций в языке Verilog. Таблицы истинности, объявление, способы подключения входов и выходов.

6. Оператор assign, назначение, особенности применения.

7. Объявление экземпляра модуля внутри испытательного файла.

8. Операторы initial и always, назначение, применение в испытательных файлах.

9. Применение временных задержек при моделировании.

10. Системные задачи, общее представление, назначение и работа задачи $stop.

11. Основные этапы подготовки проекта и его функционального моделирования в пакете ModelSim.

12. Побитовые операции в языке Verilog.

 

Лабораторная работа № 2

Иерархический проект

 

Введение

 

Цель работы – освоение подготовки проектов c использованием модулей нижнего уровня собственной или сторонней разработки.

 

Необходимые сведения

 

Иерархический проект - это проект относительно сложного устройства, которое состоит из нескольких простых, представленных в отдельных модулях. Модуль всего устройства называется модулем верхнего уровня, а модули его частей - модулями нижнего уровня. Модули нижнего уровня могут быть расположены в отдельных файлах, но могут быть расположены и в единственном конструкторском файле проекта, последовательно друг за другом.

Объявление (установка) экземпляров модулей нижнего уровня в устройстве осуществляется аналогично объявлению экземпляров примитивов, т. е. путем указания имени модуля, имени экземпляра и списка цепей, подключаемых к портам экземпляра. При этом могут использоваться два способа подключения к портам. Первый способ аналогичен применяемому в примитивах и называется позиционным. В соответствии с этим способом следующий за именем экземпляра модуля список подключаемых к портам внешних цепей (в круглых скобках) должен строго соответствовать количеству и порядку расположения подключаемых портов в описании этого модуля. В случае если к какому-либо порту не подключается никакая внешняя цепь, то в этом месте оставляется пропуск между запятыми. В приведенном ниже примере (лист. 2.1) представлены описания модулей нижнего уровня для вычисления суммы module s и переноса module carry одноразрядных слагаемых a и b с учетом входного переноса из младшего разряда cin [1, с. 116]. Последний модуль в примере module sum является модулем верхнего уровня, в котором установлены два экземпляра модулей нижнего уровня.

 

module s(a,b,cin,s); //модуль нижнего уровня

input a,b,cin; //для вычисления суммы

output s;

assign s = (a ^ b) ^ cin;

endmodule

 

module carry(a,b,cin,cout); //модуль нижнего уровня

input a,b,cin; //для вычисления переноса

output cout;

assign cout = (a & b) | ((a ^ b) & cin);

endmodule

 

module sum(aa,bb,ccin,ss,ccout); //модуль верхнего уровня

input aa,bb,ccin;

output ss,ccout;

s g1(aa,bb,ccin,ss); //экземпляр модуля s

carry g2(aa,bb,ccin,ccout); //экземпляр модуля carry

endmodule

 

Листинг 2.1. Пример модулей нижнего и верхнего уровней иерархии

 

При использовании модулей нижнего уровня в проекте следует помнить, что имена портов и переменных, объявленные внутри модуля нижнего уровня, работают только внутри этого модуля и не "видны" в теле модулей верхнего уровня или внутри других модулей нижнего уровня.

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

 

module sum(aa,bb,ccin,ss,ccout); //модуль верхнего уровня

input aa,bb,ccin;

output ss,ccout;

s g1(.a(aa),.cin(ccin),.b(bb).s(ss)); //подключение портов

carry g2(.cout(ccout),.a(aa),.b(bb),.cin(ccin));

endmodule

 

Листинг 2.2. Пример поименного подключения портов модулей нижнего уровня

 

При описании на языке Verilog электрических схем, состоящих из множества логических примитивов (модулей), могут возникать ситуации, в которых к входу или выходу экземпляра примитива (модуля нижнего уровня) должна быть подключена цепь, не соединенная с каким-либо внешним портом модуля верхнего уровня. Такая внутренняя цепь, соединяющая между собой части схемы, в отличие от портов изначально не имеет имени. Для подключения такой цепи к экземпляру примитива (модуля нижнего уровня) ее необходимо предварительно объявить как переменную типа wire (после объявления типов портов модуля). Это позволит обращаться к ней по имени, данному в объявлении.

 

Задание

 

1. Создать на языке Verilog в пакете ModelSim с использованием встроенных примитивов логики проект двоичного дешифратора 2 на 4 с

 
 

входом разрешения функционирования ena, реализующий техническое

Рис. 2.1. Схема двоичного дешифратора 2 на 4

 

решение, представленное в таблице истинности (табл. 2.1) и на следующей схеме (рис. 2.1).

 

Таблица 2.1. Таблица истинности двоичного дешифратора 2 на 4

Входы Выходы
ena y[1] y[0] f[3] f[2] f[1] f[0]
             
             
             
             
  X X        

 

В таблице истинности и на схеме дешифратора y[1:0] является информационным двухразрядным входом. На него подается прямой двоичный код в диапазоне десятичных значений от 0 до 3 (двоичные значения от 00 до 11). Каждой комбинации входных двоичных разрядов соответствует единица только на одном выходе f[3].. f[0], так называемый унитарный код. Служебный вход ena предназначен для включения и выключения дешифратора. Он потребуется при создании на базе дешифраторов 2 на 4 более сложных устройств, например дешифратора 3 на 8 (см. ниже).

При подготовке проекта для обеспечения подключения всех необходимых цепей к примитивам следует проводникам схемы, не соединенным с портами, дать имена путем объявления их переменными типа wire.

2. Подготовить испытательный файл к проекту дешифратора 2 на 4, откомпилировать файлы проекта и, промоделировав проект, убедиться в его работоспособности или выявить имеющиеся ошибки.

3. Создать второй вариант проекта этого же дешифратора с использованием четырех операторов непрерывного присваивания assign (по одному на каждый выход) и логических операций. Выполнить в применении к нему п. 2, используя подготовленный в этом пункте испытательный файл.

4. На базе модуля дешифратора 2 на 4, подготовленного в п. 1, и логических примитивов создать проект дешифратора 3 на 8. При подготовке проекта реализовать схему подключения модулей нижнего уровня, представленную на рис. 2.2. При объявлении экземпляров модуля дешифратора 2 на 4 использовать позиционный способ подключения портов (аналогичный способу подключения портов в примитивах).

5. Подготовить испытательный файл к проекту, откомпилировать файлы проекта и, промоделировав проект, убедиться в его работоспособности или выявить имеющиеся ошибки.

6. Создать второй вариант проекта этого же дешифратора с использованием поименного способа подключения портов модулей нижнего уровня. Повторить п. 5 для этого варианта (с тем же испытательным файлом).

 

Рис. 2.2. Схема двоичного дешифратора 3 на 8

7. Создать третий вариант проекта дешифратора 3 на 8 без применения модулей нижнего уровня, но с использованием оператора непрерывного присваивания assign (8 штук) и логических операций. Выполнить в применении к нему п.5, пользуясь подготовленным в этом пункте испытательным файлом.

8. Подготовить отчет.

 

Контрольные вопросы

 

1. Объявление экземпляров модулей нижнего уровня в проекте.

2. Описание модулей нижнего уровня.

3. Позиционный способ подключения портов примитивов и модулей при объявлении экземпляров.

4. Поименный способ подключения портов модулей при объявлении экземпляров.

5. Почему поименный способ подключения портов нельзя применить к экземплярам примитивов?

6. Реализация внутренних электрических цепей в модулях верхнего уровня.

7. Достоинства и недостатки проектов дешифраторов 3 на 8 на базе модулей дешифраторов 2 на 4 и на базе оператора assign.

8. Принцип функционирования двоичного дешифратора.

9. Пример применения двоичного дешифратора в цифровых устройствах.

 

 

Лабораторная работа № 3

Массивы примитивов

 

Введение

 

Цель работы – освоение подготовки проектов, включающих использование массивов примитивов и примитивов буферов с z-состоянием. Применение операций сравнения и управляющего оператора if.. else внутри процедурного оператора always.

 

Необходимые сведения

В процессе конструирования цифровых устройств иногда возникает необходимость установки в модуле нескольких примитивов или модулей нижнего уровня, выполняющих одинаковые функции. Например, в устройстве, обрабатывающем многоразрядные данные, блоки, выполняющие необходимые операции для каждого двоичного разряда, могут быть идентичными. В таких случаях язык Verilog предоставляет возможность использования массивов примитивов или модулей. Ниже приведен пример объявления массива экземпляров примитива and c подключенными к портам внешними цепями (лист. 3.1).

 

wire [7:0] a,b; //входные 8-разрядные переменные

reg [7:0] q; //выходной 8-разрядный регистр

 

and g1[7:0](q,a,b); //8 экземпляров примитива and

 

Листинг 3.1. Пример объявления массива примитивов and из 8 элементов

 

При установке массива экземпляров примитивов подключение к портам экземпляров должно осуществляться с помощью переменных с разрядностью, равной размерности массива примитивов (см. строки 1 и 2 лист. 3.1).

Наряду с возможностью применения многовходовых логических примитивов (см. табл. 1.3) язык Verilog представляет еще один вариант реализации логических функций нескольких переменных. Это унарные побитовые операции. Эти операции выполняются над всеми битами одной многоразрядной переменной и формируют одноразрядный результат (см. табл. 3.1). Например, результатом выполнения следующего кода (лист. 3.2) будет присваивание переменной b логического нуля.

 

wire [7: 0] a;

wire b;

assign a = 8'b10101111;

assign b = ~| a;

 

Листинг 3.2. Пример использования унарной побитовой операции

 

(Над всеми вместе разрядами переменной a выполняется операция ИЛИ-НЕ.)

 

Таблица 3.1. Унарные побитовые операции языка Verilog

Обозначение Применение Содержание
& & b Операция И над всеми разрядами b
~& ~& b Операция И-НЕ над всеми разрядами b
| | b Операция ИЛИ над всеми разрядами b
~| ~| b Операция ИЛИ-НЕ над всеми разрядами b
^ ^ b Операция исключающее ИЛИ над всеми разрядами b
~^ или ^~ ~^ b Операция исключающее ИЛИ-НЕ над всеми разрядами b

 

Кроме унарных побитовых операций в языке Verilog существуют еще две группы операций, дающие одноразрядный результат при многоразрядных операндах, - это операции сравнения и операции идентичности (табл. 3.2, табл. 3.3). Все операции сравнения дают результат X (не определено), если хотя бы один разряд в операндах содержит логическое значение X или Z. В операциях идентичности явным образом сравниваются все возможные логические значения разрядов, включая 0, 1, X и Z.

 

Таблица 3.2. Операции сравнения языка Verilog

Обозначение Применение Содержание
== a == b Результат 1, если a равно b, и 0, если aне равно b
!= a!= b Результат 1, если a не равно b, и 0, если aравно b
< a < b Результат 1, если a меньше b, и 0 в остальных случаях
> a > b Результат 1, если a больше b, и 0 в остальных случаях
<= a <= b Результат 1, если a меньше или равно b, и 0, если a больше b
>= a >= b Результат 1, если a больше или равно b, и 0, если a меньше b

 

 

Таблица 3.3. Операции идентичности языка Verilog

Обозначение Применение Содержание
=== a === b Результат 1, если a по всем разрядам идентично b(с учетом значений X и Z), и 0 в противном случае
!== a!== b Результат 0, если a по всем разрядам идентично b(с учетом значений X и Z), и 1 в противном случае

 

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

Устанавливаются примитивы буферов аналогично установке примитивов логических функций. Ниже приведен пример кода, обеспечи-

 

Таблица 3.4. Примитивы буферов языка Verilog

Имя примитива и порты Функция Порядок и количество портов
buff(out, in) Буфер (повторитель) (1 или более out, 1 - in)
bufif1(out,in,ctrl) Если ctrl=1, то out=in, иначе out=z (1- out, 1 - in, 1- ctrl)
bufif0(out,in,ctrl) Если ctrl=0, то out=in, иначе out=z (1- out, 1 - in, 1- ctrl)
notif1(out,in,ctrl) Если ctrl=1, то out=~in, иначе out=z (1- out, 1 - in, 1- ctrl)
notif0(out,in,ctrl) Если ctrl=0, то out=~in, иначе out=z (1- out, 1 - in, 1- ctrl)

 

вающий перевод выхода out1 в высокоимпедансное состояние при поступлении на вход control логической единицы и в состояние логической единицы при поступлении на вход нуля (лист. 3.3).

 

module prim1(out1,control);

input control;

output out1;

 

bufif0 g1(out1,1'b1,control); //объявление

//экземпляра

//буфера с

//z-состоянием

endmodule

 

Листинг 3.3. Пример применения буфера с Z-состоянием на выходе

 

Второй способ установки выхода устройства в Z-состояние иллюстрируется следующим примером (лист. 3.4).

 

module prim2(out2,control);

input control;

output out2;

reg out2;

 

always @(control) //выполняется при изменении control

if (control==1'b1)

out2 = 1'bz;

else

out2 = 1'b1;

endmodule

 

Листинг 3.4. Формирование Z-состояния на выходе out2 с помощью

управляющего оператора if.. else в процедурном операторе always

 

В этом примере применен процедурный оператор (procedural block) always, в котором можно использовать управляющие операторы (procedural programming statements), например условный оператор if.. else. В данном случае оператор if.. else обеспечивает переключение выходного порта out2 в высокоимпедансное состояние (Z) при поступлении на вход control логической единицы и перевод порта out2 в единичное состояние во всех остальных случаях. Условный оператор if.. else находится внутри оператора always и выполняется каждый раз, когда происходит изменение логического значения порта control, установленного в списке реагирования (sensitivity list) оператора always (после знака @). (Процедурный оператор always повторяется непрерывно, подобно бесконечному циклу.)

Переменные, которым присваивается какое-либо логическое значение внутри операторов always, должны быть типа reg, поскольку они должны хранить присвоенное значение до очередного выполнения оператора always. Поэтому выходной порт out2 дополнительно объявлен как переменная типа reg.

Для повышения гибкости использования условного оператора и операторов цикла, которые будут рассмотрены в последующих лабораторных работах, в языке Verilog предусмотрены логические операции (см. табл. 3.5). Логические операции применяются к операндам любой разрядности (любое значение не равное 0 считается ИСТИНОЙ) и дают одноразрядный результат.

Таблица 3.5. Логические операции языка Verilog

Обозначение Применение Содержание
! ! a Результат 1, если a равно 0, и 0 в противном случае
&& a && b Результат 1, если и a, и bне равны0, в противном случае результат 0
|| a || b Результат 1, если или a, или b,или и a, и bне равны0, в противном случае результат 0

 

Задание

1. Создать на языке Verilog в пакете ModelSim с использованием массива примитивов логики и примитива буфера с Z-состоянием проект компаратора 8-разрядных двоичных чисел с входом разрешения работы. Компаратор должен формировать на выходе логическое значение единицы при совпадении всех разрядов сравниваемых чисел и значение нуля в противном случае. Кроме двух восьмиразрядных входов для сравниваемых данных компаратор должен быть снабжен управляющим входом разрешения работы, который при поступлении на него единицы транслирует на выход результат сравнения, а при поступлении нуля переводит выход в Z-состояние.

 

Рис. 3.1. Схема возможного варианта реализации 8-разрядного компаратора

 

Пример схемной реализации компаратора приведен на рис. 3.1.

2. Подготовить испытательный файл к проекту компаратора, откомпилировать файлы проекта и, промоделировав проект, убедиться в его работоспособности или выявить имеющиеся ошибки.

3. Создать второй вариант проекта этого же компаратора с использованием оператора непрерывного присваивания assign и побитовых операций над 8-разрядными входными данными. Для формирования итогового результата сравнения (см. элемент dd на рис. 3.1) применить унарную побитовую операцию. Для обеспечения функции разрешения работы с помощью управляющего входа использовать процедурный оператор always, который будет реагировать на любое изменение результата и управляющего входа. Внутри оператора always разместить условный оператор if.. else, который обеспечит выбор между подачей на выход результата сравнения и переводом выхода в Z-состояние.

4. Используя испытательный файл, подготовленный в п. 2, промоделировав новый проект, убедиться в его работоспособности или выявить имеющиеся ошибки.

5. Повторить пп. 3 и 4 для третьего варианта компаратора, в котором для получения результата используется операция сравнения многоразрядных данных, а функционирование входа разрешения работы реализовано аналогично п. 3.

6. Подготовить отчет.

 

Контрольные вопросы

1. Побитовые операции.

2. Унарные побитовые опера







Система охраняемых территорий в США Изучение особо охраняемых природных территорий(ООПТ) США представляет особый интерес по многим причинам...

Живите по правилу: МАЛО ЛИ ЧТО НА СВЕТЕ СУЩЕСТВУЕТ? Я неслучайно подчеркиваю, что место в голове ограничено, а информации вокруг много, и что ваше право...

ЧТО ПРОИСХОДИТ ВО ВЗРОСЛОЙ ЖИЗНИ? Если вы все еще «неправильно» связаны с матерью, вы избегаете отделения и независимого взрослого существования...

Конфликты в семейной жизни. Как это изменить? Редкий брак и взаимоотношения существуют без конфликтов и напряженности. Через это проходят все...





Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2024 zdamsam.ru Размещенные материалы защищены законодательством РФ.