дополнение std_logic_vector нулями

Вопрос или проблема

как вы заполняете std_logic_vector нулями, потому что у меня возникла проблема с этим в modelsim для выполнения некоторых расчетов с фиксированной точкой

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;

entity lab91 is
    Port ( clk : in STD_LOGIC;
           x1 : in STD_LOGIC_VECTOR (15 downto 0); -- (1,16,8)
           x2 : in STD_LOGIC_VECTOR (7 downto 0);  -- (1,8,12)
           dout : out STD_LOGIC_VECTOR (20 downto 0)); -- (1,17,3) выход
end lab91;

architecture Behavioral of lab91 is
        signal original_resized : STD_LOGIC_VECTOR(19 downto 0);
        signal x1_sg : SIGNED(19 downto 0);
        signal x2_sg : SIGNED(7 downto 0);
        signal result : SIGNED(20 downto 0); -- Результат с потенциальным переполнением


begin
    process(clk)
    begin
        if rising_edge(clk) then
            original_resized <= (x1(15), x1(14), x1(13), x1(12), x1(11), x1(10), x1(9), x1(8), x1(7), x1(6), x1(5), x1(4), x1(3), x1(2), x1(1), x1(0), others=>'0'); --после сдвига dp и всего остального

            x1_sg <= SIGNED(original_resized);
            x2_sg <= SIGNED(x2);  

            -- Сложите два числа
            result <= resize((x1_sg + x2_sg),21);

            -- Присвоить результат выходу с обработкой переполнения
            dout <= STD_LOGIC_VECTOR(result);
        end if;
    end process;
end Behavioral;

у меня есть 16-битный вход и я хочу расширить это до 20 с 4 нулями сзади, как x1 + 0000

Я пробовал resize(signed(x1),20), это не сработало
Я теперь попробовал создать вектор сам без преобразования в signed
X(15) … x(1) x(0) & “0000”, это не сработало

В ОБОИХ СЛУЧАЯХ Я ЗАМЕТИЛ НЕКОТОРОЕ СТРАННОЕ
X1 => 1010110000110111
extendedx1 => 10101011000011010000
ЧЕГО Я ОЖИДАЛ (10101100001101110000)

ОБРАТИТЕ ВНИМАНИЕ на оба вектора, почти как будто сказать, что X1 сначала был сдвинут вправо, теряя LSB, а затем заполнен нулями. Это не то, чего я хотел

Ответ или решение

Пэддинг std_logic_vector нулями в VHDL

При работе с фиксированной арифметикой в VHDL, одной из распространённых задач является расширение вектора из std_logic_vector, добавляя нули. Вы уже отметили, что сталкиваетесь с проблемами при попытке дополнить ваш 16-битный сигнал x1 до 20 бит с добавлением нулей с конца. Давайте подробно рассмотрим, как правильно выполнить эту операцию.

Основная проблема

Как вы заметили, при прибавлении 0000 к вектору x1 происходит нежелательная «потеря» значений. Это связано с неправильной интерпретацией операции или с ее порядком применения. Вы ожидали, что ваш расширенный вектор будет выглядеть как 10101100001101110000, однако получили результат 10101011000011010000. Это может произойти в результате применения операций, которые не учитывают порядок бит.

Решение проблемы

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

Вот корректированный вариант вашего кода для расширения 16-битного x1 до 20 бит, добавляя 4 нуля:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity lab91 is
    Port ( clk : in STD_LOGIC;
           x1 : in STD_LOGIC_VECTOR (15 downto 0); -- (1,16,8)
           x2 : in STD_LOGIC_VECTOR (7 downto 0);  -- (1,8,12)
           dout : out STD_LOGIC_VECTOR (20 downto 0)); -- (1,17,3) output
end lab91;

architecture Behavioral of lab91 is
    signal original_resized : STD_LOGIC_VECTOR(19 downto 0);
    signal x1_sg : SIGNED(19 downto 0);
    signal x2_sg : SIGNED(7 downto 0);
    signal result : SIGNED(20 downto 0); -- Result with potential overflow
begin
    process(clk)
    begin
        if rising_edge(clk) then
            original_resized <= x1 & "0000"; -- Конкатенация x1 и 4 нулей

            x1_sg <= SIGNED(original_resized);
            x2_sg <= SIGNED(x2);  

            -- Сложение двух чисел
            result <= resize((x1_sg + x2_sg), 21);

            -- Присваивание результата на выход с проверкой переполнения
            dout <= STD_LOGIC_VECTOR(result);
        end if;
    end process;
end Behavioral;

Объяснение изменений

  • Конкатенация: Использование original_resized <= x1 & "0000"; эффективно берет весь исходный 16-битный вектор x1 и добавляет к нему 4 нуля на конце.
  • Сохранение размера: Это гарантирует, что значения сохраняются в порядке наибольшего значимого бита к наименьшему, что нужно для выполнения дальнейших арифметических операций над ними.
  • Типы данных: Обратите внимание на преобразование x1_sg <= SIGNED(original_resized);. Теперь original_resized всегда будет корректным 20-битным значением с нулями в конце.

Заключение

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

Если у вас есть какие-либо дополнительные вопросы или вам нужна помощь в других аспектах VHDL, пожалуйста, не стесняйтесь обращаться.

Оцените материал
Добавить комментарий

Капча загружается...