|
Реализация БПФ на ПЛИС, Тудности, встречаемые при реализации |
|
|
|
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. На форуме я искал и не нашел ответа на свои вопросы, тем более я уверен далее появятся новые, думаю лучше, чтоб это все было в одной теме...
|
|
|
|
|
 |
Ответов
(270 - 284)
|
Mar 24 2010, 09:00
|
Участник

Группа: Участник
Сообщений: 57
Регистрация: 26-02-08
Из: Бердск
Пользователь №: 35 384

|
Цитата(Reddy @ Mar 1 2010, 01:31)  Кстати вопрос, а почему такие формулы вычисления гармоник? -- -- -- Вычисление y1 -- y_sig(1).re <= x_sig(0).re + x_sig(1).re - x_sig(2).re - x_sig(3).re + 2; -- y_sig(1).im <= x_sig(0).im - x_sig(1).im - x_sig(2).im + x_sig(3).im + 2;
а не такое: -- -- -- Вычисление y1 -- y_sig(1).re <= x_sig(0).re + x_sig(1).im - x_sig(2).re - x_sig(3).im + 2; -- y_sig(1).im <= x_sig(0).im - x_sig(1).re - x_sig(2).im + x_sig(3).re + 2; Туда же в догонку: должно быть -- Вычисление y3 y_sig(3).re <= x_sig(0).re - x_sig(1). im - x_sig(2).re + x_sig(3). im + 2; y_sig(3).im <= x_sig(0).im + x_sig(1). re - x_sig(2).im - x_sig(3). re + 2; З.Ы. Кстати, (пользуясь случаем  ) посоветуйте, пожалуйста, литературу по алгоритмам БПФ.
Сообщение отредактировал jb83 - Mar 24 2010, 09:46
--------------------
чайник электрический
|
|
|
|
|
Mar 26 2010, 08:41
|
Местный
  
Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537

|
Цитата(jb83 @ Mar 24 2010, 12:00)  Кстати, (пользуясь случаем  ) посоветуйте, пожалуйста, литературу по алгоритмам БПФ. Например, Л. Рабинер и Б. Гоулд "Теория и применение цифровой обработки сигналов".
|
|
|
|
|
Mar 26 2010, 11:08
|
Участник

Группа: Участник
Сообщений: 57
Регистрация: 26-02-08
Из: Бердск
Пользователь №: 35 384

|
Спасибо, поищу
--------------------
чайник электрический
|
|
|
|
|
Sep 25 2010, 20:11
|
Местный
  
Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537

|
Цитата(Maverick @ Sep 22 2010, 10:37)  Какой результат, этой титанической работы? Осталось уже не так и много. Я не оставляю надежду в октябре найти, все-таки, время и довести дело до конца.
|
|
|
|
|
Oct 23 2010, 16:16
|
Местный
  
Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537

|
Продолжим, по-тихоньку. Сейчас написано много кода и, как я уже писал, пора его "причесать" и оформить в проект. Начнем с package. В БПФ у нас есть необходимость выполнять некоторые промежуточные вычисления с "повышенной" разрядностью – поэтому есть необходимость в 2-х операциях расширение знака и извлечение определенных бит (как правило это старшие разряды). Чтобы избежать неудобоваримых выражений вроде "b_size + w_size - 3 downto w_size – 2" (complex_multiplier) в коде, перенесем их в функции, где они никого с толку сбивать не будут. Напишем 2 простые функции expand_sign и get_msb. Добавим в них проверку на корректность параметров. Проверим, что нумерация бит в передаваемом векторе имеет нисходящий порядок ( a downto b ) и что кол-во бит во входном векторе и результате правильно соотносятся друг с другом.
FFT_Project.rar ( 3.4 килобайт )
Кол-во скачиваний: 177Теперь поработаем над бабочкой. В синхронном дизайне не стоит оставлять регистры без Reset. Регистры без Reset также могут доставить массу неудобств и при моделировании. В начальный момент выходы регистров устанавливаются в неопределенное состояние 'U'. Далее лавинообразно все зависимые цепи также переходят в 'U', причем 'U' имеет приоритет. К примеру, "0000" and "UUUU" = "UUUU". В результате значительная часть или весь проект быстро переходит в состояние 'U'. Не самое лучшее состояние для анализа  . Выходит проект из этого состояния гораздо медленнее (тривиальные случаи не в счет), чем попадает, что так же не упрощает анализ. Тип сброса (синхронный/асинхронный) следует выбирать исходя из конкретной задачи и платформы для ее решения. Поскольку в нашем случае никаких ограничений нет, то выбираем синхронный сброс. Посмотрим на нынешний код бабочки: Код process (switch, x_sig, y_sig) begin if (switch = '0') then
y_sig(0).re <= x_sig(0).re + x_sig(1).re + x_sig(2).re + x_sig(3).re + 2; y_sig(0).im <= x_sig(0).im + x_sig(1).im + x_sig(2).im + x_sig(3).im + 2;
...
y_reg(0).re <= y_sig(0).re(data_size-1 + 2 downto 2); y_reg(0).im <= y_sig(0).im(data_size-1 + 2 downto 2);
...
else
y_sig(0).re <= x_sig(0).re + x_sig(1).re + 1; y_sig(0).im <= x_sig(0).im + x_sig(1).im + 1;
...
y_reg(0).re <= y_sig(0).re(data_size-1 + 1 downto 1); y_reg(0).im <= y_sig(0).im(data_size-1 + 1 downto 1);
...
end if; end process;
process begin
wait until (rising_edge(CLK)); y <= y_reg;
end process; Чтобы избежать лишних промежуточных регистро ZED разделил код на 2 process – комбинаторный, где производятся все операции и регистровый, где защелкивается результат. В этом случае, упростить код помогает использование variable. В коде есть копирование в вектор с большей разрядностью с расширением знака: Код x_sig(0).re <= (1 downto 0 => x(0).re(b_size-1)) & x(0).re; x_sig(0).im <= (1 downto 0 => x(0).im(b_size-1)) & x(0).im; ... и извлечение старших бит: Код y(0).re <= y_sig(0).re(b_size-1 + 2 downto 2); y(0).im <= y_sig(0).im(b_size-1 + 2 downto 2); ... Для того, чтобы избавиться от множества одинаковых строк с разными индексами мы не ограничимся использованием функций expand_sign и get_msb из FFT_Package. Добавим в Butterfly свои expand_sign и get_msb, которые будут вызывать функции из FFT_Package для всех членов complex_data_bus.
FFT_Project.rar ( 3.4 килобайт )
Кол-во скачиваний: 177
|
|
|
|
|
Nov 28 2010, 08:44
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 23-11-08
Пользователь №: 41 876

|
Здравствуйте. Спасибо за очень полезную тему. У меня есть несколько вопросов касательно БПФ. Необходимо реализовать преобразователь на 1152, 1024, 704 и 448 отсчетов, при этом длина должна выбираться динамически. Возможно ли сделать такой универсальный преобразователь или лучше сделать четыре отдельных с фиксированной длиной? Как я понял, здесь применим алгоритм Cooley-Tukey со смешанными основаниями, т.е. например, 1152 раскладывается как 43322. Также читал про алгоритм Блуштейна (Bluestein's chirp-z) и ряд других. Какой лучше подходит для данной задачи? Может кто-то сталкивался с подобной проблемой? Буду признателен за советы.
|
|
|
|
|
Nov 29 2010, 06:37
|
Местный
  
Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102

|
Динамически тут будет сделать трудно, ибо для каждого из Ваших БПФ (на 1152, 1024, 704 и 448 отсчетов) используются разные виды "бабочек" - двухточечная, трехточечная и четырехточечная. Таким образом, алгоритм не имеет постоянной структуры вычислений. Вот если бы, например, Вам нужно было вычислить БПФ на 512, 1024 и 2048 точек, то нет проблем динамически задавать какое из этих БПФ должно выполняться, т.к. можно взять в качестве базовой операции двухточечную "бабочку", а меняется только количество этапов и количество итераций в этапе. Ну это мое мнение, оно может быть ошибочно. Касательно второго вопроса, на сколько я помню (опять же могу ошибаться), алгоритм Блуштейна включает в себя вычисление свертки, которое вычисляется с помощью БПФ. Т.е. также очень сложно будет постороить алгоритм с динамическим выбором длины. Наверное, проще всего будет дополнять исходные массивы (1152, 1024, 704 и 448) нулями до степени 2 (получатся БПФ на 2048, 1024, 1024 и 512 отсчетов соответственно), выбрать в качестве базовой операции двухточечную бабочку и делать как я описал выше.
|
|
|
|
|
Nov 29 2010, 07:47
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 23-11-08
Пользователь №: 41 876

|
К сожалению, нулями дополнить нельзя. БПФ нужно для демодулятора OFDM, соответственно длительность OFDM-символа определяет количество точек преобразования (если я все правильно понял).
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|