реклама на сайте
подробности

 
 
23 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Реализация БПФ на ПЛИС, Тудности, встречаемые при реализации
ZED
сообщение Jan 18 2009, 19:19
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Доброго времени суток!

Нужно реализовать алгоритм БПФ с прореживанием по частоте на ПЛИС, но при реализации возникают трудности, вот некоторые из них:
  1. Поворачивающие множители являются числами по модулю меньше либо равно единицы: |W|<=1. Я так понял, чтобы перейти к целым числам требуется умножать их на (2^N) и то, что после запятой отсекать (N - разрядность). Нужно ли то же самое делать с входными данными (x1 и x2) или не обязательно?
  2. Нужно реализовать операции умножения и сложения со знаковыми числами, тут у меня такая задумка: преобразовать в 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. На форуме я искал и не нашел ответа на свои вопросы, тем более я уверен далее появятся новые, думаю лучше, чтоб это все было в одной теме...
Go to the top of the page
 
+Quote Post
soldat_shveyk
сообщение Jan 18 2009, 20:55
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 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 МГц.

Ну, а если время на выполнение БПФа достаточно много, то можно обойтись обычным ДПФ-ом, легко реализуется,
и вполне себя оправдывает, да и ошибкой квантования легче управлять - операция округления одна и выполняется она в самом конце.
Go to the top of the page
 
+Quote Post
Builder
сообщение Jan 18 2009, 20:57
Сообщение #3


iBuilder©
****

Группа: Свой
Сообщений: 519
Регистрация: 14-07-04
Из: Минск
Пользователь №: 322



Цитата(ZED @ Jan 18 2009, 23:19) *
Вопрос будет ли так корректно сделать или все делается совершенно по-другому?
Буду рад любым вашим замечаниям, предложениям, советам и ссылкам. Заранее спасибо!

Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс?
Возможность посмотреть исходники вроде есть.
Go to the top of the page
 
+Quote Post
ZED
сообщение Jan 18 2009, 21:26
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Цитата
Сам не знаю как лучше, но все-же, а если посмотреть как делает та-же Альтера или Ксалинкс?
Возможность посмотреть исходники вроде есть.

Пишу в квартусе, стало быть ПЛИС Альтера, если можно дайте ссылочку на исходник. У Калинкса нашел там для фиксированной запятой, пытался разобраться, не получилось...

Цитата
Для умножения знаковых чисел надо пользоваться специальной мегафункцией, указав ей параметр "SIGNED"

Так и думал, что сначала нужно перевести к типу SIGNED.
Нужно ли то же самое делать с входными данными (x1 и x2) или не обязательно?

Цитата
Если вы делаете БПФ на ПЛИС, то надо смотреть на алгоритмы по основанию 4, а не по основанию 2.

Тоже к этому склоняюсь. буду думать...

Цитата
round(W*(N-1)) - если число положительное,

вот это не совсем понял

Сообщение отредактировал ZED - Jan 18 2009, 21:45
Go to the top of the page
 
+Quote Post
soldat_shveyk
сообщение Jan 19 2009, 10:32
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 3-07-07
Из: С-Петербург
Пользователь №: 28 859



Я малость ошибся правильно будет так:

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.
Go to the top of the page
 
+Quote Post
ZED
сообщение Jan 19 2009, 16:28
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 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;
Go to the top of the page
 
+Quote Post
soldat_shveyk
сообщение Jan 20 2009, 07:41
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 3-07-07
Из: С-Петербург
Пользователь №: 28 859



Не силен в Verilog. Помочь не могу.
А не пробовали использовать мегафункцию FFT?
Go to the top of the page
 
+Quote Post
ZED
сообщение Jan 20 2009, 15:42
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Цитата
Не силен в Verilog. Помочь не могу.
А не пробовали использовать мегафункцию FFT?


Это VHDL, мегафункцию не пробовал, кстати посоветуете какую и где скачать? Но просто хочется самому реализовать, "ручками" так сказать. Я вот тоже к сожалению не силен в vhdl, но очень хочу его освоить, вот и задаю вопросы. В книжках она как правило не освещены, либо я читаю не те книжки. Кстати слышал вышла книжка: Перельройзен Е.З. Проектируем на VHDL. - М.: Изд-во "СОЛОН-Пресс", 2004. Читал кто? Как она? К сожалению уже все раскупили, где достать не знаю...
Go to the top of the page
 
+Quote Post
soldat_shveyk
сообщение Jan 20 2009, 19:38
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 3-07-07
Из: С-Петербург
Пользователь №: 28 859



ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии,
посмотрите, поиграете параметрами - выберете что Вам подойдет.
Там еще хелп достаточно полезный приложен.
Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию.
Go to the top of the page
 
+Quote Post
ZED
сообщение Jan 20 2009, 20:28
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Цитата
Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию.

Рабинер Голд имеется, но вот с языком проблемы, вот я и спрашиваю как то или иное реализовать на vhdl, почему так или иначе синтезирует квартус и т.д.
Цитата
ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии,
посмотрите, поиграете параметрами - выберете что Вам подойдет.

Спасибо, документацию нашел, а вот сам файл не смог скачать...
Go to the top of the page
 
+Quote Post
soldat_shveyk
сообщение Jan 21 2009, 10:33
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 3-07-07
Из: С-Петербург
Пользователь №: 28 859



Для ознакомительной работы в режиме OpenCore можно скачать без проблем. Пробуйте.

Еще погуглите кракнутый FFT Compiler, в сети полно этого добра. Для начала подойдет любая, не обязательно самая свежая версия.
Там можно будет и исходники посмотреть, они как раз на VHDL.
Go to the top of the page
 
+Quote Post
ZED
сообщение Jan 21 2009, 18:04
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Вопрос по vhdl остается открытым, но похоже кроме soldat_shveyk и меня эта тема (БПФ) никого не интересует...
Go to the top of the page
 
+Quote Post
soldat_shveyk
сообщение Jan 22 2009, 08:07
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 3-07-07
Из: С-Петербург
Пользователь №: 28 859



Откопал у себя исходники всех альтеровских БПФ-ов, если надо, пришлю.
Исходники рабочие, пользовался, проверял.
Go to the top of the page
 
+Quote Post
ZED
сообщение Jan 22 2009, 19:36
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Буду очень признателен: zed1986@yandex.ru

Спасибо! yeah.gif biggrin.gif
Go to the top of the page
 
+Quote Post
ZED
сообщение Jan 30 2009, 05:06
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 264
Регистрация: 17-04-07
Из: Москва
Пользователь №: 27 102



Возникла еще одна проблема, реализую БПФ по схеме "пинг-понг", т.е бабочка, две ОЗУ и одно ПЗУ для хранения поворачивающих множителей. Бабочку нужно подключать то к одной памяти на чтение, а к другой на запись, то на оборот:

ОЗУ - 1 | Чтение | Запись | Чтение | Запись |
-------------------------------------------------------------
ОЗУ - 2 | Запись | Чтение | Запись | Чтение |

И т.д. Вопрос такой, как это сделать, пробовал делать мультиплексирование, но ничего не выходит, может кто подскажет как это реализовать?
Go to the top of the page
 
+Quote Post

23 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th September 2018 - 22:05
Рейтинг@Mail.ru


Страница сгенерированна за 0.00939 секунд с 7
ELECTRONIX ©2004-2016