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

 
 
23 страниц V  « < 7 8 9 10 11 > »   
Reply to this topicStart new topic
> Реализация БПФ на ПЛИС, Тудности, встречаемые при реализации
ZED
сообщение Apr 7 2009, 14:03
Сообщение #121


Местный
***

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



Цитата
Во-первых, подправьте код умножителей под диапазон коэффициентов -1024 ... +1024, поскольку после умножения делить нам надо теперь на 1024.

Поправил, прилагается;

Цитата
о-вторых, теперь, когда мы разобрались с умножением, нужен ли нам 0-ой умножитель в блоке умножителей?

Думаю нет, зачем нам постоянно умножать на 1?

Цитата
В-третьих, в начале было решено, что вычисление бабочки и умножение на коэф. делаем за один такт. В таком случае, регистры на выходе бабочки нужно перенести на выход умножителей.

Вот тут я не совсем понял, получается мне код для умножителей нужно впихнуть в код для бабочки? Код бабочки прилагаю: http://webfile.ru/3392071

Цитата
В-четвертых, все блоки нашего БПФ имеют на входе и выходе один и тот же набор сигналов (относящийся к данным БПФ) и эти сигналы представляют собой комплексные числа. Я предлагаю воспользоваться такой возможностью языка как record и задать тип complex_data и complex_coef для данных и коэффициентов. Еще задать тип complex_data_vector и complex_coef_vector с параметризованной размерностью, чтобы не "таскать" везде по четыре сигнала данных и по три сигнала с коэффициентами. Все это, для удобства, объявить в package - скажем fft_pkg. Все сказанное в это пункте никак не влияет на работоспособность, поэтому если не хотите, то можете этого не делать.

Сделаю позже, пока нужно с 3 пунктом разобраться.

Цитата
Вы с ModelSim работали?

Работал немного.
Прикрепленные файлы
Прикрепленный файл  complex_multiplier.rar ( 618.7 килобайт ) Кол-во скачиваний: 92
 
Go to the top of the page
 
+Quote Post
Sefo
сообщение Apr 7 2009, 22:10
Сообщение #122


Местный
***

Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537



Цитата(ZED @ Apr 7 2009, 18:03) *
Вот тут я не совсем понял, получается мне код для умножителей нужно впихнуть в код для бабочки?


С чего Вы это взяли? Никто никого не обязывает ставить регистры на выходе блока. Чисто комбинаторный блок это вполне нормально. Я имел ввиду, что бабочка у нас не будет содержать регистров - будет чисто комбинаторной, а умножители будут иметь регистры на выходе. Впрочем, если хотите, то можете поставить регистры на выходе и бабочки и умножителей - это увеличит pipeline на 1 и практически никак не повлияет на скорость вычисления самого БПФ (ну будет БПФ вычисляться на 6 тактов дольше, ну и что...)

Кстати, о бабочке. Пока Вы не убрали из нее регистры, объясните мне пожалуйста, почему бабочка тратит на вычисления аж 2 такта вместо 1? Зачем Вы сделали двойное защелкивание? Бабочка (в отличие, например, от умножителей, особенно если их синтезировать на обычных ячейках, а не на DSP-блоках) выполняет настолько простые операции, что защелкивать промежуточный результат абсолютно бессмысленно - лишняя трата регистров smile.gif.
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 8 2009, 16:12
Сообщение #123


Местный
***

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



Цитата
Чисто комбинаторный блок это вполне нормально. Я имел ввиду, что бабочка у нас не будет содержать регистров - будет чисто комбинаторной, а умножители будут иметь регистры на выходе.

Да, но бабочка содержит процесс, а это уже регистр. процесс убрать нельзя, т.к. конструкция if последовательная, а значит может содержаться только в процессе. Тут вижу выход только описывать эти 2 бабочки как компоненты, а затем применять конструкцию if generate. Ну можно в процесс засунуть тупо все сигналы, чтобы он запускался при изменении каждого из них.

Цитата
Кстати, о бабочке. Пока Вы не убрали из нее регистры, объясните мне пожалуйста, почему бабочка тратит на вычисления аж 2 такта вместо 1? Зачем Вы сделали двойное защелкивание?

Я его не хотел делать, так вышло=)) Но тем не менее Quartus ставит промежуточный регистр. Это происходит как раз из-за различных назначений сигналам yi_re_sig/yi_im_sig, i=0,1,2,3 при конструкции if else/
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 9 2009, 03:50
Сообщение #124


Местный
***

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



На счет if generate я погорячился, даже сказал бы тупанул, можно просто каждый сигнал yi_re_sig/yi_im_sig, i=0,1,2,3 посадить на case/ Таким образом уберется процесс и сгенеряться мультиплексоры. бабочка станет чисто комбинационной. Вечером попробую...
Go to the top of the page
 
+Quote Post
Sefo
сообщение Apr 9 2009, 09:20
Сообщение #125


Местный
***

Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537



Цитата(ZED @ Apr 8 2009, 20:12) *
Да, но бабочка содержит процесс, а это уже регистр.



Цитата(ZED @ Apr 9 2009, 07:50) *
На счет if generate я погорячился, даже сказал бы тупанул, можно просто каждый сигнал yi_re_sig/yi_im_sig, i=0,1,2,3 посадить на case/ Таким образом уберется процесс и сгенеряться мультиплексоры. бабочка станет чисто комбинационной. Вечером попробую...


Спокойствие... только спокойствие.

process никогда и ни при каких обстоятельствах не является признаком регистра. Покажите мне того человека, который сказал Вам, что "process - это регистр" ?

Синтезатор "детектирует" наличие регистра по конструкциям вида
CLK'event and CLK = '1', rising_edge(clk) и т.д.

Если Вы напишите такой, например, код
CODE
process(SEL,B,C,D,E)
begin
if SEL = '0' then
A <= B or C;
else
A <= C and D;
end if;
end process

то получите обычную комбинаторную логику - никаких регистров синтезатор и не подумает поставить.

Причем, если вместо process(SEL,B,C,D,E) Вы напишите process(SEL,B,C), то синтезатор все сделает правильно, но вот симулятор просимулирует неправильно.

Если вне всякого процесса Вы напишите
CODE
A <= B when rising_edge(CLK) else A;

то получите регистр и без использования process.
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 9 2009, 15:06
Сообщение #126


Местный
***

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



Цитата
process никогда и ни при каких обстоятельствах не является признаком регистра.

Я знаю. Я в принципе так и указал:
Цитата
Ну можно в процесс засунуть тупо все сигналы, чтобы он запускался при изменении каждого из них.

Просто сигналов уж больно много.
Вот проект: http://webfile.ru/3398933

Сообщение отредактировал ZED - Apr 9 2009, 15:44
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 9 2009, 15:46
Сообщение #127


Местный
***

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



Я переправил, просто исправил позже, чем вы ответили...
Go to the top of the page
 
+Quote Post
Sefo
сообщение Apr 9 2009, 15:50
Сообщение #128


Местный
***

Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537



Ok. А как обстоят дела с введением record?
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 9 2009, 17:03
Сообщение #129


Местный
***

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



В процессе, сейчас хочу все соединить поскорее, а recordом я не пользовался, нужно почитать, постараюсь завтра сделать.

Соеденил:
http://webfile.ru/3399176
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 10 2009, 03:58
Сообщение #130


Местный
***

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



Прошу прощения забыл регистры, на выходе для отсчетов y0_re, y0_im:
http://webfile.ru/3400144
Go to the top of the page
 
+Quote Post
Sefo
сообщение Apr 12 2009, 02:20
Сообщение #131


Местный
***

Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537



наконец-то выдалось немного свободного времени - посмотрел Ваш код.

1) Зачем, всетаки, приставка but к портам бабочки ?

2) Зачем в умножителе Вы ввели еще один промежуточный сигнал result_re_buf ? Чем Вам не нравится такой код smile.gif ?
CODE
process(CLK)
begin
if (rising_edge(CLK)) then
result_re <= std_logic_vector(result_re_sig(b_size + w_size - 3 downto w_size - 2 ));
result_im <= std_logic_vector(result_im_sig(b_size + w_size - 3 downto w_size - 2));
end if;
end process;


3) Зачем Вам resize в умножителе? Если бы это был просто умножитель предназначенный для чего угодно, то требуется учесть возможность переполнения при +/-. Но тогда и выход должен уже быть не 17 разрядов, а 18. Наш умножитель он только для нашего БПФ годится, а в нашем БПФ в умножителе уже не будет переполнения при +/-. Кстати, объясните почему?

4) Зачем в бабочке регистр на y0? Очень плохая идея и стиль выравнивать задержки не там где создается "перекос". У нас регистры стоят в умножителях, 0-ой умножитель удален за ненадобностью, но раз имменно в нем был регистр, то именно вместо него в блоке умножителей и надо поставить регистр для выравнивания, а не в бабочке.

Пока мы разбираемся с кодом бабочки и умножителя и вводим record (как там дела? ) давайте параллельно подумаем про память - нам скоро ей заниматься. Посмотрите, пожалуйста, на последнюю версию блок схемы. Согласно блок-схеме у нас получаются два совершенно разных блока памяти. Что нужно добавить на блок схеме, чтобы блоки памяти у нас были совершенно одинаковыми?
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 13 2009, 17:12
Сообщение #132


Местный
***

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



Цитата
1) Зачем, всетаки, приставка but к портам бабочки ?

Чтобы не запутаться, убрал...

Цитата
2) Зачем в умножителе Вы ввели еще один промежуточный сигнал result_re_buf

Опять же, чтобы не запутаться, убрал...=)

Цитата
3) Зачем Вам resize в умножителе? Если бы это был просто умножитель предназначенный для чего угодно, то требуется учесть возможность переполнения при +/-. Но тогда и выход должен уже быть не 17 разрядов, а 18. Наш умножитель он только для нашего БПФ годится, а в нашем БПФ в умножителе уже не будет переполнения при +/-. Кстати, объясните почему?

Resize не нужен т.к. мы расширили до 17 разрядов отчсеты и до 12 разрядов поворачивающие множители, убрал...

Цитата
4) Зачем в бабочке регистр на y0? Очень плохая идея и стиль выравнивать задержки не там где создается "перекос". У нас регистры стоят в умножителях, 0-ой умножитель удален за ненадобностью, но раз имменно в нем был регистр, то именно вместо него в блоке умножителей и надо поставить регистр для выравнивания, а не в бабочке.

Перенес регистр из бабочки в блок умножителей.

Цитата
Пока мы разбираемся с кодом бабочки и умножителя и вводим record (как там дела? )

Не было времени разобраться.

Цитата
Посмотрите, пожалуйста, на последнюю версию блок схемы. Согласно блок-схеме у нас получаются два совершенно разных блока памяти. Что нужно добавить на блок схеме, чтобы блоки памяти у нас были совершенно одинаковыми?

Не хватает мультиплексора, исправил, прилагаю: http://webfile.ru/3409277

Код полной бабочки: http://webfile.ru/3409275
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 14 2009, 13:08
Сообщение #133


Местный
***

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



Никак не пойму, что нужно с записью сделать, как она должна выглядеть, вот до чего я пока додумался:
Код
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

package fft_pkg is
    constant b_size: natural := 17;
    constant w_size: natural := 12;
    
    type complex_data is record
        x_re: std_logic_vector(b_size - 1 downto 0);
        x_im: std_logic_vector(b_size - 1 downto 0);
    end record;
    
    type complex_coef is record
        w_re: std_logic_vector(w_size - 1 downto 0);
        w_im: std_logic_vector(w_size - 1 downto 0);
    end record;
    
    type complex_data_vector is record
        x0: complex_data;
        x1: complex_data;
        x2: complex_data;
        x3: complex_data;
    end record;
    
    type complex_coef_vector is record
        w1: complex_coef;
        w2: complex_coef;
        w3: complex_coef;
    end record;
end package fft_pkg;



Акак же тогда с проектом быть придется задавать только входной сигнал x, сигнал для коэффициентов w и оперировать типа так:
x.x0.x_re это будет x0_re?

и с компонентами тогда как получится можно ли будет сделать так:
Код
entity full_butterfly is
generic (b_size: natural := 17;
         w_size: natural := 12);
port (
CLK: in std_logic;
switch: in std_logic;
x : in complex_data_vector;

w : in complex_coef_vector;

y0_re: out std_logic_vector(b_size - 1 downto 0);
y0_im: out std_logic_vector(b_size - 1 downto 0);
y1_re: out std_logic_vector(b_size - 1 downto 0);
y1_im: out std_logic_vector(b_size - 1 downto 0);
y2_re: out std_logic_vector(b_size - 1 downto 0);
y2_im: out std_logic_vector(b_size - 1 downto 0);
y3_re: out std_logic_vector(b_size - 1 downto 0);
y3_im: out std_logic_vector(b_size - 1 downto 0)
);
end full_butterfly;

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

component butterfly_complex is
generic (b_size: natural := 17);
port(
CLK: in std_logic;
switch: in std_logic;
x: in complex_data_vector;
y0_re: out std_logic_vector(b_size - 1 downto 0);
y0_im: out std_logic_vector(b_size - 1 downto 0);
y1_re: out std_logic_vector(b_size - 1 downto 0);
y1_im: out std_logic_vector(b_size - 1 downto 0);
y2_re: out std_logic_vector(b_size - 1 downto 0);
y2_im: out std_logic_vector(b_size - 1 downto 0);
y3_re: out std_logic_vector(b_size - 1 downto 0);
y3_im: out std_logic_vector(b_size - 1 downto 0)
);
end component butterfly_complex;


. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

butterfly: butterfly_complex
port map(
CLK => CLK,
switch => switch,
x => x;
y0_re => y0_re_connect,
y0_im => y0_im_connect,
y1_re => y1_re_connect,
y1_im => y1_im_connect,
y2_re => y2_re_connect,
y2_im => y2_im_connect,
y3_re => y3_re_connect,
y3_im => y3_im_connect
);
Go to the top of the page
 
+Quote Post
Sefo
сообщение Apr 16 2009, 22:37
Сообщение #134


Местный
***

Группа: Свой
Сообщений: 429
Регистрация: 11-08-05
Из: Санкт-Петербург
Пользователь №: 7 537



Цитата(ZED @ Apr 13 2009, 21:12) *
Resize не нужен т.к. мы расширили до 17 разрядов отчсеты и до 12 разрядов поворачивающие множители, убрал...


К сожалению, объяснить отсутствие переполнения только лишь увеличением разрядности недостаточно. Представьте, к примеру, что x_re = 32768, x_im = 32768, w_re = 1024 и w_im = 1024. В этом случае result_im = (x_re *w_im + x_im *w_re)/1024 = 65536 - однозначно переполнение... Здесь дело в свойствах БПФ. Если все реализовано правильно, то точки, поступающие на вход БПФ всегда находятся внутри единичной окружности на комплексной плоскости. Коеффициенты - это точки лежащие на краю единичной окружности ( w_re = cos(a), w_im = sin(a) ). Так что если w_re = 1024, то w_im неизбежно будет = 0. Поворачивающими их называют не случайно - при умножении на них точка всего лишь поворачивается на угол a. Она никогда не выйдет за пределы этой единичной окружности - это и есть главная причина отсутствия переполнения. Таким образом, если все сделано правильно, то случай x_re = x_im = 32768 исключен так же как и w_re = w_im = 1024.

С record Вы все сделали правильно за исключением ненужных услохнений с именами членов record. Достаточно так:
CODE
type complex_data is record
re: std_logic_vector(b_size - 1 downto 0);
im: std_logic_vector(b_size - 1 downto 0);
end record;


Что касается complex_data_vector / complex_coef_vector, то я имел ввиду следующее:

type complex_data_vector is array (natural range <>) of complex_data;
type complex_coef_vector is array (natural range <>) of complex_coef;

Впрочем, (natural range <>) – это больше для тренировки в освоении языка. При таком задании типа complex_data_vector Вы размерность указываете при использовании. т.е. Вы можете написать

CODE
entity full_butterfly is
port
(
CLK : in std_logic;

switch : in std_logic;

x : in complex_data_vector(3 downto 0);

w : in complex_coef_vector(3 downto 1);

y : out complex_data_vector(3 downto 0)
);
end full_butterfly;


В нашем случае, я, все же, склоняюсь задать размерность жестко. Т.е.

type complex_data_vector is array (3 downto 0) of complex_data;
type complex_coef_vector is array (3 downto 1) of complex_coef;

тогда

CODE
entity full_butterfly is
port
(
CLK : in std_logic;

switch : in std_logic;

x : in complex_data_vector;

w : in complex_coef_vector;

y : out complex_data_vector
);
end full_butterfly;


обратите внимание, что y, являясь выходным сигналом, тоже может быть complex_data_vector.

К сожалению, в record не возможно параметризовать размерность членов (как можно параметризовать размерность самого array) - ее приходится задавать жестко или с помощью констант. Поэтому, что касается внутренних сигналов в бабочке, то ввиду необходимости сделать их на 2 разряда больше не остается ничего другого, как прямо внутри бабочки задать "служебный" тип complex_data_p2_vector:

CODE
architecture beh_butter of butterfly_complex is

type complex_p2 is record
re : std_logic_vector(complex.re'high + 2 downto 0);
im : std_logic_vector(complex.im'high + 2 downto 0);
end record complex_p2;

type complex_data_p2_vector is array (complex_data_vector'range) of complex2;


Выносить его в общий package нет никакого смысла т.к. нигде кроме бабочки он не будет востребован.

В результате вместо замысловатого x.x0.x_re будет x(0).re, что по-моему, весьма читаемо и удобно.

Про память. Т.к. память у нас не тривиальная, то нарисуйте, пожалуйста, блок-схему ее реализации, как Вы ее себе представляете. Могу сразу сказать, что т.к. мы должны вычитывать/сохранять по 4 точки за такт, то без четырех блоков памяти не обойтись, но и 4 блока это далеко не все. Чтобы понять что там еще нужно посмотрите внимательно схему вычисления БПФ.
Go to the top of the page
 
+Quote Post
ZED
сообщение Apr 19 2009, 10:28
Сообщение #135


Местный
***

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



Ну, если предположить, что каждая память состоит из 4 блоков памятей, то нам нужны 4 самих этих блока + схема, которая будет преобразовывать адреса для каждого блока памяти:



Код
If (addr_in_0 >= 0) and (addr_in_0 <= 511) then
    addr_out_0 <= addr_in_0;
elsif (addr_in_0 >= 512) and (addr_in_0 <= 1023) then
    addr_out_0 <= addr_in_0 - 512;
elsif (addr_in_0 >= 1024) and (addr_in_0 <= 1535) then
    addr_out_0 <= addr_in_0 - 1024;
else
    addr_out_0 <= addr_in_0 - 1536;
end if


Вот что-то типа этого я думаю и так для каждого сигнала: addr_in_1, addr_in_2, addr_in_3.

Т.е. получатся схемы сравнения (компараторы) и мультиплексоры...
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 02:10
Рейтинг@Mail.ru


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