Jump to content
    

Библиотека MATH_COMPLEX.all и FFT на VHDL

Честно говоря, статья "для галочки". Самое главное там не расписано, а как вычислить саму бабочку Вы и так уже знаете. Если вычислять бабочку по конвейерной схеме, как предлагается в статье, и действительно экономить ресурсы, то "выравнивающий" FIFO совершенно лишний.

 

Я Вам как-то писал, что есть преобразование Фурье, есть разные способы его вычисления и каждый из этих способов может иметь множество разных реализаций. Предлагаю Вам поразмыслить над этим.

 

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

 

Таким образом, я считаю, что на данный момент у Вас есть вся необходимая информация и даже уже некоторый положительный опыт, чтобы решить задачу. Дерзайте.

Да, небольшой опыт есть.

Спасибо Вам.

БПФ32 работает. Нареканий нет. Но напрягает довольно большой объем ресурсов. С наскоку все было сделано по своему разумению, не оптимально.

Сейчас пытаюсь сделать то же но уменьшив ресурсы ПЛИС. Пока попробую реализовать потоковый БПФ8. Если прокатит и сэкономит ресурсы, по сравнению с тем, что был сделан, то и БПФ32 можно попробовать тем же способом. Код выставлю.

Просьба просмотреть бабочку (прореживание по частоте)

post-39850-1391671231_thumb.jpg

b_size - 15

w_size - 12

    -- бабочка (прореживание по частоте)
    
    procedure BUTTERFLY(
        signal clk    : in std_logic;
        signal a_re    : in signed(b_size downto 0);
        signal a_im    : in signed(b_size downto 0);
        signal b_re    : in signed(b_size downto 0);
        signal b_im    : in signed(b_size downto 0);

        signal w_re    : in signed(w_size - 1 downto 0);
        signal w_im    : in signed(w_size - 1 downto 0);

        signal a_res_re : out signed(b_size downto 0);
        signal a_res_im : out signed(b_size downto 0);
        signal b_res_re : out signed(b_size downto 0);
        signal b_res_im : out signed(b_size downto 0)
        ) 
        is

        variable xa_re    : signed(b_size downto 0);
        variable xa_im    : signed(b_size downto 0);
        variable xb_re    : signed(b_size downto 0);
        variable xb_im    : signed(b_size downto 0);
        
    begin
        
        if clk'event and clk = '1' then
            xa_re := a_re + b_re;
            xa_im := a_im + b_im;
            xb_re := a_re - b_re;
            xb_im := a_im - b_im;

            a_res_re <= xa_re;
            a_res_im <= xa_im;
        
            b_res_re <= resize((xb_re*w_re - xb_im*w_im), b_size + 1);
            b_res_im <= resize((xb_re*w_im + xb_re*w_re), b_size + 1);
        end if;    

    end procedure;

 

 

Share this post


Link to post
Share on other sites

Бабочка работает. В смысле суммирует, вычитает, умножает. Но не понятен один момент:

Код

b_res_re <= resize((xb_re*w_re - xb_im*w_im), b_size + 1);

При вычислении дает странную ошибку

Если, например

xb_re = 1448

w_re = 724

xb_im = 1448

w_im = -724

Результат на калькуляторе будет 2096704

Если его привести к разрядности менее 16 (например разделить на 64) то получится 32761

А реально данный код дает результат 32320

Разница существенная. Интересно почему?

Edited by Acvarif

Share this post


Link to post
Share on other sites

.

Информация отсутствует. Прошу подправить. Что означает точка?

Edited by Acvarif

Share this post


Link to post
Share on other sites

Бабочка работает. В смысле суммирует, вычитает, умножает. Но не понятен один момент:

Код

b_res_re <= resize((xb_re*w_re - xb_im*w_im), b_size + 1);

При вычислении дает странную ошибку

Если, например

xb_re = 1448

w_re = 724

xb_im = 1448

w_im = -724

Результат на калькуляторе будет 2096704

Если его привести к разрядности менее 16 (например разделить на 64) то получится 32761

А реально данный код дает результат 32320

Разница существенная. Интересно почему?

 

 

Очень просто: resize берет указанное количество младших бит. С чего Вы взяли, что она берет старшие биты?

2096704 = 1 1111 1111 1110 0100 0000
32320   =         111 1110 0100 0000

 

:smile3046:

 

БПФ32 работает. Нареканий нет. Но напрягает довольно большой объем ресурсов. С наскоку все было сделано по своему разумению, не оптимально.

Сейчас пытаюсь сделать то же но уменьшив ресурсы ПЛИС. Пока попробую реализовать потоковый БПФ8. Если прокатит и сэкономит ресурсы, по сравнению с тем, что был сделан, то и БПФ32 можно попробовать тем же способом. Код выставлю.

 

Я Вам все же настоятельно рекомендую сначала оптимизировать код вашего БПФ32. Что для этого нужно сделать и с чего начать я уже писал.

 

В вашем случае код занимает много ресурсов не потому что схема БПФ прожорлива по своей природе, а потому что код написан, не обижайтесь, кривее некуда.

 

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

Share this post


Link to post
Share on other sites

Информация отсутствует. Прошу подправить. Что означает точка?

значит что написал я какую то глупость, а потом мне стало стыдно и я все стер. А когда глупость пишешь, форум еще как на зло ее 2 раза постит:)

Share this post


Link to post
Share on other sites

Очень просто: resize берет указанное количество младших бит. С чего Вы взяли, что она берет старшие биты?

2096704 = 1 1111 1111 1110 0100 0000
32320   =         111 1110 0100 0000

Понятно. Спасибо.

Я Вам все же настоятельно рекомендую сначала оптимизировать код вашего БПФ32. Что для этого нужно сделать и с чего начать я уже писал.
Оптимизацией я займусь.

Код действительно не в дугу.

Прежде чем приступить пытаюсь осмыслить другие варианты подобных автоматов - типа потоковый БПФ8. Думаю в процессе и появятся мысли для оптипизации.

Пока застрял на простейшем многоразрядном сдвиговом регистре (переключатель для потоковой схемы). Тоесть типа

    procedure SW(
        signal clk    : in std_logic;
        signal dir    : in std_logic;
        signal a_re    : in signed(b_size downto 0);
        signal b_re    : in signed(b_size downto 0);

        signal a_res_re : out signed(b_size downto 0);
        signal b_res_re : out signed(b_size downto 0);
        ) 
        is

        variable b_sw_re    : signed(b_size downto 0);

        subtype bm_re is signed(b_size downto 0);
        type mem_bm_re is array(1 downto 0) of bm_re;
        variable b_s_re : mem_bm_re;

        subtype am_re is signed(b_size downto 0);
        type mem_am_re is array(1 downto 0) of am_re;
        variable a_s_re : mem_am_re;
        
    begin
    
        b_s_re(0) := b_re;
        if clk'event and clk = '0' then
            if dir = '1' then
                a_s_re(0) := a_re;
                b_sw_re := b_s_re(1); 
            else
                a_s_re(0) := b_s_re(1);
                b_sw_re := a_re; 
            end if;    
                a_s_re(1) := a_s_re(0); 
                b_s_re(1) := b_s_re(0); 
        end if;    

        a_res_re <= a_s_re(1);
        b_res_re <= b_sw_re;

    end procedure;

Если сделать то же самое но в виде процесса или компонента, а не процедуры, где вместо vaiable

можно использовать signal то все сдвигает как и задумано. Не врубаюсь почему variable не работает таже?

Edited by Acvarif

Share this post


Link to post
Share on other sites

Понятно. Спасибо.

Оптимизацией я займусь.

Код действительно не в дугу.

Прежде чем приступить пытаюсь осмыслить другие варианты подобных автоматов - типа потоковый БПФ8. Думаю в процессе и появятся мысли для оптипизации.

Пока застрял на простейшем многоразрядном сдвиговом регистре (переключатель для потоковой схемы). Тоесть типа

Если сделать то же самое но в виде процесса или компонента, а не процедуры, где вместо vaiable

можно использовать signal то все сдвигает как и задумано. Не врубаюсь почему variable не работает таже?

 

Вы напрасно в такие дебри полезли. Уже много раз говорил и еще раз повторю: variable в VHDL строго для опытных инженеров - всем остальным стоит забыть про существование variable.

 

Код не работает потому что Вы не понимаете всех тонкостей и подводных камней использования variable.

 

Возвращайтесь к сигналам и забудьте про variable до поры, до времени.

 

Share this post


Link to post
Share on other sites

Вы напрасно в такие дебри полезли. Уже много раз говорил и еще раз повторю: variable в VHDL строго для опытных инженеров - всем остальным стоит забыть про существование variable.

 

Код не работает потому что Вы не понимаете всех тонкостей и подводных камней использования variable.

 

Возвращайтесь к сигналам и забудьте про variable до поры, до времени.

Понял. Спасибо. Перешел на сигналы. Работает как задумано.

Но пока непонятка с бабочкой. Прописал код в матлабе для бпф8 по этому графу

post-39850-1392014270_thumb.jpg

На выходе получилась полная ерунда

Похоже бабочку я не правильно считаю post-39850-1392014800_thumb.jpg

Поскольку все входные данные комплексные, то на выходе должно быть так

A = a + b = (a_re + ja_im) + (b_re + jb_im) = (a_re + b_re) + j(a_im + b_im);

B = a - b*w = ((a_re + ja_im) - (b_re + jb_im)) * (w_re + jw_im) =

((a_re - b_re) + j(a_im - b_im))*(w_re + jw_im) =

((a_re - b_re)*w_re - (a_im - b_im)*w_im) + j((a_re - b_re)*w_im + (a_im - b_im) )*w_re)

 

Значит бабочка должна вычисляться так:

 

A_re = a_re + b_re;

A_im = a_im + b_im;

B_re = (a_re - b_re)*w_re - (a_im - b_im)*w_im;

B_im = (a_re - b_re)*w_im + (a_im - b_im) *w_re;

 

Порошу поддтвердить, что все верно. Если верно, буду искать механичекие ошибки в коде матлаб.

Пока получилось так:

==================================================
Коэффициенты fft8 реал round(cos(2*pi*n/8)*1024) n=0...3 
1024, 724, 0, -724,
Коэффициенты fft8 мним -round(sin(2*pi*n/8)*1024) n=0...3
0, -724, -1024, -724,
==================================================
Входные данные реал FFT8 
0, 724, 1024, 724, 0, -724, -1024, -724,
Входные данные мним FFT8 
1024, 724, 0, -724, -1024, -724, 0, 724,
==================================================
Выходные данные st1_re 
0, 0, 0, 0, 0, 32761, 0, -32761,
Выходные данные st1_im 
0, 0, 0, 0, 32768, 0, -32768, 0,
==================================================
Выходные данные b_st2_re 
0, 0, 0, 0, 0, 0, 0, 0,
Выходные данные b_st2_im 
0, 0, 0, 0, 0, 0, 524288, -1048352,
==================================================
Выходные данные b_st3_re 
0, 0, 0, 0, 0, 0, 0, 8388608,
Выходные данные b_st3_im 
0, 0, 0, 0, 0, 0, 0, 8388608,

Все выходные данные после каждой стадии поделены на 64

Edited by Acvarif

Share this post


Link to post
Share on other sites

Бабокча не работает. Похоже, что схитрить и выполнить за один такт все операции типа

b_re_out <= resize(((a_re_in - b_re_in)*w_re - (a_im_in - b_im_in)*w_im), b_size + 1);
b_re_out <= resize(((a_re_in - b_re_in)*w_re - (a_im_in - b_im_in)*w_im), b_size + 1);

не получается.

Не понимаю, что в этом случае нужно делать. Разделять операции вычитания и умножения по разным тактам?

Edited by Acvarif

Share this post


Link to post
Share on other sites

Ключевое слово - pipelining.

В атрибутах к entity? Можно подробнее? pipelining это как? Поток? Тоесть первый клок готовит сумму, второй умножает и готовит вторую сумму, третий умножает и готовит..

 

Share this post


Link to post
Share on other sites

В атрибутах к entity? Можно подробнее? pipelining это как? Поток? Тоесть первый клок готовит сумму, второй умножает и готовит вторую сумму, третий умножает и готовит..

Нужны дополнительные слои регистров для хранения промежуточных результатов.

См. ссылки.

pipelining

 

ссылка

Share this post


Link to post
Share on other sites

Нужны дополнительные слои регистров для хранения промежуточных результатов.

См. ссылки.

pipelining

 

ссылка

Спасибо.

Понятно.

Это значит, что мой номер не пройдет. Тоесть прежде, чем умножить два числа, которые в свою очередь сформировани из разности четерех предшествующих чисел, нужно их подготовить в каком-то промежуточном регистре. Одновременно (по одному клоку) выполнить вычитание и умножение не удастся. И тем не менее симулятор показывает, что все может работать, кроме одного (a - b ) (когда b отрицательное число). Если все числа положительные то код (как ни странно)

b_re_out <= resize(((a_re_in + b_re_in)*w_re + (a_im_in + b_im_in)*w_im), b_size + 1);

работает по одному клоку.

Edited by Acvarif

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...