ZED 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Доброго времени суток! Нужно реализовать алгоритм БПФ с прореживанием по частоте на ПЛИС, но при реализации возникают трудности, вот некоторые из них: Поворачивающие множители являются числами по модулю меньше либо равно единицы: |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. На форуме я искал и не нашел ответа на свои вопросы, тем более я уверен далее появятся новые, думаю лучше, чтоб это все было в одной теме... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
soldat_shveyk 3 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба 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 МГц. Ну, а если время на выполнение БПФа достаточно много, то можно обойтись обычным ДПФ-ом, легко реализуется, и вполне себя оправдывает, да и ошибкой квантования легче управлять - операция округления одна и выполняется она в самом конце. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Builder 1 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Вопрос будет ли так корректно сделать или все делается совершенно по-другому? Буду рад любым вашим замечаниям, предложениям, советам и ссылкам. Заранее спасибо! Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс? Возможность посмотреть исходники вроде есть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 18 января, 2009 Опубликовано 18 января, 2009 (изменено) · Жалоба Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс? Возможность посмотреть исходники вроде есть. Пишу в квартусе, стало быть ПЛИС Альтера, если можно дайте ссылочку на исходник. У Калинкса нашел там для фиксированной запятой, пытался разобраться, не получилось... Для умножения знаковых чисел надо пользоваться специальной мегафункцией, указав ей параметр "SIGNED" Так и думал, что сначала нужно перевести к типу SIGNED. Нужно ли то же самое делать с входными данными (x1 и x2) или не обязательно? Если вы делаете БПФ на ПЛИС, то надо смотреть на алгоритмы по основанию 4, а не по основанию 2. Тоже к этому склоняюсь. буду думать... round(W*(N-1)) - если число положительное, вот это не совсем понял Изменено 18 января, 2009 пользователем ZED Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
soldat_shveyk 3 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба Я малость ошибся правильно будет так: 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба Я малость ошибся правильно будет так: 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
soldat_shveyk 3 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба Не силен в Verilog. Помочь не могу. А не пробовали использовать мегафункцию FFT? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба Не силен в Verilog. Помочь не могу. А не пробовали использовать мегафункцию FFT? Это VHDL, мегафункцию не пробовал, кстати посоветуете какую и где скачать? Но просто хочется самому реализовать, "ручками" так сказать. Я вот тоже к сожалению не силен в vhdl, но очень хочу его освоить, вот и задаю вопросы. В книжках она как правило не освещены, либо я читаю не те книжки. Кстати слышал вышла книжка: Перельройзен Е.З. Проектируем на VHDL. - М.: Изд-во "СОЛОН-Пресс", 2004. Читал кто? Как она? К сожалению уже все раскупили, где достать не знаю... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
soldat_shveyk 3 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии, посмотрите, поиграете параметрами - выберете что Вам подойдет. Там еще хелп достаточно полезный приложен. Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию. Рабинер Голд имеется, но вот с языком проблемы, вот я и спрашиваю как то или иное реализовать на vhdl, почему так или иначе синтезирует квартус и т.д. ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии, посмотрите, поиграете параметрами - выберете что Вам подойдет. Спасибо, документацию нашел, а вот сам файл не смог скачать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
soldat_shveyk 3 21 января, 2009 Опубликовано 21 января, 2009 · Жалоба Для ознакомительной работы в режиме OpenCore можно скачать без проблем. Пробуйте. Еще погуглите кракнутый FFT Compiler, в сети полно этого добра. Для начала подойдет любая, не обязательно самая свежая версия. Там можно будет и исходники посмотреть, они как раз на VHDL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 21 января, 2009 Опубликовано 21 января, 2009 · Жалоба Вопрос по vhdl остается открытым, но похоже кроме soldat_shveyk и меня эта тема (БПФ) никого не интересует... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
soldat_shveyk 3 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба Откопал у себя исходники всех альтеровских БПФ-ов, если надо, пришлю. Исходники рабочие, пользовался, проверял. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба Буду очень признателен: [email protected] Спасибо! :yeah: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZED 0 30 января, 2009 Опубликовано 30 января, 2009 · Жалоба Возникла еще одна проблема, реализую БПФ по схеме "пинг-понг", т.е бабочка, две ОЗУ и одно ПЗУ для хранения поворачивающих множителей. Бабочку нужно подключать то к одной памяти на чтение, а к другой на запись, то на оборот: ОЗУ - 1 | Чтение | Запись | Чтение | Запись | ------------------------------------------------------------- ОЗУ - 2 | Запись | Чтение | Запись | Чтение | И т.д. Вопрос такой, как это сделать, пробовал делать мультиплексирование, но ничего не выходит, может кто подскажет как это реализовать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться