Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: БПФ ядро
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
Azatot
Всем доброго времени суток.Может кто-нибудь объяснить как пользоваться fft ядром, сформированным IP Core generator'ом? Прочитал datasheet на него, вроде все сделал, согласно временным диаграммам, ядро работает, но не правильно- результаты не соответствуют высчитаным вручную. Есть ли кто -нибудь, кто пользовался этим ядром и может объяснить что к чему, а еще лучше -выложить код на VHDL, где ядро используется? Был бы безмерно благодарен!
murmel1
Пользовался Этим ядром еще когда Квартус был не 8.1, а 5.0
Никаких проблем не имел.
Посмотрите внимательно на доп сигналы (групповая экспонента), проверьте временной отчет (а tco/tsu/th в порядке? используйте функциональную симуляцию), внимательно прочитайте инструкцию по шине Atlantic (недавно Altera переименовала ее в Avalon-ST). Могу завтра принести и выложить коды модулей которые загружают в нее данные из памяти и выгружают результат в другую память, но - на AHDL. Нужно ?
Azatot
Цитата(murmel1 @ Jan 11 2009, 22:56) *
Пользовался Этим ядром еще когда Квартус был не 8.1, а 5.0
Никаких проблем не имел.
Посмотрите внимательно на доп сигналы (групповая экспонента), проверьте временной отчет (а tco/tsu/th в порядке? используйте функциональную симуляцию), внимательно прочитайте инструкцию по шине Atlantic (недавно Altera переименовала ее в Avalon-ST). Могу завтра принести и выложить коды модулей которые загружают в нее данные из памяти и выгружают результат в другую память, но - на AHDL. Нужно ?

Спасибо большое,но меня интересует ядро для Xilinx, а не Altera. Всеравно спасибо.
Костян
Цитата(Azatot @ Jan 11 2009, 15:43) *
ядро работает, но не правильно- результаты не соответствуют высчитаным вручную.

Что контретно Вас не понравилось ?

Оно действительно иногда работает криво, помогает пересборка ядра.
faa
Цитата(Azatot @ Jan 11 2009, 20:43) *
Всем доброго времени суток.Может кто-нибудь объяснить как пользоваться fft ядром, сформированным IP Core generator'ом? Прочитал datasheet на него, вроде все сделал, согласно временным диаграммам, ядро работает, но не правильно- результаты не соответствуют высчитаным вручную. Есть ли кто -нибудь, кто пользовался этим ядром и может объяснить что к чему, а еще лучше -выложить код на VHDL, где ядро используется? Был бы безмерно благодарен!

Использовал корку БПФ на 4096 точек в XC3S1000: 16 бит вход, 29 бит на выхода (без усечения). На входе корки стоит умножитель для взвешивания. Все это управляется через FSM. Данные читаются из SDRAM и пишутся в нее же.
Корка БПФ, FSM, умножитель обернуты примерно так:
CODE

ibrary IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;
use WORK.common.all;

entity fft_wrap is
PORT (
clk : in std_logic;
rst : in std_logic;
start_fft : in std_logic;
--
din : in std_logic_vector(15 downto 0);
dout : out std_logic_vector(15 downto 0);
addr : out std_logic_vector(23 downto 0);
dcoef : in std_logic_vector(15 downto 0);
--
b_addrin : in std_logic_vector(10 downto 0);
b_addrout : in std_logic_vector(9 downto 0);
--
fft_rdy : out std_logic;
fft_busy : out std_logic;
fft_status : out std_logic_vector(3 downto 0);
--
fft_wr : out std_logic;
fft_rd : out std_logic;
sdr_done : in std_logic;
sdr_rddone : in std_logic

);
end fft_wrap;

architecture implement of fft_wrap is

component fft_4096
port (
clk: IN std_logic;
ce: IN std_logic;
start: IN std_logic;
unload: IN std_logic;
xn_re: IN std_logic_VECTOR(15 downto 0);
xn_im: IN std_logic_VECTOR(15 downto 0);
fwd_inv: IN std_logic;
fwd_inv_we: IN std_logic;
rfd: OUT std_logic;
xn_index: OUT std_logic_VECTOR(11 downto 0);
busy: OUT std_logic;
edone: OUT std_logic;
done: OUT std_logic;
dv: OUT std_logic;
xk_index: OUT std_logic_VECTOR(11 downto 0);
xk_re: OUT std_logic_VECTOR(28 downto 0);
xk_im: OUT std_logic_VECTOR(28 downto 0));
end component;

component mul16x16
port (
clk: IN std_logic;
a: IN std_logic_VECTOR(15 downto 0);
b: IN std_logic_VECTOR(15 downto 0);
p: OUT std_logic_VECTOR(31 downto 0));
end component;

--attribute syn_black_box : boolean;
--attribute syn_black_box of fft_4096: component is true;

constant DELAY_END : natural := 2; -- 2
constant ADDRIN_END : natural := 16#1FFF#; -- 8191
constant ADDROUT_END : natural := 16#3FFF#; -- 8191 * 2

signal xn_re_i : std_logic_vector(15 downto 0);
signal xk_re_i, xk_im_i : std_logic_vector(28 downto 0);
--
signal clk_fft : std_logic;
signal ce_i, start_i, fwd_inv_i, fwd_inv_we_i : std_logic;
signal rfd_i, busy_i, edone_i, done_i, dv_i : std_logic;
--
signal ld_in_re : std_logic;
signal addr_r, addr_x: std_logic_vector(13 downto 0);
--
type fft_state_type is (FFT_IDLE, FFT_INIT, FFT_WAIT,FFT_READ_RE, FFT_MUL_RE, FFT_READ_IM, FFT_MUL_IM,
FFT_WAIT_DV,
FFT_WRITE_REL, FFT_WRITE_REM, FFT_WRITE_IML, FFT_WRITE_IMM);
signal fft_state, fft_next_state : fft_state_type;
--
signal fft_status_i: std_logic_VECTOR(3 downto 0);
signal dmul : std_logic_VECTOR(31 downto 0);
--signal ain_mul1, bin_mul1, ain_mul2, bin_mul2 : std_logic_VECTOR(17 downto 0);


begin

clk_fft <= clk;

FFT_FSM_PROC: process(clk)
begin
if rising_edge(clk) then
if rst = RESET_ACTIVE then
fft_state <= FFT_IDLE;
else
fft_state <= fft_next_state;
addr_r <= addr_x;
end if;
end if;
end process FFT_FSM_PROC;

fwd_inv_i <= '1';

FSM_COMBINATORIAL: process(fft_state, start_fft, sdr_done, sdr_rddone, rfd_i, dv_i, addr_r)
begin
-- default
ce_i <= '0';
fwd_inv_we_i <= '0';
ld_in_re <= '0';
start_i <= '0';
fft_rdy <= '0';
fft_busy <= '1';
fft_wr <= '0';
fft_rd <= '0';
fft_status_i <= x"0";
fft_next_state <= fft_state;
addr_x <= addr_r;
case fft_state is
when FFT_IDLE =>
fft_busy <= '0';
fft_status_i <= x"f";
if start_fft ='1' then
fft_next_state <= FFT_INIT;
end if;
when FFT_INIT =>
start_i <= '1';
ce_i <= '1';
fwd_inv_we_i <= '1';
addr_x <= CONV_STD_LOGIC_VECTOR(0, addr_x'length);
fft_next_state <= FFT_WAIT;
when FFT_WAIT =>
ce_i <= '1';
if addr_r /= DELAY_END then
addr_x <= addr_r + 1;
else
fft_next_state <= FFT_READ_RE;
addr_x <= CONV_STD_LOGIC_VECTOR(0, addr_x'length);
end if;
when FFT_READ_RE =>
fft_status_i <= x"1";
if sdr_rddone = NO then
fft_rd <= '1';
else
fft_rd <= '0';
fft_next_state <= FFT_MUL_RE;
end if;
when FFT_MUL_RE =>
addr_x <= addr_r + 1;
ld_in_re <= '1';
fft_next_state <= FFT_READ_IM;
when FFT_READ_IM =>
fft_status_i <= x"2";
if sdr_rddone = NO then
fft_rd <= '1';
else
fft_rd <= '0';
fft_next_state <= FFT_MUL_IM;
end if;
when FFT_MUL_IM =>
ce_i <= '1';
if addr_r /= ADDRIN_END then
addr_x <= addr_r + 1;
fft_next_state <= FFT_READ_RE;
else
fft_next_state <= FFT_WAIT_DV;
end if;
when FFT_WAIT_DV =>
fft_status_i <= x"3";
ce_i <= '1';
if dv_i = '1' then
addr_x <= CONV_STD_LOGIC_VECTOR(0, addr_x'length);
fft_next_state <= FFT_WRITE_REL;
end if;
when FFT_WRITE_REL =>
fft_status_i <= x"4";
if sdr_done = NO then
fft_wr <= '1';
else
fft_wr <= '0';
addr_x <= addr_r + 1;
fft_next_state <= FFT_WRITE_REM;
end if;
when FFT_WRITE_REM =>
fft_status_i <= x"5";
if sdr_done = NO then
fft_wr <= '1';
else
fft_wr <= '0';
addr_x <= addr_r + 1;
fft_next_state <= FFT_WRITE_IML;
end if;
when FFT_WRITE_IML =>
fft_status_i <= x"6";
if sdr_done = NO then
fft_wr <= '1';
else
fft_wr <= '0';
addr_x <= addr_r + 1;
fft_next_state <= FFT_WRITE_IMM;
end if;
when FFT_WRITE_IMM =>
fft_status_i <= x"7";
if sdr_done = NO then
fft_wr <= '1';
elsif addr_r /= ADDROUT_END then
fft_wr <= '0';
ce_i <= '1';
addr_x <= addr_r + 1;
fft_next_state <= FFT_WRITE_REL;
else
fft_wr <= '0';
ce_i <= '1';
fft_next_state <= FFT_IDLE;
fft_rdy <= '1';
end if;
when others =>
fft_busy <= '0';
fft_status_i <= x"c";

end case;
end process FSM_COMBINATORIAL;

Inst_fft : fft_4096 port map (
clk => clk_fft, ce => ce_i, start => start_i, unload => edone_i,
xn_re => xn_re_i, xn_im => dmul(31 downto 16),
xn_index => open,
fwd_inv => fwd_inv_i, fwd_inv_we => fwd_inv_we_i,
rfd => rfd_i, busy => busy_i, edone => edone_i, done => done_i, dv => dv_i,
xk_index => open, xk_re => xk_re_i, xk_im => xk_im_i);
Inst_mult : mul16x16 port map (
clk => clk,
a => din,
b => dcoef,
p => dmul);

process(clk)
begin
if rising_edge(clk) then
if ld_in_re = '1' then
xn_re_i <= dmul(31 downto 16);
end if;
end if;
end process;

dout <= xk_re_i(15 downto 0) when addr_r(1 downto 0) = "00" else
xk_re_i(28) & xk_re_i(28) & xk_re_i(28) & xk_re_i(28 downto 16) when addr_r(1 downto 0) = "01" else
xk_im_i(15 downto 0) when addr_r(1 downto 0) = "10" else
xk_im_i(28) & xk_im_i(28) & xk_im_i(28) & xk_im_i(28 downto 16);

fft_status <= fft_status_i;

addr <= b_addrin & addr_r(12 downto 0) when (fft_state = FFT_READ_RE or fft_state = FFT_READ_IM) else
b_addrout & addr_r;

end implement;


Загрузка данных в темпе чтения из SDRAM, вычисления, выгрузка данных в SDRAM.
Память взвешивающих коэффициентов сделана в BRAM спартана.
Azatot
Спасибо всем огромное. Буду пробовать, как посоветовали.
VorteX
Я работал я ядрами FFT на Spartan и VirteX 4, правда в ISE 8 это было, но в общем-то все работало без проблем, результаты довольно точно совпадали с Матлабом. А ты пробовал примитивные сигналы, БПФ от постоянного сигнала, БПФ от синусоиды и пр?

Я на начальных этапах отладки сделал тестбенч: в Modelsim подавал данные из файла, обрабатывал и назад в файл, после чего в Матлабе сравнивал. Потом уже на плате по USB данные гонял.
Azatot
Хотелось бы опять попросить помощи. Внес поправки в код и ядро заработало, но только если на выходе положительные числа. А вот, когда на выходе должны получатся отрицательные числа, то начинается какая то мутота! Выдает черт знает что! Может, кто-нибудь подскажет как с отрицательными числами работать в этом ядре? Заранее благодарен.
VorteX
Цитата(Azatot @ Jan 23 2009, 17:22) *
Хотелось бы опять попросить помощи. Внес поправки в код и ядро заработало, но только если на выходе положительные числа. А вот, когда на выходе должны получатся отрицательные числа, то начинается какая то мутота! Выдает черт знает что! Может, кто-нибудь подскажет как с отрицательными числами работать в этом ядре? Заранее благодарен.


там вроде числа в дополнительном коде (twos complement): 0xFFFF соответствует -1, а 0x8000 соответствует -32768, попробуй задать массив из 0x8000 на вход и поглядеть что выйдет? По идее в нулевом отсчете должно быть большое отрицательное число, а остальные около нуля.
Azatot
Все огромное спасибо! Все,естественно просто,но, как обычно,то осцилограф дурной, то сам балда.smile.gifЕще раз спасибо!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.