Кусково-линейная аппроксимация логистической ф-ции. Множители подобраны из степеней двойки, из операций только сдвиг и сумма.
Y=kx+b; b-массив из 9 значений.
Схема алгоритма:

Код алгоритма
CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.math_real.all;
entity logistic is
generic ( FRAC_WIDTH: integer := 13;
DATA_WIDTH :integer :=18);
Port (
CLK: in STD_LOGIC;
DIN : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
DOUT : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0));
end logistic;
architecture Behavioral of logistic is -- Ax+b;
type i_bound_t is array (0 to 8) of std_logic_vector(DATA_WIDTH-1 downto 0);
constant boundary: i_bound_t:=(
std_logic_vector(to_signed(integer(real(7.236)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(5.846)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(5.147)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(4.442)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(3.724)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(2.977)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(2.164)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(1.065)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(0)*real(2**FRAC_WIDTH)),DATA_WIDTH))
);
constant B: i_bound_t:=(
std_logic_vector(to_signed(integer(real(7.236)*real(2**FRAC_WIDTH)),DATA_WIDTH))
,
std_logic_vector(to_signed(integer(real(0.984375)*real(2**FRAC_WIDTH)),DATA_WIDT
H)),
std_logic_vector(to_signed(integer(real(0.97265625)*real(2**FRAC_WIDTH)),DATA_WI
DTH)),
std_logic_vector(to_signed(integer(real(0.953125)*real(2**FRAC_WIDTH)),DATA_WIDT
H)),
std_logic_vector(to_signed(integer(real(0.91796875)*real(2**FRAC_WIDTH)),DATA_WI
DTH)),
std_logic_vector(to_signed(integer(real(0.859375)*real(2**FRAC_WIDTH)),DATA_WIDT
H)),
std_logic_vector(to_signed(integer(real(0.765625)*real(2**FRAC_WIDTH)),DATA_WIDT
H)),
std_logic_vector(to_signed(integer(real(0.6328125)*real(2**FRAC_WIDTH)),DATA_WID
TH)),
std_logic_vector(to_signed(integer(real(0.5)*real(2**FRAC_WIDTH)),DATA_WIDTH))
);
signal X_abs:std_logic_vector(DATA_WIDTH-1 downto 0);
signal X_shifted:std_logic_vector(DATA_WIDTH-1 downto 0);
signal Y_abs:std_logic_vector(DATA_WIDTH-1 downto 0);
signal sDIN,ssDIN:std_logic; -- pipeline sign
begin
process(CLK)
begin
if(rising_edge(CLK)) then
X_abs<=std_logic_vector(abs(signed(DIN)));
sDIN<=DIN(DATA_WIDTH-1);
ssDIN<=sDIN;
if(X_abs>boundary(0)) then
Y_abs<=std_logic_vector(to_signed(integer(2**FRAC_WIDTH),DOUT'length));
elsif X_abs>boundary(1) then
-- X_shifted<=std_logic_vector(signed(X_abs) srl 9);
Y_abs<=std_logic_vector((signed(X_abs) srl 9)+signed(B(1)));
elsif X_abs>boundary(2) then
-- X_shifted<=std_logic_vector(signed(X_abs) srl 8);
Y_abs<=std_logic_vector((signed(X_abs) srl 8)+signed(B(2)));
elsif X_abs>boundary(3) then
-- X_shifted<=std_logic_vector(signed(X_abs) srl 7);
Y_abs<=std_logic_vector((signed(X_abs) srl 7)+signed(B(3)));
elsif X_abs>boundary(4) then
-- X_shifted<=std_logic_vector(signed(X_abs) srl 6);
Y_abs<=std_logic_vector((signed(X_abs) srl 6)+signed(B(4)));
elsif X_abs>boundary(5) then
-- X_shifted<=std_logic_vector(signed(X_abs) srl 5);
Y_abs<=std_logic_vector((signed(X_abs) srl 5)+signed(B(5)));
elsif X_abs>boundary(6) then
-- X_shifted<=std_logic_vector(signed(X_abs) srl 4);
Y_abs<=std_logic_vector((signed(X_abs) srl 4)+signed(B(6)));
elsif X_abs>boundary(7) then
-- X_shifted<=std_logic_vector(signed(X_abs) srl 3);
Y_abs<=std_logic_vector((signed(X_abs) srl 3)+signed(B(7)));
else
-- X_shifted<=std_logic_vector(signed(X_abs) srl 2);
Y_abs<=std_logic_vector((signed(X_abs) srl 2)+signed(B(8)));
end if;
if((ssDIN)='1') then -- negative number
DOUT<=std_logic_vector(to_signed(integer(2**FRAC_WIDTH),DOUT'length)-signed(Y_abs));
else
DOUT<=Y_abs;
end if;
end if;
end process;
end Behavioral;
Цель: 6 и 7 Виртексы изначально. Синтез показывает 280 МГц. Если сделать сдвиг и сумму отдельно (сначала вычислять X_shifted, потом суммировать с Y_abs), скорость возрастает до 293 МГц. Неужели такую простую арифметику нельзя ускорить? Наверняка я где-то накосячил. Длина конвеера не особо критична, но должна быть одинакова для любых значений Х.