Целочисленный тип данных integer и его подтипы в VHDL
В данной статье мы обсудим целочисленный тип данных integer
VHDL.
VHDL предоставляет нам несколько вариантов для типа данных объектов. Мы уже рассмотрели std_logic
, std_logic_vector
и перечисляемые типы, а в предыдущей статье обсуждалась классификация типов данных на основе пакета, который определяет этот тип. В данной статье будет продолжено обсуждение типов данных, основное внимание будет уделено целочисленному типу данных integer
.
Классификация типов данных VHDL
В предыдущей статье мы классифицировали типы данных VHDL на основе пакета, который дает определение типа. Это показано на рисунке 1.
Мы также подробно рассказали о «стандартных типах» из пакета “standard
”. В данной статье обсуждается целочисленный тип данных integer
и его подтипы.
Целочисленный тип данных integer
Мы можем использовать тип данных integer
для определения объектов, значение которых может быть целым числом. Например, следующие строки определяют сигнал sig_int
типа integer
и присваивают ему целое число 4.
signal sig_int : integer;
sig_int <= 4;
Как показано на рисунке 2, тип данных integer
относится к категории «стандартных типов», которая определена в пакете “standard
” из библиотеки “std
”. Как обсуждалось в предыдущей статье, нам не нужно явно делать пакет “standard
” и библиотеку “std
” видимыми для проекта.
Следующий код показывает простой пример, когда два входа типа integer
, in1
и in2
, складываются вместе, и результат присваивается out1
.
library IEEE;
entity IntegerTest1 is
port( in1, in2 : in integer;
out1 : out integer);
end IntegerTest1;
architecture Behavioral of IntegerTest1 is
begin
out1 <= in1 +in2;
end Behavioral;
На рисунке 3 показан результат ISE симуляции приведенного выше кода. На этом рисунке показан десятичный эквивалент значений ввода/вывода. Например, от 200 нс до 300 нс, входы in1
и in2
равны 3 и -1 соответственно. Таким образом, выход, out1
, равен 3 + (-1) = 2.
При использовании целочисленного типа данных integer
мы не принимаем непосредственного участия в определениях на уровне битов, однако ясно, что реализация для представления определенных сигналов будет использовать несколько бит. Сколько бит будет использоваться для представления целочисленных сигналов в приведенном выше коде? VHDL не указывает точное количество бит, но любая реализация VHDL должна поддерживать как минимум 32-разрядрую реализацию типа integer
. Согласно стандарту, эта 32-разрядная реализация позволяет присваивать объекту типа integer
целое число в диапазоне от -(231-1) до +(231-1).
Иногда мы имеем дело с ограниченными значениями, и для представления небольшого значения неэффективно использовать 32-разрядный сигнал. Например, предположим, что вход in1
принимает значение от 0 до 45. Таким образом, мы можем использовать 6-разрядный сигнал вместо 32-разрядного представления, потому что 4510=1011012. Более того, предположим, что другой вход, in2
, имеет значение в диапазоне от -45 до 45, поэтому должно использоваться знаковое (signed
) представление. Учитывая бит знака, нам нужно всего семь битов вместо 32 битов по умолчанию, потому что представление двух -45 равно 1010011. Чтобы добиться значительного сокращения использования ресурсов FPGA, мы можем просто указать диапазон значений сигналов, как в следующем коде:
library IEEE;
entity IntegerTest1 is
port( in1 : in integer range 0 to 45;
in2 : in integer range -45 to 45;
out1 : out integer range -45 to 90);
end IntegerTest1;
architecture Behavioral of IntegerTest1 is
begin
out1 <= in1 + in2;
end Behavioral;
Данный код предполагает, что входы in1
и in2
находятся в диапазонах от 0 до 45 и от -45 до 45 соответственно. Поскольку out1
равен in1 + in2
, диапазон out1
будет от -45 до 90. Ограничение диапазона целых чисел уменьшает объем ресурсов FPGA, необходимых для реализации проекта. Более того, это дает возможность проверить на ошибки на ранних этапах проектирования. Например, предположим, что out1
представляет собой угол, и из системных спецификаций мы знаем, что значение этого угла ограничено диапазоном от -45 до 90.
Как указано в приведенном выше коде, мы можем применить этот диапазон к определению объекта out1
. Теперь, если мы допустим ошибку, которая заставляет значение out1
находиться за пределами указанного диапазона, программное обеспечение симулятора выдаст ошибку и идентифицирует строку кода, которая включает недопустимое присваивание. Например, если мы укажем диапазон out1
как от -45 до 89, а затем присвоим значение 45 и in1
, и in2
, ISIim симулятор прекратит моделирование со следующей ошибкой (ISim – это название симулятора, который включен в программное обеспечение ISE):
ERROR: In process IntegerTest1.vhd:17
value 90 is out of valid range -45 to 89
INFO: Simulator is stopped.
(В моем коде моделирования строка 17 содержит присваивание out1 <= in1 + in2
.) Обратите внимание, что симулятор ISIM по умолчанию не отлавливает эти ошибки, связанные с диапазоном; вы должны включить опцию «value range check» (проверка диапазона значений). Если данная опция не включена, симуляция не остановится, и целому числу, объявленному с ограниченным диапазоном, сможет быть присвоено любое значение.
Обратите внимание, что указание меньшего диапазона не всегда означает, что мы можем представить сигнал меньшим количеством бит. Например, рассмотрите следующие объявления:
signal sig_int1 : integer range 0 to 7;
signal sig_int2 : integer range 6 to 7;
signal sig_int3 : integer range -8 to 7;
signal sig_int1 : integer range -8 to 0;
Первые для объявления требуют трехразрядного представления, хотя второе объявление имеет меньший диапазон. Аналогичным образом, третье и четвертое объявления должны иметь четыре бита.
Промежуточные вычисления с ограниченными целыми числами
Важно отметить, что хотя симулятор будет проверять диапазон значений, назначенных целому числу integer
, эта проверка происходит только при фактическом присваивании значения, а не во время промежуточных вычислений. Чтобы прояснить это, рассмотрим следующий код:
library IEEE;
entity IntegerTest1 is
port( in1 : in integer range 0 to 45;
in2 : in integer range -45 to 45;
out1 : out integer range -46 to 89);
end IntegerTest1;
architecture Behavioral of IntegerTest1 is
begin
out1 <= (in1 + in2) - 1;
end Behavioral;
Предположим, что in1
и in2
равны 45. В строке 9 первым будет определено in1+in2
. Таким образом, выражение внутри круглых скобок равно 90, что будет выходить за пределы диапазона, который может принимать out1
. Тем не менее, это промежуточное вычисление, и поскольку присваивание пока не задействовано, симулятор не будет проверять диапазон результата. Затем выполняется вычитание, т.е. 90-1=89. Наконец, значение 89, которое находится теперь внутри заданного диапазона, будет присвоено out1
. Ниже показана ISE симуляция для приведенного выше кода.
В принципе, промежуточные вычисления выполняются с использованием стандартного диапазона типа integer
, т.е. 32 бита. Однако, поскольку это не будет оптимальной реализацией, программное обеспечение для синтеза будет выполнять некоторые оптимизации в зависимости от характера используемых операторов. Например, если промежуточная операция состоит в том, чтобы сложить два целых числа с диапазоном от 0 до 15, результат этого промежуточного вычисления будет иметь достаточное количество бит для представления наибольшего возможного значения, которое равно 30.
Предопределенные подтипы integer
Подтип данного типа ограничивает диапазон типа. Как показано на рисунке 2, "integer
" имеет два предопределенных подтипа:
subtype natural is integer range 0 to integer'high;
subtype positive is integer range 1 to integer'high;
Значение integer’high
представляет наибольшее значение целого числа. Подтип “natural
” (натуральный) создает сигнал, который может принимать все неотрицательные целые числа (т.е. 0, 1, 2, 3, ...), а подтип “positive
” (положительный) создает сигнал, который может принимать все положительные целые числа (1, 2, 3, ...). Хотя эта реализация последовательна в контексте VHDL, имейте в виду, что математическое сообщество не соглашается с тем, включен ли ноль в набор натуральных чисел.
Резюме
- Целочисленный тип данных
integer
и его подтипы определены в пакете “standard
” из библиотеки “std
”. Типinteger
используется для определения объектов, значения которых всегда являются целым числом. - VHDL не указывает точное количество бит для целого числа, но любая реализация VHDL должна поддерживать как минимум 32-разрядную реализацию.
- Мы можем указать диапазон значений, который будет иметь объект типа
integer
. - Ограничение диапазона уменьшает количество ресурсов FPGA, необходимых для реализации проекта. Более того, это дает нам возможность отловить ошибки на ранних этапах проектирования.
- Симулятор ISIM по умолчанию не отлавливает ошибки, связанные с диапазоном; вы должны включить опцию «value range check» (проверка диапазона значений).
- Данная проверка выполняется только при присваивании значения, а не во время промежуточных вычислений.