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

Пожалуй дам Вам денек еще помучиться. Поймите, нужно по первым двум этапам выявить довольно простую закономерность.

Как минимум, Вы должны были заметить, что записанная на предыдущем этапе точка на следующем должна быть прочитана из того же самого места. Т.е. если на 3-ем этапе Вы 32 точку записали в банк №1 по адресу 0, то на 4-ом этапе, когда она Вам понадобится Вы должны ее прочитать строго из того же места, а Вы ее читаете из банка №1 по адресу 32. Разница между записью на предыдущем этапе и чтением на текущем заключается лишь в том, какие именно точки и в какой момент времени Вы пишете/читаете, но адрес конкретной точки при чтении такой же как и при записи. Это должно быть очевидно.

Должно всегда соблюдаться следующее:
1) все 512 данных в каждом банке памяти должны быть прочитаны и все 2048 результатов записаны во все банки памяти на свои уникальные места.
2) из 1 следует, что комбинация №банка и адрес на каждом этапе может встречаться только один раз (разумеется, один раз при чтении и один раз при записи).

Еще должно помочь то, что я не даром разделил бабочки на блоки.

Дерзайте.
ZED
Вот моя очередная попытка!
Sefo
Замечательно! Так бы сразу!

Проблемы 6-го этапа давайте пока отложим и по горячим следам займемся реализацией управления для 1 - 5 этапов. Кодом просьба пока не увлекаться. Чтобы я сразу смог увидеть направление мысли и поправить, если пойдете не туда и чтобы Вы не тратили зря время, напишите, буквально в двух словах, как или с помощью чего Вы собираетесь реализовывать выявленную закономерность адресов для банков памяти и номеров банков для миксера.
ZED
Ну, если в двух словах, с помощью счетчика с переменным модулем счета, мультиплексоров и управляющей логики.
Sefo
Про счетчики с переменным модулем счета все понятно - это для формирования ядресов памяти и стробов для управления миксерами, "поворачивающими" банки памяти . А каким образом и с помошью чего Вы собираетесь формировать начальные значения для счетчиков и сам модуль счета?

Про назначение мультиплексоров не совсем понятно. Если для реализации миксеров для "поворота" банков, то замечу, что код такого миксера удобно описать с помощью одного case и в качестве управления достаточно 2-х "проводов". Если для чего-то другого, то расскажите подробнее - мне кажется, что для другого они не нужны.

Т.к. сейчас речь и идет об управляющей логике, то добавление управляющей логики в саму управляющую логику настораживает. Так что поясните, что за управляющую логику Вы имели ввиду?

Напишите, пожалуйста, код миксера на входе в бабочку и миксера на выходе умножителей с использованием одного case и 2-х бит управления. Модуль пусть будет чисто комбинаторный.
ZED
Цитата
Про назначение мультиплексоров не совсем понятно. Если для реализации миксеров для "поворота" банков, то замечу, что код такого миксера удобно описать с помощью одного case и в качестве управления достаточно 2-х "проводов". Если для чего-то другого, то расскажите подробнее - мне кажется, что для другого они не нужны.

Ну так case и сгегнерит мультиплексоры.
Цитата
Т.к. сейчас речь и идет об управляющей логике, то добавление управляющей логики в саму управляющую логику настораживает. Так что поясните, что за управляющую логику Вы имели ввиду?

Под управляющей логикой я имел задание модуля счета, генерацию сигналов управления мультиплексорами.
Цитата
Про счетчики с переменным модулем счета все понятно - это для формирования ядресов памяти и стробов для управления миксерами, "поворачивающими" банки памяти . А каким образом и с помошью чего Вы собираетесь формировать начальные значения для счетчиков и сам модуль счета?

Не знаю, то или не то вы от меня ждали, но прилагаю код (mixer).
Цитата
А каким образом и с помошью чего Вы собираетесь формировать начальные значения для счетчиков и сам модуль счета?

Попробовал написать код, несколько запутался, сейчас голова не варит уже, то, что получилось также прилагаю(gen_addr).

http://webfile.ru/3617925
Sefo
Цитата(ZED @ May 16 2009, 17:52) *
Ну так case и сгегнерит мультиплексоры.


Я имел ввиду, что не нужно писать код для четырех отдельных мультиплексоров, а можно все в одном case объединить. Кстати сказать, case не во всех случаях ведет к мультиплексорам.

С миксерами все хорошо, только еще один нужен т.к. миксер перед бабочкой отличается от того, что стоит после умножителей.

С gen_addr, наоборот, все плохо. Даже прокомментировать сложно smile.gif.

Во-первых, т.к. работает он абсолютно неправильно, то неясно для чего он предназначен. Для генерации адресов для чтения данных или для записи?

Во-вторых, что при чтении, что при записи, инкремент адреса всегда 1. Поэтому выражение addr_in_0_sig <= addr_in_0_sig + 1 + dec_block + 6*dec_bank; в корне не верно хотябы потому, что инкремент в нем = 1 + dec_block + 6*dec_bank.

В-третьих, написав

if (count_point(to_integer(i)) = '1') then
count_block <= count_block + dec_block;
count_mix <= count_mix + 1;
end if;

Вы, очевидно, хотели, чтобы через каждые 2^(i+1) тактов у Вас происходил инкремент счетчика блоков и менялось управление миксером. Но Вы явно упустили из виду одно свойство count_point(i) – это не единичный импульс происходящий 1 раз в 2^(i+1). Этот сигнал представляет собой меандр - 2^(i) тактов = '0' и потом 2^(i) тактов = '1' потом все повторяется. Таким образом count_block и count_mix стоят намертво 2^(i) тактов, а затем на протяжении 2^(i) тактов на каждом фронте клока инкрементируются, потом опять стоят, потом опять молотят.

Придется сначала объяснить Вам как сделать управляющую логику. Жаль… Я надеялся, что поняв логику формирования адресов и управления миксерами Вам не составит труда описать это на VHDL.
ZED
Вот новый вариант, так сказать вторая попытка, более продуманная генерации адресов на чтение:
http://webfile.ru/3634105
Sefo
Цитата(ZED @ May 21 2009, 20:34) *
Вот новый вариант, так сказать вторая попытка, более продуманная генерации адресов на чтение:
http://webfile.ru/3634105


Что же, так значительно лучше! Но... есть 2 ошибки и 1 недостаток.

Начнем с недостатка. Плохо, когда в схеме управления нет сигнала, приводящего ее в исходное состояние из любого положения.

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

Если схема управления должна сбрасываться отдельно от остальной части схемы, то следует использовать синхронный сброс.

В нашем случае управление сбрасываться должно независимо от остальной части схемы. Соответственно сброс (в нашем случае правильнее сказать инициализация) д.б. синхронным.

Теперь про ошибки.

При чтении диапазон адресов меняется один раз на 4 блока бабочек и записан 4-мя строчками, но если Вы внимательно посмотрите на схему БПФ, то должны будете заметить, что против одной и той же строчки в разных блокак разный номер банка памяти. Т.е. при чтении, адреса, как и данные, нужно "вращать" относительно банков. Возьмем для примера 3-ий этап. У Вас addr_rd_0 четыре раза подряд считает 0 ... 31. Посмотрите на схему в блоке №0 addr_rd_0 действительно д.б. 0...31, но в блоке бабочек №1 из 0-го банка нужно вычитать данные по адресам 96...127, в блоке бабочек №2 диапазон адресов для 0-го банка уже 64...95. Поскольку миксеры предусматривают "вращение" только данных, то "вращением" адресов должна заняться логика управления. В принципе, ничто не мешает дополнить миксер, но в учебных целях я объясню как это можно сделать красиво прямо в логике управления без лишних затрат.

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

Нажмите для просмотра прикрепленного файла

На последнем такте 2-го этапа (значение etap = 1) у Вас addr_rd_0-3 = 127, 255, 383, 511 (кстати, должно было бы быть 255, 383, 511, 127). На первом такте 3-го этапа у Вас должно было бы быть 0, 32, 64, 96, но т.к. инкременты и базовый адрес отстают на такт от смены этапа Вы имеете адреса с базовым адресом и инкрементами предыдущего этапа 0, 128, 256, 384.

Что касается сигнала управления миксером, то его значение правильно только благодаря его особенностям.

Над ошибками подумайте, осознайте, но код исправлять не спешите - я Вам объясню все управление целиком, тогда и код напишите начисто. Т.к. времени у меня сейчас очень мало и за 1 день управление мне не описать, поломайте голову над проблемой записи данных на 5-м этапе и чтения/записи на 6-м. Я где-то выше уже задавал этот вопрос.
kas
Цитата(Sefo @ Mar 9 2009, 02:52) *
По этой же причине (неправильная разрядность), видимо, Вы для округления прибавляете 4, вместо 2 - это приведет к неправильным вычислениям.

(-32 + 2)/4 = -7.5, отбрасываем младшие разряды получаем -7, а должны получить -8. При сумме больше нуля прибавление двойки перед делением на 4 дает нужный результат, а вот когда сумма меньше нуля, то появляется ошибка. Я что-то упустил?
Sefo
Цитата(kas @ Jun 3 2009, 07:03) *
(-32 + 2)/4 = -7.5, отбрасываем младшие разряды получаем -7, а должны получить -8. При сумме больше нуля прибавление двойки перед делением на 4 дает нужный результат, а вот когда сумма меньше нуля, то появляется ошибка. Я что-то упустил?


Да. Отбрасывать надо двоичные разряды у двоичного числа. Дело в том, что если у числа в дополнительном коде отбросить дробные разряды то, оно округлится к меньшему из соседних целых чисел (независимо от того, положительное оно или отрицательное). Так что если Вы число -7.5 переведете в двоичный вид (1000.1b) и отбросите дробные биты (.1b), то получите -8 (1000b).

Смотрите: -32 (100000b в двоичном дополнительном коде), прибавляем 2 (10b), получаем -30 (100010b) теперь делим на 4 - т.е отбрасываем 2 младших двоичных разряда (или сдвигаем на 2 разряда вправо - как Вам больше нравится) и получаетм 1000, что для числа в дополнительном коде с разрядностью 4 означает -8, если хотим сохранить разрядность исходного числа, то расширяем знак и получаем 111000, что для числа с разрядностью 6 все равно -8.

smile.gif
kas
Цитата(Sefo @ Jun 4 2009, 01:53) *
Да. Отбрасывать надо двоичные разряды у двоичного числа. Дело в том, что если у числа в дополнительном коде отбросить дробные разряды то, оно округлится к меньшему из соседних целых чисел (независимо от того, положительное оно или отрицательное). Так что если Вы число -7.5 переведете в двоичный вид (1000.1b) и отбросите дробные биты (.1b), то получите -8 (1000b).

Смотрите: -32 (100000b в двоичном дополнительном коде), прибавляем 2 (10b), получаем -30 (100010b) теперь делим на 4 - т.е отбрасываем 2 младших двоичных разряда (или сдвигаем на 2 разряда вправо - как Вам больше нравится) и получаетм 1000, что для числа в дополнительном коде с разрядностью 4 означает -8, если хотим сохранить разрядность исходного числа, то расширяем знак и получаем 111000, что для числа с разрядностью 6 все равно -8.

smile.gif

я не совсем удачно пример выбрал и, в попыхах, посчитал неправильно unsure.gif
вот, набросал небольшую програмку, и получил вот такой результат:
a = -31 (11100001b) a+2 = -29 (11100011b) (a+2)>>2 11111000 = -8; a/4= -7.75 - правильно
a = -30 (11100010b) a+2 = -28 (11100100b) (a+2)>>2 11111001 = -7; a/4= -7.50 - неправильно?
a = -29 (11100011b) a+2 = -27 (11100101b) (a+2)>>2 11111001 = -7; a/4= -7.25 - правильно
a = -28 (11100100b) a+2 = -26 (11100110b) (a+2)>>2 11111001 = -7; a/4= -7.00 - правильно
a = -27 (11100101b) a+2 = -25 (11100111b) (a+2)>>2 11111001 = -7; a/4= -6.75 - правильно
a = -26 (11100110b) a+2 = -24 (11101000b) (a+2)>>2 11111010 = -6; a/4= -6.50 - неправильно?
a = -25 (11100111b) a+2 = -23 (11101001b) (a+2)>>2 11111010 = -6; a/4 = -6.25 - правильно
a = -24 (11101000b) a+2 = -22 (11101010b) (a+2)>>2 11111010 = -6; a/4 = -6.00 - правильно
...
a = 24 (00011000b) a+2 = 26 (00011010b) (a+2)>>2 00000110 = 6; a/4 = 6.00 - правильно
a = 25 (00011001b) a+2 = 27 (00011011b) (a+2)>>2 00000110 = 6; a/4 = 6.25 - правильно
a = 26 (00011010b) a+2 = 28 (00011100b) (a+2)>>2 00000111 = 7; a/4 = 6.50 - правильно
a = 27 (00011011b) a+2 = 29 (00011101b) (a+2)>>2 00000111 = 7; a/4 = 6.75 - правильно
a = 28 (00011100b) a+2 = 30 (00011110b) (a+2)>>2 00000111 = 7; a/4 = 7.00 - правильно
a = 29 (00011101b) a+2 = 31 (00011111b) (a+2)>>2 00000111 = 7; a/4 = 7.25 - правильно
a = 30 (00011110b) a+2 = 32 (00100000b) (a+2)>>2 00001000 = 8; a/4 = 7.50 - правильно
a = 31 (00011111b) a+2 = 33 (00100001b) (a+2)>>2 00001000 = 8; a/4 = 7.75 - правильно

Получается ошибки при округлении отрицательных чисел все-таки будут?
Sefo
Цитата(kas @ Jun 4 2009, 10:53) *
я не совсем удачно пример выбрал и, в попыхах, посчитал неправильно unsure.gif
вот, набросал небольшую програмку, и получил вот такой результат:
...
a = -30 (11100010b) a+2 = -28 (11100100b) (a+2)>>2 11111001 = -7; a/4= -7.50 - неправильно?
...
a = -26 (11100110b) a+2 = -24 (11101000b) (a+2)>>2 11111010 = -6; a/4= -6.50 - неправильно?

Получается ошибки при округлении отрицательных чисел все-таки будут?


Нет, ошибок в округлении нет - Вы ошиблись, решив, что -7.5 должно округляться к -7. Нарисуем числовую ось:

Нажмите для просмотра прикрепленного файла

Когда значение попадает строго посередине между двух целых чисел, то его округляют к большему. Соответственно, для +7.5 большим является 8, а вот для -7.5 большим является -7. Так что никакой ошибки округления тут нет.

Цитата(ZED @ May 21 2009, 20:34) *


Что-то от Вас не слышно никаких соображений про чтение/запись на последнем этапе...
kas
Цитата(Sefo @ Jun 4 2009, 15:50) *
Нет, ошибок в округлении нет - Вы ошиблись, решив, что -7.5 должно округляться к -7. Нарисуем числовую ось:

Нажмите для просмотра прикрепленного файла

Когда значение попадает строго посередине между двух целых чисел, то его округляют к большему. Соответственно, для +7.5 большим является 8, а вот для -7.5 большим является -7. Так что никакой ошибки округления тут нет.


А разве числовая ось не должна быть зеркальной относительно нуля? Если мы будем отрицательные числа с дробной частью равной 0.5 округлять до большего по абсолютной величине, то мы получем смещение.
Sefo
Что-то я Вас не понимаю...

Цитата(kas @ Jun 4 2009, 13:52) *
А разве числовая ось не должна быть зеркальной относительно нуля?


Разумеется должна. Такая и есть. Так и нарисовано.


Цитата(kas @ Jun 4 2009, 13:52) *
Если мы будем отрицательные числа с дробной частью равной 0.5 округлять до большего по абсолютной величине, то мы получем смещение.


Мы и не округляем отрицательные числа до большего по абсолютной величине - мы просто округляем к большему, когда дробная часть = 0.5 (независимо от знака числа).

Какое смещение Вы имеете ввиду?
kas
Цитата(Sefo @ Jun 4 2009, 18:58) *
Что-то я Вас не понимаю...

blush.gif

Цитата(Sefo @ Jun 4 2009, 18:58) *
Разумеется должна. Такая и есть. Так и нарисовано.

? rolleyes.gif
Нажмите для просмотра прикрепленного файла

Цитата(Sefo @ Jun 4 2009, 18:58) *
Мы и не округляем отрицательные числа до большего по абсолютной величине - мы просто округляем к большему, когда дробная часть = 0.5 (независимо от знака числа).
Какое смещение Вы имеете ввиду?

Например как на этой картинке
Нажмите для просмотра прикрепленного файла


И уже совсем по детски конечно, но Matlab -7.5 округляет до -8
Вот я и пытаюсь разобраться. smile.gif
Sefo
Понятно, к чему Вы клоните smile.gif. Вы не очень удачно выбрали цитату для своего вопроса. Существуют разные методы округления. В той цитате, что Вы привели для своего вопроса
Цитата
По этой же причине (неправильная разрядность), видимо, Вы для округления прибавляете 4, вместо 2 - это приведет к неправильным вычислениям.


Речь шла не о выборе метода округления, а о неправильной реализации выбранного. Должно было быть реализовано выражение X/4+0.5, что соответствует (Х + 2)/4, а было реализовано (Х + 4)/4, что соответствует Х/4 + 1, что не подпадает под округление никаким способом. Округление к простому большему числа с дробной частью 0.5 весьма просто в реализации, посравнению с приведенным вами, а дает не такие уж плохие результаты - ведь к какому числу округлить значение, находящееся строго по середине решить не так-то просто smile.gif. Вы вот говорите, что округлять отрицательные числа с дробной частью (д.ч.) 0.5 в большую чторону неверно по причине... и приводите пример. Но почему Вы считаете, что отрицательные числа округляются неверно? На точно таком же основании можно утверждать, что это положительные числа округляются неверно! Если отрицат. числа с д.ч. 0.5 округлять в большую чторону, а вот положительные в меньшую, то никакого смещения наблюдаться не будет, а отличие по модулю от истинного значения, между прочим, в обоих случаях одинаково.

Существуют методы, в которых округление чисел с д.ч. 0.5 происходит то в одну сторону, то в другую случайным образом, но равное количество раз в каждую сторону.

Можно придумать еще много способов округления, учитывающих особенности конкрентых систем и имеющие лучшее "качество" округления, чем наиболее распространенные методы. Так что этот вопрос можно обсуждать долго.

Так что как округлять надо решать в зависимости от имеющейся задачи.
ZED
Простите пока временно не могу продолжать работу - слишком сильные напряги с дипломом. Вообще защищаюсь 26, но может раньше смогу приступить к работе. Еще раз приношу свои извинения.
Sefo
Цитата(ZED @ Jun 8 2009, 14:31) *
Простите пока временно не могу продолжать работу - слишком сильные напряги с дипломом. Вообще защищаюсь 26, но может раньше смогу приступить к работе. Еще раз приношу свои извинения.


Удачи при защите диплома! Какая у Вас тема?
Reddy
Извиняюсь за вопрос! Я честно говоря так и не понял какой формат используется для арифметических операций? - с "плавающей точкой", с "блочной плавающей запятой"?
Sefo
Цитата(Reddy @ Jun 14 2009, 14:44) *
Извиняюсь за вопрос! Я честно говоря так и не понял какой формат используется для арифметических операций? - с "плавающей точкой", с "блочной плавающей запятой"?


С фиксированной точкой. Данные 17-ти разрядные, коэффициенты 12-ти разрядные. Диапазону значений -1.0 ... +1.0 соответствует диапазон значений от -32768 до +32768 для данных и -2048 ... +2048 для коэффициентов.
Reddy
Цитата(Sefo @ Jun 15 2009, 12:29) *
С фиксированной точкой. Данные 17-ти разрядные, коэффициенты 12-ти разрядные. Диапазону значений -1.0 ... +1.0 соответствует диапазон значений от -32768 до +32768 для данных и -2048 ... +2048 для коэффициентов.


А не маловато ли разрядов для коэффициентов? 2048 - отриц. + '0' + 2048 - положит. = 4097 > 12 бит.
Потом а какова будет размерность промежуточных результатов? Насколько я понял она может вырости на 4*sqrt(2) - т.е около 6 раз.
Ещё один момент который мне не совсем понятен.
После каждого этапа, мы маштабируем результат и используем округление (отсечение), чтобы втиснуться в разрядность. Но не исказит ли это результат преобразования Фурье (динамический диапазон) ?
Sefo
Цитата(Reddy @ Jun 15 2009, 17:43) *
А не маловато ли разрядов для коэффициентов?


Да, запамятовал smile.gif, -1024 ... +1024

Цитата(Reddy @ Jun 15 2009, 17:43) *
Потом а какова будет размерность промежуточных результатов? Насколько я понял она может вырости на 4*sqrt(2) - т.е около 6 раз.


Ну, всетаки, не размерность, а разрядность. Она не меняется. rolleyes.gif Все данные и коэффициенты находятся внутри единичной окружности на комплексной плоскости и в силу особенностей вычислений результат тоже остается внутри единичной окружности. Я кажется об этом уже писал.

Цитата(Reddy @ Jun 15 2009, 17:43) *
После каждого этапа, мы маштабируем результат и используем округление (отсечение), чтобы втиснуться в разрядность. Но не исказит ли это результат преобразования Фурье (динамический диапазон) ?


Используется округление, а не отсечение. Мы масштабируем не для того, чтобы "втиснуться" в разрядность. В бабочке мы делим результаты на 4 (а на последнем этапе на 2) чтобы результат соответствовал формуле (1/N)*СУММА(...). У нас N = 2048. На первых 5-ти этапах мы каждый результат делим на 4, а на последнем делим на 2 - получаем ((1/4)^5) / 2 = 1/2048, ну а СУММА(...) вычисляется выражениями бабочки и умножителями.

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

Кроме того, на практике, нужно всегда искать разумный баланс между сложностью реализации / объемом "железа" / точностью / быстродействием.
Reddy
В смысле вместо стандартного ДПФ
Нажмите для просмотра прикрепленного файла
используем как бы нормированное
Нажмите для просмотра прикрепленного файла
Тогда согласен, в том смысле что нам не столько важны абсолютные значения бинов сколько их отношения
Sefo
Цитата(ZED @ Jun 8 2009, 14:31) *
Простите пока временно не могу продолжать работу - слишком сильные напряги с дипломом. Вообще защищаюсь 26, но может раньше смогу приступить к работе. Еще раз приношу свои извинения.


Как прошла защита?

Продолжим освоение БПФ?
ZED
Цитата
Как прошла защита?

Продолжим освоение БПФ?


Спасибо, защита прошла на УРА, защитился на отлично, мне нужно немного времени, чтобы восстановить всю картину, а так я с удовольствием продолжу работу над БПФ!
ZED
Я думаю, что на 5 этапе банки вращать не следует, а запись и чтение будут одинаковыми, файл прилагаю. С Ошибками согласен позже исправлю.
ZED
Блин удалилось сообщение, в общем для чтения и записи на последних этапах адресация видимо одна и та же, файл прикрепляю.
Sefo
Цитата(ZED @ Jul 2 2009, 10:34) *
Я думаю, что на 5 этапе банки вращать не следует, а запись и чтение будут одинаковыми, файл прилагаю. С Ошибками согласен позже исправлю.


Без вращения банков Вы действительно сможете читать и писать на 6-м этапе, но Вы не сможете таким образом записать данные на 5-ом этапе. Посмотрите на Вашу схему - результаты вычисления первой бабочки должны будут попасть, соответственно, в банки 0,2,0,2, при этом банки 1 и 3 остаются незадействованы, а в банки 0 и 2 Вы должны будуте записать по 2 результата за раз, что невозможно осуществить.

Таким образом запись на 6-м этапе действительно может осуществляться без вращения банков, а вот запись на 5-ом этапе и, как следствие, чтение на 6-ом этапе нужно продумать.

P.S. Пришла пора 5-ый и 6-ой этап на схеме разъединить, чтобы можно было четко нарисовать для них номера банков и адреса памяти при чтении и записи.
petrov
Цитата(Sefo @ Apr 17 2009, 02:37) *
К сожалению, объяснить отсутствие переполнения только лишь увеличением разрядности недостаточно. Представьте, к примеру, что 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.


Квантованные поворачивающие коэффициенты могут превышать единицу.

Например

abs(round(1024*exp(-i*2*pi/256)^1))-1024 = 0.3051

round(round(1024*exp(-i*2*pi/256)^1)*conj(round(1024*exp(-i*2*pi/256)^1))/1024) = 1025

Я так понимаю что у вас переполнения в таком случае не будет только из-за того что за счёт расширения входных данных до 17 бит образуется большой запас на переполнение?
Sefo
Цитата(petrov @ Jul 8 2009, 15:26) *
Квантованные поворачивающие коэффициенты могут превышать единицу.


Значит плохо отквантовали smile.gif

Можно, конечно, положиться и на запас в 1 бит, но лучше "хорошо" отквантовать коэффициенты.

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

Возьмем Ваш пример, только уберем '-' из под exp - просто для удбства, так угол будет около нуля. Если вещественную часть 1024*exp(i*2*pi/256) Вы округлили к 1024 (т.е. к 1.0), то чтобы не вылезти за единичную окружность относительно мнимой части у Вас уже не остается выбора - она должна быть равна 0, а не 25. Т.к. 2*pi/256 это угол в 1.40625 градуса, то выбрав 1024 - i*0 Вы имеете ошибку по углу в 1.40625 градуса и ошибку по модулю 0.

Округлим вещественную часть 1024*exp(i*2*pi/256) к 1023. В этом случае мнимая часть имеет некоторую свободу выбора значения smile.gif Чтобы модуль коэффициента был = 1 мнимая часть д.б. 45.24378. Угол, соответственно, = 2.5323 градуса. Как видите, в этом случае, ошибка по углу меньше, чем в предыдущем 1.13 градуса.

Ну а теперь вещественную часть 1024*exp(i*2*pi/256) округлим к 1023, а мнимую к 25. Угол будет 1.39991, модуль 1023.3054. Таким образом, ошибка по углу 0.00634 т.е. меньше процента, а ошибка по амплитуде 0.6946 тоже меньше процента и никакого переполнения.

При выборе 1024 + i*25 Вы получаете угол 1.39854 и ошибку по углу 0.00771 (что больше, чем в предыдущем случае), модуль 1024.3051 и ошибку по модулю 0.3051 и, самое главное, переполнение! Причем данный вариант по ошибкам не имеет никаких особенных преимуществ перед предыдущим.
petrov
Цитата(Sefo @ Jul 9 2009, 15:09) *
Ну а теперь вещественную часть 1024*exp(i*2*pi/256) округлим к 1023, а мнимую к 25. Угол будет 1.39991, модуль 1023.3054. Таким образом, ошибка по углу 0.00634 т.е. меньше процента, а ошибка по амплитуде 0.6946 тоже меньше процента и никакого переполнения.


Так это получается round(1023*exp(i*2*pi/256)^1) и

Цитата(Sefo @ Apr 5 2009, 19:27) *
Если говорить очень кратко, то в силу того, что значения всех коэффициентов уменьшаются (пусть даже всего-то на 1/2048), коэффициенты перестают быть значениями e^(-j*2*pi*n/N) в соответствующих точках и теряют свое главное свойство - ортогональность.
Sefo
Цитата(petrov @ Jul 9 2009, 16:46) *
Так это получается round(1023*exp(i*2*pi/256)^1) и


Ну и что?

Сформулируйте, пожалуйста, вопрос в явном и развернутом виде. Две цитаты, которые Вы привели, относятся к разным проблемам. Поэтому искать в них противоречие бессмысленно.
petrov
Цитата(Sefo @ Jul 10 2009, 12:21) *
Ну и что?

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


Мне показалось что есть некоторое противоречие.

Сначала вы говорите что округлять к диапазону -2047...2047 плохо.
Затем говорите что переполнения не будет потому-что модуль коэффициента не превышает 1, и заостряете внимание на этом.
Я вам возражаю что многие квантованные поворачивающие коэффициенты будут превышать 1.
Вы приводите пример что будете квантовать по другому, фактически к диапазону -2047...2047.
Sefo
Цитата(petrov @ Jul 10 2009, 12:38) *
Сначала вы говорите что округлять к диапазону -2047...2047 плохо.


Не округлять. Сначала мы выбирали диапазон целых чисел, которые будут соответствовать диапазону -1.0 ... +1.0. Есть точная формула X*W, которую надо реализовать в целочисленной арифметике. Чтобы это сделать мы Re(W) и Im(W), находящиеся в диапазоне -1.0 ... +1.0 заменяем целыми числами в диапазоне -К ... +К и формулу X*W заменяем полностью эквивалентной (X*(К*W)) / К. Причем (К*W) мы предвычисляем и записываем в память и при вычислениях просто берем нужное значение из памяти. Если Вы возьмете К не являющееся степенью 2, то Вы усложните себе реализацию. Деление на число, являющееся степенью 2 это сверх тривиальная операция, а вот деление на все остальные числа уже нет. Если Вы выберите К = 2047, равно как 2046 или 1999 Вам потребуется ставить делитель. Если же Вы решите из экономии и упрощения железа поделить не на К, а на число близкое К, но являющееся степенью двойки G, то Вы получите формулу (X*(К*W)) / G, которая уже не эквивалентна X*W.

Если Вы реализуете вычисление (X*(К*W)) / К, то с увеличением разрядности Вы будите стремиться к истинному значению X*W, но если Вы реализуете (X*(К*W)) / G, то можете считать хоть в арифметике с плавающей точкой и точностью представления long double - Вы никогда не получите значение X*W (частные вырожденные случаи не в счет).

Цитата(petrov @ Jul 10 2009, 12:38) *
Затем говорите что переполнения не будет потому-что модуль коэффициента не превышает 1, и заостряете внимание на этом.
Я вам возражаю что многие квантованные поворачивающие коэффициенты будут превышать 1.


Поскольку (К*W) предвычисляется, то тут не стоит лениться. Нужно не просто округлить Re и Im по отдельности, а найти такие целочисленные значения Re и Im при которых получается наименьшая ошибка по углу и модулю по сравнению с истинными значениями и нет выхода за пределы единичной окружности.

Цитата(petrov @ Jul 10 2009, 12:38) *
Вы приводите пример что будете квантовать по другому, фактически к диапазону -2047...2047.


Цитата(petrov @ Jul 10 2009, 12:38) *
Так это получается round(1023*exp(i*2*pi/256)^1) и


Это утверждение неверно. То, что значения Re и Im, вычисленные (точнее даже сказать найденные) для одного конкретного угла совпадают со значениями, вычесленными по формуле которая применялась бы если бы диапазон был выбран -1023 ... +1023 ни очем не говорит. Для другого ула такого совпадения может и не быть. Для угла 0 градусов, например, такого совпадения не будет - будет, соответственно 1024 + i*0 и 1023 + i*0. Кроме того, как я уже писал, просто вычислить и округлить по отдельности Re и Im не самое лучшее решение. И может оказаться, что если Вы для диапазона -1023 ... +1023 и данного угла именно найдете подходящие числа Re и Im, то они не совпадут со значениями, которые были найдены для диапазона -1024 ... +1024 и того же угла. (рекомендую это проверить в качестве упражнения).

Надеюсь, я понятно объяснил.
petrov
Цитата(Sefo @ Jul 10 2009, 15:06) *
Это утверждение неверно. То, что значения Re и Im, вычисленные (точнее даже сказать найденные) для одного конкретного угла совпадают со значениями, вычесленными по формуле которая применялась бы если бы диапазон был выбран -1023 ... +1023 ни очем не говорит. Для другого ула такого совпадения может и не быть. Для угла 0 градусов, например, такого совпадения не будет - будет, соответственно 1024 + i*0 и 1023 + i*0. Кроме того, как я уже писал, просто вычислить и округлить по отдельности Re и Im не самое лучшее решение. И может оказаться, что если Вы для диапазона -1023 ... +1023 и данного угла именно найдете подходящие числа Re и Im, то они не совпадут со значениями, которые были найдены для диапазона -1024 ... +1024 и того же угла. (рекомендую это проверить в качестве упражнения).

Надеюсь, я понятно объяснил.


Вот вызывает сомнение что так произвольно можно округлять, многие точки пусть и не все совпадут с round(1023*exp(i*2*pi/256)^1). Шум квантования комплексной экспоненты будет явно больше чем для случая простого округления. Стоят ли эти ухищрения тех потерь в точности перобразования, может действительно просто добавить лишний разряд к данным?
Sefo
Цитата(petrov @ Jul 10 2009, 15:45) *
Вот вызывает сомнение что так произвольно можно округлять, многие точки пусть и не все совпадут с round(1023*exp(i*2*pi/256)^1). Шум квантования комплексной экспоненты будет явно больше чем для случая простого округления. Стоят ли эти ухищрения тех потерь в точности перобразования, может действительно просто добавить лишний разряд к данным?


Это не ухищрения - это один из способов реализации. Между прочим, методов округления довольно много и этот вопрос здесь уже затрагивался. По какому именно пути пойти решать разработчику. Хотите, добавьте разряд, хотите округлите коэффициенты с дополнительным условием не выхода за пределы единичной окружности. Но вот чего точно не стоит делать, так это использовать выражение round(1023*exp(i*2*pi/256)^1) в случае, если Вы в качестве диапазона значений выбрали -1024 ... +1024 - лучше добавьте разряд и не мучайтесь smile.gif. Когда ZED сделает БПФ я предлагаю вернуться к этому вопросу и провести пару практических экспериментов.



Цитата(ZED @ Jul 6 2009, 11:22) *
Блин удалилось сообщение, в общем для чтения и записи на последних этапах адресация видимо одна и та же, файл прикрепляю.


Куда Вы подевались? Вы, вроде, собирались всерьез взяться за дело после защиты?

Вы читали мое сообщение о неверности вашего предположения об одинаковости адресации на последних этапах?
ZED
С интернетом были проблемы, а с работы файлы почему-то не отправлялись, в общем прикрепляю.
Sefo
Цитата(ZED @ Jul 16 2009, 21:20) *
С интернетом были проблемы, а с работы файлы почему-то не отправлялись, в общем прикрепляю.


Лучше, но пока еще неправильно. Из-за того, что на 6-ом этапе мы нереходим от 4-х т.б. к 2-х т.б. да еще и вычисляем 2-х т.б. по две за раз "ломается" алгоритм адресации. основная проблема в том, что записав данные на 5-ом этапе так как Вы это нарисовали Вы не можете прочитать их на 6-ом для вычисления двух бабочек одновременно. На 6-ом этапе на первой же итерации Вы попытаетесь прочитать 4 точки из банков 0, 1, 1, 3, на второй итерации из банков 2, 3, 0, 3 - как видите, всегда присутствует попытка прочитать две точки из одного и того же банка одновременно. Подумайте еще немного - нужно чуть-чуть поменять нумерацию банков при записи на 5-ом этапе.
ZED
Вот, поправил!
Sefo
Цитата(ZED @ Jul 19 2009, 11:36) *
Вот, поправил!


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

http://webfile.ru/3858995
Sefo
Еще раз извиняюсь за столь длительный перерыв.

Начнем с вопроса на засыпку. Откуда взялся коэффициент W1028? На последнем этапе все коэффициенты должны быть равны W0. Если Вы посмотрите предыдущие этапы, то в каждом блоке у самой первой бабочки все коэффициенты равны W0, а на самом последнем этапе каждая бабочка первая и единственная в блоке (просто в целях оптимизации и ускорения вычислений мы на последнем этапе их сразу по две обрабатываем и еще есть особенность расположения отсчетов в памяти – вот у нас и выходит, что на последнем этапе в одном "условном" блоке четыре 2-х точечные бабочки).

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

Я забыл важный нюанс. На этапах с 1 по 5 мы бабочки всегда вычисляли в нарисованном порядке. На последнем этапе нам уже не важен порядок вычисления бабочек. Правда, нам его придется учесть при перестановке гармоник когда мы будем вычитывать результаты из БПФ. Так вот, если продолжить формировать номера банков и адреса по привычному алгоритму, то получится, что мы просто будем вычислять бабочки не по порядку, как нарисовано, а немного в разнобой. Сначала вычислим 0-ю и 2-ю бабочки, затем 1-ю и 3-ю бабочки и т.д. Исправленную схему прилагаю. На всякий случай напомню, что однинаковым цветом залиты банки, из которых данные вычитываются/записываются одновременно. Это важно помнить, когда будете разбираться.

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

Нажмите для просмотра прикрепленного файла
Krolm
Добрый день! тоже хочется вклиниться, но из-за нехватки времени на реализацию... приходится брать готовое что-то.... вопщем как обычно sad.gif вопрос такой : Вот на Альтере выложили БПФ на 32к точки. я правильно понимаю, что просто изменив параметры получаю свой fft - мне нужен на 512, или изменилось число входных данных и это уже совсем другой вычислитель получается и надо искать на 512 точек готовый?

parameter data_width = 16; //The number of bits in the input data for both real and imag parts
parameter twiddle_width = 16; //The number of bits in the twiddle factor for both real and imag parts
parameter transform_length = 32768;
parameter coshex_init_file = "fft_32K_coshex.hex";
parameter sinhex_init_file = "fft_32K_sinhex.hex";
parameter log2_transform_length = 15;
parameter mram_buf_add_width = 15;

а ну наверно надо другие син кос коеффициенты, да?

спасибо.
ZED
Не знаю, я не сталкивался с Альтеровским БПФ, если там только 32 точечный, то прощек самому писать 512 (я так думаю), чем из 32-точечных слепить 512-точечный. Так что или свой или ищи готовый на 512.
ZED
Да, там действительно нет коэффициента W1028? хотя кстати он тождественно равен W0. Там везде будут только W0. Вот я только немного с порядком не разобрался. При 4-х точечной бабочки у нас на выходе порядок отсчетов четвиричноинверсный, а при 2-х точечной - двоичноинверсный. Какой же порядок будет в нашем случае (даже если мы будем вычислять бабочки в разнобой)?

Честно говоря несовсем представляю другую реализацию gen_addr, но очень интересно.
Sefo
Цитата(ZED @ Sep 3 2009, 12:51) *
хотя кстати он тождественно равен W0.

Увы, тождественно не равен. Кстати сказать, нет такого коэффициента, который был бы тождественно равен какому либо другому коэффициенту. Бывают тривиальные коэффициенты.


Цитата(ZED @ Sep 3 2009, 12:51) *
При 4-х точечной бабочки у нас на выходе порядок отсчетов четвиричноинверсный, а при 2-х точечной - двоичноинверсный. Какой же порядок будет в нашем случае (даже если мы будем вычислять бабочки в разнобой)?


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

Цитата(ZED @ Sep 3 2009, 12:51) *
Честно говоря несовсем представляю другую реализацию gen_addr, но очень интересно.


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

Стал расписывать реализацию схемы управления и понял, что зря я 30 августа на 6 этапе решил за блок посчитать четыпе 2-х точечные бабочки – не стоит выбиваться из общего алгоритма, так что исправленная схема БПФ прилагается.

Очевидно, что нужен счетчик на 512 тактов, переполнение которого означает переход к следующему этапу БПФ и сам счетчик этапов. С этим все ясно.

Рассмотрим чтение и запись отдельно.

Начнем с чтения. По схеме хорошо видно, что количество бабочек в блоке и, соответственно количество тактов на блок с каждым этапом уменьшается в 4 раза. Исключение составляет последний 6-ой этап, где разница в 2 раза (на 4-ом этапе 8 тактов на блок, на 5-ом 2 такта, а на 6-ом 1 такт). При переходе от одного блока к другому мы вращаем банки памяти. Для реализации этого алгоритма нам необходим счетчик с переменным модулем счета COUNTER(8 downto 0). При этом модуль счета удобно формировать сдвиговым регистром, который при переходе к следующему этапу будет сдвигать свое значение вправо на 2 разряда. Тот факт, что на 6 этапе делить надо не на 4, а на 2 учиывается автоматически (в данном конкретном случае). Таким образом, начальное значение сдвигового регистра MODULE(8 downto 0) = (others => '1') (т.е. 511), далее при переходе к очередному этапу MODULE(8 downto 0) <= "00" & MODULE(8 downto 2). В результате сдвигов получаем следующий набор значений 511, 127, 31, 7, 1 и 0. При 0 мы будем вращать банки на каждом такте, что соответствует поведению на 6-ом этапе. Когда значение COUNTER будет становится равно модулю счета (если считаем вверх) происходит инкремент 2-х битного счетчика номера банка BANK_COUNTER(1 downto 0) . На всякий случай напомню, что наш "вращатель" банков на вход получает только одно 2-х разрядное число – номер начального банка. Само по себе значение номера блока нам, вобщем-то не нужно. Поcкольку количество блоков всегда кратно 4, то при переходе от этапа к этапу BANK_COUNTER(1 downto 0) всегда будет обнуляться и поэтому какой-либо сброс в начале следующего этапа не требуется. Т.е. В начале "заряжаем" COUNTER и BANK_COUNTER, а затем они крутятся себе особо не обращая внимания на смену этапов.

С адресами сложнее, но и интереснее. Но об этом в ближайшие дни.

Нажмите для просмотра прикрепленного файла
ZED
Цитата
Ваш gen_addr посмотрел, но мы сделаем другую реализацию – вычисление номеров банков и адресов настолько единообразно от этапа к этапу, что жалко заводить на каждый этап по "when …" с константами.


MODULE(8 downto 0) <= (others => '1')
MODULE(8 downto 0) <= "00" & MODULE(8 downto 2)
MODULE(8 downto 0) <= "0000" & MODULE(8 downto 4)
и т.д.

В Этом случае разве не понадобятся when?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.