Главная страница

МПСиС_Лабораторный практикум. Учебное пособие по курсу Микропроцессорные средства и системы Под редакцией доктора технических наук, доцента


Скачать 15.57 Mb.
НазваниеУчебное пособие по курсу Микропроцессорные средства и системы Под редакцией доктора технических наук, доцента
АнкорМПСиС_Лабораторный практикум.pdf
Дата27.12.2017
Размер15.57 Mb.
Формат файлаpdf
Имя файлаМПСиС_Лабораторный практикум.pdf
ТипУчебное пособие
#13173
страница2 из 4
1   2   3   4

/* и закан- чиваются символами */.
Представление
чисел в синтезируемых описаниях. Основным типом синтезируемых констант являются целочисленные константы, которые могут быть безразмерными и размерными.
Формат размерного числа в общем случае имеет вид:
<разрядность>'<формат><значение>, где <разрядность> - число бит в двоичном представлении числа; поле
<формат> может принимать значения d, D, если число десятичное;
h, H, если число шестнадцатеричное; o, O, если число восьмеричное;
<значение> -цифры 0 - 9 или буквы a, b, c, d, e, f в зависимости от ука- занного формата.
Пример
1. Представление чисел в Verilog HDL.
3 'b010 // 3-битное двоичное число
8 'h1A // 8-битное шестнадцатеричное число
4 'd3 // 4-битное десятичное число
-4 'd3 // 4-битное отрицательное десятичное число
8 'o6 // 8-битное восьмеричное число
10 // безразмерное десятичное число 'hA5 // безразмерное шестнадцатеричное число
Для логического разделения разрядов при записи констант может быть использован символ подчеркивания (_). Verilog игнорирует дан- ный символ на любой позиции константы, кроме первого символа.
Например, с точки зрения Verilog HDL 8'b1010_1110 и 8'b10101110 - это одна и та же константа.
Синтезируемые
типы данных. При разработке синтезируемых
RTL-описаний в основном применяются типы wire, tri, reg.
Типы wire и tri относятся к типу данных «цепь», который исполь- зуется для описания соединений в схеме. Цепи не могут хранить при- своенную им величину, к ним необходимо прилагать непрерывное воздействие. Тип wire применяется, когда цепь подключена только к одному источнику сигнала. Тип tri допускает подключение одной це- пи к нескольким источникам.

14
Тип reg используется для описания переменных, хранящих свои значения между процедурными присваиваниями, например, данный тип может применяться для описания аппаратного регистра. В то же время
reg можно использовать и для описания комбинационной логики.
Указанные типы данных могут объявляться как векторы, т.е. быть многоразрядными. Если при объявлении разрядность не указана, то по умолчанию цепь или переменная считается однобитной. В Verilog- описании допускается обращение к отдельным битам векторов.
В Verilog HDL разрешено объявление одномерных массивов цепей и переменных. Элемент массива может быть как скалярным, так и мно- горазрядным. При этом побитное обращение к элементам массива невозможно. Массивы в основном используются для описания памяти и регистровых файлов.
Пример
2. Объявление цепей, переменных, векторов, массивов и
обращений
к ним.
wire a; // объявление скалярной цепи типа wire
reg b; // объявление скалярной переменной типа reg
wire [3:0] c; // объявление 4-битного вектора типа wire
reg [1:0] d; // объявление 2-битного вектора типа reg
wire [7:0] e [0:7]; // массив из восьми 8-битных векторов типа wire
reg [2:0] f [0:9]; // массив из десяти 3-битных векторов типа reg d[1]; // обращение к 1-му биту вектора d f[3]; // обращение к 3-му вектору массива f
wire signed [7:0] g; //объявление 8-битного знакового вектора типа
wire
reg signed [7:0] i; // объявление 8-битного знакового вектора типа reg
В языке Verilog данные могут принимать одно из четырех возмож- ных состояний: 1 - логическая единица или значение true; 0 - логический нуль или значение false; z - состояние высокого импеданса; x - неизвестное логическое состояние.
Для объявления цепей и переменных со знаком используется клю- чевое слово signed.
Параметры
. Для объявления констант внутри модуля в Verilog
HDL применяют ключевое слово parameter. Параметры не могут ис- пользоваться как переменные или цепи.
Пример
3. Использование параметров.
parameter width=8; // объявление параметра width

15
reg [width-1:0] a; // объявление 8-разрядной переменной типа reg
Операторы
предназначены для указания, какие действия необхо- димо проводить с операндами. Операнд может быть константой, пере- менной, цепью, одним или несколькими битами вектора типа wire или
reg, элементом массива. Комбинации из операторов и операндов обра- зуют выражения.
В языке Verilog операторы могут быть трех видов: унарный, бинарный и тернарный. Унарный оператор ставится перед операндом,
бинарный - между двумя операндами, тернарный имеет в своем составе два подоператора для разделения трех операндов.
Операторы объединения и повторения используются для объеди- нения нескольких размерных операндов. Объединяемые операнды ука- зываются в фигурных скобках через запятую. Перед фигурными скоб- ками может стоять константа повторения, тогда комбинация операндов, перечисленных в скобках, повторяется указанное число раз.
Пример
4. Операторы объединения и повторения.
reg a=1 'b1;
reg [3:0] b=4 'b1010;
reg [5:0] c; c={a, b[1:0], a, b[3:2]}; // c=6 'b110110 c={2{a}, b[3:0]}; // c=6 'b111010
Арифметические операторы могут быть унарными и бинарными.
Унарные операторы (+ и –) используются для определения знака одного операнда. При этом отрицательные числа представляются в дополни- тельном коде. Бинарные арифметические операторы выполняют ариф- метические действия сложения (+), вычитания (–), умножения (*), де- ления (/), возведения в степень (**) и вычисления по модулю (%) над двумя операндами.
Отметим, что использование в синтезируемых Verilog-описаниях операторов сложения, вычитания и умножения приводит к синтезу сум- маторов и умножителей. В то же время большинство синтезаторов не поддерживают операции деления, вычисления по модулю и возведе- ния в степень. Исключение составляют операции со степенями 2.
Пример
5. Арифметические операторы.
reg [3:0] a=4 'b0010, b=4 'b0011, c=4 'b001x; d=a+b; // d=4 'b0101 d=a-b; // d=4 'b1111

16 d=2**b; // d=4 'b1000 d=a*b; // d=4 'b0110 d=a+c; // d=4 'bxxxx
Операторы отношения. Выражения, использующие операторы больше (>), больше либо равно (>=), меньше (<), меньше либо равно
(<=), возвращают логический нуль, если заданное отношение ложно, или логическую единицу, если отношение истинно.
Пример
6. Операторы отношения.
reg [3:0] a=4 'b0010, b=4 'b0011, c=4 'b001z; a>=b; // возвращает логический нуль (0) aЛогические операторы отрицания (!), И (&&), ИЛИ (||) могут при- меняться как к операндам, так и к выражениям, результаты которых трактуются как операнды.
Пример
7. Логические операторы.
reg [3:0] a=4 'b0010, b=4 'b0011, c=4 'b001x;
(a>0) && (b>=0); // возвращает логическую единицу (1)
(a>0) || (c>=0); // возвращает неопределенное состояние (x)
Операторы равенства/неравенства сравнивают операнды побитно и возвращают логическую единицу, если результат сравнения истина, или логический нуль, если результат сравнения ложь. Если операнды имеют разную разрядность, то недостающие биты дополняются нулями до нужной разрядности.
Различают логические операторы равенства/неравенства (==, !=), которые возвращают неопределенное состояние (x), если операнды со- держат биты со значением x, и условные операторы равен- ства/неравенства (===, !==), которые сравнивают операнды с учетом значений x, z и возвращают значения 0 и 1.
Пример
8. Операторы равенства/неравенства.
reg [3:0] a=4 'b0010, b=4 'b0011, c=4 'b001x, d=4 'b001x; a==b; // возвращает логический нуль (0) a!=b; // возвращает логическую единицу (1)
{a[3:1], a[1]} == b; // возвращает логическую единицу (1) c==d; // возвращает неопределенное состояние (x) c===d; // возвращает логическую единицу (1)

17
Побитовые операторы выполняют логические операции отрица- ния (

), И (&), ИЛИ (|), исключающее ИЛИ (^) с соответствующими би- тами операндов. Если операнды имеют разную разрядность, то старшие биты более короткого операнда дополняются нулями.
Пример
9. Побитовые операторы.
reg [3:0] a=4 'b0010, b=4 'b0011, c=4 'b001x; d=a&b; // d=4 'b0010 d=a|b; // d=4 'b0011 d=a|c; // d=4 'b001x d=a^b; // d=4 'b0001 d=a; // d=4 'b1101
Операторы свертки являются унарными и выполняют побитовые логические операции над векторным операндом, результатом является один бит.
Пример
10. Операторы свертки.
reg [3:0] a=4 'b1010;
reg [1:0]b=2 'b11; d=|a; // d=1 'b0 d=&b; // d=1 'b1 d=&a; // d=1 'b1
Операторы сдвига осуществляют сдвиг операнда на заданное ко- личество бит влево или вправо. Существуют два типа операторов сдви- га: логические операторы (<< и >>) и арифметические (<<< и >>>).
Пример
11. Операторы сдвига.
reg [3:0] a=4 'b0010;
reg signed [3:0] b=4 'b1011; с=a << 1; // c=4 'b0100 c=b >> 2; // c=4 'b0010 c=b >> 2; // c=4 'b1000
Условный оператор - это единственный в Verilog тернарный опе- ратор. В общем случае он записывается в виде
<условие> ? <выражение 1> : <выражение 2>;
Сначала проверяется указанное условие. Если оно истинно, то вы- полняется выражение 1; если ложно, то выполняется выражение 2.

18
Пример
12. Условный оператор.
d=c ? a : b; // мультиплексор 2 в 1 g[7:0]=f ? e[7:0] : 8 'bz; // 8-разрядный буфер с третьим состоянием
В табл.1.1 перечислены операторы в порядке убывания приоритета
(слева направо).
Таблица
1.1
Приоритет
операторов Verilog HDL
Уровень приоритета
13 12 11 10 9 8
7 6
5 4 3
2 1
Операторы
+

!

**
*
/
%
+

<<
>>
<<<
>>>
<
<=
>
>=
==
!=
===
!==
&
&
^
^
^
|

&& || ?:
Непрерывные
присваиванияиспользуются для присваивания ка- ких-либо величин скалярным или векторным цепям. Считается, что непрерывное присваивание - одна из основных конструкций Verilog
HDL для описания на уровне потока данных. Эта конструкция позволя- ет описывать логические функции на более высоком уровне, чем соеди- нения между логическими вентилями.
Непрерывные присваивания выполняются с помощью ключевого слова assign. В общем случае синтаксис выглядит следующим образом:
assign <сила сигнала> #<задержка> <присваивание>, однако параметры в данной конструкции являются несинтезируемыми, поэтому при составлении синтезируемых описаний будем использовать следующий формат:
assign <присваивание>
Verilog допускает применение неявных непрерывных присваива- ний. В этом случае ключевое слово assign заменяется на wire, т.е. ис- пользуется конструкция вида wire <присваивание>.
Пример
13. Непрерывные присваивания.
reg [3:0] a;
wire [1:0] b;

19
wire c, d;
assign c = d;
assign c = d | a[2] ;
wire e = b[1]; // неявное непрерывное присваивание
assign b = {a[3], a[1]};
Процедурные
присваивания, структурная конструкция always.
Процедурные присваивания используются для присваивания каких-либо величин переменным в структурных конструкциях. Существует два ти- па процедурных присваиваний: блокирующие (=) и неблокирующие
(<=). Блокирующие присваивания выполняются в том порядке, в каком они описаны в блоке. Неблокирующие присваивания выполняются па- раллельно.
В Verilog HDL определены две основные структурные конструк- ции, которые обозначаются ключевыми словами initial и always.
Verilog-модуль может содержать любое количество таких конструкций, все они выполняются параллельно, и порядок их описания в модуле не имеет значения. Вложенность процедурных конструкций не допуска- ется. Кроме того, запрещены процедурные присваивания одной пере- менной в разных структурных конструкциях. Исключение составляет инициализация переменной с помощью конструкции initial и присваи- вание ей значений в конструкции always.
Структурная конструкция initial выполняется только один раз, начи- ная с нулевого момента времени. В синтезируемых Verilog-описаниях дан- ная конструкция используется для инициализации элементов памяти.
Структурная конструкция always повторяется циклически, начиная с нулевого момента времени. Данная конструкция и непрерывные при- сваивания являются основными инструментами для создания синтези- руемого Verilog-описания. В синтезируемых описаниях используется следующая форма записи процедурных блоков:
always @ (событие)
begin
<процедурные присваивания/операторы>
end
Под событием подразумевается изменение уровня указанного сиг- нала или появление положительного (posedge) либо отрицательного
(negedge) перепада. При таком описании все присваивания и операторы блока будут выполняться при каждом возникновении какого-либо со-

20 бытия. В одном блоке могут использоваться несколько событий, для этого применяется ключевое слово or. Однако в одном блоке нельзя комбинировать изменения уровня сигнала и перепады. Для описания изменения уровня сигнала в качестве события указывается имя сигнала.
Описание события-перепада в общем случае имеет вид:
posedge/negedge <сигнал> or posedge/negedge <сигнал> or
В случае, когда событием является изменение уровня любого сиг- нала, используемого в блоке, можно использовать конструкцию
always @ *
begin
<процедурные присваивания/операторы>
end
Пример
14. Блоки always.
reg [3:0] a;
wire [3:0] b;
wire c;
always @ (a or b) begin// этот и следующий блок always a <= &b; // эквивалентны,
end // оба описывают комбинационную схему
always @ *
a <= &b;
always @ (posedge c) // данный блок эквивалентен триггеру,
a <= b; // фиксирующему состояние сигнала b по переднему
// фронту сигнала с.
Внутри блоков initial и always могут использоваться не только операторы и присваивания, но и поведенческие конструкции Verilog.
Основными поведенческими конструкциями для создания синтезируе- мых Verilog-описаний являются условные конструкции (if-else) и кон- струкции ветвления (case).
Синтезируемая
поведенческая условная конструкция (if-else)
аналогична условным конструкциям других языков высокого уровня.
При ее выполнении проверяется указанное условие и в зависимости от результата проверки выполняется то или иное действие.
В общем случае условная конструкция имеет вид:

21
if (<условие>)
<процедурная операция 1>;
else
<процедурная операция 2>;
Допускается использование оператора if без оператора else. Если необходима проверка нескольких условий, то возможно использование сложных конструкций вида
if (<условие 1>)
<процедурная операция>;
else if (<условие 2>)
else
<процедурная операция>;
Синтезируемая
поведенческая конструкция ветвления(case).
Для проверки множества условий применяют конструкции ветвления, обозначаемые ключевыми словами case, endcase, default. Ветвь default необязательна и выполняется, если проверка всех условий дала резуль- тат ложь.
В общем случае конструкция имеет вид:
case (<выражение>) значение 1: <процедурная операция 1>; значение 2: <процедурная операция 2>;
default: <процедурная операция по умолчанию>;
endcase
Структура
Verilog-модуля. Модуль является основной иерархи- ческой единицей Verilog-описания. Модуль взаимодействует с другими модулями через свои порты ввода/вывода (входы, выходы, двунаправ- ленные порты). Внутри модуля объявляют константы, цепи, перемен- ные, указывают параметры портов ввода/вывода, описывают непрерыв- ные присваивания и структурные конструкции. Кроме того, внутри модуля могут быть подключены другие модули для создания иерархи- ческой структуры.
Синтезируемый Verilog-модуль может иметь структуру вида
module <имя модуля> (<список портов>);
<объявление параметров>
<объявление входных портов>
<объявление выходных портов>

22
<объявление двунаправленных портов>
<объявление цепей>
<объявление переменных>
<подключение модулей нижнего уровня иерархии>
<непрерывные присваивания>
<структурные блоки>
endmodule
Ниже приведен пример модуля, в котором описан двухвходовый ло- гический элемент И. Далее на его основе создана иерархическая структура из двух элементов И. Отметим, что при подключении модулей and_2 внут- ри модуля and_4, помимо названия модуля, указаны уникальные имена m1 и m2, это необходимо для именования множества модулей в иерархической структуре (в том числе имеющих одно и то же описание).
Стандарт Verilog-2001 допускает упрощенную запись объявления портов, в которой объединяются список портов, их объявление и указы- вается их тип (цепь или переменная). Так, заголовок модуля and_2 мож- но переписать в виде module and_2 (input wire a, input wire b, output
wire c).
Пример
15. Модуль с иерархической структурой.
module and_2 (a, b, c);
input a;
input b;
output c;
assign c = a&b;
endmodule
module and_4 (a, b, c, d, e);
input a;
input b;
input c;
input d;
output e;
wire r_1, r_2; and_2 m1 ( .(a), .(b), .(r_1) ); and_2 m2 ( .(c), .(d), .(r_2) );
assign e = r1&r2;
endmodule

23
При создании иерархической структуры и подключении портов ввода/вывода необходимо соблюдать следующие правила:
• входы внутри модуля могут быть только цепью, а подключаться извне могут как к цепям, так и к переменным;
• выходы внутри модуля могут быть как цепью, так и переменной, а подключаться извне могут только к цепям;
• двунаправленные порты внутри модуля могут быть только цепью и подключаться могут только к цепям.
1.4. Примеры синтезируемых Verilog-описаний
Отличия
в использовании блокирующего и неблокирующего
процедурных
присваиваний.Как отмечалось ранее, блокирующие присваивания выполняются в порядке их записи в последовательном блоке begin-end, а неблокирующие присваивания выполняются парал- лельно. На рис.1.6 приведены результаты синтеза двух Verilog- описаний, отличающихся только типом процедурного присваивания.
Видно, что в случае неблокирующего присваивания все три присваива- ния выполняются параллельно и, следовательно, синтезируются три триггера, а в случае блокирующего присваивания происходит перепри- сваивание переменных и синтезируется только один триггер:
module ShiftReg_NBlock ( input clk, input d, output reg q );
reg a, b;
always @ (posedge clk)
begin a <= d; b <= a; q <= b;
end
endmodule
module ShiftReg_Block ( input clk, input d, output reg q );
reg a, b;
always @ (posedge clk)
begin a = d; b = a; q = b;
end
endmodule

24
Рис.1.6. Результаты синтеза ShiftReg_NBlock (а) и ShiftReg_Block (б)
D-триггер по переднему фронту с синхронными сбросом и
установкой
(активный уровень «1»).
module DFF ( input clk, input set, input reset, input d, output reg q );
always @ (posedge clk)
if (set) q <= 1 'b1;
else if (reset) q <= 1 'b0;
else q <= d;
endmodule
D-триггер по переднему фронту с асинхронными сбросом и
установкой
(активный уровень «0»).
module DFF ( input clk, input set, input reset, input d, output reg q );
always @ (posedge clk or negedge set or negedge reset)
if (!set) q <= 1 'b1;
else if (!reset) q <= 1 'b0;
else q <= d;
endmodule
Триггер
-защелка.
module Latch ( input enable, input data, output reg q );
always @ (enable)
if (enable) q <= data;
endmodule
4-разрядный двоичный счетчик с асинхронным сбросом (ак-
тивный
уровень «1»).
module Counter ( input clk, input reset, output reg [3:0] q );
always @ (posedge clk or posedge reset)
if (reset) q <= 4 'b0000; else q <= q + 1‘b1;
endmodule

25
Комбинационный
сумматор, описанный с помощью непре-
рывного
присваивания assign и конструкции always.
module Adder1 ( input [3:0] a, input [3:0] b, output [4:0] sum );
assign sum = a + b;
endmodule
module Adder2 ( input [3:0] a, input [3:0] b, output reg [4:0] sum );
always @ (a or b) sum = a + b;
endmodule
Сумматор
с накоплением и синхронным сбросом (аккумулятор).
module Acc (input clk, input reset, input [3:0] a, output reg [7:0] sum);
always @ (posedge clk)
if (reset) sum <= 8 'b0000_0000; else sum = sum + a;
endmodule
Синхронное
8-разрядное ОЗУ на 256 элементов.
module RAM ( input clk, input wr, input [7:0] Address,
input [7:0] InputData, output [7:0] OutputData );
reg [7:0] RAM_data [0:255];
always @ (posedge clk) if (wr) RAM_data[Address] <= InputData; else OutputData <= RAM_data[Address];
endmodule
Синхронное
8-разрядное ПЗУ на 256 элементов.Основным отличи- ем от предыдущего описания является наличие конструкции initial, которая используетсядля инициализации памяти. В этой конструкции применена системная функция $readmemh. В качестве аргументов передаются имя текстового файла с данными в определенном формате и имя массива, кото- рый необходимо инициализировать при компиляции проекта.
В приведенном примере конфигурационный файл должен содер- жать 256 строк, каждая из них содержит 8-разрядное число, записанное в шестнадцатеричном формате.
module ROM ( input clk, input [7:0] Address, input [7:0] InputData,
output [7:0] OutputData );
reg [7:0] ROM_data [0:255];
initial $readmemh("ROM.hex", ROM_data);
always @ (posedge clk)
OutputData <= ROM_data[Address];
endmodule

26
Комбинационная
логика.Для описания комбинационной логики можно использовать как непрерывные присваивания, так и блочную конструкцию always. В случае применения блочных конструкций в ка- честве события указывается либо символ *, либо перечень сигналов, из- менение уровня которых влияет на результат работы схемы.
module LogicAssign ( input a, input b, input c, output out );
assign out = (a^b) | c;
endmodule
module LogicAlways ( input a, input b, input c, output reg out );
always @ (a or b)
// или always @ * out = (a^b) | c;
endmodule
Мультиплексоры
. Verilog-описание мультиплексоров может быть основано как на условных конструкциях, так и на конструкциях ветвле- ния. Отличие заключается в том, что сложные условные конструкции
(if-else) синтезируются в приоритетно-дешифрированную логику, а
case-конструкции - в параллельную. На рис.1.7 приведены результаты синтеза обоих вариантов описания мультиплексора.
module MuxIfElse ( input a, input b, input c, input [2:0] select,
output reg out );
always @ *
if (select[0]) out = a;
else if (select[1]) out = b;
else if (select[2]) out = c;
else out = 1 'b0;
endmodule
module MuxCase ( input a, input b, input c, input [2:0] select,
output reg out );
always @ *
case (select)
3 'b001:out = a;
3 'b010:out = b;
3 'b100:out = c;
default: out = 1 'b0;
endcase
endmodule

27
Рис.1.7. Результаты синтеза сложных условных конструкций if-else (а) и конструкции ветвления case (б)
1.5. Основы разработки несинтезируемых описаний
на
языке Verilog
Часто при разработке цифровой аппаратуры на ПЛИС проект до- стигает такого размера, что использование графических средств задания тестовых воздействий весьма затруднено. В этом случае целесообразно создать файл, который будет содержать тестовые воздействия в тексто- вом виде. Такой файл носит название файла тестовых воздействий
(testbench).
В основе создания файла тестовых воздействий лежит разработка
HDL-описания модели тестовых воздействий, представляющих вирту- альное периферийное оборудование, осуществляющее взаимодействие с разработанным в рамках проекта устройством. При этом по сложности проект и модель тестовых воздействий могут быть сопоставимы.
Процессы разработки файла тестовых воздействий и проекта с ис- пользованием Verilog HDL практически полностью совпадают. Модель тестовых воздействий может включать в себя те же конструкции, опи- санные с помощью тех же синтаксических правил. Однако для расши- рения функциональных возможностей были введены несинтезируемые конструкции, значительно упрощающие процесс моделирования. Имен- но об этих особенностях разработки файлов тестовых воздействий пой- дет речь в этом разделе.
Несинтезируемые
типы данных. В языке Verilog предусмотрены специальные возможности для интерпретации регистров как целых или

28 действительных чисел, а также для хранения информации о временных отсчетах моделирования (модельном времени).
Любую информацию можно хранить в переменных типа reg, но для большего удобства хранения целых чисел и информации о времен- ных отсчетах моделирования, а также организации самодокументирова- ния кода применяют предусмотренные в языке Verilog HDL типы пере- менных integer (32 разряда) и time (64 разряда) соответственно.
Пример
16. Объявление переменных типов integer и time.
integer A;
time M1, M2;
В отличие от типа reg, тип integer является знаковым, т.е. подчи- няющимся соответствующим правилам арифметики. Переменные типа
time не являются знаковыми.
Допускается также использование массивов чисел типов integer и
time, которые объявляются аналогично массивам регистрового типа.
Пример
17. Объявление массивов чисел типов integer и time.
integer R [1:64];
time M3 [1:100];
Для упрощения и ускорения разработки HDL-описаний моделей тестовых воздействий в стандарте языка Verilog предусмотрено приме- нение действительных чисел и средств их обработки. Регистры действи- тельного типа и действительные константы создаются с помощью клю- чевого слова real.
Действительные числа могут быть представлены как в формате с фиксированной запятой, так и с плавающей.
Пример
18. Объявление переменных типа real.
real А = 83.375; //формат с фиксированной запятой
real В = 1.2е-5; //формат с плавающей запятой
real С = 4.13е10; //формат с плавающей запятой
Явное указание выделяемого для действительного сигнала количе- ства разрядов в языке Verilog не поддерживается. Присваивание цело- численному регистру действительного значения приводит к округлению последнего до ближайшего целого числа. Таким образом, язык Verilog, в отличие от таких строго типизированных языков, как VHDL или Ada, допускает неявное преобразование типов данных.

29
Необходимо отметить, что не все операторы могут быть примене- ны к вещественным числам. Следующие операции не могут быть вы- полнены переменными типа real:
• описание положительного или отрицательного фронтов (posedge,
negedge);
• выбор отдельного бита или группы битов;
• применение в качестве индексов массивов, битов или групп битов;
• создание массива вещественных чисел.
Основные
структурные конструкции моделирования. Струк- турные конструкции always и initial являются базовыми в поведенче- ском моделировании электронных устройств.
Каждый из этих операторов представляет собой отдельный поток обработки данных. Все потоки выполняются в модели параллельно, а начало выполнения потоков совпадает с началом модельного времени, однако не допускается использование конструкций с вложенными опе- раторами always и initial.
В языке Verilog операторы always и initial представляют собой по- следовательные или параллельные блоки поведенческих операторов, сгруппированные по функциональному признаку. Поскольку примене- ние оператора always было описано ранее, здесь остановимся на опера- торе initial.
Оператор initial предназначен для формирования начальных усло- вий моделирования, запускается один раз в начале процесса и не повто- ряется после его остановки.
Синтаксис оператора initial:
initial begin
<процедурные присваивания/операторы>;
end
Если в модуле более одного блока initial, то все они будут запуще- ны параллельно в нулевой отсчет времени моделирования. Остановка выполнения одного из блоков initial не зависит от других блоков этого же типа. Если в блоке initial более одного поведенческого оператора, то необходимо заключить их в операторные скобки begin..end. В против- ном случае операторные скобки можно опустить.
Пример
19. Использование структурного оператора initial.
initial x = 4'b1010; //в блоке один поведенческий оператор
initial begin //в блоке два поведенческих оператора
Line000 = 1'b1;
Line001 = 1'b0;
end

30
При разработке файла тестовых воздействий часто возникает необ- ходимость в задании в конструкции initial задержек выполнения пове- денческих операторов, например, при формировании временных диа- грамм для простых моделей тестовых воздействий. В этом случае задержка формируется следующим образом:
initial begin
<процедурное присваивание/оператор_1>;
# <задержка>
<процедурное присваивание/оператор_2>;
end где <задержка> - константа, указывающая число шагов моделирования, начиная от текущего, на которое будет задержано выполнение блока
<процедурного присваивания/оператора_2>.
Для иллюстрации функционирования механизма задержек рас- смотрим работу модуля, представленного в следующем примере.
Пример
20. Использование задержек в конструкции initial.
`timescale 1ns/ 1ps
module Delay_Demo;
reg a;
initial begin
#50 a = 1'b1;
#40 a = 1'b0;
end
endmodule
Первая строка модуля представляет собой директиву компилятора
<`timescale>, определяющую длительность одного шага моделирования
(1 нс) и дискретность временного интервала (1 пс).
До значения модельного времени 50 нс сигнал a на временной диа- грамме имеет значение х, на 50 нс произойдет присваивание a = 1. Задерж- ка вычисляется от текущего значения модельного времени. Таким образом, значение сигнала a в результате выполнения второго оператора присваива- ния изменится с 1 на 0 в момент времени 50 нс + 40 нс = 90 нс.
Поскольку все операторы в поведенческих блоках initial выполня- ются последовательно, то задержку можно интерпретировать как интер- вал времени выполнения оператора, причем изменение значений управ- ляемых оператором сигналов происходит в конце указанного интервала

31
времени. Сумма всех задержек в последовательном блоке определяет общее время выполнения блока операторов.
Общая
характеристика подпрограмм в языке Verilog. Одним из наиболее распространенных методов повышения эффективности про- грамм моделирования и процессов их разработки, а также читаемости кода является процедурная декомпозиция программ. Задача декомпози- ции состоит в выделении отдельных функционально независимых участков кода, решающих определенные задачи. Это позволяет распре- делить задачи между отдельными разработчиками, участвующими в со- здании проекта, и существенно сократить время его написания за счет возможности повторного использования фрагментов кода.
Язык Verilog включает два типа независимых фрагментов кода
(подпрограмм), обеспечивающих возможность реализовать декомпози- цию программы: функции (function) и задачи (task).
Функции в языке Verilog мало отличаются от функций в традици- онных языках программирования, например Pascal или C. Задачи в язы- ке Verilog больше напоминают процедуры в языке Pascal. В то же время различия между обоими типами подпрограмм в языке Verilog являются более глубокими, чем в Pascal, и не ограничиваются различиями в спо- собах обмена информацией с основной программой.
К ограничениям, соблюдающимся при создании функций в языке
Verilog, относятся следующие:
• изнутри функций допускается вызов других функций, но не до- пускается вызов задач;
• функции всегда должны выполняться мгновенно, за нулевой про- межуток модельного времени;
• функции не могут содержать никаких операторов задержки или контроля событий;
• функции всегда возвращают в качестве результата только одно значение, а список их формальных параметров не может содержать ар- гументов типа output или inout.
Задачи лишены перечисленных ограничений и позволяют вызывать как функции, так и другие задачи, управлять задержками и осуществ- лять контроль событий, а также могут иметь произвольное число вход- ных, выходных и двунаправленных параметров.
Общие для задач и функций свойства состоят в следующем:
• могут использоваться локальные переменные и регистры целого и действительного типов, а также типа time;
• нельзя применять локальные цепи (wires);

32
• могут использоваться только поведенческие операторы и вызы- ваться из других блоков поведенческих операторов (always, initial и пр.). Функции также могут быть вызваны из операторов непрерывного присваивания assign.
Задачи
(task) предназначены для выполнения каких-либо общих процедур в нескольких различных местах описания и разбиения боль- ших участков кода на малые. Из приведенного далее примера можно видеть, что по синтаксису и способу описания интерфейса задачи по- добны модулям:
task <идентификатор задачи>;
<описание интерфейса>;
begin
<процедурные присваивания/операторы>;
end
endtask
Описание интерфейса определяет направленность и порядок сле- дования портов (список формальных параметров задачи). Типы портов должны быть определены внутри задачи.
Пример
21. Использование конструкции task.
task example;
//описание интерфейса
input I1, I2, I3;
output O1, O2, O3;
//описание задачи
begin
if (I1 && !I2 && !I3) {O1, O2, O3} = 3’b100;
else if (!I1 && I2 && !I3) {O1, O2, O3} = 3’b010;
else if (!I1 && !I2 && I3) {O1, O2, O3} = 3’b001;
else {O1, O2, O3} = 3’b000;
end
endtask
Вызов задач осуществляется изнутри поведенческих блоков путем указания их идентификаторов и перечня (в круглых скобках) фактиче- ских параметров. При этом фактические параметры должны быть пере- числены в том же порядке, что и соответствующие им формальные па- раметры в разделе описания интерфейса. Вызов задачи в программе не обязательно должен следовать ниже текста описания самой задачи.

33
Так как Verilog не имеет конструкций, аналогичных модулям в языке Pascal, библиотекам в языках С/С++ или пакетам в VHDL, то для подключения к программе внешних задач следует пользоваться систем- ной функцией $include.
Например, если существует необходимость включения в текущий модуль задачи, исходный текст которой размещен в файле scenario.v, то следует в произвольном месте модуля поместить команду:
$include scenario.v
Функции
(function). Для создания подпрограммы-функции необ- ходимо воспользоваться парой ключевых слов function и endfunction.
Описание функции может размещаться в произвольном месте модуля, вызывающего данную функцию. Обязательным условием объявления функции в языке Verilog является наличие хотя бы одного входного па- раметра (аргумента). Для определения возвращаемого функцией резуль- тата следует разместить в ее теле оператор присваивания, в котором имя изменяемого сигнала совпадает с именем текущей функции:
function <тип результата> <идентификатор функции>;
<перечень входных параметров>;
//должен присутствовать как минимум один входной параметр
begin
<процедурные присваивания/операторы>;
//определение возвращаемого функцией результата
<идентификатор функции> = <возвращаемый результат>;
end
endfunction
Приведем в качестве примера функцию, определяющую большее из двух беззнаковых целых чисел.
Пример
22. Использование конструкции function.
`timescale 10 ns/1ps
module Function_Demo (Res, X1, X2);
input X1, X2;
output Res;
wire [15:0] Res;
wire X1, X2;
//заголовок функции:
function min;
input [15:0] A,B; //два входных параметра

34
//тело функции
begin
if (Aelse min = B; // в противном случае – сигнал B
end
endfunction
//вызов функции в операторе непрерывного присваивания:
assign Res = min (X1,X2);
endmodule
Подключение библиотечных функций, как и библиотечных задач, осуществляется с применением системной функции $include.

35
1   2   3   4


написать администратору сайта