ZED 0 January 18, 2009 Posted January 18, 2009 · Report post Доброго времени суток! Нужно реализовать алгоритм БПФ с прореживанием по частоте на ПЛИС, но при реализации возникают трудности, вот некоторые из них: Поворачивающие множители являются числами по модулю меньше либо равно единицы: |W|<=1. Я так понял, чтобы перейти к целым числам требуется умножать их на (2^N) и то, что после запятой отсекать (N - разрядность). Нужно ли то же самое делать с входными данными (x1 и x2) или не обязательно? Нужно реализовать операции умножения и сложения со знаковыми числами, тут у меня такая задумка: преобразовать в integer соответствующего диапазона: от -(2^N)/2 до (2^N)/2 - 1, произвести нужные арифметические операции и преобразовать обратно std_logic_vector, код прилагается: library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; entity butterfly is generic (b_size: natural := 14); port ( x1, x2, w: in std_logic_vector(b_size - 1 downto 0); y1, y2: out std_logic_vector(b_size - 1 downto 0) ); end entity butterfly; architecture behavioral of butterfly is signal x1_int, x2_int, w_int: integer range -8192 to 8191; signal y1_int: integer range -8192 to 8191; signal y2_int: integer range -134217728 to 134217727; -- Т.к. производится умножение на поворачивающий множитель begin process (CLK) is begin -- Преобразовываю в тип integer: x1_int <= conv_integer(x1); x2_int <= conv_integer(x2); w_int <= conv_integer(w); y1_int <= conv_integer(y1); y2_int <= conv_integer(y2); -- Вычисляю бабочку и преобразовываю обратно в std_logic_vector (b_size - 1 downto 0): y1 <= conv_std_logic_vector(x1_int + x2_int, b_size); y2 <= conv_std_logic_vector((x1_int - x2_int) * w_int, b_size); end process; end architecture behavioral; Вопрос будет ли так корректно сделать или все делается совершенно по-другому? Буду рад любым вашим замечаниям, предложениям, советам и ссылкам. Заранее спасибо! P.S. На форуме я искал и не нашел ответа на свои вопросы, тем более я уверен далее появятся новые, думаю лучше, чтоб это все было в одной теме... Quote Share this post Link to post Share on other sites More sharing options...
soldat_shveyk 4 January 18, 2009 Posted January 18, 2009 · Report post 1. Чтобы поворачивающий множитель W, меньший единицы, преобразовать в целое число, имеющее разрядность N бит, надо выполнить следующее преобразование: round(W*(N-1)) - если число положительное, (2^N) - round(abs(W)*(N-1)) - если число отрицательное. Правила приведены для дополнительного кода. 2. Для умножения знаковых чисел надо пользоваться специальной мегафункцией, указав ей параметр "SIGNED" 3. Если вы делаете БПФ на ПЛИС, то надо смотреть на алгоритмы по основанию 4, а не по основанию 2. Получается намного удобнее и эффективнее. Классическая бабочка - наследие от процессоров DSP, где она сделана аппаратно. Ядром алгоритма БПФ по основанию 4 является более сложный 4-х точечный БПФ, где все поворачивающие множители равны либо 1, либо -1. На ПЛИС удобно реализуется на сумматорах, можно сделать комбинаторную сехему, выполняющею этот самый 4-х точечный БПФ за один такт. Я такое делал, железно работало на частотах выше 100 МГц. Ну, а если время на выполнение БПФа достаточно много, то можно обойтись обычным ДПФ-ом, легко реализуется, и вполне себя оправдывает, да и ошибкой квантования легче управлять - операция округления одна и выполняется она в самом конце. Quote Share this post Link to post Share on other sites More sharing options...
Builder 1 January 18, 2009 Posted January 18, 2009 · Report post Вопрос будет ли так корректно сделать или все делается совершенно по-другому? Буду рад любым вашим замечаниям, предложениям, советам и ссылкам. Заранее спасибо! Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс? Возможность посмотреть исходники вроде есть. Quote Share this post Link to post Share on other sites More sharing options...
ZED 0 January 18, 2009 Posted January 18, 2009 (edited) · Report post Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс? Возможность посмотреть исходники вроде есть. Пишу в квартусе, стало быть ПЛИС Альтера, если можно дайте ссылочку на исходник. У Калинкса нашел там для фиксированной запятой, пытался разобраться, не получилось... Для умножения знаковых чисел надо пользоваться специальной мегафункцией, указав ей параметр "SIGNED" Так и думал, что сначала нужно перевести к типу SIGNED. Нужно ли то же самое делать с входными данными (x1 и x2) или не обязательно? Если вы делаете БПФ на ПЛИС, то надо смотреть на алгоритмы по основанию 4, а не по основанию 2. Тоже к этому склоняюсь. буду думать... round(W*(N-1)) - если число положительное, вот это не совсем понял Edited January 18, 2009 by ZED Quote Share this post Link to post Share on other sites More sharing options...
soldat_shveyk 4 January 19, 2009 Posted January 19, 2009 · Report post Я малость ошибся правильно будет так: round(W*(2^(N-1)-1)) Пример: допустим, поворачивающий множитель равен W=0.077391 и нужно преобразовать в 16-разрядную целочисленную форму, представленную в дополнительном коде (1 знаковый бит + 15 бит мантисса). (2^15) - 1 = 32767. 0.077391 * 32767 = 2535.8709 - дробную часть нельзя просто отбросить, нужно выполнять честное округление, чтобы ошибка была центрированая, поэтому round(2535.8709) = 2536. Quote Share this post Link to post Share on other sites More sharing options...
ZED 0 January 19, 2009 Posted January 19, 2009 · Report post Я малость ошибся правильно будет так: round(W*(2^(N-1)-1)) Теперь понятно, спасибо! Вот такой еще вопрос возник, нужно реализовать ПЗУ (ROM) для поворачивающих множителей, планирую подавать адрес и читать из файла, но Квартус синтезирует RAM память, а не ROM со всякими там WE, data_in и т.д., которые соответственно подключены либо к генератору нуля или единицы. А из файла не читает, не пойму может я где ошибся или нужно что-то указывать при синтезе, вот мой код: library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use std.textio.all; entity fft_rom is generic(addr_size : natural := 5; data_size : natural := 14); port( clk: in std_logic; addr: in std_logic_vector (addr_size - 1 downto 0); data: out std_logic_vector (data_size - 1 downto 0) ); end entity fft_rom; architecture behavioral of fft_rom is type RomType is array (0 to 2**5) of bit_vector(data_size - 1 downto 0); -- Функция чтения из файла: function FillRom (RomFileName: in string) return RomType is file RomFile: text is in RomFileName; variable RomFileLine : line; variable ROM: RomType; begin for i in RomType'range loop readline(RomFile, RomFileLine); read (RomFileLine, ROM(i)); end loop; return ROM; end function; -- конец функции signal ROM: RomType := FillRom("C:\ROM.dat"); begin process(clk) begin if (clk'event and clk = '1') then data <= to_stdlogicvector(ROM(conv_integer(addr))); end if; end process; end architecture behavioral; С Квартусом никогда не работал, может кто чего посоветует? P.S. Также остается открытым вопрос, корректно таким способом организовать бабочку или же это делается другими методами? library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity butterfly is generic (b_size: natural := 14); port(CLK: in std_logic; x1: in std_logic_vector(b_size - 1 downto 0); x2: in std_logic_vector(b_size - 1 downto 0); w: in std_logic_vector(b_size - 1 downto 0); y1: out std_logic_vector(b_size - 1 downto 0); y2: out std_logic_vector(b_size- 1 downto 0) ); end entity butterfly; architecture behavioral of butterfly is signal x1_int : integer range -8192 to 8191; signal x2_int : integer range -8192 to 8191; signal w_int : integer range -8192 to 8191; signal y1_int : integer range -8192 to 8192; signal y2_int : integer range -13427728 to 13427727; begin x1_int <= to_integer(signed (x1)); x2_int <= to_integer(signed (x2)); w_int <= to_integer(signed (w)); process (CLK) begin if (rising_edge(CLK)) then y1_int <= x1_int + x2_int; y2_int <= (x1_int - x2_int)*w_int; end if; end process; y1 <= std_logic_vector(to_signed(y1_int, b_size)); y2 <= std_logic_vector(to_signed(y2_int, b_size)); end behavioral; Quote Share this post Link to post Share on other sites More sharing options...
soldat_shveyk 4 January 20, 2009 Posted January 20, 2009 · Report post Не силен в Verilog. Помочь не могу. А не пробовали использовать мегафункцию FFT? Quote Share this post Link to post Share on other sites More sharing options...
ZED 0 January 20, 2009 Posted January 20, 2009 · Report post Не силен в Verilog. Помочь не могу. А не пробовали использовать мегафункцию FFT? Это VHDL, мегафункцию не пробовал, кстати посоветуете какую и где скачать? Но просто хочется самому реализовать, "ручками" так сказать. Я вот тоже к сожалению не силен в vhdl, но очень хочу его освоить, вот и задаю вопросы. В книжках она как правило не освещены, либо я читаю не те книжки. Кстати слышал вышла книжка: Перельройзен Е.З. Проектируем на VHDL. - М.: Изд-во "СОЛОН-Пресс", 2004. Читал кто? Как она? К сожалению уже все раскупили, где достать не знаю... Quote Share this post Link to post Share on other sites More sharing options...
soldat_shveyk 4 January 20, 2009 Posted January 20, 2009 · Report post ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии, посмотрите, поиграете параметрами - выберете что Вам подойдет. Там еще хелп достаточно полезный приложен. Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию. Quote Share this post Link to post Share on other sites More sharing options...
ZED 0 January 20, 2009 Posted January 20, 2009 · Report post Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию. Рабинер Голд имеется, но вот с языком проблемы, вот я и спрашиваю как то или иное реализовать на vhdl, почему так или иначе синтезирует квартус и т.д. ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии, посмотрите, поиграете параметрами - выберете что Вам подойдет. Спасибо, документацию нашел, а вот сам файл не смог скачать... Quote Share this post Link to post Share on other sites More sharing options...
soldat_shveyk 4 January 21, 2009 Posted January 21, 2009 · Report post Для ознакомительной работы в режиме OpenCore можно скачать без проблем. Пробуйте. Еще погуглите кракнутый FFT Compiler, в сети полно этого добра. Для начала подойдет любая, не обязательно самая свежая версия. Там можно будет и исходники посмотреть, они как раз на VHDL. Quote Share this post Link to post Share on other sites More sharing options...
ZED 0 January 21, 2009 Posted January 21, 2009 · Report post Вопрос по vhdl остается открытым, но похоже кроме soldat_shveyk и меня эта тема (БПФ) никого не интересует... Quote Share this post Link to post Share on other sites More sharing options...
soldat_shveyk 4 January 22, 2009 Posted January 22, 2009 · Report post Откопал у себя исходники всех альтеровских БПФ-ов, если надо, пришлю. Исходники рабочие, пользовался, проверял. Quote Share this post Link to post Share on other sites More sharing options...
ZED 0 January 22, 2009 Posted January 22, 2009 · Report post Буду очень признателен: zed1986@yandex.ru Спасибо! :yeah: Quote Share this post Link to post Share on other sites More sharing options...
ZED 0 January 30, 2009 Posted January 30, 2009 · Report post Возникла еще одна проблема, реализую БПФ по схеме "пинг-понг", т.е бабочка, две ОЗУ и одно ПЗУ для хранения поворачивающих множителей. Бабочку нужно подключать то к одной памяти на чтение, а к другой на запись, то на оборот: ОЗУ - 1 | Чтение | Запись | Чтение | Запись | ------------------------------------------------------------- ОЗУ - 2 | Запись | Чтение | Запись | Чтение | И т.д. Вопрос такой, как это сделать, пробовал делать мультиплексирование, но ничего не выходит, может кто подскажет как это реализовать? Quote Share this post Link to post Share on other sites More sharing options...