Перейти к содержанию
    

Реализация БПФ на ПЛИС

Попробовал, но не могу проверить (Quartus сломался) и не знаю, вообще так это делается или нет. Вот код:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity butterfly_complex is
    generic (b_size: natural := 16);
    
    port(CLK: in std_logic; 
         x1_re: in std_logic_vector(b_size - 1 downto 0);
         x1_im: in std_logic_vector(b_size - 1 downto 0);
         x2_re: in std_logic_vector(b_size - 1 downto 0);
         x2_im: in std_logic_vector(b_size - 1 downto 0);
         x3_re: in std_logic_vector(b_size - 1 downto 0);
         x3_im: in std_logic_vector(b_size - 1 downto 0);
         x4_re: in std_logic_vector(b_size - 1 downto 0);
         x4_im: in std_logic_vector(b_size - 1 downto 0);         
        
         y1_re: out std_logic_vector(b_size - 1 downto 0);
         y1_im: out std_logic_vector(b_size - 1 downto 0);
         y2_re: out std_logic_vector(b_size - 1 downto 0);
         y2_im: out std_logic_vector(b_size - 1 downto 0);
         y3_re: out std_logic_vector(b_size - 1 downto 0);
         y3_im: out std_logic_vector(b_size - 1 downto 0);
         y4_re: out std_logic_vector(b_size - 1 downto 0);
         y4_im: out std_logic_vector(b_size - 1 downto 0)        
        );
end entity butterfly_complex;


architecture beh_butter of butterfly_complex is
-- Сигналы для конвертации типов std_logic -> signed:
signal x1_re_sig : signed(b_size + 2 downto 0);
signal x1_im_sig : signed(b_size + 2 downto 0);
signal x2_re_sig : signed(b_size + 2 downto 0);
signal x2_im_sig : signed(b_size + 2 downto 0);
signal x3_re_sig : signed(b_size + 2 downto 0);
signal x3_im_sig : signed(b_size + 2 downto 0);
signal x4_re_sig : signed(b_size + 2 downto 0);
signal x4_im_sig : signed(b_size + 2 downto 0);

signal y1_re_sum : signed(b_size + 2 downto 0);
signal y1_im_sum : signed(b_size + 2 downto 0);
signal y2_re_sum : signed(b_size + 2 downto 0);
signal y2_im_sum : signed(b_size + 2 downto 0);
signal y3_re_sum : signed(b_size + 2 downto 0);
signal y3_im_sum : signed(b_size + 2 downto 0);
signal y4_re_sum : signed(b_size + 2 downto 0);
signal y4_im_sum : signed(b_size + 2 downto 0);

signal y1_re_sig : signed(b_size - 1 downto 0);
signal y1_im_sig : signed(b_size - 1 downto 0);
signal y2_re_sig : signed(b_size - 1 downto 0);
signal y2_im_sig : signed(b_size - 1 downto 0);
signal y3_re_sig : signed(b_size - 1 downto 0);
signal y3_im_sig : signed(b_size - 1 downto 0);
signal y4_re_sig : signed(b_size - 1 downto 0);
signal y4_im_sig : signed(b_size - 1 downto 0);

begin
        x1_re_sig <= resize(SIGNED(x1_re), b_size + 3);
        x1_im_sig <= resize(SIGNED(x1_im), b_size + 3);
        x2_re_sig <= resize(SIGNED(x2_re), b_size + 3);
        x2_im_sig <= resize(SIGNED(x2_im), b_size + 3);
        x3_re_sig <= resize(SIGNED(x3_re), b_size + 3);
        x3_im_sig <= resize(SIGNED(x3_im), b_size + 3);
        x4_re_sig <= resize(SIGNED(x4_re), b_size + 3);
        x4_im_sig <= resize(SIGNED(x4_im), b_size + 3);
        
        -- Вычисление y1_re:
        y1_re_sum <= x1_re_sig + x2_re_sig + x3_re_sig + x4_re_sig + "0000000000000000100";
        
        -- Вычисление y1_im:
        y1_im_sum <= x1_im_sig + x2_im_sig + x3_im_sig + x4_im_sig + "0000000000000000100";

        -- Вычисление y2_re:
        y2_re_sum <= x1_re_sig + x2_im_sig - x3_re_sig - x4_im_sig + "0000000000000000100";

        -- Вычисление y2_im:
        y2_im_sum <= x1_im_sig - x2_re_sig - x3_im_sig + x4_re_sig + "0000000000000000100";

        -- Вычисление y3_re:
        y3_re_sum <= x1_re_sig - x2_re_sig + x3_re_sig - x4_re_sig + "0000000000000000100";

        -- Вычисление y3_im:
        y3_im_sum <= x1_im_sig - x2_im_sig + x3_im_sig - x4_im_sig + "0000000000000000100";

        -- Вычисление y4_re:
        y4_re_sum <= x1_re_sig - x2_im_sig - x3_re_sig + x4_im_sig + "0000000000000000100";

        -- Вычисление y4_im:
        y4_im_sum <= x1_im_sig + x2_re_sig - x3_im_sig - x4_re_sig + "0000000000000000100";
        
        y1_re_sig(b_size - 1 downto 0) <= y1_re_sum(b_size + 2 downto 3);
        y1_im_sig(b_size - 1 downto 0) <= y1_im_sum(b_size + 2 downto 3);
        y2_re_sig(b_size - 1 downto 0) <= y2_re_sum(b_size + 2 downto 3);
        y2_im_sig(b_size - 1 downto 0) <= y2_im_sum(b_size + 2 downto 3);
        y3_re_sig(b_size - 1 downto 0) <= y3_re_sum(b_size + 2 downto 3);
        y3_im_sig(b_size - 1 downto 0) <= y3_im_sum(b_size + 2 downto 3);
        y4_re_sig(b_size - 1 downto 0) <= y4_re_sum(b_size + 2 downto 3);
        y4_im_sig(b_size - 1 downto 0) <= y4_im_sum(b_size + 2 downto 3);
        

process (CLK)
begin
    if (rising_edge(CLK)) then

        -- Вычисление y1_re:
        
        y1_re_sum <= CONV_STD_LOGIC_VECTOR(y1_re_sig, b_size);

        -- Вычисление y1_im:
        y1_im_sum <= CONV_STD_LOGIC_VECTOR(y1_im_sig, b_size);

        -- Вычисление y2_re:
        y2_re_sum <= CONV_STD_LOGIC_VECTOR(y2_re_sig, b_size);

        -- Вычисление y2_im:
        y2_im_sum <= CONV_STD_LOGIC_VECTOR(y2_im_sig, b_size);

        -- Вычисление y3_re:
        y3_re_sum <= CONV_STD_LOGIC_VECTOR(y3_re_sig, b_size);

        -- Вычисление y3_im:
        y3_im_sum <= CONV_STD_LOGIC_VECTOR(y3_im_sig, b_size);

        -- Вычисление y4_re:
        y4_re_sum <= CONV_STD_LOGIC_VECTOR(y4_re_sig, b_size);

        -- Вычисление y4_im:
        y4_im_sum <= CONV_STD_LOGIC_VECTOR(y4_im_sig, b_size);

    end if;
end process;

end beh_butter;

Изменено пользователем ZED

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кроме того, что код оказался не компилируем, различных преобразований, все же, многовато :). С разрядностью тоже переборщили, хотя и всего на 1 разряд. По этой же причине (неправильная разрядность), видимо, Вы для округления прибавляете 4, вместо 2 - это приведет к неправильным вычислениям.

 

Разберемся с разрядностью. При сложении 4 чисел самое большое | маленькое, что мы можем получить это max(x)*4 | min(x)*4. Поскольку умножение на 4 есть не что иное как сдвиг влево на 2 разряда, то

 

1) переполнение при любых числах на входе БПФ не может превысить 2 разряда.

2) в обоих крайних случаях мы получим "00" в двух младших разрядах.

 

Из 1) и 2) следует, что разрядность сумы должна быть только лишь на 2 разряда больше, чем данные и для округления перед делением на 4 мы можем прибавить "000000000000000010" (т.е. 2) не опасаясь переполнения.

 

Для бабочки достаточно использования только std_logic_vector. Кстати, лучше нумеровать точки с 0. Вот код.

 

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity butterfly_complex is
generic (b_size: natural := 16);

port(CLK: in std_logic; 
	 x0_re: in std_logic_vector(b_size-1 downto 0);
	 x0_im: in std_logic_vector(b_size-1 downto 0);
	 x1_re: in std_logic_vector(b_size-1 downto 0);
	 x1_im: in std_logic_vector(b_size-1 downto 0);
	 x2_re: in std_logic_vector(b_size-1 downto 0);
	 x2_im: in std_logic_vector(b_size-1 downto 0);
	 x3_re: in std_logic_vector(b_size-1 downto 0);
	 x3_im: in std_logic_vector(b_size-1 downto 0);		 

	 y0_re: out std_logic_vector(b_size-1 downto 0);
	 y0_im: out std_logic_vector(b_size-1 downto 0);
	 y1_re: out std_logic_vector(b_size-1 downto 0);
	 y1_im: out std_logic_vector(b_size-1 downto 0);
	 y2_re: out std_logic_vector(b_size-1 downto 0);
	 y2_im: out std_logic_vector(b_size-1 downto 0);
	 y3_re: out std_logic_vector(b_size-1 downto 0);
	 y3_im: out std_logic_vector(b_size-1 downto 0)		
	);
end entity butterfly_complex;

architecture beh_butter of butterfly_complex is

signal x0_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x0_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x1_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x1_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x2_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x2_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x3_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x3_im_sig : std_logic_vector(b_size-1 + 2 downto 0);

signal y0_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y0_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y1_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y1_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y2_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y2_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y3_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y3_im_sig : std_logic_vector(b_size-1 + 2 downto 0);

Begin --=======================================================

x0_re_sig <= (1 downto 0 => x0_re(b_size-1)) & x0_re;
x0_im_sig <= (1 downto 0 => x0_im(b_size-1)) & x0_im;
x1_re_sig <= (1 downto 0 => x1_re(b_size-1)) & x1_re;
x1_im_sig <= (1 downto 0 => x1_im(b_size-1)) & x1_im;
x2_re_sig <= (1 downto 0 => x2_re(b_size-1)) & x2_re;
x2_im_sig <= (1 downto 0 => x2_im(b_size-1)) & x2_im;
x3_re_sig <= (1 downto 0 => x3_re(b_size-1)) & x3_re;
x3_im_sig <= (1 downto 0 => x3_im(b_size-1)) & x3_im;

          --------------------------------------

-- Вычисление y0
y0_re_sig <= x0_re_sig + x1_re_sig + x2_re_sig + x3_re_sig + 2;
y0_im_sig <= x0_im_sig + x1_im_sig + x2_im_sig + x3_im_sig + 2;

-- Вычисление y1
y1_re_sig <= x0_re_sig + x1_im_sig - x2_re_sig - x3_im_sig + 2;
y1_im_sig <= x0_im_sig - x1_re_sig - x2_im_sig + x3_re_sig + 2;

-- Вычисление y2
y2_re_sig <= x0_re_sig - x1_re_sig + x2_re_sig - x3_re_sig + 2;
y2_im_sig <= x0_im_sig - x1_im_sig + x2_im_sig - x3_im_sig + 2;

-- Вычисление y3
y3_re_sig <= x0_re_sig - x1_im_sig - x2_re_sig + x3_im_sig + 2;
y3_im_sig <= x0_im_sig + x1_re_sig - x2_im_sig - x3_re_sig + 2;

          --------------------------------------

process (CLK)
begin
if (rising_edge(CLK)) then

	y0_re <= y0_re_sig(b_size-1 + 2 downto 2);
	y0_im <= y0_im_sig(b_size-1 + 2 downto 2);
	y1_re <= y1_re_sig(b_size-1 + 2 downto 2);
	y1_im <= y1_im_sig(b_size-1 + 2 downto 2);
	y2_re <= y2_re_sig(b_size-1 + 2 downto 2);
	y2_im <= y2_im_sig(b_size-1 + 2 downto 2);
	y3_re <= y3_re_sig(b_size-1 + 2 downto 2);
	y3_im <= y3_im_sig(b_size-1 + 2 downto 2);

end if;
end process;


end beh_butter;

 

 

Теперь идем дальше. 2-х точечная бабочка это всего лишь A+B и A-B. Как несложно видеть и то и другое со всеми входными данными и в разных комбинациях у нас есть в формулах 4-х Т.Б. (недаром же ее можновычислить через 2-х Т.Б. :)). Учитывая, что у нас из памяти за такт вычитывается по 4 точки, то нам неплохо бы "выжать" из формул 4-х Т.Б. две 2-х Т.Б. В качестве входа для первой 2-х Т.Б. возьмем Х0 и Х1, а в для второй Х2 и Х3. Разумеется, на вход бабочки нужно добавить сигнал управления типом бабочки, а выходные регистры должны должны защелкивать соответствующий результат.

 

Дерзайте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пока на ум пришло только это:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity butterfly_complex is
generic (b_size: natural := 16);

port(CLK: in std_logic;
x0_re: in std_logic_vector(b_size-1 downto 0);
x0_im: in std_logic_vector(b_size-1 downto 0);
x1_re: in std_logic_vector(b_size-1 downto 0);
x1_im: in std_logic_vector(b_size-1 downto 0);
x2_re: in std_logic_vector(b_size-1 downto 0);
x2_im: in std_logic_vector(b_size-1 downto 0);
x3_re: in std_logic_vector(b_size-1 downto 0);
x3_im: in std_logic_vector(b_size-1 downto 0);

switch: in std_logic_vector;

y0_re: out std_logic_vector(b_size-1 downto 0);
y0_im: out std_logic_vector(b_size-1 downto 0);
y1_re: out std_logic_vector(b_size-1 downto 0);
y1_im: out std_logic_vector(b_size-1 downto 0);
y2_re: out std_logic_vector(b_size-1 downto 0);
y2_im: out std_logic_vector(b_size-1 downto 0);
y3_re: out std_logic_vector(b_size-1 downto 0);
y3_im: out std_logic_vector(b_size-1 downto 0)
);
end entity butterfly_complex;

architecture beh_butter of butterfly_complex is

signal x0_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x0_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x1_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x1_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x2_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x2_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x3_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x3_im_sig : std_logic_vector(b_size-1 + 2 downto 0);

signal y0_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y0_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y1_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y1_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y2_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y2_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y3_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y3_im_sig : std_logic_vector(b_size-1 + 2 downto 0);

Begin --=======================================================

x0_re_sig <= (1 downto 0 => x0_re(b_size-1)) & x0_re;
x0_im_sig <= (1 downto 0 => x0_im(b_size-1)) & x0_im;
x1_re_sig <= (1 downto 0 => x1_re(b_size-1)) & x1_re;
x1_im_sig <= (1 downto 0 => x1_im(b_size-1)) & x1_im;
x2_re_sig <= (1 downto 0 => x2_re(b_size-1)) & x2_re;
x2_im_sig <= (1 downto 0 => x2_im(b_size-1)) & x2_im;
x3_re_sig <= (1 downto 0 => x3_re(b_size-1)) & x3_re;
x3_im_sig <= (1 downto 0 => x3_im(b_size-1)) & x3_im;

--------------------------------------
if (switch = '0') then

-- Вычисление y0
y0_re_sig <= x0_re_sig + x1_re_sig + x2_re_sig + x3_re_sig + 2;
y0_im_sig <= x0_im_sig + x1_im_sig + x2_im_sig + x3_im_sig + 2;

-- Вычисление y1
y1_re_sig <= x0_re_sig + x1_im_sig - x2_re_sig - x3_im_sig + 2;
y1_im_sig <= x0_im_sig - x1_re_sig - x2_im_sig + x3_re_sig + 2;

-- Вычисление y2
y2_re_sig <= x0_re_sig - x1_re_sig + x2_re_sig - x3_re_sig + 2;
y2_im_sig <= x0_im_sig - x1_im_sig + x2_im_sig - x3_im_sig + 2;

-- Вычисление y3
y3_re_sig <= x0_re_sig - x1_im_sig - x2_re_sig + x3_im_sig + 2;
y3_im_sig <= x0_im_sig + x1_re_sig - x2_im_sig - x3_re_sig + 2;

--------------------------------------
else

-- Вычисление y0
y0_re_sig <= x0_re_sig + x1_re_sig + 1;
y0_im_sig <= x0_im_sig + x1_im_sig + 1;

-- Вычисление y1
y1_re_sig <= x0_re_sig - x1_im_sig + 1;
y1_im_sig <= x0_im_sig - x1_re_sig + 1;

-- Вычисление y2
y2_re_sig <= x2_re_sig + x3_re_sig + 1;
y2_im_sig <= x2_im_sig + x3_im_sig + 1;

-- Вычисление y3
y3_re_sig <= x2_re_sig - x3_im_sig + 1;
y3_im_sig <= x2_im_sig - x3_re_sig + 1;


process (CLK)
begin
if (rising_edge(CLK)) then
if (switch = '0') then
y0_re <= y0_re_sig(b_size-1 + 2 downto 2);
y0_im <= y0_im_sig(b_size-1 + 2 downto 2);
y1_re <= y1_re_sig(b_size-1 + 2 downto 2);
y1_im <= y1_im_sig(b_size-1 + 2 downto 2);
y2_re <= y2_re_sig(b_size-1 + 2 downto 2);
y2_im <= y2_im_sig(b_size-1 + 2 downto 2);
y3_re <= y3_re_sig(b_size-1 + 2 downto 2);
y3_im <= y3_im_sig(b_size-1 + 2 downto 2);
else
y0_re <= y0_re_sig(b_size-1 + 1 downto 1);
y0_im <= y0_im_sig(b_size-1 + 1 downto 1);
y1_re <= y1_re_sig(b_size-1 + 1 downto 1);
y1_im <= y1_im_sig(b_size-1 + 1 downto 1);
y2_re <= y2_re_sig(b_size-1 + 1 downto 1);
y2_im <= y2_im_sig(b_size-1 + 1 downto 1);
y3_re <= y3_re_sig(b_size-1 + 1 downto 1);
y3_im <= y3_im_sig(b_size-1 + 1 downto 2);
end if;
end process;


end beh_butter;

Изменено пользователем ZED

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"if" не может быть использован вне процесса. Этот код не компилируем.

 

Вне процесса можно A <= B when x = y else C;

 

Исправляйте. Либо поместите в процесс, либо примените конструкцию с when.

 

Еще однобитовый switch не может быть std_logic_vector :) Максимум std_logic.

Изменено пользователем Sefo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"if" не может быть использован вне процесса. Этот код не компилируем.

Да точно, забыл...

 

Вне процесса можно A <= B when x = y else C;

Да, но нескольким значениям значений не присвоишь, а жаль...

 

Исправляйте. Либо поместите в процесс, либо примените конструкцию с when.

Выход только поместить в процесс...

 

Еще однобитовый switch не может быть std_logic_vector smile.gif Максимум std_logic.

CTL+C CTL+V =)) Исправил, просинтезировать нет возможности...

 

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity butterfly_complex is
generic (b_size: natural := 16);

port(CLK: in std_logic;
x0_re: in std_logic_vector(b_size-1 downto 0);
x0_im: in std_logic_vector(b_size-1 downto 0);
x1_re: in std_logic_vector(b_size-1 downto 0);
x1_im: in std_logic_vector(b_size-1 downto 0);
x2_re: in std_logic_vector(b_size-1 downto 0);
x2_im: in std_logic_vector(b_size-1 downto 0);
x3_re: in std_logic_vector(b_size-1 downto 0);
x3_im: in std_logic_vector(b_size-1 downto 0);

switch: in std_logic;

y0_re: out std_logic_vector(b_size-1 downto 0);
y0_im: out std_logic_vector(b_size-1 downto 0);
y1_re: out std_logic_vector(b_size-1 downto 0);
y1_im: out std_logic_vector(b_size-1 downto 0);
y2_re: out std_logic_vector(b_size-1 downto 0);
y2_im: out std_logic_vector(b_size-1 downto 0);
y3_re: out std_logic_vector(b_size-1 downto 0);
y3_im: out std_logic_vector(b_size-1 downto 0)
);
end entity butterfly_complex;

architecture beh_butter of butterfly_complex is

signal x0_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x0_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x1_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x1_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x2_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x2_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x3_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal x3_im_sig : std_logic_vector(b_size-1 + 2 downto 0);

signal y0_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y0_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y1_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y1_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y2_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y2_im_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y3_re_sig : std_logic_vector(b_size-1 + 2 downto 0);
signal y3_im_sig : std_logic_vector(b_size-1 + 2 downto 0);

Begin --=======================================================

x0_re_sig <= (1 downto 0 => x0_re(b_size-1)) & x0_re;
x0_im_sig <= (1 downto 0 => x0_im(b_size-1)) & x0_im;
x1_re_sig <= (1 downto 0 => x1_re(b_size-1)) & x1_re;
x1_im_sig <= (1 downto 0 => x1_im(b_size-1)) & x1_im;
x2_re_sig <= (1 downto 0 => x2_re(b_size-1)) & x2_re;
x2_im_sig <= (1 downto 0 => x2_im(b_size-1)) & x2_im;
x3_re_sig <= (1 downto 0 => x3_re(b_size-1)) & x3_re;
x3_im_sig <= (1 downto 0 => x3_im(b_size-1)) & x3_im;

--------------------------------------

process (CLK)
begin
if (rising_edge(CLK)) then
if (switch = '0') then

-- Вычисление y0
y0_re_sig <= x0_re_sig + x1_re_sig + x2_re_sig + x3_re_sig + 2;
y0_im_sig <= x0_im_sig + x1_im_sig + x2_im_sig + x3_im_sig + 2;

-- Вычисление y1
y1_re_sig <= x0_re_sig + x1_im_sig - x2_re_sig - x3_im_sig + 2;
y1_im_sig <= x0_im_sig - x1_re_sig - x2_im_sig + x3_re_sig + 2;

-- Вычисление y2
y2_re_sig <= x0_re_sig - x1_re_sig + x2_re_sig - x3_re_sig + 2;
y2_im_sig <= x0_im_sig - x1_im_sig + x2_im_sig - x3_im_sig + 2;

-- Вычисление y3
y3_re_sig <= x0_re_sig - x1_im_sig - x2_re_sig + x3_im_sig + 2;
y3_im_sig <= x0_im_sig + x1_re_sig - x2_im_sig - x3_re_sig + 2;

y0_re <= y0_re_sig(b_size-1 + 2 downto 2);
y0_im <= y0_im_sig(b_size-1 + 2 downto 2);
y1_re <= y1_re_sig(b_size-1 + 2 downto 2);
y1_im <= y1_im_sig(b_size-1 + 2 downto 2);
y2_re <= y2_re_sig(b_size-1 + 2 downto 2);
y2_im <= y2_im_sig(b_size-1 + 2 downto 2);
y3_re <= y3_re_sig(b_size-1 + 2 downto 2);
y3_im <= y3_im_sig(b_size-1 + 2 downto 2);

else

-- Вычисление y0
y0_re_sig <= x0_re_sig + x1_re_sig + 1;
y0_im_sig <= x0_im_sig + x1_im_sig + 1;

-- Вычисление y1
y1_re_sig <= x0_re_sig - x1_im_sig + 1;
y1_im_sig <= x0_im_sig - x1_re_sig + 1;

-- Вычисление y2
y2_re_sig <= x2_re_sig + x3_re_sig + 1;
y2_im_sig <= x2_im_sig + x3_im_sig + 1;

-- Вычисление y3
y3_re_sig <= x2_re_sig - x3_im_sig + 1;
y3_im_sig <= x2_im_sig - x3_re_sig + 1;

y0_re <= y0_re_sig(b_size-1 + 1 downto 1);
y0_im <= y0_im_sig(b_size-1 + 1 downto 1);
y1_re <= y1_re_sig(b_size-1 + 1 downto 1);
y1_im <= y1_im_sig(b_size-1 + 1 downto 1);
y2_re <= y2_re_sig(b_size-1 + 1 downto 1);
y2_im <= y2_im_sig(b_size-1 + 1 downto 1);
y3_re <= y3_re_sig(b_size-1 + 1 downto 1);
y3_im <= y3_im_sig(b_size-1 + 1 downto 2);
end if;
end if;
end process;


end beh_butter;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Когда у Вас будет возможность просинтезировать код? Потому что мы подошли к самому интересному - во что Квартус превращает наш код и как его заставить сделать то, что нам нужно.

 

Попробуйте просинтезировать Квартусом простое выражение (в отдельном проекте) R = A+B+1 (или R = A+B+'1'), где R,A и B есть std_logic_vector(15 downto 0) и посмотрите в RTL Viewer что получилось.

 

Как Вы думаете, что должно было получиться, если бы Квартус был бы "умнее"? Какую стандартную операцию представляет из себя выражение A+B+1?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Квартус синтезирует 2 сумматора, на вход одного из которых подана единица. Операция должна быть округлением...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот это-то и плохо. У нас обычное суммирование с переносом. A+B+carry - это полный сумматор. Это мы его используем для округления, а еще такой сумматор используется для вычисления суммы чисел на нескольких полных сумматорах, когда разрядность самих чисел больше разрядности сумматора. Самое обидное, что ячейки ПЛИС все это позволяют. Если запустить Квартусовский Мегавизард, то Вы найдете там сумматор со входом переноса, который при синтезе будет занимать ровно столько ячеек, сколько разрядов и ни одной больше. А на наш код он ставит аж 2 сумматора!

 

К сожалению, Квартус не отличается хорошей оптимизацией математических выражеий. Если он видит два '+' он ставит 2 сумматора.

 

Есть идеи, как его заставить реализовать A+B+1 на одном сумматоре в VHDL, не прибегая к использованию его мегафункций?

Изменено пользователем Sefo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Извиняюсь за длительную паузу. Прием очень простой. Если обоим операндам приписать по одному разряду справа равному '1', то при сложении неизбежно образуется перенос, который сложится со младшим разрядом (точнее, бывшим младшим разрядом) суммы, а т.к. результат самого сложения двух констант, равных '1' никогда использоваться не будет, то Квартус в процессе оптимизации эту ячейку удалит. Да даже если и не удалит, то такой "довесок" в n раз меньше, чем второй сумматор на n разрядов.

 

signal A : std_logic_vector(n-1 downto 0);

signal B : std_logic_vector(n-1 downto 0);

 

signal SUM : std_logic_vector(n-1 downto 0); -- SUM = (A + B + 1);

 

Объявляем промежуточный сигна на один разряд больше.

 

signal S std_logic_vector(n downto 0);

 

Тогда

 

S <= (A & '1') + (B & '1');

 

SUM <= S(n downto 1);

 

Кстати, к A+B+m, где m > 1 описанный прием уже не применить.

 

Предлагаю Вам с этим немного поэкспериментировать на досуге.

 

Идем дальше. К сожалению, все вышесказанное (не только конкретно в этом сообщении) про сложение не работает для вычитания. Для A-B+1 придется ставить 2 сумматора.

Кроме того, в отличие от A+B, A-B уже не гарантирует '0' в младшем разряде в крайних случаях. Для сложения крайние случаи это когда оба слагаемых либо максимальны, либо минимальны, а для вычитания – когда одна переменная имеет максимальное значение, а другая минимальное. А поскольку '0' не гарантирован, то при отбрасывании младшего разряда при сдвиге вправо ничего страшного не произойдет, а вот при округлении (т.е. прибавлении 1 перед сдвигом) результат может переполнится больше чем на 1 разряд по сравнению с разрядностью исходных переменных.

Пример:

( (-32768) – (32767) + 1 ) >> 1 = (-65535 + 1) >> 1 = -65534 >> 1 = -32767 все в порядке - разность переполнилась на один "законный" разряд, после сложения переполнения не произошло и после деления на 2 все вернулось обратно к 16-ти разрядам.

Теперь другой пример:

( (32767) – (-32768) + 1 ) >> 1 = (65535 + 1) >> 1 = -65536 >> 1 = -32768 фигня получилась - разность переполнилась на один "законный" разряд, а после добавления 1 переполнилась еще раз, превратившись в отрицательное число.

Такое поведение вычитания обусловлено как раз несимметричностью дополнительного кода – модуль максимального числа на 1 меньше модуля минимального. При вычитании, так скажем, самого отрицательного числа :) оно меняет знак, станивится положительным и... для его представления нужно уже на 1 разряд больше т.к. оно становится всего на единицу больше максимального положительного числа.

 

Какие отсюда следуют выводы?

 

1) избавиться от лишних сумматоров нам удасться лишь для y0_re и y0_im (для случая 2-х Т.Б. еще и y2), где у нас сплошное суммирование. С этим должно быть все понятно.

 

2) при вычислении y1,2,3 у нас может возникнуть переполнение. Тут нужно учесть, что локально увеличить разрядность мы не можем т.к. это переполнение не устраняется делением на 4 или 2.

 

Есть 2 варианта:

 

Первый, увеличить разрядность данных повсеместно на 1 и расширить диапазон значений только на нехватающую 1 т.е. 16-ти разрядные данные сделать 17-ти разрядными, а диапазон сделать от -32768 до +32768. Этот способ очень прост т.к. достаточно 16-ти разрядные данные АЦП расширить знаком до 17-ти разрядных и все.

 

Второй, это на выходе из АЦП заменять -32768 на 32767. Не очень "честно", но если сохранять разрядность, то "честно" все равно не получится, а резать в бабочке гораздо более затратно по ресурсам ПЛИС.

 

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

 

Что касается переполнения, то выбирайте, увеличим разрядность или срежем на выходе АЦП?

 

Вопросы есть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прошу прощения, что долго не отвечал, просто по учебе загрузили, надеюсь все к среде разрулить и вплотную заняться делом!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, спасибо, разрулил более менее, надеюсь еще какое-то время меня трогать не будут=))

 

Да, вопросы есть:

 

1. Не совсем понятно , что значит "локально увеличить разрядность". Это имеется ввиду в ПЛИС resize?

 

2. Почему бы в ПЛИС не сделать так:

 

signal A : std_logic_vector(n-1 downto 0);
signal B : std_logic_vector(n-1 downto 0);
signal SUM_buf : std_logic_vector(n downto 0);
signal SUM : std_logic_vector(n downto 0);

SUM_buf <= resize(A, n+1) -  resize(B, n+1)
SUM <= SUM_buf(n downto 1);

Изменено пользователем ZED

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Локально, это имеется ввиду внутри бабочки. В случае (A+B+C+D)/4 с округлением (т.е. (A+B+C+D+2) >> 2) мы можем (и делаем) объявить внутри бабочки сигналы A_ B_ C_ D_ с разрядностью на 2 больше, чем A,B,C,D. Складываем их, прибавляем 2 (для округления) и отбросываем 2 младших разряда (т.е. /4). В этом случае, выполнив все необходимые операции, мы снова возвращаемся к разрядности такой же как и у A,B,C,D. У нас на входе разрядность n, внутри бабочки разрядность n+2, а на выходе опять n. И при этом мы нигде ничего не реряем. При наличие вычитания, если мы не будем округлять, а просто отбрасывать 2 младших разряда, то мы тоже ничего не потеряем и разрядность результата будет такая же как и разрядность входных данных. Но при наличие вычитания и желания проделать операции с округлением результата мы в некоторых случаях сможем получить результат (именно конечный результат), для представления которого нам не хватит разрядности такой же как и у входных данных - нам потребуется на один разряд больше. (см пример в пред. сообщении) Т.е. выход будет на один разряд больше ==> выход умножителей придется сделать на 1 разряд больше ==> разрядность памяти придется увеличить на 1 разряд ==> вход бабочки тоже увеличится на 1 разряд - круг замкнулся т.к. наши данные во время вычисления БПФ "гуляют" по кругу.

 

2)Так как Вы написали - это (A-B)/2 без округления (т.е. (A-B)>>1), а Вы в бабочке округляете (т.е. (A-B+1)>>1). Я же ведь даже конкретный пример привел - просимулируйте.

 

 

Теперь понятно?

 

На всякий случай повторю - не делай мы в бабочке округления при делении на 4 никаких проблем бы не было.

Изменено пользователем Sefo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...