Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Реализация БПФ на ПЛИС
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
Страницы: 1, 2, 3, 4, 5, 6, 7
ZED
Доброго времени суток!

Нужно реализовать алгоритм БПФ с прореживанием по частоте на ПЛИС, но при реализации возникают трудности, вот некоторые из них:
  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. На форуме я искал и не нашел ответа на свои вопросы, тем более я уверен далее появятся новые, думаю лучше, чтоб это все было в одной теме...
soldat_shveyk
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 МГц.

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

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

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

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

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

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

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

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

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

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.
ZED
Цитата
Я малость ошибся правильно будет так:
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;
soldat_shveyk
Не силен в Verilog. Помочь не могу.
А не пробовали использовать мегафункцию FFT?
ZED
Цитата
Не силен в Verilog. Помочь не могу.
А не пробовали использовать мегафункцию FFT?


Это VHDL, мегафункцию не пробовал, кстати посоветуете какую и где скачать? Но просто хочется самому реализовать, "ручками" так сказать. Я вот тоже к сожалению не силен в vhdl, но очень хочу его освоить, вот и задаю вопросы. В книжках она как правило не освещены, либо я читаю не те книжки. Кстати слышал вышла книжка: Перельройзен Е.З. Проектируем на VHDL. - М.: Изд-во "СОЛОН-Пресс", 2004. Читал кто? Как она? К сожалению уже все раскупили, где достать не знаю...
soldat_shveyk
ALTERA FFT Compiler - все основное там есть. Для моделирования достаточно оригинальной версии,
посмотрите, поиграете параметрами - выберете что Вам подойдет.
Там еще хелп достаточно полезный приложен.
Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию.
ZED
Цитата
Если не подойдут Вам оригинальные варианты, то берем Рабинера-Голда, и впред, создавать свою реализацию.

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

Спасибо, документацию нашел, а вот сам файл не смог скачать...
soldat_shveyk
Для ознакомительной работы в режиме OpenCore можно скачать без проблем. Пробуйте.

Еще погуглите кракнутый FFT Compiler, в сети полно этого добра. Для начала подойдет любая, не обязательно самая свежая версия.
Там можно будет и исходники посмотреть, они как раз на VHDL.
ZED
Вопрос по vhdl остается открытым, но похоже кроме soldat_shveyk и меня эта тема (БПФ) никого не интересует...
soldat_shveyk
Откопал у себя исходники всех альтеровских БПФ-ов, если надо, пришлю.
Исходники рабочие, пользовался, проверял.
ZED
Буду очень признателен: zed1986@yandex.ru

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

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

И т.д. Вопрос такой, как это сделать, пробовал делать мультиплексирование, но ничего не выходит, может кто подскажет как это реализовать?
BuTeK
поделитесь рабочей коркой БПФ на почту cvik@tut.by
ZED
Цитата
поделитесь рабочей коркой БПФ на почту cvik@tut.by


Рабочей пока нету, тем более она у меня не дома, так что до понедельника...
анатолий
Проще всего сначала представить данные в формате Integer с диапазоном.
Тогда и отлаживать, и видеть вычисления проще, и сравнить с Матлабом можно,
и синтезируется нормально.
Напр. Бабочка программируется так:
YR<=AR+BR*WR/32768-BI*WI/32768;
и т.д.,
где все числа - в диапазоне -32768... 32767.
Напр. коэффициент WR= 0,999=32767.
Вот только двоичную инверсию лучше делать с переводом адреса с целого в вектор и обратно.
А в конце все это можно перевести в векторные данные и соптимизировать по точности и т.п.
ZED
Спасибо, Анатолий, я так и делал, возник вопрос как лучше усекать после вычисления бабочки и сколько разрядов брать...
ZED
В общем нужно масштабировать данные после операций бабочки, вопрос как это сделать? Тут похоже ключевая фраза: "блочная плавающая точка". Может есть у кого какая-нибудь информация по этому поводу? Также вопросы какие разряды брать после умножителя (знаю на форуме было две темы по этому поводу, но там все так путанно, столько мнений, в общем теряюсь где правда, где нет). То же дело обстоит с сумматорами. Подскажите пожалуйста или дайте ссылки на инфу...
Sefo
Как ваши дела с БПФ? Если вопрос еще актуальный и хочется разобраться самому во всех тонкостях и написать свой собственный БПФ, а не хоть как-нибудь "пристроить" чужой, то могу Вас "провести" по процессу создания БПФ своими руками от начала и до конца. Только начать придется с начала, но зато будет нужный Вам результат.
BuTeK
Конечно актуально! Поделитесь информацией... Очень итересно!
ZED
Вопрос еще актуальный, буду очень признателен. Особенно хочется разобраться во всех тонкостях
Sefo
Сначала давайте определимся что мы хотим и выберем подходящую архитектуру БПФ. Основой алгоритма вычисления БПФ является бабочка - на n-точечную бабочку в определенном порядке подаются данные, на выходе результаты умножаются на доворачивающие коэффициенты и сохраняются в памяти, на след. этапе через бабочку прогоняются данные предыдущего этапа и.т.д.

Чтобы не зарубится сразу в дебри сделаем БПФ на фиксированное число точек и, к тому же, являющееся степенью 4, 8 или 2. От того, какому числу будет кратно количество точек зависит какие бабочки нам потребуются и сколько будет этапов. Например, если взять 16 точек, то взяв 2-х точечную бабочку получим 3 этапа и, если принять, что бабочка и умножение на доворачивающие коэффициенты делается за один такт, то потратим 8*3=24 такта (т.е. на каждом этапе мы считаем по 8 бабочек). В случае с 4-х точечной бабочкой БПФ вычислится за 4*2=8 тактов (т.е. на каждом этапе мы считаем по 4 бабочки). Если взять 8-ми точечную бабочку (Т.Б.), то придется вычислять БПФ в 2 этапа и одной 8-ми Т.Б. будет недостаточно - либо на первом, либо на последнем этапе потребуется 2-х точечная бабочка. Тактов это займет 2+8=10 (т.е. на первом этапе вычисляем две 8-ми Т.Б., а на втором восемь 2-х Т.Б.). Если взять 32 точки, то портебуется либо 8-ми и 4-х Т.Б., либо 4-х и 2-х Т.Б., либо только 2-х Т.Б. Этапов потребуется соответственно 2, 3, 5. Тактов потребуется соответственно 4+8=12, 8+8+16=32, 5*16=80. В общем, чтобы понять, сколько этапов и какие бабочки нужны, надо разложить кол-во точек БПФ N на произведение a*b*c*...=N, где сами множители это степень бабочки, а их количество это количество необходимых этапов. Например при N = 16 подходят след. разложения 2*2*2=16, 4*4=16, 8*2=16. При N = 32 возьмем разложения, соответствующие описанным выше примерам: 8*4=32, 4*4*2=32, 2*2*2*2*2=32. Понятно, что в некоторых случаях количество этапов это просто показатель степени (2^5=32)

Далее нужно определится с необходимым быстродействием. Речь не идет пока о частоте клока - речь идет о простом количестве тактов (т.е. их интервал в нс, мс, мкс и т.д. не имеет значения). Одновременно нужно определится и с необходимым количеством ресурсов микросхемы. В БПФ связь этих двух параметров довольно четкая - мало тактов - много места, много тактов мало места. Например, выше, все расчеты тактов делались исходя из того, что бабочка и умножение на коэффициенты делаются за один такт. Это очень быстро, но для 4-х Т.Б. потребуется 8*4=24 сумматора (8 т.к. суммируем комплексные числа) и 3 комплексных(!) умножителя (т.е. 4*3=12 умножителей и 2 сумматора). Однако, если все это вычислять за 4 такта, то надо 8 сумматоров и 1 комплексный умножитель - существенно меньше по ресурсам, но в 4 раза медленнее. Кроме того 8-ми Т.Б. сама по себе больше 4-х, а 4-х больше 2-х. smile.gif

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

Итак :

1) скольки точечное БПФ нужно?

2) Какой баланс выбираем между быстродействием, ресурсами и частотой клока?

Еще одно замечание. Для вычисления 4-х и 2-х Т.Б. нужны только сумматоры, а вот при вычислении 8-ми Т.Б. потребуется еще 2 умножителя. Правда умножать они будут всегда на константу - SQRT(2) (кажется).
ZED
Не совсем понял про разделение бабочки и поворачивающих множителей. Ведь сама бабочка включает в себя домножение на поворачивающий множитель. Вот к примеру бабочка с прореживанием по частоте:

W - поворачивающий множитель, который меняется от бабочки к бабочке и от этапа к этапу.
Теперь с количеством точек: нужно 2048.
Выбор баланса - быстродействие.
Также предлагаю реализовать алгоритм с постоянной структурой по схеме "пинг-понг":


Прореживание по частоте.
Суть метода: В ОЗУ-1 находятся отсчеты сигнала, над которыми будет производиться БПФ, на нечетных этапах данные берутся из ОЗУ-1, а поворачивающие множители из ПЗУ, вычисляется бабочка и результат записывается в ОЗУ-2 (бабочка одна). Те же действия повторяются над всеми парами точек. Для четных этапов все наоборот: данные берутся из ОЗУ-2, поворачивающие множители по-прежнему из ПЗУ, вычисляется бабочка и результат записывается в ОЗУ-1.
Sefo
Про разделение бабочки и поворачивающих множителей я Вам объясню завтра - сейчас времени нет. W на маленьком рисунке это "не тот" поворачивающий коэффициент, о котором я писал. Это важный вопрос для понимания "тонкостей" БПФ, поэтому предлагаю сделать паузу до моего подробного ответа завтра.
ZED
Хорошо, жду с нетерпением, завтра я буду вечером и с удовольствием прочту. Спасибо!
Sefo
На рисунке показана базовая операция для БПФ с прореж. по частоте, если бы было прореживание по времени, то умножение на W было бы нарисовано не на выходе, а на входе. Кроме того, значение W зависит от положения бабочки в схеме алгоритма. В некоторых случаях, умножение на W является тривиальным: когда W = -+1 + j0 умножение как таковое вообще отсутствует, когда W = 0 +- j1 реальная и мнимая части просто меняются местами и изменяется знак. Алгоритмов вычисления БПФ можно придумать много, а способов реализации каждого - еще больше. К примеру, если при реализации алгоритма используется несколько экземпляров бабочек, чтобы распараллелить вычисления, то, может оказаться, что какие-то экземпляры бабочек всегда будут получать тривиальные коэффициенты и им комплексные умножители вообще не понадобятся. В конце концов, суть БПФ в том, что ДПФ большего порядка вычисляются через ДПФ меньшего. Ведь n-точечная бабочка это не что иное, как n-точечное ДПФ. Вы сами можете легко получить формулы для вычисления n-точечных бабочек просто расписав n-точечное ДПФ и упростив выражения. Поэтому, если рассуждать строго, считать умножение на W частью бабочки, как на вашей картинке, неправильно. В любом случае, с инженерной точки зрения, умножение на W следует вынести за пределы бабочки. Это дает возможность лучше понять где и на чем можно сэкономить при реализации алгоритма БПФ и это так же дает некоторые удобства самой реализации. Так что далее, упоминая бабочку, я буду иметь ввиду "чистую" бабочку.

Теперь про некоторые особенности бабочек.

Если Вы распишите 2-х и 4-х точечное ДПФ, то увидите, что все коэффициенты тривиальные: либо вещественная, либо мнимая 1! При реализации, умножение на такие коэффициенты не требует использования умножителей. Поэтому, 2-х и 4-х точечные бабочки "дешевые" для реализации. Все что нужно, это сложить, вычесть и поменять местами Re и Im.

С 8-ми и более Т.Б. дела обстоят хуже – если Вы их распишите, то увидите, что появляются нетривиальные коэффициенты – SQRT(2)/2. Тут без умножителей не обойтись. Правда, умножители эти всегда умножают на константу, что несколько экономит место (если нет DSP блоков или речь идет об ASIC, а не о ПЛИС). Из-за этого нюанса, внесение в бабочку еще и умножения на W может запутать новичка.

Итак важная особенность бабочки ("чистой") в том, что она всегда вычисляется одинаково, в каком бы алгоритме она не применялась.

Фактически, различия между алгоритмами состоят лишь в порядке подачи данных на бабочки и месте умножения на доворачивающие коэффициенты W (до или после бабочки).

Теперь про реализацию.

Хотите Пин-понг – реализуем пин-понг. Но Вы уверены, что 2-х Т.Б. Вас устроит по быстродействию? Ведь 2-х точечная бабочка для 2048 точек это 11*1024 = 11264 такта (4-х + 2-х точечная сделают все за 512*5 + 1024 = 3584).
ZED
Честно говоря, конечно лучше бы 4-х Т.Б. Но как с ней сделать алгоритм на 2048 точек, нам ведь все равно потребуется 2-х Т.Б. ? Если это можно сделать с 4-х Т.Б. я вполне согласен!
Sefo
Итак, делаем более быстрый вариант с 4-х и 2-х Т.Б.

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

Не знаю, насколько у Вас много времени, но лучше, если Вы нарисуете схему и блок-схему в чем-нибудь вроде Visio, чтобы было проще ее редактировать, исправляя ошибки или оптимизируя (и Вам и мне).

Поскольку мы уже подходим к реализации, то мне необходимо знать какой Вы спроектировали интерфейс между БПФ и самой системой - т.е. кто является источником данных и какой протокол передачи их в БПФ, кто является приемником данных и по какому протоколу он их будет принимать. Также мне надо знать какая(какие) ПЛИС будут использованы и какая частота клока.

Если я правильно нпонял, то средой разработки будет Квартус и Вы с ним не очень знакомы. Можно полюбопытствовать какой у Вас опыт разработки и какими программами Вы пользовались?
ZED
Пока никакого интерфейса я не проектировал, считал, что данные уже лежат в одном из ОЗУ (Точнее в двух - для реальной и мнимой части). Опыт разработки у меня очень маленький, был отдаленно знаком с Ise WebPack, но уже все забыл. С квартусом да не очень знаком, ибо иногда не подозреваю что он выкинет в RTL на тот или иной участок кода. Схема получается довольно-таки громоздкая из-за мультиплексирования, переключения шин, да и задержек с адресами. Так что не уверен, что она будет понятна. У меня в принципе основной вопрос как масштабировать результаты после бабочки и домножения на поворачивающие множители, т. е. все упирается в реализацию бабочки и домножения и масштабирования.
Sefo
Я не спроста предложил Вам пройти путь создания БПФ своими руками от самого начала. Почитав вашу переписку я пришел к выводу, что проблема масштабирования коэффициентов совсем не единственная. Фактически я предложил показать Вам как работать с Квартусом, как писать на VHDL и как проектировать нетривиальные вещи. Пришлите ту блок-схему которая у Вас есть - уверен, она может быть значительно упрощена. И в результате этого упрощения упростится и реализация. Я бы даже сказал, что это подозрительно, что она у Вас слишком громоздкая.

P.S. Поймите, если Вы реализуете БПФ кое-как, потратив немеряно времени на отладку и накладывая одну заплату на другую - Вы ничему не научитесь. Я сталкивался с глюками Квартуса, видел как он делает некоторые вещи нерационально, но... я не могу сказать про него, что я "иногда не подозреваю что он выкинет в RTL на тот или иной участок кода". На правильно написанный код действия Квартуса всегда предсказуемы.
ZED
Вот пожалуйста, мои инсинуации: http://ifolder.ru/10661141
___________
|D Q |
|___CLK____|

Это задержка на несколько тактов (на 3, если бабочка выполняется за один такт, т.к. из памяти данные поступают через 2 такта после подачи адреса)

Mux - соответственно мультиплексоры

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

Непонятно назначение блока на входе памяти данных с одним входом D, двумя выходами Q и сигналом Sel (Sel_demux). Какую функцию они выполняют? Ведь если D, по вашей задумке должно подаваться только на один из Q, то что тогда что будет на другом??? smile.gif

Еще непонятно назначение мультиплексоров на выходе из памяти. Получается, что данные, которые всегда являются вещественной частью (согласно схеме), могут (и будут) попадать на вход бабочки, куда должна подаваться мнимая часть и наоборот. Похоже баг.
ZED
Цитата
Непонятно назначение блока на входе памяти данных с одним входом D, двумя выходами Q и сигналом Sel (Sel_demux). Какую функцию они выполняют? Ведь если D, по вашей задумке должно подаваться только на один из Q, то что тогда что будет на другом??? smile.gif


Это переключатель шины, он выдает сигнал со входа D на выход Q_1 или Q_2, в зависимости от сигнала sel_demux

У нас базовая операция (БО) бабочка должна сначала брать данные из памяти 1, а потом из памяти 2, поэтому нужны мультиплексоры в том числе и на выходе из памяти.

Цитата
Получается, что данные, которые всегда являются вещественной частью (согласно схеме), могут (и будут) попадать на вход бабочки, куда должна подаваться мнимая часть и наоборот. Похоже баг.

Да тут я просто перепутал, там в бабочке по-другому расположены сигналы? должно быть так:
http://ifolder.ru/10668100

Цитата
Это не блок схема, а схема электрическая принципиальная. Но поскольку она не полностью дорисована, то она с практической точки зрения безполезна - из нее с трудом видна структура устройства и она недостаточно детальна, чтобы по ней кодировать (к тому же если ее один в один перенести в VHDL, то получится не самое лечшее использование возможностей языка).


Тогда просто не совсем уверен, что должно называться блок-схемой
Sefo
Но что подается на Q2 когда D подается на Q1?
ZED
На Q2 подается Z, когда D подается на Q1
Sefo
smile.gif Это ножки ПЛИС можно физически перевести в третье состояние, а внутри ПЛИС увы, такого сделать нельзя. Но самое главное, бессмысленно. Таким образом, если Вы не позаботетесь о том, чтобы память, в которую резутьтаты бабочки в данный момент писать не надо, была заблокирована для записи соответствующим сигналом, ваша схема работать не будет. Выходы бабочки нужно подсоединить одновременно к обеим блокам памяти (и не мудрить с "демультиплексорами" smile.gif ) и разрешать запись только в ту память, которая в данный момент является приемником.

Кроме блок схемы я просил Вас еще нарисовать схему алгоритма БПФ, причем, раз уж мы решили делать с помощью 4-х и 2-х Т.Б., то имеется ввиду именно эта схема (конечно-же не надо расписывать "честно" все 2048 точек smile.gif). Вы ее уже нарисовали?

Блок-схема должна отражать основные блоки и потоки данных и управления. На блок схеме нет смысла расписывать, что, например, память состоит из двух блоков - как ее реализовать мы решим позже. Сначала нужно понять какими свойствами должно обладать память, что ей нужно на вход, какое управление и что у нее быдет на выходе. Между прочим, нет особой необходимости вещественную и мнимую части хранить строго в разных блоках памяти. Можно и в одном блоке - решить, что n старших разрядов это Re, а n младших разрядов Im.

Когда мы нарисуем хорошую блок-схему мы поймем какие блоки нам нужны и как они будут взаимодействовать. После этого можно будет прорабатывать внутренности каждого блока по-отдельности.
ZED
Цитата
Это ножки ПЛИС можно физически перевести в третье состояние, а внутри ПЛИС увы, такого сделать нельзя. Но самое главное, бессмысленно. Таким образом, если Вы не позаботетесь о том, чтобы память, в которую резутьтаты бабочки в данный момент писать не надо, была заблокирована для записи соответствующим сигналом, ваша схема работать не будет. Выходы бабочки нужно подсоединить одновременно к обеим блокам памяти (и не мудрить с "демультиплексорами" smile.gif ) и разрешать запись только в ту память, которая в данный момент является приемником.


Согласен, можно шину подключить к 1-ой и 2-ой ОЗУ, нам ведь все равно, сигнал WE в принципе все разреши (когда можно записывать, а когда нет)

Цитата
Кроме блок схемы я просил Вас еще нарисовать схему алгоритма БПФ, причем, раз уж мы решили делать с помощью 4-х и 2-х Т.Б., то имеется ввиду именно эта схема (конечно-же не надо расписывать "честно" все 2048 точек smile.gif). Вы ее уже нарисовали?


Не не нарисовал, т.к. не особо понимаю как делать с помощью 2-х бабочек (2-х ТБ и 4-х ТБ) какие там нужны поворачивающие множители. Может вы что подскажите?

Цитата
Блок-схема должна отражать основные блоки и потоки данных и управления. На блок схеме нет смысла расписывать, что, например, память состоит из двух блоков - как ее реализовать мы решим позже. Сначала нужно понять какими свойствами должно обладать память, что ей нужно на вход, какое управление и что у нее быдет на выходе. Между прочим, нет особой необходимости вещественную и мнимую части хранить строго в разных блоках памяти. Можно и в одном блоке - решить, что n старших разрядов это Re, а n младших разрядов Im.


Память должна быть двухпортовая, должна иметь сигнал разрешения записи WE, соответственно она должна тактироваться (CLK).
Sefo
Поскольку мы выбрали схему пин-понг, то двухпортовая память нам здесь вообще не нужна. У нас на каждом этапе каждый модуль памяти используется либо на запись, либо на чтение. Так что нужна самая обычная память.

Схему алгоритма я нарисую, но, видимо, к вечеру понедельника или во вторник.

Вы же, попробуйте, всетаки, нарисовать блок-схему и продумайте интерфейс БПФ с внешним миром. Как-то же надо данные туда загрузить, а результаты выгрузить smile.gif. Или для Вас БПФ это совсем учебный пример, который и в ПЛИС никода в реальности прошиваться не будет?
ZED
Не, это не учебный, ну я думаю там отсчеты будут поступать через АЦП в буферную внешнюю ОЗУ, а оттуда загружаться внутрь ПЛИС в ОЗУ-1, но я не селен в ПЛИСах, поэтому не могу продумать сей интерфейс, может подскажите где прочитать?
Sefo
Все внешние интерфейсы всегда определяются тем, к чему вы подсоединяете свое. В данном случае, есть 2 варианта.

1) Отсчеты АЦП нужны только для БПФ

2) Только некоторая часть отсчетов АЦП "идет" в БПФ.

В 1) подключите АЦП напрямую к ПЛИС и к памяти БПФ. Вам останется только перед БПФ поставить небольшой блок управления, который будет определять когда можно загружать данные АЦП в БПФ (т.е. когда оно их "ждет") и формировать адрес для памяти БПФ и пару управляющих сигналов.

Во 2-м случае, нужно либо "честно" в нужные моменты времени перекачивать данные из буферного внешнего ОЗУ в память БПФ, либо попытаться свести все к варианту 1), т.е подсоединить выход АЦП и к ПЛИС и к внешнему ОЗУ параллельно и по каки-нибудь сигналам внешней синхронизации "выхватывать" нужные порции данных АЦП из потока.

Раз задача реальная, то расскажите мне по-подробнее, какую роль в ней играет ПЛИС и БПФ и тогда я смогу подсказать как лучше организовать интерфейсы.
ZED
Не, у меня первый вариант, я так понимаю, что блок должен генерить сигнал ClockEnable для ОЗУ-1...
Sefo
Только не ClockEnable, а Write_Enable. Он так же должен следить за состоянием БПФ и когда тот освободится стартовать очередную закачку данных в БПФ.

Вот обещанная схема алгоритма БПФ http://ifolder.ru/10719475. Каждый этап я нарисовал на отдельном листе (за исключением 5-го и 6-го - они на одном листе). На схеме номера точек, это адрес памяти, при этом на 1-ом этапе, слева, адрес памяти соответствует также порядковому номеру входного отсчета. Я пока не нарисовал как переставлены выходные гармоники - в ближайшее время дорисую.

В качестве упражнения для Вас на 4, 5 и 6 этапах я оставил незаполненными поворачивающие коэффициенты. Вам нужно, посмотрев как W образуются на 1, 2 и 3 этапах, распространить эту же логику на оставшиеся. На 6-м этапе будьте внимательны - там есть небольшой подвох (т.е. все очень логично, но можно по "инерции" ошибиться).

Итак: с Вас блок схема БПФ и недостающие коэффициенты на схеме алгоритма БПФ
Sefo
Куда же Вы пропали?
ZED
Прошу прощения, у меня просто возникли очень сложные дела, их нужно было решить, поэтому пропал. Коэффициенты я заполнил, блок-схема в процессе, надеюсь в понедельник вечером представить результаты. Еще раз дико извиняюсь...
ZED
Вот исправленный БПФ-алгоритм и недоделанная схема, может завтра довершу ее, если получится, а сейчас уже поздно...
Sefo
Стоп, стоп! С блок-схемой притормозите - к сожалению, Вы опять рисуете схему электрическую принципиальную, к тому же опять намудрили с мультиплексорами. Я вечером нарисую блок-схему, а Вы ее доработаете - так, думаю, лучше будет, иначе зря потратите кучу времени.

С коэффициентами на 6-м этапе, увы, ошиблись. Какие бы Вы там коэффициенты написали бы, если бы я Вас не предостерег от возможной ошибки?
Sefo
Вот блок-схема БПФ. Вам нужно дорисовать к ней интерфейс с внешним миром. После этого начнем прорабатывать реализацию блоков БПФ.

Что с коэффициентами на 6-м этапе? Есть хоть какие-нибудь соображения?

Теперь немного про вашу схему.

Вы так и не вынесли умножители на поворачивающие множители за пределы бабочки. Почему? Поверьте мне наслово (убедитесь при реализации нашего БПФ), что удобнее их вынести.

Вы почему-то нарисовали бабочку, которая получает за такт только половину данных. Почему? Почему Вы не хотите дать ей сразу все 4 точки?
Если сделать 4-х точечную бабочку, получающую данные за 2 такта, то получится усложнение всей схемы БПФ и самой бабочки. При однотактовой 4-х Т.Б. мы получаем выигрыш по быстродействию перед схемой с 2-х Т.Б. больше чем в 3 раза, а реализовав БПФ на 4-х точечной 2-х тактовой бабочке, мы получаем выигрыш менее чем в 2 раза. По моему мнению это нерационально.

Если уж Вы стали рисовать 2-х тактовую 4-х ТБ, то демультиплексор из 2 в 3 ненужен, даже несмотря на то, что данные подаются еще и на 2-х ТБ smile.gif. Нужен обычный мультиплексор 2 в один (поскольку данные нужно брать то из одной памяти, то из другой). Мы ведь этот ляп уже обсуждали. Почему Вы его снова допустили?
ZED
А вот, что подразумевалось под блок-схемой=)) Спасибо, понял... Алгоритм переделал, по крайней мере я думаю, что так должно быть. А как дать бабочке сразу 4 отсчета, я просто не представляю это возможным, кроме как через задержку на один так два из них.
Цитата
Мы ведь этот ляп уже обсуждали. Почему Вы его снова допустили?

Мы обсуждали ляп про переключение шины.
Цитата
Нужен обычный мультиплексор 2 в один (поскольку данные нужно брать то из одной памяти, то из другой)

Вы предлагаете подключать данные еще и к 2-х Т.Б. всегда?
Цитата
Вот блок-схема БПФ. Вам нужно дорисовать к ней интерфейс с внешним миром.

Не знаю, то ли вы от меня ожидали, но вот вроде так, строго не судите, просто очень сложно все это не в живую обсуждать, а вот так по написанному понять чужие мысли...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.