БПФ на 8 точек (FFT 8 point) на VHDL
БПФ на ПЛИС построить несложно, поскольку для этого существуют готовые ядра, в том числе и с открытым кодом. Но все дело в том, что минимальное количество точек в готовых ядрах БПФ равно 64. Если нужно количество точек меньше чем 64, например 16 или даже 8 то вполне приемлимый вариант написать код БПФ самостоятельно. Заодно можно протестировать и выбранный алгоритм построения БПФ на ПЛИС. В данном посте представлен VHDL код FFT 8 point выполненый по алгоритму прореживания по времени. Код довольно громоздкий но на его базе можно уяснить общий принцип написания и как все крутится.
Прежде чем представить код разберем собственно алгоритм БПФ прореживания по времени, который представлен на картинке ниже.
Все достаточно просто. Основная операция данного алгоритма - операция бабочка, которая состоит из одного комплексного умножения и двух операций комплексного суммирования и комплексного вычитания.
В коде на VHDL это выглядит предельно просто:
-- Бабочка (прореживание по времени)
-- A = x + Wn * y;
-- A_r + j*A_i = (x_r + j* x_i) + ( w_r + j*w_i) *(y_r + j*y_i);
-- A_r + j*A_i = (x_r + (w_r * y_r ) –( w_i *y_i)) + j*(x_i +( w_i *y_r) +( w_r * y_i));
-- A_r = x_r + (w_r * y_r ) –( w_i *y_i);
-- A_i = x_i +( w_i *y_r) +( w_r * y_i);
-- B = x - Wn * y;
-- B_r + j*B_i = (x_r + j* x_i) - ( w_r + j*w_i) *(y_r + j*y_i);
-- B_r + j*B_i = ( x_r - (w_r *y_r) + (w_i * y_i)) + (x_i – (w_r *y_i ) – (w_i * y_r ));
-- B_r =( x_r - (w_r *y_r) + (w_i * y_i);
-- B_i = x_i – (w_r * y_i ) – (w_i * y_r );
-- fft8 разбит на 3 стадии.
-- На каждой стадии, которая занимает 2 тактовых импульса, производится
-- 4 комплексных умножения и 8 комплексных суммирований
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.numeric_std.all;
entity fft8vhd is
Generic (
-- размерность входных данных
b_size: natural := 15;
-- размерность пов. множит
w_size: natural := 12
);
Port (
-- тактовая частота
clk : in std_logic;
-- общий сброс
rst : in std_logic;
-- входные данные реал
dinr0 : in std_logic_vector(b_size downto 0);
dinr1 : in std_logic_vector(b_size downto 0);
dinr2 : in std_logic_vector(b_size downto 0);
dinr3 : in std_logic_vector(b_size downto 0);
dinr4 : in std_logic_vector(b_size downto 0);
dinr5 : in std_logic_vector(b_size downto 0);
dinr6 : in std_logic_vector(b_size downto 0);
dinr7 : in std_logic_vector(b_size downto 0);
-- входные данные мним
dini0 : in std_logic_vector(b_size downto 0);
dini1 : in std_logic_vector(b_size downto 0);
dini2 : in std_logic_vector(b_size downto 0);
dini3 : in std_logic_vector(b_size downto 0);
dini4 : in std_logic_vector(b_size downto 0);
dini5 : in std_logic_vector(b_size downto 0);
dini6 : in std_logic_vector(b_size downto 0);
dini7 : in std_logic_vector(b_size downto 0);
-- импульс записи данных
wrdata : in std_logic;
-- выход счетчика стадий
ctfout : out std_logic_vector(2 downto 0);
-- выходы данных реал
doutr0 : out std_logic_vector(b_size downto 0);
doutr1 : out std_logic_vector(b_size downto 0);
doutr2 : out std_logic_vector(b_size downto 0);
doutr3 : out std_logic_vector(b_size downto 0);
doutr4 : out std_logic_vector(b_size downto 0);
doutr5 : out std_logic_vector(b_size downto 0);
doutr6 : out std_logic_vector(b_size downto 0);
doutr7 : out std_logic_vector(b_size downto 0);
-- выходы данных мним
douti0 : out std_logic_vector(b_size downto 0);
douti1 : out std_logic_vector(b_size downto 0);
douti2 : out std_logic_vector(b_size downto 0);
douti3 : out std_logic_vector(b_size downto 0);
douti4 : out std_logic_vector(b_size downto 0);
douti5 : out std_logic_vector(b_size downto 0);
douti6 : out std_logic_vector(b_size downto 0);
douti7 : out std_logic_vector(b_size downto 0);
-- тестовые выходы бабочки
dout_r_tst_up : out std_logic_vector(b_size downto 0);
dout_i_tst_up : out std_logic_vector(b_size downto 0);
dout_r_tst_down : out std_logic_vector(b_size downto 0);
dout_i_tst_down : out std_logic_vector(b_size downto 0)
);
end fft8vhd;
architecture behavioural of fft8vhd is
attribute multstyle : string;
-- на базе логики
attribute multstyle of behavioural : architecture is "logic";
-- на базе встроенных умножителей
--attribute multstyle of behavioural : architecture is "dsp";
-- счетчик стадий
signal s_ctf : std_logic_vector(2 downto 0);
-- признак загрузки данных
signal s_ld : std_logic;
-- флаг разрешения преобразования
signal s_begpr : std_logic;
---------------------------------------------------------------
-- буферные сигналы реал
subtype sdbr is signed(b_size downto 0);
type memory_sdbr is array(7 downto 0) of sdbr;
signal s_in_r_sig : memory_sdbr;
-- буферные сигналы мним
subtype sdbi is signed(b_size downto 0);
type memory_sdbi is array(7 downto 0) of sdbi;
signal s_in_i_sig : memory_sdbi;
-----------------------------------------------------------------
-- сигналы умножения 1_ой стадии реал
subtype mult1_re_sig is signed(b_size + w_size + 1 downto 0);
type memory_mult1_re_sig is array(3 downto 0) of mult1_re_sig;
signal s_mult1_re_sig : memory_mult1_re_sig;
-- сигналы умножения 1_ой стадии мним
subtype mult1_im_sig is signed(b_size + w_size + 1 downto 0);
type memory_mult1_im_sig is array(3 downto 0) of mult1_im_sig;
signal s_mult1_im_sig : memory_mult1_im_sig;
-- сигналы суммы 1_ой стадии реал
subtype sum1_re_sig is signed(b_size downto 0);
type memory_sum1_re_sig is array(7 downto 0) of sum1_re_sig;
signal s_sum1_re_sig : memory_sum1_re_sig;
-- сигналы суммы 1_ой стадии мним
subtype sum1_im_sig is signed(b_size downto 0);
type memory_sum1_im_sig is array(7 downto 0) of sum1_im_sig;
signal s_sum1_im_sig : memory_sum1_im_sig;
-------------------------------------------------------------------
-- сигналы умножения 2_ой стадии реал
subtype mult2_re_sig is signed(b_size + w_size + 1 downto 0);
type memory_mult2_re_sig is array(3 downto 0) of mult2_re_sig;
signal s_mult2_re_sig : memory_mult2_re_sig;
-- сигналы умножения 2_ой стадии мним
subtype mult2_im_sig is signed(b_size + w_size + 1 downto 0);
type memory_mult2_im_sig is array(3 downto 0) of mult2_im_sig;
signal s_mult2_im_sig : memory_mult2_im_sig;
-- сигналы суммы 2_ой стадии реал
subtype sum2_re_sig is signed(b_size downto 0);
type memory_sum2_re_sig is array(7 downto 0) of sum2_re_sig;
signal s_sum2_re_sig : memory_sum2_re_sig;
-- сигналы суммы 2_ой стадии мним
subtype sum2_im_sig is signed(b_size downto 0);
type memory_sum2_im_sig is array(7 downto 0) of sum2_im_sig;
signal s_sum2_im_sig : memory_sum2_im_sig;
-----------------------------------------------------------------
-- сигналы умножения 3_й стадии реал
subtype mult3_re_sig is signed(b_size + w_size + 1 downto 0);
type memory_mult3_re_sig is array(3 downto 0) of mult3_re_sig;
signal s_mult3_re_sig : memory_mult3_re_sig;
-- сигналы умножения 3_й стадии мним
subtype mult3_im_sig is signed(b_size + w_size + 1 downto 0);
type memory_mult3_im_sig is array(3 downto 0) of mult3_im_sig;
signal s_mult3_im_sig : memory_mult3_im_sig;
-- сигналы суммы 3_й стадии реал
subtype sum3_re_sig is signed(b_size downto 0);
type memory_sum3_re_sig is array(7 downto 0) of sum3_re_sig;
signal s_sum3_re_sig : memory_sum3_re_sig;
-- сигналы суммы 3_й стадии мним
subtype sum3_im_sig is signed(b_size downto 0);
type memory_sum3_im_sig is array(7 downto 0) of sum3_im_sig;
signal s_sum3_im_sig : memory_sum3_im_sig;
-----------------------------------------------------------
-- сигналы для поворачивающих множителей реал
signal s_w_r_8_0_sig: signed(w_size - 1 downto 0);
signal s_w_r_8_1_sig: signed(w_size - 1 downto 0);
signal s_w_r_8_2_sig: signed(w_size - 1 downto 0);
signal s_w_r_8_3_sig: signed(w_size - 1 downto 0);
-- сигналы для поворачивающих множителей мним
signal s_w_i_8_0_sig: signed(w_size - 1 downto 0);
signal s_w_i_8_1_sig: signed(w_size - 1 downto 0);
signal s_w_i_8_2_sig: signed(w_size - 1 downto 0);
signal s_w_i_8_3_sig: signed(w_size - 1 downto 0);
-- поворачивающие множители
-- round(cos(2*pi*n/8)*1024)
-- round(sin(2*pi*n/8)*1024)
-- n = 0...3
-- реал
constant c_w_r_8_0 : integer := 1024;
constant c_w_r_8_1 : integer := 724;
constant c_w_r_8_2 : integer := 0;
constant c_w_r_8_3 : integer := -724;
-- мним
constant c_w_i_8_0 : integer := 0;
constant c_w_i_8_1 : integer := -724;
constant c_w_i_8_2 : integer := -1024;
constant c_w_i_8_3 : integer := -724;
begin
-- счетчик стадий
process(clk, s_ctf)
begin
if clk'event and clk = '1' then
if rst = '0' then
s_ctf <= (others => '0');
s_begpr <= '0';
elsif s_ld = '1' and s_begpr = '0' then
s_begpr <= '1';
end if;
if s_begpr = '1' then
s_ctf <= s_ctf + 1;
if s_ctf = 6 then
s_ctf <= (others => '0');
s_begpr <= '0';
end if;
end if;
end if;
ctfout <= s_ctf;
end process;
-- загрузка данных
process(clk)
begin
if clk'event and clk = '1' then
if rst = '0' or s_ctf = 6 then
s_ld <= '0';
elsif wrdata = '1' and s_ld = '0' then
-- реал входные данные
s_in_r_sig(0) <= signed(dinr0);
s_in_r_sig(1) <= signed(dinr1);
s_in_r_sig(2) <= signed(dinr2);
s_in_r_sig(3) <= signed(dinr3);
s_in_r_sig(4) <= signed(dinr4);
s_in_r_sig(5) <= signed(dinr5);
s_in_r_sig(6) <= signed(dinr6);
s_in_r_sig(7) <= signed(dinr7);
-- мним входные данные
s_in_i_sig(0) <= signed(dini0);
s_in_i_sig(1) <= signed(dini1);
s_in_i_sig(2) <= signed(dini2);
s_in_i_sig(3) <= signed(dini3);
s_in_i_sig(4) <= signed(dini4);
s_in_i_sig(5) <= signed(dini5);
s_in_i_sig(6) <= signed(dini6);
s_in_i_sig(7) <= signed(dini7);
-- реал поворачивающие множители
s_w_r_8_0_sig <= to_signed(c_w_r_8_0, w_size);
s_w_r_8_1_sig <= to_signed(c_w_r_8_1, w_size);
s_w_r_8_2_sig <= to_signed(c_w_r_8_2, w_size);
s_w_r_8_3_sig <= to_signed(c_w_r_8_3, w_size);
-- мним поворачивающие множители
s_w_i_8_0_sig <= to_signed(c_w_i_8_0, w_size);
s_w_i_8_1_sig <= to_signed(c_w_i_8_1, w_size);
s_w_i_8_2_sig <= to_signed(c_w_i_8_2, w_size);
s_w_i_8_3_sig <= to_signed(c_w_i_8_3, w_size);
-- загрузка состоялась
s_ld <= '1';
end if;
end if;
end process;
-- операция fft8 (прореживание по времени)
-- architecture behavioral of fft_radix_2 is
-- signal product_1,product_2 : std_logic_vector(32 downto 0);
-- begin
-- product_1 <= (y_r*w_r) - (y_i*w_i);
-- product_2 <= (y_r*w_i) + (y_i*w_r);
-- A_r <= x_r + product_1(15 downto 0);
-- A_i <= x_i + product_2(15 downto 0);
-- B_r <= x_r - product_1(15 downto 0);
-- B_i <= x_i - product_2(15 downto 0);
process(clk, s_sum3_re_sig, s_sum3_im_sig, s_sum1_re_sig, s_sum1_im_sig, s_sum2_re_sig, s_sum2_im_sig)
begin
if clk'event and clk = '1' then
-- 1_я стадия fft8 s_ctf = 1,2
if s_ctf = 1 and s_begpr = '1' then
-- комплексное умножение 1_я стадия (результат в b_size + w_size + 2)
-- 1_я бабочка
s_mult1_re_sig(0) <= resize((s_in_r_sig(4)*s_w_r_8_0_sig - s_in_i_sig(4)*s_w_i_8_0_sig), b_size + w_size + 2);
s_mult1_im_sig(0) <= resize((s_in_r_sig(4)*s_w_i_8_0_sig + s_in_i_sig(4)*s_w_r_8_0_sig), b_size + w_size + 2);
-- 2_я бабочка
s_mult1_re_sig(1) <= resize((s_in_r_sig(6)*s_w_r_8_0_sig - s_in_i_sig(6)*s_w_i_8_0_sig), b_size + w_size + 2);
s_mult1_im_sig(1) <= resize((s_in_r_sig(6)*s_w_i_8_0_sig + s_in_i_sig(6)*s_w_r_8_0_sig), b_size + w_size + 2);
-- 3_я бабочка
s_mult1_re_sig(2) <= resize((s_in_r_sig(5)*s_w_r_8_0_sig - s_in_i_sig(5)*s_w_i_8_0_sig), b_size + w_size + 2);
s_mult1_im_sig(2) <= resize((s_in_r_sig(5)*s_w_i_8_0_sig + s_in_i_sig(5)*s_w_r_8_0_sig), b_size + w_size + 2);
-- 4_я бабочка
s_mult1_re_sig(3) <= resize((s_in_r_sig(7)*s_w_r_8_0_sig - s_in_i_sig(7)*s_w_i_8_0_sig), b_size + w_size + 2);
s_mult1_im_sig(3) <= resize((s_in_r_sig(7)*s_w_i_8_0_sig + s_in_i_sig(7)*s_w_r_8_0_sig), b_size + w_size + 2);
elsif s_ctf = 2 and s_begpr = '1' then
-- комплексное суммирование 1-я стадия (результат в b_size)
-- 0_вой выход 1_ой стадии
s_sum1_re_sig(0) <= s_in_r_sig(0) + s_mult1_re_sig(0)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(0) <= s_in_i_sig(0) + s_mult1_im_sig(0)(b_size + w_size - 2 downto w_size - 2);
-- 1_вый выход 1_ой стадии
s_sum1_re_sig(1) <= s_in_r_sig(0) - s_mult1_re_sig(0)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(1) <= s_in_i_sig(0) - s_mult1_im_sig(0)(b_size + w_size - 2 downto w_size - 2);
-- 2_ой выход 1_ой стадии
s_sum1_re_sig(2) <= s_in_r_sig(2) + s_mult1_re_sig(1)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(2) <= s_in_i_sig(2) + s_mult1_im_sig(1)(b_size + w_size - 2 downto w_size - 2);
-- 3_ий выход 1_ой стадии
s_sum1_re_sig(3) <= s_in_r_sig(2) - s_mult1_re_sig(1)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(3) <= s_in_i_sig(2) - s_mult1_im_sig(1)(b_size + w_size - 2 downto w_size - 2);
-- 4_ый выход 1_ой стадии
s_sum1_re_sig(4) <= s_in_r_sig(1) + s_mult1_re_sig(2)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(4) <= s_in_i_sig(1) + s_mult1_im_sig(2)(b_size + w_size - 2 downto w_size - 2);
-- 5_ый выход 1_ой стадии
s_sum1_re_sig(5) <= s_in_r_sig(1) - s_mult1_re_sig(2)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(5) <= s_in_i_sig(1) - s_mult1_im_sig(2)(b_size + w_size - 2 downto w_size - 2);
-- 6_ой выход 1_ой стадии
s_sum1_re_sig(6) <= s_in_r_sig(3) + s_mult1_re_sig(3)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(6) <= s_in_i_sig(3) + s_mult1_im_sig(3)(b_size + w_size - 2 downto w_size - 2);
-- 7_ой выход 1_ой стадии
s_sum1_re_sig(7) <= s_in_r_sig(3) - s_mult1_re_sig(3)(b_size + w_size - 2 downto w_size - 2);
s_sum1_im_sig(7) <= s_in_i_sig(3) - s_mult1_im_sig(3)(b_size + w_size - 2 downto w_size - 2);
---------------------------------------------------------------------------------------
-- 2_я стадия fft8 s_ctf = 3,4
elsif (s_ctf = 3) and s_begpr = '1' then
-- комплексное умножение 2_я стадия (результат в b_size + w_size + 2)
-- 1_я бабочка
s_mult2_re_sig(0) <= resize((s_sum1_re_sig(2)*s_w_r_8_0_sig - s_sum1_im_sig(2)*s_w_i_8_0_sig), b_size + w_size + 2);
s_mult2_im_sig(0) <= resize((s_sum1_re_sig(2)*s_w_i_8_0_sig + s_sum1_im_sig(2)*s_w_r_8_0_sig), b_size + w_size + 2);
-- 2_я бабочка
s_mult2_re_sig(1) <= resize((s_sum1_re_sig(3)*s_w_r_8_2_sig - s_sum1_im_sig(3)*s_w_i_8_2_sig), b_size + w_size + 2);
s_mult2_im_sig(1) <= resize((s_sum1_re_sig(3)*s_w_i_8_2_sig + s_sum1_im_sig(3)*s_w_r_8_2_sig), b_size + w_size + 2);
-- 3_я бабочка
s_mult2_re_sig(2) <= resize((s_sum1_re_sig(6)*s_w_r_8_0_sig - s_sum1_im_sig(6)*s_w_i_8_0_sig), b_size + w_size + 2);
s_mult2_im_sig(2) <= resize((s_sum1_re_sig(6)*s_w_i_8_0_sig + s_sum1_im_sig(6)*s_w_r_8_0_sig), b_size + w_size + 2);
-- 4_я бабочка
s_mult2_re_sig(3) <= resize((s_sum1_re_sig(7)*s_w_r_8_2_sig - s_sum1_im_sig(7)*s_w_i_8_2_sig), b_size + w_size + 2);
s_mult2_im_sig(3) <= resize((s_sum1_re_sig(7)*s_w_i_8_2_sig + s_sum1_im_sig(7)*s_w_r_8_2_sig), b_size + w_size + 2);
elsif s_ctf = 4 and s_begpr = '1' then
-- комплексное суммирование 2_я стадия (результат в b_size)
-- 0_вой выход 2_й стадии
s_sum2_re_sig(0) <= s_sum1_re_sig(0) + s_mult2_re_sig(0)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(0) <= s_sum1_im_sig(0) + s_mult2_im_sig(0)(b_size + w_size - 2 downto w_size - 2);
-- 2_ой выход 2_ой стадии
s_sum2_re_sig(2) <= s_sum1_re_sig(0) - s_mult2_re_sig(0)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(2) <= s_sum1_im_sig(0) - s_mult2_im_sig(0)(b_size + w_size - 2 downto w_size - 2);
-- 1_й выход 2_й стадии
s_sum2_re_sig(1) <= s_sum1_re_sig(1) + s_mult2_re_sig(1)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(1) <= s_sum1_im_sig(1) + s_mult2_im_sig(1)(b_size + w_size - 2 downto w_size - 2);
-- 3_й выход 2_ой стадии
s_sum2_re_sig(3) <= s_sum1_re_sig(1) - s_mult2_re_sig(1)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(3) <= s_sum1_im_sig(1) - s_mult2_im_sig(1)(b_size + w_size - 2 downto w_size - 2);
-- 4_й выход 2_й стадии
s_sum2_re_sig(4) <= s_sum1_re_sig(4) + s_mult2_re_sig(2)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(4) <= s_sum1_im_sig(4) + s_mult2_im_sig(2)(b_size + w_size - 2 downto w_size - 2);
-- 6_й выход 2_ой стадии
s_sum2_re_sig(6) <= s_sum1_re_sig(4) - s_mult2_re_sig(2)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(6) <= s_sum1_im_sig(4) - s_mult2_im_sig(2)(b_size + w_size - 2 downto w_size - 2);
-- 5_й выход 2_й стадии
s_sum2_re_sig(5) <= s_sum1_re_sig(5) + s_mult2_re_sig(3)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(5) <= s_sum1_im_sig(5) + s_mult2_im_sig(3)(b_size + w_size - 2 downto w_size - 2);
-- 7_й выход 2_ой стадии
s_sum2_re_sig(7) <= s_sum1_re_sig(5) - s_mult2_re_sig(3)(b_size + w_size - 2 downto w_size - 2);
s_sum2_im_sig(7) <= s_sum1_im_sig(5) - s_mult2_im_sig(3)(b_size + w_size - 2 downto w_size - 2);
---------------------------------------------------------------------------------------
-- 3_я стадия fft8 s_ctf = 5,6
elsif (s_ctf = 5) and s_begpr = '1' then
-- комплексное умножение 3_я стадия (результат в b_size + w_size + 2)
-- 1_я бабочка
s_mult3_re_sig(0) <= resize((s_sum2_re_sig(4)*s_w_r_8_0_sig - s_sum2_im_sig(4)*s_w_i_8_0_sig), b_size + w_size + 2);
s_mult3_im_sig(0) <= resize((s_sum2_re_sig(4)*s_w_i_8_0_sig + s_sum2_im_sig(4)*s_w_r_8_0_sig), b_size + w_size + 2);
-- 2_я бабочка
s_mult3_re_sig(1) <= resize((s_sum2_re_sig(5)*s_w_r_8_1_sig - s_sum2_im_sig(5)*s_w_i_8_1_sig), b_size + w_size + 2);
s_mult3_im_sig(1) <= resize((s_sum2_re_sig(5)*s_w_i_8_1_sig + s_sum2_im_sig(5)*s_w_r_8_1_sig), b_size + w_size + 2);
-- 3_я бабочка
s_mult3_re_sig(2) <= resize((s_sum2_re_sig(6)*s_w_r_8_2_sig - s_sum2_im_sig(6)*s_w_i_8_2_sig), b_size + w_size + 2);
s_mult3_im_sig(2) <= resize((s_sum2_re_sig(6)*s_w_i_8_2_sig + s_sum2_im_sig(6)*s_w_r_8_2_sig), b_size + w_size + 2);
-- 4_я бабочка
s_mult3_re_sig(3) <= resize((s_sum2_re_sig(7)*s_w_r_8_3_sig - s_sum2_im_sig(7)*s_w_i_8_3_sig), b_size + w_size + 2);
s_mult3_im_sig(3) <= resize((s_sum2_re_sig(7)*s_w_i_8_3_sig + s_sum2_im_sig(7)*s_w_r_8_3_sig), b_size + w_size + 2);
elsif s_ctf = 6 and s_begpr = '1' then
-- комплексное суммирование 3_я стадия (результат в b_size)
-- 0_вой выход 3_й стадии
s_sum3_re_sig(0) <= s_sum2_re_sig(0) + s_mult3_re_sig(0)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(0) <= s_sum2_im_sig(0) + s_mult3_im_sig(0)(b_size + w_size - 2 downto w_size - 2);
-- 1_ой выход 3_ой стадии
s_sum3_re_sig(1) <= s_sum2_re_sig(1) + s_mult3_re_sig(1)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(1) <= s_sum2_im_sig(1) + s_mult3_im_sig(1)(b_size + w_size - 2 downto w_size - 2);
-- 2_й выход 3_й стадии
s_sum3_re_sig(2) <= s_sum2_re_sig(2) + s_mult3_re_sig(2)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(2) <= s_sum2_im_sig(2) + s_mult3_im_sig(2)(b_size + w_size - 2 downto w_size - 2);
-- 3_й выход 3_ой стадии
s_sum3_re_sig(3) <= s_sum2_re_sig(3) + s_mult3_re_sig(3)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(3) <= s_sum2_im_sig(3) + s_mult3_im_sig(3)(b_size + w_size - 2 downto w_size - 2);
-- 4_й выход 3_й стадии
s_sum3_re_sig(4) <= s_sum2_re_sig(0) - s_mult3_re_sig(0)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(4) <= s_sum2_im_sig(0) - s_mult3_im_sig(0)(b_size + w_size - 2 downto w_size - 2);
-- 5_й выход 3_ой стадии
s_sum3_re_sig(5) <= s_sum2_re_sig(1) - s_mult3_re_sig(1)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(5) <= s_sum2_im_sig(1) - s_mult3_im_sig(1)(b_size + w_size - 2 downto w_size - 2);
-- 6_й выход 3_й стадии
s_sum3_re_sig(6) <= s_sum2_re_sig(2) - s_mult3_re_sig(2)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(6) <= s_sum2_im_sig(2) - s_mult3_im_sig(2)(b_size + w_size - 2 downto w_size - 2);
-- 7_й выход 3_ой стадии
s_sum3_re_sig(7) <= s_sum2_re_sig(3) - s_mult3_re_sig(3)(b_size + w_size - 2 downto w_size - 2);
s_sum3_im_sig(7) <= s_sum2_im_sig(3) - s_mult3_im_sig(3)(b_size + w_size - 2 downto w_size - 2);
end if;
end if;
-- выходной результат
doutr0 <= std_logic_vector(s_sum3_re_sig(0));
doutr1 <= std_logic_vector(s_sum3_re_sig(1));
doutr2 <= std_logic_vector(s_sum3_re_sig(2));
doutr3 <= std_logic_vector(s_sum3_re_sig(3));
doutr4 <= std_logic_vector(s_sum3_re_sig(4));
doutr5 <= std_logic_vector(s_sum3_re_sig(5));
doutr6 <= std_logic_vector(s_sum3_re_sig(6));
doutr7 <= std_logic_vector(s_sum3_re_sig(7));
douti0 <= std_logic_vector(s_sum3_im_sig(0));
douti1 <= std_logic_vector(s_sum3_im_sig(1));
douti2 <= std_logic_vector(s_sum3_im_sig(2));
douti3 <= std_logic_vector(s_sum3_im_sig(3));
douti4 <= std_logic_vector(s_sum3_im_sig(4));
douti5 <= std_logic_vector(s_sum3_im_sig(5));
douti6 <= std_logic_vector(s_sum3_im_sig(6));
douti7 <= std_logic_vector(s_sum3_im_sig(7));
-- тестовые выходы бабочи
dout_r_tst_up <= std_logic_vector(s_sum2_re_sig(1));
dout_i_tst_up <= std_logic_vector(s_sum2_im_sig(1));
dout_r_tst_down <= std_logic_vector(s_sum1_re_sig(1));
dout_i_tst_down <= std_logic_vector(s_sum1_im_sig(1));
end process;
end behavioural;
Все выполняется за 7 тактов тактовой частоты, после полной загрузки данных в буфер. Данный код не является идеалом, предназначен для общего понимания операций с комплексными числами на VHDL.
Для лучшего понимания, как все крутится, представлен готовый проект FFT 8 точек на VHDL для Quartus90. В проекте также представлен файл симулятора где показано, что все работает верно. На вход подаются две сдвинутые на 90 градусов друг относительно друга синусоиды. Синусоиды представлены в виде 8-ми выборок через 45 градусов. После завершения работы БПФ, получаем всплеск на одном из выходов, мнимом или действительном. При этом на других выходах нули. Кому проект пригодился оставьте свой коммент. Предложения и замечания тоже по ссылке для добавления комментов.
Электроника :
- Техника электроника (11)
- Полезная электроника (4)
- Электроника для всех (5)
- Техника для дома (6)
- Cхемотехника ПЛИС (11)
- Пректирование PCAD (4)
Программирование :
- Микроконтроллеры (9)
- ПЛИС VHDL Verilog (29)
- C++ Builder (7)
- Visual Studio C++ C# (7)
- Java programming (7)
- Matlab programming (4)
Сайтостроение :
- Сайтостроение HTML (5)
- Сайтостроение PHP (8)
- PHP CMS на файлах (3)
- Web инструменты (9)
- Полезное вебмастеру (11)
- SEO раскрутка сайта (4)
- PHP скрипты (3)
Реклама :
Книги и учебники :
- Шаблоны сайтов (6)
- Книги и учебники (2)
Компьютер и интернет :
Поиск по сайту :
Реклама :
Облако меток :
Бесплатная подписка :
Статистика :
- Популярность (3)
- Посещаемость (3)
- Поисковые запросы (3)