redpitaya-puzzlefw/fpga/rtl/shift_engine.vhd

91 lines
2.3 KiB
VHDL

--
-- Signed or unsigned variable right-shift.
--
-- Joris van Rantwijk 2024
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity shift_engine is
generic (
-- Input word length.
input_data_bits: integer range 4 to 64;
-- Output word length.
output_data_bits: integer range 4 to 64;
-- Number of bit positions to pre-shift left before shifting right.
pre_shift_left: integer range 0 to 16;
-- True to apply sign extension when shifting.
-- False to apply zero extension.
signed_data: boolean
);
port (
-- Main clock, active on rising edge.
clk: in std_logic;
-- Data input operand.
-- A new input word is accepted on every clock cycle.
in_data: in std_logic_vector(input_data_bits - 1 downto 0);
-- Shift input operand.
-- It indicates the number of bit positions to shift right, expressed
-- as an unsigned integer in range 0 to 15.
-- A new input word is accepted on every clock cycle.
in_shift: in std_logic_vector(3 downto 0);
-- Shifted output data.
-- The output corresponds to the input delayed by 1 clock cycle.
out_data: out std_logic_vector(output_data_bits - 1 downto 0)
);
end entity;
architecture arch of shift_engine is
-- Output register.
signal r_data: std_logic_vector(output_data_bits - 1 downto 0);
begin
-- Drive output.
out_data <= r_data;
--
-- Synchronous process.
--
process (clk) is
begin
if rising_edge(clk) then
if signed_data then
r_data <= std_logic_vector(
shift_right(
shift_left(
resize(signed(in_data), output_data_bits),
pre_shift_left),
to_integer(unsigned(in_shift))));
else
r_data <= std_logic_vector(
shift_right(
shift_left(
resize(unsigned(in_data), output_data_bits),
pre_shift_left),
to_integer(unsigned(in_shift))));
end if;
end if;
end process;
end architecture;