DocsTech
/
VERILOG HDL
/

~ cd 8. примитивы, объявляемые пользователем (udp) verilog hdl

Экземпляры новых 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-Синтаксис для UDPs

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).

Последовательные UDP имеют дополнительное поле, вставленное между входными полями и выходным полем. Это дополнительное поле представляет текущее состояние UDP и считается эквивалентным текущему выходному значению. Оно разделено двоеточиями. Каждая строка определяет выход на основе текущего состояния, определенных комбинаций входных значений и не более одного входного перехода (см. 8.4). Строка, подобная той, что показана ниже, является ошибкой:
...
Копировать
(01) (10) 0 : 0 : 1 ;

Если все входные значения заданы как x, то состояние выхода должно быть задано как x.

Нет необходимости явно указывать все возможные комбинации входных значений. Все комбинации входных значений, которые не указаны явно, приводят к состоянию выхода по умолчанию x.

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

8.1.5 Значения Z в UDP

Значение z в записи таблицы не поддерживается и считается недопустимым. Значения z, передаваемые на входы UDP, должны рассматриваться так же, как и значения x.

8.1.6 Краткое описание символов

Чтобы улучшить читаемость и облегчить написание таблицы состояний, предусмотрено несколько специальных символов. В таблице 8-1 приведено значение всех символов значений, которые действительны в табличной части определения UDP.

Таблица 8-1- Символы таблицы UDP
СимволИнтерпретацияКомментарии
0Логический 0
1Логический 1
xНеопределенноеРазрешено в полях ввода и выводадля всех UDPs и в поле текущего состояния последовательных UDP.
?Обозначение для 0, 1, и xНе допускается в поле вывода.
bОбозначение для 0 и 1Разрешено в полях ввода во всех UDPs и в поле текущего состояния последовательных UDP. Не допускается в поле вывода.
Без измененийРазрешено только в поле вывода последовательного UDP.
(vw)Переход значения с v на wv и 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), или символом перехода, таким как r. Записи, подобные следующим, являются незаконными:
...
Копировать
(01) (01) 0 : 0 : 1 ;

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

Если поведение UDP чувствительно к фронтам любого входа, желаемое состояние выхода должно быть указано для всех фронтов всех входов.

Например:

Следующий пример описывает D-флип с нарастающим фронтом импульса:
...
Копировать
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.

Таблица 8-2 initial декларации в UDP и модулях
Начальные декларации в UDPНачальные декларации в модулях
Содержание ограничено одной процедурной декларацией о назначенииСодержимым может быть одна процедурная декларации любого типа или блочное декларация, содержащее более одной процедурной декларации
Процедурный оператор присваивания должен присвоить значение регистру, идентификатор которого совпадает с идентификатором выходного клеммаПроцедурные операторы присваивания в начальных состояниях могут присваивать значения регистру, идентификатор которого не совпадает с идентификатором выходного клемма
Процедурный оператор присваивания должен присвоить одно из следующих значений: 1’b1, 1’b0, 1’bx, 1, 0Процедурные операторы присваивания могут присваивать значения любого размера, системы счисления и значения

Например:

Пример 1 В следующем примере показан последовательный UDP, содержащий начальное утверждение.
...
Копировать
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.

Пример 2 Следующий пример и рисунок 8-1 показывают, как значения применяются в модуле, который создается последовательном 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 Примитивы, объявляемые пользователем (UDP) Verilog HDL. Рисунок 8-1 Схема модуля и симуляция времени с переходом начального значения.
Рисунок 8-1 Схема модуля и симуляция времени с переходом начального значения.

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 ]
Синтаксис 8-2 — Синтаксис для экземпляров UDP

Экземпляры UDP задаются внутри модулей так же, как и вентиля (см. 7.1). Имя экземпляра необязательно, как и для вентилей. Порядок подключения портов соответствует порядку, указанному в определении UDP. Можно указать только две задержки, поскольку z не поддерживается для UDP. Для массива экземпляров UDP может быть указан необязательный диапазон. Правила соединения портов остаются такими же, как описано в п. 7.1.

Например:

Следующий пример создает экземпляр флип-флопа D-типа d_edge_ff (определен в п. 8.4).
...
Копировать
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, их чувствительное к уровню или фронтам поведение, а также случай входных значений, которые включает каждая из них.

Таблица 8-3 Совмещение чувствительных к уровню и чувствительных к фронту записей
ВходВключенный случайПоведение
? ?? 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.

Главная
Курсы
Вебинары
3. Лексические правила(Синтаксис) Verilog HDL
4. Типы данных Verilog HDL
5. Выражения и Операторы Verilog HDL
6. Назначения (Assignments) в Verilog HDL
7. Моделирование на уровне вентилей и переключателей в Verilog HDL
8. Примитивы, объявляемые пользователем (UDP) Verilog HDL
9. Процедурные назначения. Поведенческое моделирование в Verilog HDL.
9. If, case for, while и repeat Verilog HDL
9. Initial, always, задержки, блоки Verilog HDL
10. Задачи(task) и функции (function) в Verilog HDL
11. Семантика планирования. Стек (stack) в Verilog HDL
12. Модули(module). Переопределение параметров(defparam).
12. Порты. Иерархические имена в Verilog HDL
12. Generate блоки Verilog HDL
12. Иерархические имена Verilog HDL
13. Конфигурирование содержимого конструкции
13. Использование библиотек. Конфигурирование содержимого конструкции в Verilog HDL
14. Specify блоки в Verilog HDL
15. Setup, hold, setuphold и recovery в Verilog HDL
15. Skew, period, width и nochange Verilog HDL
15. Проверка синхронизации сигналов в Verilog HDL
16. Бэканнотирование с использованием стандартного формата задержки (SDF) в Verilog HDL
17. Системные задачи и функции
17.2 Файлы. Запись и чтение файлов Verilog
17. Задачи временной шкалы, управления, PLA и стохастического анализа Verilog
$time, $stime и $realtime Verilog
17.8. Функции преобразования Verilog
17.9. Функции распределения вероятностей Verilog
17.10. Ввод командной строки. 17.11. Математические функции
18. Дамп файлы изменения значений (VCD)
18. Формат файла VCD расширенные и четырьмя состояниями
19. Директивы компилятора Verilog HDL
20. Обзор интерфейса языка программирования (PLI) Verilog
28. Зашифрованные оболочки
Закрыть