
Назначение является основным механизмом для помещения значений в сети(провода) и переменные. Существует две основные формы назначения:
- Непрерывное назначение, которое присваивает значения сеткам
- Процедурное назначение, которое присваивает значения переменным
Существуют две дополнительные формы назначений, assign/unassign и force/release, которые называются процедурные непрерывные назначения, описанные в 9.3.
Назначение состоит из двух частей, левой и правой, разделенных символом равенства ( = ) или, в случае неблокирующего процедурного назначения, парой символов «меньше либо равно» ( <= ). Правая часть может быть любым выражением, которое оценивается в значение. Левая часть указывает на переменную, которой должно быть присвоено значение правой части. Левая часть может принимать одну из форм, приведенных в таблице 6-1, в зависимости от того, является ли назначение непрерывным или процедурным.
Тип заявления | Левая сторона |
---|---|
Непрерывное назначение | Сеть (векторная или скалярная) Константная битовая выбока векторной сети Константная частичная выборка векторной сети Константный индексированный частичный выбор векторной сети Конкатенация или вложенная конкатенация любой из вышеперечисленных левых частей |
Процедурное назначение | Переменные (векторные или скалярные) Битовая выборка векторного переменной reg, integer или time Константная часть выборки вектора переменной reg, integer или time Индексированная часть выборки вектора переменной reg, integer или time Слово памяти Конкатенация или вложенная конкатенация любой из вышеперечисленных левых частей |
6.1 Непрерывные назначения
Непрерывные назначения должны переносить значения на сетки, как векторные, так и скалярные. Это назначение должно происходить всякий раз, когда изменяется значение правой части.
Непрерывные назначения обеспечивают способ моделирования комбинационной логики без указания взаимосвязи вентелей. Вместо этого в модели указывается логическое выражение, которое управляет сетью(проводом).
Синтаксис непрерывных назначений приведен в разделе Синтаксис 6-1.
net_declaration ::=
net_type [ signed ] [ delay3 ] list_of_net_identifiers ;
| net_type [ drive_strength ] [ signed ] [ delay3 ] list_of_net_decl_assignments ;
| net_type [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_identifiers ;
| net_type [ drive_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_decl_assignments ;
| trireg [ charge_strength ] [ signed ] [ delay3 ] list_of_net_identifiers ;
| trireg [ drive_strength ] [ signed ] [ delay3 ] list_of_net_decl_assignments ;
| trireg [ charge_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_identifiers ;
| trireg [ drive_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_decl_assignments ;
list_of_net_decl_assignments ::=
net_decl_assignment { , net_decl_assignment }
net_decl_assignment ::=
net_identifier = expression
continuous_assign ::=
assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;
list_of_net_assignments ::=
net_assignment { , net_assignment }
net_assignment ::=
net_lvalue = expression
6.1.1 Назначение сети при объявлении
Первые две альтернативы объявления сети обсуждаются в разделе 4.2. Третья альтернатива, назначение в объявлении сети, позволяет поместить непрерывное назначение на сеть в том же операторе, который объявляет сеть.
Например:
wire (strong1, pull0) mynet = enable ;
Поскольку сеть может быть объявлена только один раз, для конкретной сети может быть выполнено только одно назначение по объявлению сети. Это отличается от заявления о непрерывном назначении, что одна сеть может получить несколько назначений в форме непрерывного назначения.
Перевод Официального Стандарта Verilog HDL
6.1.2 Непрерывного назначения (assign)
Оператор непрерывного назначения(присваивания) должен поместить непрерывное назначение на тип данных сети. Сеть может быть явно объявлена или может наследовать неявное объявление в соответствии с правилами неявного объявления, определенными в п. 4.5.
Назначения в сетях должны быть непрерывными и автоматическими. Другими словами, каждый раз, когда операнд в выражении правой части меняет значение, вся правая часть должна быть оценена. Если новое значение отличается от предыдущего, то новое значение должно быть присвоено левой части.
Например:
wire mynet ;
assign (strong1, pull0) mynet = enable ;
module adder (sum_out, carry_out, carry_in, ina, inb);
output [3:0] sum_out;
output carry_out;
input [3:0] ina, inb;
input carry_in;
wire carry_out, carry_in;
wire [3:0] sum_out, ina, inb;
assign {carry_out, sum_out} = ina + inb + carry_in;
endmodule
module select_bus(busout, bus0, bus1, bus2, bus3, enable, s);
parameter n = 16;
parameter Zee = 16'bz;
output [1:n] busout;
input [1:n] bus0, bus1, bus2, bus3;
input enable;
input [1:2] s;
tri [1:n] data; // объявление сети
// объявление сети с непрерывным присвоением
tri [1:n] busout = enable ? data : Zee;
// заявление о назначении с четырьмя непрерывными заданиями
assign
data = (s == 0) ? bus0 : Zee,
data = (s == 1) ? bus1 : Zee,
data = (s == 2) ? bus2 : Zee,
data = (s == 3) ? bus3 : Zee;
endmodule
Во время моделирования этого примера происходит следующая последовательность событий:
- Значение s, входной переменной селектора шин, проверяется в операторе assign. На основе значения s сети данные получают данные с одной из четырех входных шин.
- Настройка сети данных запускает непрерывное назначение в объявлении сети для busout. Если разрешение установлено, содержимое data назначается на busout; если разрешение равно 0, содержимое Zee назначается на busout.
6.1.3 Задержки
Задержка, заданная для непрерывного назначения, должна определять время между изменением значения правого операнда и назначением, выполненным в левой части. Если левая часть ссылается на скалярную сеть, то задержка должна рассматриваться так же, как и для задержек стробов; то есть, могут быть заданы различные задержки для нарастания, спада и перехода на высокий импеданс выхода (см. пункт 7).
Если левый операнд ссылается на векторную сеть, то может быть применено до трех задержек. Следующие правила определяют, какая задержка управляет назначением:
- Если правая часть совершает переход от ненулевого значения к нулевому, то используется задержка спада.
- Если правая часть совершает переход к z, то используется задержка выключения.
- Во всех остальных случаях используется задержка нарастания.
Указание задержки в непрерывном назначении, которое является частью объявления сети, рассматривается иначе, чем указание задержки сети и последующее непрерывное назначение сети. Значение задержки может быть применено к сети в объявлении сети, как в следующем примере:
wire #10 wireA;
В ситуациях, когда правый операнд изменяется до того, как предыдущее изменение успело распространиться на левую часть, выполняются следующие действия:
- Оценивается значение правого выражения.
- Если это значение правой стороны отличается от значения, которое в данный момент запланировано для распространения на левую сторону, то запланированное в данный момент событие распространения переносится в другое время.
- Если новое значение правой части равно текущему значению левой части, событие не запланировано.
- Если новое значение правой стороны отличается от текущего значения левой стороны, задержка рассчитывается стандартным способом с использованием текущего значения левой стороны, вновь рассчитанного значения правой стороны и задержек, указанных в объявлении. Затем планируется новое событие распространения, которое произойдет в будущем через единицы времени задержки.
6.1.4 Сила
Сила источника непрерывного назначения может быть задана пользователем. Это относится только к назначениям скалярным сеткам следующих типов:
Тип сети | Тип сети | Тип сети |
---|---|---|
wire | tri | trireg |
wand | triand | tri0 |
wor | trior | tri1 |
Непрерывные назначения, управляющие силой, могут быть указаны либо в объявлении сети, либо в отдельном назначении с помощью ключевого слова assign. Спецификация силы, если она предусмотрена, должна следовать непосредственно за ключевым словом (либо за ключевым словом типа сети, либо за словом assign) и предшествовать любой указанной задержке. Когда непрерывное назначение управляет сетью(проводом), сила значения должна моделироваться, как указано.
Спецификация силы привода должна содержать одно значение силы, которое применяется, когда значение, присваиваемое сети, равно 1, и второе значение силы, которое применяется, когда присваиваемое значение равно 0. Следующие ключевые слова определяют значение силы для присвоения 1:
supply1 strong1 pull1 weak1 highz1
Следующие ключевые слова должны определять значение силы для присвоения 0:
supply0 strong10 pull0 weak0 highz0
Порядок двух характеристик силы может быть произвольным. Следующие два правила ограничивают использование спецификаций силы источника:
- Спецификации силы (highz1, highz0) и (highz0, highz1) должны рассматриваться как недопустимые конструкции.
- Если сила источника не указана, то по умолчанию она будет равна (strong1, strong0).
6.2 Процедурные назначения
Основное обсуждение процедурных назначений содержится в пункте 9.2. Однако описание основных идей в этом пункте подчеркивает различия между непрерывными назначениями и процедурными назначениями.
Как было сказано в разделе 6.1, непрерывные назначения управляют сетью(проводами) подобно тому, как управляют сетью вентелей. Выражение в правой части можно представить как комбинаторную схему, которая непрерывно управляет сетью. Процедурные назначения, напротив, помещают значения в переменные. Назначение не имеет продолжительности. Вместо этого переменная сохраняет значение назначения до следующего процедурного назначения этой переменной.
Процедурные назначения возникают в процедурах, таких как always, initial (см. 9.9), task и function (см. пункт 10), и могут рассматриваться как «триггерные» назначения. Триггер срабатывает, когда поток выполнения в симуляции достигает назначения в процедуре. Достижение назначения можно контролировать с помощью условных операторов. Элементы управления событиями, элементы управления задержкой, операторы if, case и циклические операторы могут использоваться для управления оценкой присвоений. В пункте 9 приведены подробности и примеры.
6.2.1 Назначение объявления переменной
Назначение объявления переменной — это особый случай процедурного назначения, поскольку оно назначает переменной значение. Оно позволяет поместить начальное значение в переменную в том же операторе, который объявляет переменную. Назначение должно быть связано с константным выражением. Назначение не имеет продолжительности. Вместо этого переменная сохраняет значение до следующего назначения этой переменной. Назначение объявления переменной массиву не допускается. Назначения объявления переменной разрешены только на уровне модуля. Если одной и той же переменной назначаются разные значения, как в начальном блоке, так и в назначении объявления переменной, порядок оценки не определен.
Например:
reg[3:0] a = 4'h4;
reg[3:0] a;
initial a = 4'h4;
reg [3:0] array [3:0] = 0;
integer i = 0, j;
real r1 = 2.5, n300k = 3E6;
time t1 = 25;
realtime rt1 = 2.5;
6.2.2 Синтаксис объявления переменных
Синтаксис для назначения объявлений переменных приведен в Синтаксисе 6-2.
integer_declaration ::=
integer list_of_variable_identifiers ;
real_declaration ::=
real list_of_real_identifiers ;
realtime_declaration ::=
realtime list_of_real_identifiers ;
reg_declaration ::=
reg [ signed ] [ range ] list_of_variable_identifiers ;
time_declaration ::=
time list_of_variable_identifiers ;
real_type ::=
real_identifier { dimension }
| real_identifier = constant_expression
variable_type ::=
variable_identifier { dimension }
| variable_identifier = constant_expression
list_of_real_identifiers ::=
real_type { , real_type }
list_of_variable_identifiers ::=
variable_type { , variable_type }