У меня есть вектор signal tmp : std_logic_vector(15 downto 0)
Мне нужно сдвинуть его влево или вправо от n бит. как я могу реализовать эту операцию. Я думал о операции конкатенации, но я не знал, как это использовать.
У меня есть вектор signal tmp : std_logic_vector(15 downto 0)
Мне нужно сдвинуть его влево или вправо от n бит. как я могу реализовать эту операцию. Я думал о операции конкатенации, но я не знал, как это использовать.
Используйте библиотеку ieee.numeric_std
и соответствующий векторный тип для чисел, над которыми вы работаете (unsigned
или signed
).
Тогда операторы sla
/sra
для арифметических сдвигов (т.е. заполняют знаковым битом в сдвигах справа и lsb в левых сдвигах) и sll
/srl
для логических сдвигов (т.е. заполняют с помощью 0).
Вы передаете параметр оператору для определения количества сдвигатых битов:
A <= B srl 2; -- logical shift right 2 bits
Я понятия не имею, что я пишу выше (спасибо Валу за то, что указали это!)
Конечно, правильный способ смены типов signed
и unsigned
- с функциями shift_left
и shift_right
, определенными в ieee.numeric_std
.
Операторы сдвига и поворота sll
, ror
и т.д. предназначены для векторов boolean
, bit
или std_ulogic
, и может иметь интересное неожиданное поведение в том, что арифметические сдвиги дублируют конечный бит даже при сдвиге влево.
И многое другое можно найти здесь:
http://jdebp.eu./FGA/bit-shifts-in-vhdl.html
Однако ответ на исходный вопрос по-прежнему
sig <= tmp sll number_of_bits;
Есть два способа добиться этого. Конкатенация и функции сдвига/поворота.
Конкатенация - это "ручной" способ делать вещи. Вы указываете, какую часть исходного сигнала вы хотите "сохранить", а затем конкатенацию данных на одном конце или другом. Например: tmp <= tmp (14 до 0) и '0';
Функции сдвига (логические, арифметические): это общие функции, которые позволяют вам перемещать или поворачивать вектор разными способами. Функции: sll (сдвиг влево логический), srl (сдвиг вправо логический). Логический сдвиг вставляет нули. Арифметические сдвиги (sra/sla) вставляют левый самый или самый правый бит, но работают так же, как логический сдвиг. Обратите внимание, что для всех этих операций вы указываете, что вы хотите сдвинуть (tmp), и сколько раз вы хотите выполнить сдвиг (n бит)
Поворот функций: rol (вращение влево), ror (поворот вправо). Вращение делает именно это, MSB попадает в LSB, и все сдвигается влево (ролл) или наоборот для ror.
Вот полезная ссылка, которую я нашел (см. первую страницу).
Лично я считаю, что конкатенация - лучшее решение. Общая реализация была бы
entity shifter is
generic (
REGSIZE : integer := 8);
port(
clk : in str_logic;
Data_in : in std_logic;
Data_out : out std_logic(REGSIZE-1 downto 0);
end shifter ;
architecture bhv of shifter is
signal shift_reg : std_logic_vector(REGSIZE-1 downto 0) := (others<='0');
begin
process (clk) begin
if rising_edge(clk) then
shift_reg <= shift_reg(REGSIZE-2 downto 0) & Data_in;
end if;
end process;
end bhv;
Data_out <= shift_reg;
Оба будут реализованы как сдвиговые регистры. Если вам нужно больше регистров сдвига, чем вы готовы тратить ресурсы (EG делит 1000 номеров на 4), вы можете использовать BRAM для хранения значений и одного регистра сдвига, чтобы содержать "индексы", которые приводят к правильный сдвиг всех чисел.
Я бы не предлагал использовать sll
или srl
с помощью std_logic_vector.
Во время моделирования sll
дал мне значение "U" для этих битов, где я ожидал 0.
Используйте функции shift_left()
, shift_right()
.
Например:
OP1 : in std_logic_vector(7 downto 0);
signal accum: std_logic_vector(7 downto 0);
accum <= std_logic_vector(shift_left(unsigned(accum), to_integer(unsigned(OP1))));
accum <= std_logic_vector(shift_right(unsigned(accum), to_integer(unsigned(OP1))));
Обычно это делается вручную, выбирая соответствующие биты из вектора, а затем добавляя 0s.
Например, чтобы сдвинуть вектор 8 бит
variable tmp : std_logic_vector(15 downto 0)
...
tmp := x"00" & tmp(15 downto 8);
Надеюсь, этот простой ответ полезен кому-то.
add_Pbl <= to_stdlogicvector(to_bitvector(dato_cu(25 downto 2)) sll 1);
add_Pbl is a std_logic_vector of 24 bit
dato_cu is a std_logic_vector of 32 bit
Сначала вам нужно преобразовать функцию std_logic_vector
с помощью функции to_bitvector()
потому что инструкция sll работает с логическими 1 и 0 битами.