- 8.1 Объявление UDP
- 8.1.1 Заголовок UDP
- 8.1.2 Объявление портов UDP
- 8.1.3 Объявление initial последовательном UDP
- 8.1.4 Таблица состояния UDP
- 8.1.5 Значения Z в UDP
- 8.1.6 Краткое описание символов
- 8.2 Комбинационные UDPs
- 8.3 Последовательные UDPs, чувствительные к уровню
- 8.4 Чувствительные к фронтам последовательные UDP
- 8.5 Инициализация последовательного UDP
- 8.6 Экземпляры UDP
- 8.7 Описание совмещения чувствительности к уровню и фронту
- 8.8 Доминирование чувствительности к уровню

Экземпляры новых UDP могут быть использованы точно таким же образом, как и примитивы вентилей, для представления моделируемой схемы
Следующие два типа поведения могут быть представлены в UDP:
1) Комбинационный — моделируется комбинационным UDP.
2) Последовательный — моделируется последовательным UDP.
Комбинационный UDP использует значение своих входов для определения следующего значения своего выхода. Последовательный UDP использует значение своих входов и текущее значение своего состояния для определения значения своего выхода. Последовательные UDP обеспечивают возможность моделирования последовательных схем, таких как флип-флопы и защелки.
Последовательный UDP может моделировать поведение, чувствительное как к уровню, так и к фронту.
Каждый UDP имеет ровно один выход, который может находиться в одном из трех состояний: 0, 1 или x. Трехсоставное значение z не поддерживается. В последовательных UDP выход всегда имеет то же значение, что и внутреннее состояние.
Значения z, передаваемые на входы UDP, должны рассматриваться так же, как и значения x.
8.1 Объявление UDP
Определения UDP не зависят от модулей. Они находятся на том же уровне, что и определения модулей в иерархии синтаксиса. UDP могут появляться в любом месте исходного текста, как до, так и после их экземпляра внутри модуля. Они не должны появляться между ключевыми словами module и endmodule.
Реализации могут ограничивать максимальное количество определений UDP в модели, но они должны допускать не менее 256.
Формальный синтаксис определения UDP приведен в Синтаксисе 8-1.
udp_declaration ::=
{ attribute_instance } primitive udp_identifier ( udp_port_list ) ;
udp_port_declaration { udp_port_declaration }
udp_body
endprimitive
| { attribute_instance } primitive udp_identifier ( udp_declaration_port_list ) ;
udp_body
endprimitive
udp_port_list ::=
output_port_identifier , input_port_identifier { , input_port_identifier }
udp_declaration_port_list ::=
udp_output_declaration , udp_input_declaration { , udp_input_declaration }
udp_port_declaration ::=
udp_output_declaration ;
| udp_input_declaration ;
| udp_reg_declaration ;
udp_output_declaration ::=
{ attribute_instance } output port_identifier
| { attribute_instance } output reg port_identifier [ = constant_expression ]
udp_input_declaration ::=
{ attribute_instance } input list_of_port_identifiers
udp_reg_declaration ::=
{ attribute_instance } reg variable_identifier
udp_body ::=
combinational_body | sequential_body
combinational_body ::=
table combinational_entry { combinational_entry } endtable
combinational_entry ::=
level_input_list : output_symbol ;
sequential_body ::=
[ udp_initial_statement ] table sequential_entry { sequential_entry } endtable
udp_initial_statement ::=
initial output_port_identifier = init_val ;
init_val ::= 1'b0 | 1'b1 | 1'bx | 1'bX | 1'B0 | 1'B1 | 1'Bx | 1'BX | 1 | 0
sequential_entry ::=
seq_input_list : current_state : next_state ;
seq_input_list ::=
level_input_list | edge_input_list
level_input_list ::=
level_symbol { level_symbol }
edge_input_list ::=
{ level_symbol } edge_indicator { level_symbol }
edge_indicator ::=
( level_symbol level_symbol ) | edge_symbol
current_state ::= level_symbol
next_state ::= output_symbol | -
output_symbol ::= 0 | 1 | x | X
level_symbol ::= 0 | 1 | x | X | ? | b | B
edge_symbol ::= r | R | f | F | p | P | n | N | *
8.1.1 Заголовок UDP
Определение UDP должно иметь одну из двух альтернативных форм. Первая форма должна начинаться с ключевого слова primitive, за которым следует идентификатор, являющийся именем UDP. За ним следует разделенный запятыми список имен портов, заключенных в круглые скобки, после которых ставится точка с запятой. За заголовком определения UDP должны следовать объявления портов и таблица состояний. Определение UDP должно завершаться ключевым словом endprimitive.
Вторая форма должна начинаться с ключевого слова primitive, за которым следует идентификатор, являющийся именем UDP. За ним следует разделенный запятыми список объявлений портов, заключенных в круглые скобки, за которыми следует точка с запятой. За заголовком определения UDP должна следовать таблица состояний. Определение UDP должно завершаться ключевым словом endprimitive.
UDP имеют несколько портов ввода и ровно один порт вывода; двунаправленные порты ввода- вывода в UDP не допускаются. Все порты UDP должны быть скалярными; векторные порты не допускаются.
Выходной порт должен быть первым в списке портов.
8.1.2 Объявление портов UDP
UDP должны содержать объявления входного и выходного портов. Объявление выходного порта начинается с ключевого слова output, за которым следует одно имя выходного порта. Объявление входного порта начинается с ключевого слова input, за которым следует одно или несколько имен входных портов.
Последовательные UDP должны содержать объявление reg для выходного порта, либо в дополнение к объявлению output, когда UDP объявляется с использованием первой формы заголовка UDP, либо как часть объявления output_declaration. Комбинационные UDP не могут содержать объявление reg. Начальное значение порта вывода может быть указано в initial объявлении в последовательном UDP (см. 8.1.3).
Реализации могут ограничивать максимальное количество входов в UDP, но они должны допускать не менее 9 входов для последовательных UDP и 10 входов для комбинационных UDP.
8.1.3 Объявление initial последовательном UDP
Последовательный оператор UDP initial задает значение выходного порта, когда начинается моделирование. Этот оператор начинается с ключевого слова initial. Следующий за ним оператор должен быть оператором присваивания, который присваивает выходному порту однобитное литеральное значение.
8.1.4 Таблица состояния UDP
Таблица состояний определяет поведение UDP. Она начинается с ключевого слова table и завершается ключевым словом endtable. Каждая строка таблицы завершается точкой с запятой.
Каждая строка таблицы создается с помощью различных символов (см. таблицу 8-1), которые обозначают входные значения и состояние выхода. Поддерживаются три состояния — 0, 1 и x.
Состояние z явно исключено из рассмотрения в UDP. Для обозначения определенных комбинаций состояний определен ряд специальных символов. Они описаны в таблице 8-1.
Порядок полей входного состояния каждой строки таблицы состояний берется непосредственно из списка портов в заголовке определения UDP. Он не связан с порядком объявлений входных портов.
Комбинационные UDP имеют одно поле на вход и одно поле на выход. Поля ввода отделяются от поля вывода двоеточием (:). Каждая строка определяет выход для определенной комбинации входных значений (см. 8.2).
(01) (10) 0 : 0 : 1 ;
Если все входные значения заданы как x, то состояние выхода должно быть задано как x.
Нет необходимости явно указывать все возможные комбинации входных значений. Все комбинации входных значений, которые не указаны явно, приводят к состоянию выхода по умолчанию x.
Не допускается, чтобы одна и та же комбинация входов, включая края, была указана для разных выходов.
8.1.5 Значения Z в UDP
Значение z в записи таблицы не поддерживается и считается недопустимым. Значения z, передаваемые на входы UDP, должны рассматриваться так же, как и значения x.
8.1.6 Краткое описание символов
Чтобы улучшить читаемость и облегчить написание таблицы состояний, предусмотрено несколько специальных символов. В таблице 8-1 приведено значение всех символов значений, которые действительны в табличной части определения UDP.
Символ | Интерпретация | Комментарии |
---|---|---|
0 | Логический 0 | |
1 | Логический 1 | |
x | Неопределенное | Разрешено в полях ввода и выводадля всех UDPs и в поле текущего состояния последовательных UDP. |
? | Обозначение для 0, 1, и x | Не допускается в поле вывода. |
b | Обозначение для 0 и 1 | Разрешено в полях ввода во всех UDPs и в поле текущего состояния последовательных UDP. Не допускается в поле вывода. |
— | Без изменений | Разрешено только в поле вывода последовательного UDP. |
(vw) | Переход значения с v на w | v и w могут быть любыми из 0, 1, x, ? или b и допустимы только в поле ввода. |
* | Такой же, как и (??) | Любое изменение значения на входе. |
r | Такой же, как и (01) | Восходящий фронт на входе. |
f | Такой же, как и (10) | Падающий фронт на входе. |
p | Обозначение для (01), (0 x) и (x1) | Потенциальный положительный фронт на входе. |
n | Обозначение для (10), (1x) и (x0) | Потенциальный отрицательный фронт на входе. |
8.2 Комбинационные UDPs
В комбинационных UDPs состояние выхода определяется исключительно как функция текущих состояний входа. Каждый раз, когда состояние входа изменяется, UDP оценивается, и состояние выхода устанавливается в значение, указанное в строке таблицы состояний, которая соответствует всем состояниям входа. Все комбинации входов, которые не указаны явно, приводят состояние выхода к неизвестному значению x.
Например:
primitive multiplexer (mux, control, dataA, dataB);
output mux;
input control, dataA, dataB;
table
// control dataA dataB mux
0 1 0 : 1 ;
0 1 1 : 1 ;
0 1 x : 1 ;
0 0 0 : 0 ;
0 0 1 : 0 ;
0 0 x : 0 ;
1 0 1 : 1 ;
1 1 1 : 1 ;
1 x 1 : 1 ;
1 0 0 : 0 ;
1 1 0 : 0 ;
1 x 0 : 0 ;
x 0 0 : 0 ;
x 1 1 : 1 ;
endtable
endprimitive
Первая запись в этом примере может быть объяснена следующим образом: когда control равно 0, dataА равны 1, и dataB равен 0, то выходной mux равен 1.
Входная комбинация 0xx (управление=0, данныеA=x, данныеB=x) не задана. Если эта комбинация возникает во время моделирования, значение выходного порта mux станет x.
primitive multiplexer (mux, control, dataA, dataB);
output mux;
input control, dataA, dataB;
table
// control dataA dataB mux
0 1 ? : 1 ; // ? = 0 1 x
0 0 ? : 0 ;
1 ? 1 : 1 ;
1 ? 0 : 0 ;
x 0 0 : 0 ;
x 1 1 : 1 ;
endtable
endprimitive
8.3 Последовательные UDPs, чувствительные к уровню
Чувствительное к уровню последовательное поведение представлено так же, как и комбинационное, за исключением того, что выход объявлен как тип reg и в каждой записи таблицы есть дополнительное поле. Это новое поле представляет текущее состояние UDP. Поле выхода в последовательном UDP представляет следующее состояние.
Например:
primitive latch (q, clock, data);
output q;
reg q;
input clock, data;
table
// clock data q q+
0 1 : ? : 1 ;
0 0 : ? : 0 ;
1 ? : ? : - ; // - = no change
endtable
endprimitive
Это описание отличается от комбинационной модели UDP двумя способами. Во-первых, выходной идентификатор q имеет дополнительное объявление reg, указывающее на наличие внутреннего состояния q. Выходное значение UDP всегда совпадает с внутренним состоянием. Во-вторых, добавлено поле для текущего состояния, которое отделяется двоеточиями от входов и выхода.
8.4 Чувствительные к фронтам последовательные UDP
При чувствительном к уровню поведении для определения выходного значения достаточно значений входов и текущего состояния. Поведение, чувствительное к фронтам, отличается тем, что изменения на выходе вызываются определенными переходами входов. Это делает таблицу состояний таблицей переходов.
(01) (01) 0 : 0 : 1 ;
Все переходы, которые не влияют на выход, должны быть явно указаны. В противном случае такие переходы приводят к изменению значения выхода на x. Все неуказанные переходы по умолчанию принимают значение выхода x.
Если поведение UDP чувствительно к фронтам любого входа, желаемое состояние выхода должно быть указано для всех фронтов всех входов.
Например:
primitive d_edge_ff (q, clock, data);
output q; reg q;
input clock, data;
table
// clock data q q+
// получают выход по нарастающему фронту тактового сигнала
(01) 0 : ? : 0 ;
(01) 1 : ? : 1 ;
(0?) 1 : 1 : 1 ;
(0?) 0 : 0 : 0 ;
// игнорирование срезов
(?0) ? : ? : - ;
// игнорировать изменения данных на постоянном тактовом сигнале
? (??) : ? : - ;
endtable
endprimitive
Термины, такие как (01), представляют собой переходы входных значений. В частности, (01) представляет собой переход от 0 к 1. Первая строка в таблице предыдущего определения UDP интерпретируется следующим образом: когда такстовый сигнал переходит значение с 0 на 1, а данные равны 0, выход переходит в 0 независимо от текущего состояния.
Переход тактового сигнала из 0 в x при данных равных 0, и текущем состоянии, равном 1, приведет к выходу q в Х.
8.5 Инициализация последовательного UDP
Начальное значение на выходном порту последовательного UDP может быть задано с помощью оператора initial, который обеспечивает процедурное назначение. Начальное утверждение является необязательным.
Как и начальные декларации в модулях, начальное декларация в UDP начинается с ключевого слова initial. Допустимое содержимое начальных деклараций в UDP и допустимые левая и правая стороны их процедурных деклараций присваивания отличаются от начальных деклараций в модулях. Неполный список различий между этими двумя типами начальных утверждений описан в таблице 8-2.
Начальные декларации в UDP | Начальные декларации в модулях |
---|---|
Содержание ограничено одной процедурной декларацией о назначении | Содержимым может быть одна процедурная декларации любого типа или блочное декларация, содержащее более одной процедурной декларации |
Процедурный оператор присваивания должен присвоить значение регистру, идентификатор которого совпадает с идентификатором выходного клемма | Процедурные операторы присваивания в начальных состояниях могут присваивать значения регистру, идентификатор которого не совпадает с идентификатором выходного клемма |
Процедурный оператор присваивания должен присвоить одно из следующих значений: 1’b1, 1’b0, 1’bx, 1, 0 | Процедурные операторы присваивания могут присваивать значения любого размера, системы счисления и значения |
Например:
primitive srff (q, s, r);
output q;
reg q;
input s, r;
initial q = 1'b1;
table
// s r q q+
1 0 : ? : 1 ;
f 0 : 1 : - ;
0 r : ? : 0 ;
0 f : 0 : - ;
1 1 : ? : 0 ;
endtable
endprimitive
Выход q имеет начальное значение 1 в начале моделирования. Спецификация задержки на экземпляре UDP не задерживает время моделирования присвоения этого начального значения выходу. Когда начинается моделирование, это значение является текущим состоянием в таблице состояний. Задержки не допускаются в начальной декларации UDP.
primitive dff1 (q, clk, d);
input clk, d;
output q;
reg q;
initial q = 1'b1;
table
// clk d q q+
r 0 : ? : 0 ;
r 1 : ? : 1 ;
f ? : ? : - ;
? * : ? : - ;
endtable
endprimitive
module dff (q, qb, clk, d);
input clk, d;
output q, qb;
dff1 g1 (qi, clk, d);
buf #3 g2 (q, qi);
not #5 g3 (qb, qi);
endmodule
UDP dff1 содержит оператор initial, который устанавливает начальное значение его выхода в 1. Модуль dff содержит экземпляр UDP dff1.
На рисунке 8-1 показана схема предыдущего модуля и время распространения моделирования начального значения выхода UDP.
На рисунке 8-1 выходной сигнал с выхода UDP qi включает сети q и qb. В момент времени моделирования 0 значение qi изменяется на 1. Это начальное значение qi не распространяется на сеть q до момента времени моделирования 3, и не распространяется на сеть qb до момента времени моделирования 5.

8.6 Экземпляры UDP
Синтаксис для создания экземпляра UDP показан в Синтаксисе 8-2.
udp_instantiation ::=
udp_identifier [ drive_strength ] [ delay2 ]
udp_instance { , udp_instance } ;
udp_instance ::=
[ name_of_udp_instance ] ( output_terminal , input_terminal { , input_terminal } )
name_of_udp_instance ::=
udp_instance_identifier [ range ]
Экземпляры UDP задаются внутри модулей так же, как и вентиля (см. 7.1). Имя экземпляра необязательно, как и для вентилей. Порядок подключения портов соответствует порядку, указанному в определении UDP. Можно указать только две задержки, поскольку z не поддерживается для UDP. Для массива экземпляров UDP может быть указан необязательный диапазон. Правила соединения портов остаются такими же, как описано в п. 7.1.
Например:
module flip;
reg clock, data;
parameter p1 = 10;
parameter p2 = 33;
parameter p3 = 12;
d_edge_ff #p3 d_inst (q, clock, data);
initial begin
data = 1;
clock = 1;
#(20 * p1) $finish;
end
always #p1 clock = ~clock;
always #p2 data = ~data;
endmodule
8.7 Описание совмещения чувствительности к уровню и фронту
Определения UDP позволяют совмещать конструкции чувствительные к уровню и фронту в одной таблице. При изменении входных данных сначала обрабатываются случаи чувствительные к фронту, а затем случаи чувствительные к уровню. Таким образом, когда чувствительные к уровню и чувствительные к фронту случаи задают разные выходные значения, результат задается чувствительным к уровню случаем.
primitive jk_edge_ff (q, clock, j, k, preset, clear);
output q; reg q;
input clock, j, k, preset, clear;
table
// clock jk pc state output/next state
? ?? 01 : ? : 1 ; // предустановка значения
? ?? *1 : 1 : 1 ;
? ?? 10 : ? : 0 ; // очистка значения
? ?? 1* : 0 : 0 ;
r 00 00 : 0 : 1 ;
r 00 11 : ? : - ;
r 01 11 : ? : 0 ;
r 10 11 : ? : 1 ;
r 11 11 : 0 : 1 ;
r 11 11 : 1 : 0 ;
f ?? ?? : ? : - ;
b *? ?? : ? : - ; // j and k transition cases
b ?* ?? : ? : - ;
endtable
endprimitive
В этом примере логика предустановки и очистки чувствительна к уровню. Когда комбинация предустановки и очистки имеет значение 01, выход имеет значение 1. Аналогично, когда комбинация предустановки и очистки имеет значение 10, на выходе значение 0.
Остальная логика чувствительна к фронтам тактовых импульсов. В обычных случаях тактовой синхронизации флип-флоп чувствителен к нарастающему фронту тактового сигнала, на что указывает символ r в поле тактового сигнала в этих записях. Нечувствительность к спадающему фронту тактового сигнала обозначается дефисом (-) в поле вывода (см. таблицу 8-1) для записи с f в качестве значения тактового сигнала. Помните, что для данного входного перехода должен быть указан желаемый выход, чтобы избежать нежелательных значений x на выходе. Последние две записи показывают, что переходы на входах j и k не изменяют выход при постоянном низком или высоком значении тактового сигнала.
8.8 Доминирование чувствительности к уровню
В таблице 8-3 показаны чувствительные к уровню и фронтам записи в примере из раздела 8.7, их чувствительное к уровню или фронтам поведение, а также случай входных значений, которые включает каждая из них.
Вход | Включенный случай | Поведение |
---|---|---|
? ?? 01: ?: 1; | 0 00 01: 0: 1; | Чувствительный к уровню |
f ?? ??: ?: -; | f 00 01: 0: 0; | Чувствительный к фронтам |
Включенные случаи определяют противоположные значения следующего состояния для одной и той же комбинации входа и текущего состояния. Включенный случай, чувствительный к уровню, указывает, что когда значения входов clock, jk и pc равны 0, 00 и 01, а текущее состояние равно 0, выход изменяется на 1. Включенный случай, чувствительный к фронту, указывает, что когда clock падает с 1 на 0, другие входы jk и pc равны 00 и 01, а текущее состояние равно 0, выход изменяется на 0.
Если сначала обрабатывается регистр, чувствительный к фронту, а затем регистр, чувствительный к уровню, выход изменяется на 1.