Verilog: типы данных

VerilogDataType

Типы данных в языке Verilog

Данные в языке Verilog предназначены для сохранения состояний (регистры) и для передачи состояний между моделируемыми объектами (цепи).

 

Возможные состояния линий связи

 

В языке Verilog данные могут принимать одно из четырех возможных состояний:

1 – представляет логическую 1 или значение «истинно» (true)

0 – представляет логический 0 или значение «ложно» (false)

z – представляет состояние высокого импеданса

x – представляет неизвестное логическое состояние

Почти все типы данных в Verilog принимают одно из этих состояний за небольшим исключением: такой тип данных как event вообще не удерживает состояний, а тип trireg может принимать z-состояние только в начальный момент времени, до первой инициализации – в дальнейшем в это состояние он больше не переходит.

 

Регистры и цепи

 

Регистры и цепи являются двумя наиболее важными группами данных. Эти группы различаются по способу назначения данных и их удержания. Также они представляют собой различные логические структуры.

Цепи

Цепи представляют типы данных предназначенных для соединения между собой структурных объектов, например, логических вентилей. Цепи не удерживают своего состояния (за исключением типа trireg) их состояние дожно непрерывно удерживаться (continious assignment) выходом с логического вентиля или комбинационной схемы. Если к цепи не подключен источник (driver) то цепь переходит в состояние высокого импеданса. Исключение составляет цепь типа trireg которая удерживает предыдущее состояние (но это не регистр!).

Регистры

Регистры представляют собой элементы хранения данных. Ключевое слово для данных этого типа – reg. Регистры сохраняют свое состояние от одного назначения до другого. Операция назначения состояния действует как триггер который изменяет состояние элемента хранения данных. По умолчанию регистровые данные принимают неизвестное состояние (х).

Объявление цепей и регистров

Цепи объявляются по следующим синтаксическим правилам:

 

 

Элементы объявления заключенные в квадратные скобки являются необязательными.

nettype – тип цепи, может принимать значения wire, wand, wor, tri и т.д. drive_strength – определяет «мощность» источника (драйвера).

expand_range – определяет разрядность цепи, по умолчанию цепь одно-разрядная.

delay – определяет задержку распостранения по цепи в установленных временных единицах или иначе указывает задержку от момента назначения состояния цепи до его фактического установления.

list_of_variables – список объявляемых переменных, разделяемых запятой.

Есть отличия при объявлении переменной типа trireg:

trireg [charge_strength] [expand_range] [delay] <list_of _variables>;

trireg – ключевое слово. charge_strength – определяет «емкость» источника.

Регистры определяются иначе:

reg [range] <list_of _reg_variables>;

reg – ключевое слово.

range – определяет разрядность регистровой переменной, по умолчанию регистр одноразрядный.

list_of_reg_variables – список объявляемых регистровых переменных, разделяемых запятой.

Ключевые слова определяющие тип цепи приведены ниже:

 

«Мощность» определяется одним из следующих выражений: drive_strength: (<strength1>, <strength0>) или (<strength0>, <strength1>), где strength1 и strength0 опрределяют «мощность» источника в состояниях лог.1 и лог.0 соответственно. Ключевые слова определяющие «мощность» следующие:

 

Комбинации (highz1, highz0) или (highz0, highz1) являются недопустимыми. По умолчанию «мощность» цепи определяется как (strong1, strong0).

«Емкость» источника определяется так: charge_sterngth: (<capacitor_size>), где capacitor_size определяется одним из следующих ключевых слов:

 

По умолчанию «емкость» устанавливается как (medium).
Замечание: «мощность» или «емкость» источника могут иметь практическое значение при моделировании схемы с целью получить наиболее объективные результаты, большинство систем синтеза эти объявления игнорируют.

Объявления разрядности для цепи и регистра несколько отличаются:

 

Ключевые слова scalared и vectored определяют скалярная это цепь или это вектор. Различие заключается в следующем: скалярность подразумевает, что разработчик может использовать (читать или устанавливать) отдельные биты или часть (группу) битов. Векторизованная цепь может быть прочитана или установлена лишь целиком. По умолчанию цепь устанавливается как scalared. Границы диапазона msb и lsb представляются либо в числовой форме (константы) или в виде константных выражений – т.е. все входящие в выражение операнды являются константами. Кроме того границы диапазона не могут представляться отрицательными или дробными числами. При этом msb может быть меньше или равно lsb.

Замечание: По стандарту разрядность цепей или регистров не ограничивается, но системы синтеза могут иметь ограничения на разрядность переменных.

Многоразрядные цепи и регистры подчиняются арифметике по модулю 2 в степени n, где n – количество разрядов.

Временные задержки (delay) будут подробно рассмотрены в пункте ХХ.

Примеры объявлений цепей или регистров

В cледующем листинге приведены примеры объявлений цепей и регистров. 

 

 

Типы цепей

 

Существует несколько различных типов цепей – все эти типы представлены в следующих секциях.

Типы wire и tri

Цепи типов wire и tri предназначены для соединения элементов. Эти типы идентичны по синтаксису и по их функциональному назначению. Различие в ключевых словах показывает лишь их назначение в модели. Цепи типа wire обычно используются для того, чтобы показать, что цепь имеет лишь один драйвер, в то время как тип tri используется чтобы показать, что у цепи несколько источников – обычно это трех- стабильные шины.

Логические конфликты в случае нескольких источников приводят к неопределенному состоянию, за исключением случаев, когда лишь один источник находится в состоянии лог.1 или лог.0, тогда как остальные находятся в z-состоянии. Это наглядно демонстрируется таблицей истинности (табл. 3-1) для случая цепи с двумя драйверами. По вертикали отображены состояния одного источника, по горизонтали – другого. Необходимо заметить, что «мощность» источников одинакова.

 

Типы wand, triand, wor, trior

Типы wand, triand, wor, trior используются для моделирования цепей с разрешающей логикой. Эти типы позволяют разрешать конфликты в цепях с несколькими источниками. Цепи wand или triand создают такую конфигурацию, что результирующее состояние будет лог.0 в случае если хотя бы один из источников находится в лог.0. Эти типы идентичны по синтаксису и по функциональному назначению (также как для типов wire и tri). Ниже приведена таблица истинности для цепи wand или triand с двумя источниками равной «мощности» (табл. 3-2).

 

Типы wor или trior

Цепи wor или trior создают такую конфигурацию, что результирующее состояние будет лог.1 в случае если хотя бы один из источников находится в лог.1. Эти типы идентичны по синтаксису и по функциональному назначению (также как для типов wire и tri). Ниже приведена таблица истинности для цепи wor или trior с двумя источниками равной «мощности» (табл. 3-3).

 

 

Тип trireg

Цепи типа trireg сохраняют свое состояние и используются для моделирования цепей с сохранением заряда (отсюда и термин «емкость»). Цепи этого типа могут быть в одном из двух состояний:

• В состоянии когда хотя бы один источник находится в состояниях лог.1, лог.0 или неизвестном состоянии – это состояние распостраняется по цепи. Это состояние с подключенным драйвером (driven state). «Мощность» в этом состоянии может быть supply, strong, pull или weak в зависимости от мощности источника.

• В состоянии когда все источники находятся в состоянии высокого импеданса. Цепь удерживает последнее состояние когда источник был подключен, высокоимпедансное состояние не распостраняется по цепи этого типа. «Мощность» «драйвера» цепи в этом состоянии может быть small, medium или large.

В случае конфликта источников подключенных к цепи правило разрешения аналогично представленному в табл. 3-1, за тем исключением, что вместо z-состояния цепь будет удерживать состояние предшествующее установке всех источников в состояние высокого импеданса.

Типы tri1, tri0, supply1, supply0

Типы tri1 и tri0 моделируют цепи с резистивной подтяжкой (pull-up, pull-down) к состоянию лог.1 и лог.0 соответственно. Когда все источники цепи такого типа находятся в состоянии высокого импеданса, то цепь устанавливается в соответствующее лог. состояние с «мощностью» pull. Таблица истинности в остальных состояниях идентична табл. 3-1 (если «мощности» драйверов по крайней мере strong). Типы supply1 и supply0 моделируют источники питания подключенные к этой цепи. Тип supply1 моделирует источник питания Vdd или Vss, а supply0 моделирует подключение к «земле». Цепи подобного типа никогда не подключаются к выходу вентиля и к оператору назначения состояния, поскольку их «мощность» выше «мощности» любого другого источника.

 

Замечание: Все перечисленные типы цепей кроме типов wire и tri могут иметь практическое значение при моделировании схемы с целью получить наиболее объективные результаты, большинство систем синтеза эти типы приводят к допустимым типам wire и tri. Использование этих типов может привести к различным результатам в процессе моделирования и реального функционирования схемы. Применение вышеперечисленных типов допустимо в случае если точно известно, что система синтеза правильно интерпретирует эти типы и платформа на которой разрабатывается устройство позволяет реализовать цепи подобных типов.

Элементы памяти

В языке Verilog элементы памяти моделируются как массивы регистров. Подобные массивы могут быть использованы для моделирования ПЗУ, ОЗУ или регистровых файлов. Каждый регистр в массиве определяется как элемент или слово и адресуется одномерным индексом. Многомерных массивов в Verilog HDL по стандарту 1995г. не предусмотрено. Ниже представлен синтаксис массива регистров.

 

Здесь range определяет разрядность элемента массива, как и для регистра он может объявляться в возрастающем и убывающем диапазоне (это важно – игнорирование возрастание или убывание диапазона может приводить к ошибкам), может представлять собой константные выражения. Имя массива – memory_name – подчиняется всем правилам написания идентификаторов. Интерес представляет размерность массива заключенная в квадратные скобки. Выражения const_expr могут представлять из себя любую положительную константу или константное выражение.

В отличие от разрядности регистра возрастание или убывание диапазона не играет никакой роли. Существует некоторое ограничение: нельзя непосредственно обратится к отдельному биту или группе битов элемента массива. Для этого необходимо скопировать элемент в отдельный регистр и лишь тогда обратиться к соответствующим битам регистра. Эта ситуация представлена на листинге 3-2.

 

 

 

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

 

Переменные типов integer и time

 

При моделировании цифровых устройств могут быть очень полезны такие переменные языка Verilog как integer и time. Конечно можно использовать отдельный регистр для вычисления текущего времени в процессе моделирования, но удобнее использовать переменные типа integer или time, так как это повышает самодокументирование кода. Синтаксис для объявления переменных этого типа приведен ниже.

 

Переменные типа time используются в случаях, когда в процессе моделирования требуются какие-либо манипуляции с временными отсчетами для диагностики и устранения ошибок. Этот тип данных обычно используется совместно с системной функцией $time, размерность этой переменной 64 бита. Переменные типа integer обычно используются как переменные общего назначения, для хранения отсчетов, которые не связаны с каким-либо аппаратным регистром. Разрядность переменных типа integer 32 бита.

 

Замечание: Некоторые системы синтеза могут ограничивать размерность переменных типа integer и time.

 

Допускается использование массивов переменных типа integer и time. Пример объявления массивов приведен ниже:

 

Значения этим переменным присваиваются также как и регистровым переменным. Переменная типа time ведет себя точно также как 64-х разрядная регистровая переменная. Это беззнаковая переменная и подчиняется беззнаковой арифметике. Пременные типа integer напротив подчиняются знаковой арифметике, что приводит к различным результатам по сравнению с 32-х разрядной регистровой переменной. Регистровые переменные подчиняются беззнаковой арифметике.

Простой пример: мы можем присвоить регистровой переменной отрицательное значение – допустим 16-и разрядной переменной мы присвоили значение -24 (-16’d24), а в результате в следующей арифметической операции в этой переменной окажется число 65512 – целое положительное число! С переменной типа integer этого не произойдет – в арифметической операции будет использовано именно -24. Об этом важном различии необходимо помнить при операциях с регистровыми и целыми переменными.

 

Вещественные числа

 

Кроме переменных типа integer и time Verilog HDL поддерживает использование вещественных констант и переменных. Объявление подобных переменных выполняется с помощью ключевого слова real. За некоторым исключением эти переменные могут использоваться в тех же случаях что и переменные типа integer и time.

 

 

Основные отличия переменных типа real:

• Не все операторы языка Verilog могут быть использованы с переменными типа real.

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

Определение вещественных чисел

Вещественные числа могут определяться как десятичной нотации (например 12.47), так и в научной нотации (например 38е8, что обозначает 38 умноженное на 10 в степени 8). Вещественные числа определенные с десятичной точкой должны иметь хотя бы одну цифру с каждой стороны от десятичной точки. Ниже приведены некоторые примеры корректных реальных чисел:

1.2

0.1

2394.26331

1.2Е12 (Символ экспоненты может быть как е так и Е)

1.30е-2

0.1е-0

23Е10

29Е-2

236.123_763_е-12 (Символ подчеркивания игнорируется)

Пример неверного определения вещественных чисел – опущена цифра с одной из сторон от десятичной точки:

.12

3.е7

.2Е-7

Операторы и вещественные числа

Результатом применения логических операторов и операторов отношения к вещественным числам является однобитовое скалярное значение. Не все операторы могут быть использованы с вещественными числами. В следующем разделе приведена таблица операторов и указано, какие операторы могут быть применены, а какие нет. Также вещественные константы и переменные не могут быть применены в следующих контекстах:

• Дескрипторы фронта/среза (posedge, negedge) не могут быть применеы к вещественным переменным.

• Выбор отдельного бита (bit-select) или группы битов (part-select) для переменной, объявленной как real.

• Вещественные числа не могут быть индексами для выбора отдельного бита или группы битов.

• Не может быть массивов вещественных чисел.

Преобразование вещественных чисел

Вещественные числа преобразуются к целому типу по следующему правилу: преобразование идет к ближайшему целому числу, т.е. числа 35.7 и 35.5 будут преобразованы к числу 36, а число 35.2 – к 35. Подобное преобразование имеет место когда вещественное число присваивается к переменной целого типа. В разделе «Системные функции и задачи» обсуждаются системные функции для точного преобразования вещественных чисел.

 

Параметры в Verilog

 

Параметры языка Verilog не относятся ни регистрам ни к цепям. Параметры не могут быть переменными – это всегда константы. Объявляются параметры следующим образом:

 

 

Замечание: Некоторые системы синтеза позволяют указывать диапазон в объявлении параметра.

 

При объявлении параметр всегда должен быть проинициализинован – list_of_assignmens содержит выражения присваивания, разделенные запятой, где с правой стороны должна находиться константа или константное выражение. При этом константное выражение может содержать как константы, так и ранее определенные параметры. Примеры объявления параметров приведены в листинге 3-3.

 

 

 

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