Подписка на новости

Опрос

Нужны ли комментарии к статьям? Комментировали бы вы?

Реклама

 

2008 №4

Краткий курс HDL. Часть 2.1. Описание языка Verilog

Каршенбойм Иосиф


Все статьи цикла:

Начало описания языка Verilog и немного о VHDL для сравнения

В этом разделе будет дано вступление к описанию языка Verilog. Для сравнения также будет приведена небольшая часть описания языка VHDL. Это сделано для того, чтобы читатель смог оперативно сравнивать конструкции этих двух языков. Для дополнительного изучения можно порекомендовать список литературы.

VHDL

Для VHDL приняты следующие соглашения об именах, применяемых пользователями в своих проектах:

  • VHDL не отличает строчные и прописные буквы.
  • Два знака «--» используются для строчного комментария.
  • В именах могут использоваться цифры и символ подчеркивания — «_».
  • Имена могут начинаться с цифры или буквы.
  • Нельзя использовать два символа подчеркивания «__» или использовать символ подчеркивания в конце имени.
  • Имена компонентов схемы должны быть уникальными. Например, нельзя назвать сигнал именем «А» и дать шине имя «А(7 downto 0)».

Зарезервированные слова VHDL приведены в таблице 1.

Таблица 1. Зарезервированные слова VHDL
Зарезервированные слова VHDL

Verilog

Для Verilog приняты следующие соглашения об именах, применяемых пользователями в своих проектах:

  • Verilog отличает строчные и прописные буквы.
  • Два знака «//» используются для строчного комментария. Набор знаков «/*» используется для начала блочного комментария, а «*/»— для конца комментария.
  • В именах можно использовать цифры, буквы, символ подчеркивания «_» и символ «$».
  • Имена могут начинаться с цифры, буквы или символа подчеркивания «_».
  • В именах нельзя использовать символ пробела.

Зарезервированные слова Verilog приведены в таблице 2.

Таблица 2. Зарезервированные слова Verilog
Зарезервированные слова Verilog

Сигналы или переменные могут быть представлены следующими логическими уровнями:

  • 0: ноль, логический низкий уровень, «ложно», «земля» (zero, logic low, false, ground);
  • 1: единица, логический высокий уровень, «истина», «питание» (one, logic high, power);
  • X: неизвестное значение (unknown);
  • Z: высокий импеданс, неподключенный сигнал, третье состояние (high impedance, unconnected, tri-state).

Операторы

Операторы могут быть трех типов: унитарные, бинарные и тернарные. Унитарные операторы производят действия над единственным операндом. Бинарные операнды производят действия над двумя операндами. Тернарные операторы имеют два оператора, которые делают выбор для трех операндов. Примеры этих операндов:

В языках VHDL и Verilog используются следующие арифметические и битовые операторы:

  • арифметические (Arithmetic);
  • конкатенации (объединения) (Concentration);
  • повторения (Replication);
  • условные (Conditional);
  • равенства (Equality);
  • логические побитовые (Logical Bit-wise);
  • логического сравнения (Logical Comparison);
  • свертки (Reduction);
  • отношения (Relational);
  • сдвига (Shift);
  • унитарные арифметические (Unary Arithmetic (Sign)).

Операнды (Operands)

Есть несколько типов операндов, которые могут быть определены в выражениях. Самый простой тип — это цепь или регистр, и, если при этом указывается на полную разрядность цепи или регистра, то можно приводить только название цепи или регистра. В этом случае все биты, составляющие цепь или выходы регистра, используются как операнд.

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

На элемент памяти можно сослаться как на операнд. Конкатенация других операндов (включая вложенные конкатенации) может быть определена как операнд. Запрос функции — это тоже операнд.

Операторы и возможность их применения в VHDL или в Verilog приведены в таблице 3. Приоритеты выполнения операторов в Verilog приведены в таблице 4.

Таблица 3. Операторы и возможность их применения в VHDL или в Verilog
Операторы и возможность их применения в VHDL или в Verilog
Таблица 4. Приоритеты выполнения операторов
Приоритеты выполнения операторов

Битовые операторы (Bit-Wise Operators)

Битовые операторы позволяют производить побитовые операции над двумя или более операндами (табл. 5–9).

Таблица 5. Поразрядная инверсия
Поразрядная инверсия
Таблица 6. Поразрядная операция «И» (AND)
Поразрядная операция «И» (AND)
Таблица 7. Поразрядная операция «ИЛИ» (Or)
Поразрядная операция «ИЛИ» (Or)
Таблица 8. Поразрядная операция «Исключающее ИЛИ» (exclusive Or)
Поразрядная операция «Исключающее ИЛИ» (exclusive Or)
Таблица 9. Поразрядная операция «Исключающее ИЛИ5НЕ» (exclusive NOR)
Поразрядная операция «Исключающее ИЛИ5НЕ» (exclusive NOR)

Обратите внимание на то, что необходимо отличать битовые операторы & и | от логических операторов && и ||. Например, если x = 1 и y = 2, то битовая операция x & y в результате даст 0, в то время как x && y — в результате даст 1. Когда операнды имеют неравное число битов, то операнд, имеющий меньшее число битов, будет заполнен нулями в старших разрядах.

Операторы приведения

Операторы приведения выполняют операции побитно над операндом, чтобы произвести результат, имеющий разрядность 1 бит. Первый шаг операции выполняется над первым и вторым битами операнда, в соответствии с таблицами 10–12. Вторые и последующие шаги выполняются аналогично с однобитовым результатом предшествующего шага и следующими битами операнда.

Таблица 10. Оператор приведения по «И» (AND)
Оператор приведения по «И» (AND)
Таблица 11. Оператор приведения по «ИЛИ» (Or)
Оператор приведения по «ИЛИ» (Or)
Таблица 12. Оператор приведения по «Исключающему ИЛИ» (exclusive Or)
Оператор приведения по «Исключающему ИЛИ» (exclusive Or)

Необходимо отметить, что оператор приведения по «И-НЕ» и оператор приведения по «ИЛИ-НЕ» выполняет те же операции, что и операторы приведения по «И» и «ИЛИ» соответственно, но результаты их работы при этом будут инверсными. Результаты работы операторов приведения даны в таблицах 13, 14.

Таблица 13. Результаты работы оператора приведения для «И», «ИЛИ», «И-НЕ» и «ИЛИ-НЕ»
Результаты работы оператора приведения для «И», «ИЛИ», «И-НЕ» и «ИЛИ-НЕ»
Таблица 14. Результаты работы оператора приведения для «Исключающего ИЛИ» и «Исключающего ИЛИ-НЕ»
Результаты работы оператора приведения для «Исключающего ИЛИ» и «Исключающего ИЛИ-НЕ»

Ограничения синтаксиса

В языке Verilog есть два ограничения синтаксиса, предназначенные для того, чтобы защитить текст описания от ошибки, которая возникает при неправильной записи выражения. Эти ошибки бывает достаточно трудно найти, потому что они возникают из-за неправильного положения пробела и символа в выражении. Для примера можно рассмотреть два выражения. Выражения строк 1 и 2 внешне почти похожи, но дают совершенно разный результат (пример 1).

Как защитить пользователей от этого типа ошибок? Необходимо использовать круглые скобки для того, чтобы отделить сокращение ИЛИ или И (reduction or or and) оператор от поразрядного ИЛИ или И (bit-wise or or and) оператора. В примере 2 показан синтаксис, который требует круглых скобок.

Операторы сдвига

Операторы сдвига, << и >> выполняют сдвиг операнда, находящегося слева от оператора, влево или вправо на то число позиций двоичного разряда, которое указано справа от оператора сдвига. При сдвиге данных оба оператора производят заполнение освободившихся позиций двоичного числа нулями. Пример 3 иллюстрирует действия, выполняемые этими операциями.

В 3-м примере 4-битовому регистру start присвоено значение 0001. После сдвига влево на два разряда регистр будет содержать число 0100.

Условный оператор

Условный оператор имеет три операнда, отделенные двумя операторами, записанными в следующем порядке (пример 4)

Если cond_expr оценивается как ложное — false, то для результата будет использовано выражение false_expr. Если условное выражение истинно — true, то для результата будет использовано выражение true_expr.

Если cond_expr или true_expr и false_expr содержат символы неоднозначности — Х, то для того чтобы вычислить конечный результат, используйте таблицу 15.

Таблица 15. Работа условного оператора
Работа условного оператора

Если разрядность операндов различна, то операнд с меньшей разрядностью будет слева дополнен нулями (старшие разряды) так, чтобы соответствовать разрядности операнда с большей разрядностью.

В примере 5 показано то, как можно использовать условный оператор для того, чтобы выполнить шину с третьим состоянием.

Шина busa управляется сигналом drive_busa. В том случае, когда этот сигнал 1, на шину передаются данные — data, в противном случае шина переключается в третье состояние. Если значение сигнала drive_busa неизвестно, то и значение данных на шине busa тоже неизвестно.

Конкатенация — Concatenation

Конкатенация — объединение битов, находящихся в двух или более выражениях. Для записи конкатенации используются символы фигурных скобок { и }, с запятыми, отделяющими выражения, находящиеся в этих скобках. Пример 6 объединяет четыре выражения.

Пример 6 эквивалентен другой записи, которая приведена в примере 7.

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

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

Числа

Постоянные числа могут быть определены в десятичном (d or D), шестнадцатеричном (h or H), восьмеричном (o or O) или в двоичном (b or B) формате.

Они могут произвольно начинаться со знака + или – и могут быть написаны в одном из следующих форматов.

  1. <size>'<base><number>: самая полная форма для записи числа.
  2. <base><number>: эта форма записи использует разрядность по умолчанию и является машинно-зависимой, но, по крайней мере, равняется 32 битам.
  3. <number>: эта форма записи использует разрядность по умолчанию для десятичного формата.

Наиболее простой формат 3 — беззнаковое десятичное число, содержащее, в любом порядке, последовательность цифр от 0 до 9. Хотя пользователь, возможно, не определил размерность написанного числа, Verilog сам вычисляет разрядность числа, примененного в выражении. Обычно в выражениях разрядность примененных в операторах чисел одинакова. И для использования выбирают требуемое число битов, начиная с наименьшего значащего бита.

Формат 1 определяет постоянный размер для разрядности и записывается следующим образом:

При этом неизвестные и высокоимпедансные значения можно использовать во всех числах, кроме десятичных. В каждом случае применение символов x или z представляет данное число битов, имеющих состояние x — неизвестное значение или z— высокий импеданс. При записи чисел, кроме z, может быть использован символ ?. Его применяют в операторе case для того, чтобы улучшить читаемость текста.

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

Символ подчеркивания может вставляться в числа с любым основанием для того, чтобы улучшить читаемость кода. Но, конечно, символ подчеркивания не может быть первым символом в записи числа. Приведем примеры двоичных чисел: 12'b 0x0x_1101_0zx1 и 12'b 0x0x11010zx1. Как мы видим, первое число читать значительно легче. А это пример неправильной записи: 8'b_0001_1010.

Примеры записи чисел, в которых не определена разрядность:

  • 792 — десятичное число;
  • 'h 7d9 — шестнадцатеричное число;
  • 'o 7746 — восьмеричное число.

В примере 10 показаны формы записи чисел, в которых определена разрядность.

В примере 11 показаны формы записи чисел со знаком и отрицательных чисел. А в примере 12 показаны формы записи чисел со знаком «?».

Вещественные числа могут быть записаны в десятичном или научном формате. Если число записано в десятичном формате, оно должно иметь, по крайней мере, одну цифру после десятичной точки (пример 13).

Преобразование вещественного числа в целое число

Язык Verilog преобразовывает вещественные числа в целые, округляя вещественное число к самому близкому целому числу, а не отбрасывая десятичную часть. Например, вещественные числа 35,7 и 35,5 и округляются до значения 36, а 35,2 становится 35. Неявное преобразование имеет место, когда вы назначаете вещественное число как целое число (real to an integer).

Строки

Строка — это последовательность символов, ограниченная слева и справа кавычками. Они должны быть расположены на одной строке. В строке можно использовать специальные ESC-символы, для чего необходимо применять следующим образом символ «\»:

  • \n печатать текст с новой строки. Аналогично применению клавиши RETURN.
  • Символ табуляции \t. Эквивалентно тому, что происходит при нажатии на клавишу табуляции.
  • Применение двух символов \\ является эквивалентом применения символа «\».
  • \« является символом «.
  • \ddd — символ ASCII, определяющий цифру. (В этой записи использовано от одной до трех восьмеричных цифр.)
  • %% — это печать знака %.

В примере 14 показаны правильная и неправильная формы записи строки.

Параметры (Parameters)

В языке Verilog параметры не принадлежат к какому-либо регистру или группе цепей. Параметры не переменные, они — константы. Параметры могут быть как местные, локальные, так и глобальные. Синтаксис для объявлений параметров показан в примере 15.

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

<list_of_assignments> — список назначений, разделенный запятыми, где правая сторона назначения должна быть постоянным выражением, то есть выражением, содержащим только постоянные числа и предварительно определенные параметры. В следующем примере 16 показано объявление параметров.

Хотя параметры в Verilog представляют собой константы, они могут быть изменены во время компиляции для того, чтобы принять новые значения, которые отличаются от определенных в назначении объявления. Это позволяет пользователю настраивать инстансы модулей при их установке в проекте. Вы можете изменить параметр утверждением defparam или изменить параметр в утверждении инстанса модуля. Обычно параметры используются для задания значения времени задержки или разрядности (ширины) переменных.

Функции

Определение функции должно начаться с ключевого слова функция — function, сопровождаемого дополнительным ключевым словом автоматическая — automatic и дополнительным указателем signed, диапазоном или типом возвращаемого значения из функции, затем идет само название функции, потом или точка с запятой, или список портов функции, заключенных в круглые скобки, и точка с запятой. И, наконец, определение должно закончиться ключевым словом endfunction. Дополнительно можно использовать параметр range_or_type. Если функция определена по умолчанию, то есть без диапазона или типа, то ее представляют как функцию, возвращающую значение от однобитового регистра. Если используется параметр range_or_type, то необходимо определить, что представляет собой возвращаемое значение функции — реальное, целое число, время, реальное время или значение с диапазоном битов — [n:m]. Функция должна иметь по крайней мере один объявленный вход (одну входную переменную).

Ключевое слово automatic (автоматический) объявляет рекурсивную функцию со всеми функциональными объявлениями, распределенными динамически для каждого рекурсивного обращения. К автоматическим вызовам функции нельзя обратиться при помощи иерархических ссылок. Автоматические функции могут быть вызваны по их иерархическому названию.

Входы функции могут быть объявлены двумя способами. В первом способе необходимо дать название функции, сопровождаемое точкой с запятой. После точки с запятой должны следовать одно или более объявлений входов, которые могут быть произвольно установлены при объявлении тем блока. После объявлений тем для функции должна следовать «начинка» функции, то есть поведенческие утверждения (behavioral statement) и затем ключевое слово endfunction. Пример 17 определяет функцию, названную getbyte, используя при этом спецификацию диапазона.

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

Значения, возвращаемые из функции

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

В следующем примере иллюстрируется это понятие. Для функции getbyte, определенной в примере 18, возвращаемое значение будет выглядеть следующим образом:

В примере 18, использующем ту же функцию getbyte, создается новое слово, представляющее собой конкатенацию результатов двух вызовов функции:

Правила работы с функциями

При использовании функции имеют больше ограничений, чем задачи. Сформулируем шесть правил использования функций:

  1. Определение функции не должно содержать утверждений, которые связаны с управлением по времени, то есть не должно содержать любых утверждений, содержащих #, @ или wait.
  2. Функции не могут запускать задачи — task.
  3. Определение функции должно содержать, по крайней мере, один входной аргумент.
  4. Определение функции не должно иметь аргументов, объявленных как выход или как двунаправленный вход/выход.
  5. Определение функции должно включать в себя назначение результата работы функции на внутреннюю переменную, которая имеет то же самое название, что и имя функции.
  6. Функция не должна иметь неблокирующих назначений.

В примере 19 показано определение функции с именем factorial, которая возвращает целочисленное значение. Функция factorial вызывается итерационно, и результаты ее работы выводятся на монитор.

Результаты симуляции будут следующие:

Использование постоянных функций (constant functions)

Вызовы функций постоянных значений (Constant function calls) используются для того, чтобы поддержать возможность проведения вычислений значений параметров во время разработки. Вызов функций постоянных значений должен быть вызовом функции для вычисления постоянного значения, которое находится локально в том модуле, где выполнен вызов, и аргументы функции представляют собой также постоянные выражения.

Функции постоянных значений представляют собой подмножество нормальных функций Verilog, которые должны иметь следующие ограничения:

  • Они не должны содержать иерархические ссылки.
  • Любая функция, вызванная в пределах функций постоянных значений, должна быть вызовом функции для вычисления постоянного значения, которое находится в текущем модуле, в котором и выполнен вызов. Системные же функции не должны вызываться.
  • Все системные задачи в пределах постоянной функции должны игнорироваться. Единственная системная задача, которая может быть вызвана, это команда $display, но и она должна игнорироваться при вызове во время разработки.
  • Все значения параметра, используемые в пределах функции, должны быть определены перед вызовом функции. Все идентификаторы, которые не являются параметрами или функциями, должны быть объявлены локально для данной функции. Если эти идентификаторы используют какое-нибудь значение параметра, которое затронуто прямо или косвенно, при использовании утверждения defparam, то результат будет не определен. Это может привести к ошибкам, или постоянная функция может возвратить неопределенное значение.
  • Они не должны быть объявлены в пределах выполнения оператора generate.
  • Они сами не должны использовать постоянные функции в любом контексте, требующем постоянного выражения. Вызовы функций постоянных значений выполняются во время разработки. Их выполнение не имеет никакого воздействия на начальные значения переменных, используемых или во время моделирования, или среди многократных вызовов функции во время разработки. В каждом из этих случаев переменные будут инициализированы, так же как и при обычном моделировании. В примере 20 представлено определение функции, названной clogb2, которая возвращает целое число, равное округленному в большую сторону значению логарифма по основанию 2.

Цепи, регистры, память, представление чисел и времени (Wire Registers, Memories, Integers and Time)

Цепь — wire

Цепи на схеме соответствуют физическим проводам, которые подключаются ко всем компонентам схемы. Разрядность цепей по умолчанию — один бит. Цепи не хранят значения сигнала, и для того чтобы состояние сигнала в цепи было определено, какой-либо источник сигнала должен непрерывно управлять ею. Если цепь имеет несколько источников сигнала — драйверов (например, два выхода вентилей подключены к одной цепи), то значение результирующего сигнала в цепи имеет значение, согласно тому, какой тип цепи используется. Названия цепей и выполняемые ими функции приведены в таблице 16.

Таблица 16. Названия цепей и выполняемые ими функции
Названия цепей и выполняемые ими функции

Регистры

Регистры — это термин, применяемый для названия класса устройств, применяемых в цифровых схемах. Эти устройства могут запоминать информацию и хранить ее. Они определяются ключевым словом reg и могут иметь произвольную разрядность. Размер значения по умолчанию — 1 бит. Пример записи такого регистра: reg My1BitReg — определяет регистр, названный My1BitReg и имеющий разрядность в 1 бит, в то время как запись reg [15:0] My16BitReg определяет 16-разрядный регистр, названный My16BitReg. Регистры, имеющие разрядность, равную 1 биту, называют скаляром (scalar), а регистры, имеющие разрядность более 1 бита, называют вектором (vector). Название разрядов шины начинается со старшего бита (в этом случае это бит, имеющий номер 15) и заканчивается младшим битом шины. Но регистр может быть объявлен и так — reg [0:15] My16BitReg, при этом старший бит в названии шины будет иметь номер 0. Соответственно, и все другие биты шины будут пронумерованы по-другому.

Далее, регистр может быть объявлен как знаковый — reg signed [15:0] My16BitReg. Такая форма записи указывает на то, что при работе с этим регистром данные должны быть обработаны как число со знаком (двоичное дополнение).

Общая форма записи регистра показана в примере 21.

<
>

В выражениях языка можно использовать как один бит, так и несколько соседних битов векторного регистра (или шины). Выбор одного бита из регистра или шины называют выбором бита (bit-select), а выбор нескольких соседних битов называется выбор группы (part-select).

Следующий пример показывает выбор бита из acc, этот бит адресуется операндом index:

Выбор части битов из регистра или цепи показан на следующем примере:

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

Блоки памяти

Память описывается как массив регистров. Вот синтаксис для описания такого массива:

Блоки памяти определяются при использовании объявления регистра (пример 23):

Так определяется массив из 32 слов, названный lookUpTable, где каждое слово имеет разрядность в 11 битов. Память используется в выражениях следующим образом, например,

Это запись показывает, что пятое слово в памяти lookUpTable загружено значением 75. Блоки памяти могут быть многомерными. Вот так объявляются двух- и трехмерные массивы (пример 24).

Если 8-битовый регистр а_reg уже объявлен, то запись данных в этот регистр выглядит следующим образом:

Группы битов, выбранные как часть регистра или шины, и выбор бита могут быть применены и к блокам памяти. Чтобы выбрать часть битов памяти, к ней, в конце записи, добавляется еще один индекс. Таким образом, выбор битов от бита 7 и до бита 0 из памяти threeDarray может быть записан так (пример 25):

Чтение элементов массива памяти вне диапазона, определенного для чтения, возвращает неизвестное значение — x. Запись в элементы массива памяти вне диапазона, определенного для записи, не имеет никакого эффекта. Выбрать одновременно больше чем одно слово из памяти невозможно.

Целые числа и время

Регистры используются для того, чтобы моделировать аппаратные средства. Иногда бывает полезно выполнить дополнительные вычисления в целях моделирования. Например, мы можем захотеть выключить какое-либо управление в проверяемом узле после того, как прошло определенное время при симуляции. Если мы используем регистры с этой целью, то операции на них могут быть перепутаны с действиями фактических аппаратных средств. Целые числа (Integer) и переменные времени (time) обеспечивают возможность для описания вычислений, необходимых для моделирования. Они делают описание более наглядным и самодокументируемым и облегчают сопровождение проектов. Для объявления целых чисел используется ключевое слово integer и далее идет список переменных. Объявление временито же самое, за исключением того, что используется ключевое слово time (пример 26).

Целое число обычно имеет разрядность в 32 бита. Операции с целым числом, как правило, выполняются в двоичном коде с дополнением, поэтому старший бит указывает признак знака. Переменная времени — это обычно 64-битовая переменная, используемая с системной функцией $time.

Системные задания и функции (Display and Write Tasks)

Стандартные системные задания и функции и их краткие описания приведены в таблице 17.

Таблица 17. Стандартные системные задания и функции
Стандартные системные задания и функции

Вывод на монитор

Основное системное задание — это $display (табл. 18). С его помощью можно просмотреть переменные, строки, выражения. Оно чаще всего употребляется на практике.

Таблица 18. Формат команды Display
Формат команды Display

Пример использования:

где p1, p2, p3,..., pn могут быть текстовыми строками, переменными или выражениями. Формат системного задания $display аналогичен printf в языке Cи. По умолчанию системное задание $display добавляет новую строку при выводе текста на монитор. $display без параметров используется для перехода на новую строку.

В отличие от $display, системное задание $write при выводе данных на монитор не выполняет переход на новую строку.

Инициализация памяти

Представим себе, что мы применяем в модели память. Как было уже сказано, память описывается как массив регистров. Вот синтаксис для описания массива регистров:

Как же записать данные при инициализации проекта в такую память? Системная функция $readmemb как раз и позволяет читать бинарные данные из файла и загружать эти данные в моделируемую память. Синтаксис этой функции:

где <file_name> — имя и путь к файлу, содержащему двоичные данные, параметр <reg_name> — это 2D-массив регистров, в котором хранятся данные, и, как опции, две цифры, которые указывают начальный и конечный адрес данных.

Файл инициализации может содержать только двоичные данные, пробелы и комментарии. Функцию $readmemb обычно вызывают при инициализации памяти в блоке initial. Функция $readmemh аналогична функции $readmemb, но работает с шестнадцатеричными данными.

Необходимо отметить, что если ранее программа XST, поставляемая фирмой Xilinx, не имела возможности выполнять инициализацию памяти таким образом, но теперь такая возможность уже есть. Пример, показывающий чтение двоичных данных из файла:

Кроме бинарных или шестнадцатеричных данных, пробелов и комментариев, файлы инициализации могут также содержать адресные метки:

В примере 27 показана форма записи данных в файле инициализации памяти.

Продолжение следует

Литература

  1. IEEE Standard Verilog Hardware Description Language, IEEE Computer Society, IEEE, New York, NY, IEEE Std 1364-2001.
  2. IEEE Standard Hardware Description Language Based on the Verilog Hardware Description Language, IEEE Computer Society, IEEE, New York, NY, IEEE Std 1364-1995.
  3. Bergeron J. Writing Testbenches. Functional Verification of HDL Models. Kluwer Academic Publishers, 2000.
  4. Thomas D. E., Moorby P. R. The Verilog® Hardware Description Language. Fifth Edition. Kluwer Academic Publishers, 2002.
  5. Palnitkar S. Verilog HDL: A Guide to Digital Design and Synthesis. Second Edition. Prentice Hall PTR, 2003.
  6. HDL Chip Design. Douglas Smith, 3rd edition, 1997.
  7. Madhavan R. Quick Reference for Verilog HDL. AMBIT Design Systems, Inc.
  8. Емец С. Verilog — инструмент разработки цифровых электронных схем // Схемотехника. 2001. № 1–4.
  9. Поляков А. К. Языки VHDL и VERILOG в проектировании цифровой аппаратуры. М.: Солон, 2003.
  10. Стешенко В. Б. ПЛИС фирмы ALTERA: элементная база, система проектирования и языки описания аппаратуры. М.: Додэка-ХХI, 2007.
  11. Xilinx Synthesis Technology (XST) User Guide. 1991-2000 Xilinx.
  12. Using Verilog to Create CPLD Designs. XAPP143 (v1.0) August 22, 2001.
  13. Verilog Tutorial. Deepak Kumar Tala. 2005. http://www.asic-world.com

Скачать статью в формате PDF  Скачать статью Компоненты и технологии PDF

 


Другие статьи по данной теме:

Сообщить об ошибке