Типы данных VHDL: некоторые классификации и перечисляемый тип

Добавлено 10 ноября 2018 в 22:59

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

VHDL предоставляет нам несколько вариантов для типа данных объектов. В предыдущих статьях мы рассмотрели типы std_logic и std_logic_vector. В данной статье сначала будут рассмотрены классификации типов данных VHDL, а затем будет рассмотрен перечисляемый тип.

Классификация типов данных VHDL

Классификация типов данных VHDL помогает лучше понять эту тему. Общий метод классификации показан на рисунке 1.

Рисунок 1 – Каждая группа типов данных VHDL (показана оранжевым цветом) определяется в VHDL пакете (показан синим цветом)
Рисунок 1 – Каждая группа типов данных VHDL (показана оранжевым цветом) определяется в VHDL пакете (показан синим цветом)

На этом рисунке классификация типов данных основана на пакете, который определяет тип. VHDL пакеты показаны на рисунке синим цветом. Каждый из этих пакетов включает определение некоторых типов данных VHDL (которые показаны оранжевым цветом).

Например, типы данных “std_logic” и “std_logic_vector” являются “standard_logic типами”. Как показано на рисунке 1, эти типы берутся из пакета “std_logic_1164”. Ранее мы видели, что для использования типов данных “std_logic” и “std_logic_vector” нам в своем коде нужно включить пакет “std_logic_1164” из библиотеки “ieee”. То есть требуются следующие строки кода.

library ieee;
use ieee.std_logic_1164.all

Аналогично перед использованием любого другого типа данных нам нужно сделать соответствующий пакет видимым для кода. В данной статье будут рассмотрены перечисляемые типы данных. Существует несколько предопределенных перечисляемых типов в категории «стандартных типов» из пакета “standard”. Данный пакет включен в VHDL библиотеку “std”. Поэтому, чтобы использовать «стандартные типы», мы должны сделать библиотеку “std” и пакет “standard” видимыми для проекта:

library std;
use std.standard.all

Однако, поскольку вышеупомянутая библиотека и пакет используются часто, они добавляются в код по умолчанию. Следовательно, нет необходимости явно включать приведенные выше операторы в наш код. Теперь давайте рассмотрим секцию «стандартных типов» на рисунке 1 более подробно.

Стандартные типы

В этой категории есть несколько типов данных. Они показаны на рисунке 2 ниже.

Рисунок 2 – Различные типы данных в категории «стандартных типов»
Рисунок 2 – Различные типы данных в категории «стандартных типов»

Как показано на этом рисунке, некоторые из этих типов могут быть сгруппированы вместе. Например, типы “boolean”, “bit”, “character” и “severity_level” могут быть сгруппированы как «перечисляемые типы» и так далее. В данной статье будут объяснены и приведены примеры для типа данных перечисление, а в будущих статьях мы продолжим обсуждение типов данных, показанных на рисунке 2.

Перечисляемые типы

Перечисляемые типы данных лучше всего объяснить с помощью примера. Предположим, что вы разрабатываете цифровую систему, которая может находиться в одном из трех следующих состояний: инициализация, работа и ожидание. В каждом из этих состояний система выполняет определенные операции. Например, в состоянии инициализации система может обновлять свои входы. В рабочем состоянии она может выполнять некоторые арифметические операции. В режиме ожидания она может перейти в режим с низким энергопотреблением. Нам всё равно, какое условие переводит систему из одного состояния в другое. Для нас важно, как представить это состояние системы. Один из способов может представлять состояние системы с использованием двухбитового сигнала, например, st_x. Сигнал st_x может быть определен в VHDL как двухэлементный тип данных “std_logic_vector”. Мы можем рассматривать каждое состояние этого сигнал как код для состояния системы; например:

st_x(1)st_x(0)Состояние системы
00Инициализация
01Работа
10Ожидание

Мы можем постоянно проверять st_x и выполнять требуемые операции на основе состояния системы, которое закодировано в значение st_x. Например, предположим, что в рабочем состоянии предполагается, что система выполняет логическую операцию И с входами значениями a1 и a2 и назначает результат выходу out1. Однако в двух других состояниях out1 должен быть равен третьему входу под названием a3. Следующий код может использоваться для описания поведения выхода out1 (более подробную информацию о параллельных присваиваниях смотрите в этой статье).

with st_x select
    out1 <= (a1 and a2) when "01",
             a3 when others;

Проблема этого метода заключается в том, что нам нужно помнить, какой код используется для представления каждого состояния системы. Это увеличивает вероятность ошибки. Что, если бы мы могли использовать слова вместо строки из единиц и нулей для представления состояний системы в нашем коде? Слова имеют для нас гораздо большее значение, чем нули и единицы. Фактически это то, что может сделать VHDL тип данных перечисления.

Перечисляемый тип данных может использоваться для определения сигнала, который имеет слова в качестве своих значений. Например, мы можем определить st_x как сигнал, который может принимать три значения: “st_initializing”, “st_operating” и “st_idle”. (Вы могли бы использовать другие слова, но, конечно, вы хотели бы выбрать идентификаторы, которые делают код более чистым и интуитивно понятным.) Однако нам нужно сначала определить тип данных, прежде чем мы определим сигнал этого типа. Логическим выбором для имени этого типа данных будет “sys_state”. Сигналы этого типа данных могут принимать три значения: “st_initializing”, “st_operating” и “st_idle”. Следующий код может использоваться для определения этого нового типа данных:

type sys_state is (st_initializing, st_operating, st_idle);

Как вы можете видеть, имя типа данных, “sys_state”, идет с ключевыми словами “type” и “is”. Значения, определенные для этого типа данных, заключены в круглые скобки. Это называется типом данных перечисления, потому что значения перечислены в списке. Теперь мы можем определить сигнал st_x типа “sys_state”.

signal st_x : sys_state;

Обратите внимание, что st_x может принимать только значения, определенные для типа “sys_state”. Теперь, когда у нас есть этот перечисляемый тип данных, следующий код может использоваться для описания поведения выхода out1 в приведенном выше примере.

with st_x select
    out1 <= (a1 and a2) when st_operating,
             a3 when others;

На рисунок 3 показана симуляция Xilinx ISE для приведенного выше присваивания “with/select”. Как вы можете видеть, от 200 нс до 400 нс сигнал st_x равен “st_operating” и, следовательно, out1 равен a1 И a2. Для других значений st_x выход соответствует значению a3.

Рисунок 3 – Результаты симуляции
Рисунок 3 – Результаты симуляции

Подобно тому, что мы делаем с другими типами данных, мы можем использовать оператор присваивания для назначения значений сигналу st_x. Например, чтобы присвоить st_x значение “st_initializing”, мы можем написать:

st_x <= st_initializing;

Несколько перечисляемых типов, имеющих общее значение

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

type sys_stateA is (st_initializing, st_operating, st_idle);
type sys_stateB is (st_multiply, st_add, st_idle);
signal st_xA : sys_stateA;
signal st_xB : sys_stateB;

Как вы можете видеть, буквальное значение “st_idle” является общим для двух типов («буквальное» относится к значению, которое вставляется разработчиком непосредственно в код VHDL). Однако VHDL считает это приемлемым, потому что мы имеем дело с двумя разными типами данных: “sys_stateA” и “sys_stateB”. Если мы назначаем "st_idle" сигналам st_xA и st_xB, используемый тип данных дает понять, что означает "st_idle". Следовательно, оба следующих присваивания будут корректными:

st_xA <= st_idle;
st_xB <= st_idle;

Начальное значение перечисляемых типов

Самый левый элемент списка перечисления будет считаться значением по умолчанию, то есть начальным значением, присвоенным объектам этого типа. Например, значение по умолчанию st_xA и st_xB будут "st_initializing" и "st_multiply" соответственно.

Перечисление символов

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

type char_enum is (‘c’, ‘z’, ‘1’);

Как показано на рисунке 2, типы “boolean”, “bit” и “character” являются предопределенными перечисляемыми типами. Тип “bit” кратко обсуждался в предыдущей статье. Этот тип может принимать либо символ ‘0’, либо ‘1’. Ниже приведены определения типов для предопределенных типов данных "bit" и "boolean".

type bit is (‘0’, ‘1’);
type boolean is (false, true);

Резюме

  • Одним из распространенных способов классификации типов данных VHDL является классификация, основанная на пакете, который определяют тип.
  • Поскольку библиотека “std” и пакет “standard” используются часто, они добавляются в код по умолчанию. Следовательно, нет необходимости явно делать их для проекта видимыми.
  • Типы “boolean”, “bit”, “character” и “severity_level” являются перечисляемыми типами, доступными в пакете “standard”.
  • Вместо использования кодирования на уровне битов, мы можем использовать перечисляемые типы данных для описания проекта на более абстрактном уровне.
  • Возможно иметь общие значения между двумя различными определяемыми пользователем перечисляемыми типами данных.
  • Самый левый элемент списка перечисления – это значение по умолчанию, присваиваемое объектам перечисляемого типа данных.

Теги

CPLDFPGAHDL (язык описания аппаратуры)VHDLXilinx ISEПеречислениеПеречисляемые типы данныхПрограммируемая логикаТипы данных VHDL

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.