Как использовать Signed и Unsigned в VHDL
Типы со знаком и без знака в VHDL являются битовыми векторами, как и тип std_logic_vector. Разница в том, что хотя std_logic_vector отлично подходит для реализации шин данных, он бесполезен для выполнения арифметических операций.
Если вы попытаетесь добавить любое число к типу std_logic_vector, ModelSim выдаст ошибку компиляции:Нет допустимых записей для инфиксного оператора «+». Это потому, что компилятор не знает, как интерпретировать этот набор битов, которым является вектор.
Эта запись в блоге является частью серии учебных пособий по основам VHDL.
Мы должны объявить наш вектор как знаковый или беззнаковый, чтобы компилятор обработал его как число.
Синтаксис для объявления сигналов со знаком и без знака:signal <name> : signed(<N-bits> downto 0) := <initial_value>;
signal <name> : unsigned(<N-bits> downto 0) := <initial_value>;
Как и в случае со std_logic_vector, диапазоны могут быть to
. или downto
любой диапазон. Но объявление сигналов с диапазонами, отличными от downto 0
настолько необычна, что тратить больше времени на эту тему только запутает нас. Начальное значение является необязательным, по умолчанию это 'U'
для всех битов.
Мы уже использовали integer
тип для арифметических операций в предыдущих руководствах. Итак, зачем нам нужны подписанные и беззнаковые типы? Большинство цифровых дизайнеров предпочитают иметь больше контроля над тем, сколько битов на самом деле использует сигнал.
Кроме того, значения со знаком и без знака переносятся, а симулятор выдает ошибку времени выполнения, если integer
увеличивается до бесконечности. Наконец, у подписанных и неподписанных могут быть другие значения, такие как 'U'
. и 'X'
, тогда как целые числа могут иметь только числовые значения. Эти мета-значения могут помочь нам обнаружить ошибки в нашем дизайне.
Упражнение
В этом видео мы узнаем, как подписанные и неподписанные сигналы ведут себя одинаково и чем они отличаются:
Окончательный код, который мы создали в этом руководстве:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T12_SignedUnsignedTb is end entity; architecture sim of T12_SignedUnsignedTb is signal UnsCnt : unsigned(7 downto 0) := (others => '0'); signal SigCnt : signed(7 downto 0) := (others => '0'); signal Uns4 : unsigned(3 downto 0) := "1000"; signal Sig4 : signed(3 downto 0) := "1000"; signal Uns8 : unsigned(7 downto 0) := (others => '0'); signal Sig8 : signed(7 downto 0) := (others => '0'); begin process is begin wait for 10 ns; -- Wrapping counter UnsCnt <= UnsCnt + 1; SigCnt <= SigCnt + 1; -- Adding signals Uns8 <= Uns8 + Uns4; Sig8 <= Sig8 + Sig4; end process; end architecture;
Окно осциллограммы в ModelSim, увеличенные интересные части:
Анализ
Основание всех сигналов в форме сигнала установлено в шестнадцатеричном формате, чтобы мы могли сравнивать их одинаково.
В примере с оборачивающим счетчиком мы видим, что сигналы со знаком и без знака ведут себя совершенно одинаково. Оба UnsCnt
и SigCnt
начинаются с 0 и увеличиваются один за другим до FF. Hex FF (десятичное число 255) — это наибольшее значение, которое могут содержать наши 8-битные сигналы. Следовательно, следующее приращение возвращает их оба обратно к 0.
Мы создали два 4-битных сигнала Uns4
и Sig4
, и дал им обоим начальное значение «1000». Из формы волны видно, что они оба просто шестнадцатеричные 8 (двоичные 1000).
Последние два 8-битных сигнала, которые мы создали, были Uns8
. и Sig8
. Из формы волны видно, что их начальные значения равны 0, как и следовало ожидать. Но оттуда они ведут себя по-другому! По-видимому, знаковые и беззнаковые типы имеют значение при добавлении двух сигналов разной длины.
Это связано с так называемым расширением знака. . Сложение положительных или отрицательных чисел, хранящихся в векторах одинаковой длины, является той же операцией в цифровой логике. Это из-за того, как работает дополнение до двух. Если векторы имеют разную длину, самый короткий вектор придется удлинить.
Беззнаковое 4-битное двоичное число «1000» представляет собой десятичное число 8, а знаковое 4-битное число «1000» представляет собой десятичное число -8. «1» в крайнем левом месте числа со знаком указывает на то, что это отрицательное число. Таким образом, два 4-битных сигнала расширяются компилятором по-разному.
Это визуализация того, как расширение знака создает разные значения для Uns8
. и Sig8
сигналы:
Вывод
- Сигналы со знаком и без знака — это векторы, которые можно использовать в арифметических операциях.
- Сигналы подписанного и неподписанного типа будут автоматически переполняться
- Расширение Sign может создавать разные результаты для подписанных и неподписанных типов
Перейти к следующему руководству »
VHDL
- Подписанный и неподписанный в VHDL
- Как использовать процедуру в процессе в VHDL
- Как использовать нечистую функцию в VHDL
- Как использовать функцию в VHDL
- Как использовать процедуру в VHDL
- Как использовать константы и общую карту в VHDL
- Как использовать создание экземпляра карты портов в VHDL
- Как бесплатно установить симулятор и редактор VHDL
- Микроконтроллер PIC18:что это такое и как его использовать
- Что такое позиционное обозначение и как мы его используем в ассемблере?