|
Реализация БПФ на ПЛИС, Тудности, встречаемые при реализации |
|
|
|
Jan 18 2009, 19:19
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102

|
Доброго времени суток! Нужно реализовать алгоритм БПФ с прореживанием по частоте на ПЛИС, но при реализации возникают трудности, вот некоторые из них: - Поворачивающие множители являются числами по модулю меньше либо равно единицы: |W|<=1. Я так понял, чтобы перейти к целым числам требуется умножать их на (2^N) и то, что после запятой отсекать (N - разрядность). Нужно ли то же самое делать с входными данными (x1 и x2) или не обязательно?
- Нужно реализовать операции умножения и сложения со знаковыми числами, тут у меня такая задумка: преобразовать в integer соответствующего диапазона: от -(2^N)/2 до (2^N)/2 - 1, произвести нужные арифметические операции и преобразовать обратно std_logic_vector, код прилагается:
CODE 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. На форуме я искал и не нашел ответа на свои вопросы, тем более я уверен далее появятся новые, думаю лучше, чтоб это все было в одной теме...
|
|
|
|
|
Jan 18 2009, 20:55
|
Местный
  
Группа: Свой
Сообщений: 454
Регистрация: 3-07-07
Из: С-Петербург
Пользователь №: 28 859

|
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 МГц.
Ну, а если время на выполнение БПФа достаточно много, то можно обойтись обычным ДПФ-ом, легко реализуется, и вполне себя оправдывает, да и ошибкой квантования легче управлять - операция округления одна и выполняется она в самом конце.
|
|
|
|
|
Jan 18 2009, 20:57
|
iBuilder©
   
Группа: Свой
Сообщений: 519
Регистрация: 14-07-04
Из: Минск
Пользователь №: 322

|
Цитата(ZED @ Jan 18 2009, 23:19)  Вопрос будет ли так корректно сделать или все делается совершенно по-другому? Буду рад любым вашим замечаниям, предложениям, советам и ссылкам. Заранее спасибо! Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс? Возможность посмотреть исходники вроде есть.
|
|
|
|
|
Jan 18 2009, 21:26
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102

|
Цитата Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс? Возможность посмотреть исходники вроде есть. Пишу в квартусе, стало быть ПЛИС Альтера, если можно дайте ссылочку на исходник. У Калинкса нашел там для фиксированной запятой, пытался разобраться, не получилось... Цитата Для умножения знаковых чисел надо пользоваться специальной мегафункцией, указав ей параметр "SIGNED" Так и думал, что сначала нужно перевести к типу SIGNED. Нужно ли то же самое делать с входными данными (x1 и x2) или не обязательно? Цитата Если вы делаете БПФ на ПЛИС, то надо смотреть на алгоритмы по основанию 4, а не по основанию 2. Тоже к этому склоняюсь. буду думать... Цитата round(W*(N-1)) - если число положительное, вот это не совсем понял
Сообщение отредактировал ZED - Jan 18 2009, 21:45
|
|
|
|
|
Jan 19 2009, 16:28
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102

|
Цитата Я малость ошибся правильно будет так: 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;
|
|
|
|
|
Jan 20 2009, 15:42
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102

|
Цитата Не силен в Verilog. Помочь не могу. А не пробовали использовать мегафункцию FFT? Это VHDL, мегафункцию не пробовал, кстати посоветуете какую и где скачать? Но просто хочется самому реализовать, "ручками" так сказать. Я вот тоже к сожалению не силен в vhdl, но очень хочу его освоить, вот и задаю вопросы. В книжках она как правило не освещены, либо я читаю не те книжки. Кстати слышал вышла книжка: Перельройзен Е.З. Проектируем на VHDL. - М.: Изд-во "СОЛОН-Пресс", 2004. Читал кто? Как она? К сожалению уже все раскупили, где достать не знаю...
|
|
|
|
|
Jan 20 2009, 20:28
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102

|
Цитата Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию. Рабинер Голд имеется, но вот с языком проблемы, вот я и спрашиваю как то или иное реализовать на vhdl, почему так или иначе синтезирует квартус и т.д. Цитата ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии, посмотрите, поиграете параметрами - выберете что Вам подойдет. Спасибо, документацию нашел, а вот сам файл не смог скачать...
|
|
|
|
|
Jan 30 2009, 05:06
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102

|
Возникла еще одна проблема, реализую БПФ по схеме "пинг-понг", т.е бабочка, две ОЗУ и одно ПЗУ для хранения поворачивающих множителей. Бабочку нужно подключать то к одной памяти на чтение, а к другой на запись, то на оборот:
ОЗУ - 1 | Чтение | Запись | Чтение | Запись | ------------------------------------------------------------- ОЗУ - 2 | Запись | Чтение | Запись | Чтение |
И т.д. Вопрос такой, как это сделать, пробовал делать мультиплексирование, но ничего не выходит, может кто подскажет как это реализовать?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|