Вопрос или проблема
как вы заполняете 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, пожалуйста, не стесняйтесь обращаться.